⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
	ld	[%l1 + %lo(_cpcb)], %l1	st	%l0, [%l1 + PCB_WIM]	! cpcb->pcb_wim = cwp;	save	%g0, %g0, %g0		! back to window I	LOADWIN(%sp)	save	%g0, %g0, %g0		! back to R	save	%g0, %g0, %g0		! and then to T	wr	%l0, 0, %psr		! fix those cond codes....	nop				! (let them settle in)	RETTwinuf_user:	/*	 * Underflow from user mode.	 *	 * We cannot use rft_user (as noted above) because	 * we must re-execute the `restore' instruction.	 * Since it could be, e.g., `restore %l0,0,%l0',	 * it is not okay to touch R's registers either.	 *	 * We are now in window I.	 */	btst	7, %sp			! if unaligned, it is invalid	bne	winuf_invalid	 EMPTY	PTE_OF_ADDR(%sp, %l7, winuf_invalid)	CMP_PTE_USER_READ(%l7)		! if first page not readable,	bne	winuf_invalid		! it is invalid	 EMPTY	SLT_IF_1PAGE_RW(%sp, %l7)	! first page is readable	bl,a	winuf_ok		! if only one page, enter window X	 restore %g0, 1, %l1		! and goto ok, & set %l1 to 1	add	%sp, 7*8, %l5	PTE_OF_ADDR(%l5, %l7, winuf_invalid)	CMP_PTE_USER_READ(%l7)		! check second page too	be,a	winuf_ok		! enter window X and goto ok	 restore %g0, 1, %l1		! (and then set %l1 to 1)winuf_invalid:	/*	 * We were unable to restore the window because %sp	 * is invalid or paged out.  Return to the trap window	 * and call trap(T_WINUF).  This will save R to the user	 * stack, then load both R and I into the pcb rw[] area,	 * and return with pcb_nsaved set to -1 for success, 0 for	 * failure.  `Failure' indicates that someone goofed with the	 * trap registers (e.g., signals), so that we need to return	 * from the trap as from a syscall (probably to a signal handler)	 * and let it retry the restore instruction later.  Note that	 * window R will have been pushed out to user space, and thus	 * be the invalid window, by the time we get back here.  (We	 * continue to label it R anyway.)  We must also set %wim again,	 * and set pcb_uw to 1, before enabling traps.  (Window R is the	 * only window, and it is a user window).	 */	save	%g0, %g0, %g0		! back to R#if 0		/* this gives `as' mild heartburn */	save	%g0, 1, %l4		! back to T, then %l4 = 1#else	save	%g0, %g0, %g0		! back to T	mov	1, %l4			! and set %l4 = 1#endif	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	st	%l4, [%l6 + PCB_UW]	! pcb_uw = 1	ld	[%l6 + PCB_WIM], %l5	! get log2(%wim)	sll	%l4, %l5, %l4		! %l4 = old %wim	wr	%l4, 0, %wim		! window I is now invalid again	set	UPAGES*NBPG-CCFSZ-80, %l5	add	%l6, %l5, %sp		! get onto kernel stack	CHECK_SP_REDZONE(%l6, %l5)	/*	 * Okay, call trap(T_WINUF, psr, pc, &tf).	 * See `slowtrap' above for operation.	 */	wr	%l0, PSR_ET, %psr	std	%l0, [%sp + CCFSZ + 0]	! tf.tf_psr, tf.tf_pc	rd	%y, %l3	std	%l2, [%sp + CCFSZ + 8]	! tf.tf_npc, tf.tf_y	mov	T_WINUF, %o0	st	%g1, [%sp + CCFSZ + 20]	! tf.tf_global[1]	mov	%l0, %o1	std	%g2, [%sp + CCFSZ + 24]	! etc	mov	%l1, %o2	std	%g4, [%sp + CCFSZ + 32]	add	%sp, CCFSZ, %o3	std	%g6, [%sp + CCFSZ + 40]	std	%i0, [%sp + CCFSZ + 48]	! tf.tf_out[0], etc	std	%i2, [%sp + CCFSZ + 56]	std	%i4, [%sp + CCFSZ + 64]	call	_trap			! trap(T_WINUF, pc, psr, &tf)	 std	%i6, [%sp + CCFSZ + 72]	! tf.tf_out[6]	ldd	[%sp + CCFSZ + 0], %l0	! new psr, pc	ldd	[%sp + CCFSZ + 8], %l2	! new npc, %y	wr	%l3, 0, %y	ld	[%sp + CCFSZ + 20], %g1	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	ldd	[%sp + CCFSZ + 40], %g6	ldd	[%sp + CCFSZ + 48], %i0	! %o0 for window R, etc	ldd	[%sp + CCFSZ + 56], %i2	ldd	[%sp + CCFSZ + 64], %i4	wr	%l0, 0, %psr		! disable traps: test must be atomic	ldd	[%sp + CCFSZ + 72], %i6	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	ld	[%l6 + PCB_NSAVED], %l7	! if nsaved is -1, we have our regs	tst	%l7	bl,a	1f			! got them	 wr	%g0, 0, %wim		! allow us to enter windows R, I	b,a	return_from_trap	/*	 * Got 'em.  Load 'em up.	 */1:	mov	%g6, %l3		! save %g6; set %g6 = cpcb	mov	%l6, %g6	st	%g0, [%g6 + PCB_NSAVED]	! and clear magic flag	restore				! from T to R	restore				! from R to I	restore	%g0, 1, %l1		! from I to X, then %l1 = 1	rd	%psr, %l0		! cwp = %psr;	sll	%l1, %l0, %l1	wr	%l1, 0, %wim		! make window X invalid	and	%l0, 31, %l0	st	%l0, [%g6 + PCB_WIM]	! cpcb->pcb_wim = cwp;	nop				! unnecessary? old wim was 0...	save	%g0, %g0, %g0		! back to I	LOADWIN(%g6 + PCB_RW + 64)	! load from rw[1]	save	%g0, %g0, %g0		! back to R	LOADWIN(%g6 + PCB_RW)		! load from rw[0]	save	%g0, %g0, %g0		! back to T	wr	%l0, 0, %psr		! restore condition codes	mov	%l3, %g6		! fix %g6	RETT	/*	 * Restoring from user stack, but everything has checked out	 * as good.  We are now in window X, and %l1 = 1.  Window R	 * is still valid and holds user values.	 */winuf_ok:	rd	%psr, %l0	sll	%l1, %l0, %l1	wr	%l1, 0, %wim		! make this one invalid	sethi	%hi(_cpcb), %l2	ld	[%l2 + %lo(_cpcb)], %l2	and	%l0, 31, %l0	st	%l0, [%l2 + PCB_WIM]	! cpcb->pcb_wim = cwp;	save	%g0, %g0, %g0		! back to I	LOADWIN(%sp)	save	%g0, %g0, %g0		! back to R	save	%g0, %g0, %g0		! back to T	wr	%l0, 0, %psr		! restore condition codes	nop				! it takes three to tangle	RETT#endif /* end `real' version of window underflow trap handler *//* * Various return-from-trap routines (see return_from_trap). *//* * Return from trap, to kernel. *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l4 = %wim *	%l5 = bit for previous window */rft_kernel:	btst	%l5, %l4		! if (wim & l5)	bnz	1f			!	goto reload;	 wr	%l0, 0, %psr		! but first put !@#*% cond codes back	/* previous window is valid; just rett */	nop				! wait for cond codes to settle in	RETT	/*	 * Previous window is invalid.	 * Update %wim and then reload l0..i7 from frame.	 *	 *	  T I X	 *	0 0 1 0 0   (%wim)	 * [see picture in window_uf handler]	 *	 * T is the current (Trap) window, I is the Invalid window,	 * and X is the window we want to make invalid.  Window X	 * currently has no useful values.	 */1:	wr	%g0, 0, %wim		! allow us to enter window I	nop; nop; nop			! (it takes a while)	restore				! enter window I	restore	%g0, 1, %l1		! enter window X, then %l1 = 1	rd	%psr, %l0		! CWP = %psr & 31;	and	%l0, 31, %l0	sll	%l1, %l0, %l1		! wim = 1 << CWP;	wr	%l1, 0, %wim		! setwim(wim);	sethi	%hi(_cpcb), %l1	ld	[%l1 + %lo(_cpcb)], %l1	st	%l0, [%l1 + PCB_WIM]	! cpcb->pcb_wim = l0 & 31;	save	%g0, %g0, %g0		! back to window I	LOADWIN(%sp)	save	%g0, %g0, %g0		! back to window T	/*	 * Note that the condition codes are still set from	 * the code at rft_kernel; we can simply return.	 */	RETT/* * Return from trap, to user.  Checks for scheduling trap (`ast') first; * will re-enter trap() if set.  Note that we may have to switch from * the interrupt stack to the kernel stack in this case. *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l4 = %wim *	%l5 = bit for previous window *	%l6 = cpcb * If returning to a valid window, just set psr and return. */rft_user:!	sethi	%hi(_want_ast), %l7	! (done below)	ld	[%l7 + %lo(_want_ast)], %l7	tst	%l7			! want AST trap?	bne,a	softtrap		! yes, re-enter trap with type T_AST	 mov	T_AST, %o0	btst	%l5, %l4		! if (wim & l5)	bnz	1f			!	goto reload;	 wr	%l0, 0, %psr		! restore cond codes	nop				! (three instruction delay)	RETT	/*	 * Previous window is invalid.	 * Before we try to load it, we must verify its stack pointer.	 * This is much like the underflow handler, but a bit easier	 * since we can use our own local registers.	 */1:	btst	7, %fp			! if unaligned, address is invalid	bne	rft_invalid	 EMPTY	PTE_OF_ADDR(%fp, %l7, rft_invalid)	CMP_PTE_USER_READ(%l7)		! try first page	bne	rft_invalid		! no good	 EMPTY	SLT_IF_1PAGE_RW(%fp, %l7)	bl,a	rft_user_ok		! only 1 page: ok	 wr	%g0, 0, %wim	add	%fp, 7*8, %l5	PTE_OF_ADDR(%l5, %l7, rft_invalid)	CMP_PTE_USER_READ(%l7)		! check 2nd page too	be,a	rft_user_ok	 wr	%g0, 0, %wim	/*	 * The window we wanted to pull could not be pulled.  Instead,	 * re-enter trap with type T_RWRET.  This will pull the window	 * into cpcb->pcb_rw[0] and set cpcb->pcb_nsaved to -1, which we	 * will detect when we try to return again.	 */rft_invalid:	b	softtrap	 mov	T_RWRET, %o0	/*	 * The window we want to pull can be pulled directly.	 */rft_user_ok:!	wr	%g0, 0, %wim		! allow us to get into it	wr	%l0, 0, %psr		! fix up the cond codes now	nop; nop; nop	restore				! enter window I	restore	%g0, 1, %l1		! enter window X, then %l1 = 1	rd	%psr, %l0		! l0 = (junk << 5) + CWP;	sll	%l1, %l0, %l1		! %wim = 1 << CWP;	wr	%l1, 0, %wim	sethi	%hi(_cpcb), %l1	ld	[%l1 + %lo(_cpcb)], %l1	and	%l0, 31, %l0	st	%l0, [%l1 + PCB_WIM]	! cpcb->pcb_wim = l0 & 31;	save	%g0, %g0, %g0		! back to window I	LOADWIN(%sp)			! suck hard	save	%g0, %g0, %g0		! back to window T	RETT/* * Return from trap.  Entered after a *	wr	%l0, 0, %psr * which disables traps so that we can rett; registers are: * *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc * * (%l3..%l7 anything). * * If we are returning to user code, we must: *  1.  Check for register windows in the pcb that belong on the stack. *	If there are any, reenter trap with type T_WINOF. *  2.  Make sure the register windows will not underflow.  This is *	much easier in kernel mode.... */return_from_trap:!	wr	%l0, 0, %psr		! disable traps so we can rett! (someone else did this already)	and	%l0, 31, %l5	set	wmask, %l6	ldub	[%l6 + %l5], %l5	! %l5 = 1 << ((CWP + 1) % nwindows)	btst	PSR_PS, %l0		! returning to userland?	bnz	rft_kernel		! no, go return to kernel	 rd	%wim, %l4		! (read %wim in any case)rft_user_or_recover_pcb_windows:	/*	 * (entered with %l4=%wim, %l5=wmask[cwp]; %l0..%l2 as usual)	 *	 * check cpcb->pcb_nsaved:	 * if 0, do a `normal' return to user (see rft_user);	 * if > 0, cpcb->pcb_rw[] holds registers to be copied to stack;	 * if -1, cpcb->pcb_rw[0] holds user registers for rett window	 * from an earlier T_RWRET pseudo-trap.	 */	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	ld	[%l6 + PCB_NSAVED], %l7	tst	%l7	bz,a	rft_user	 sethi	%hi(_want_ast), %l7	! first instr of rft_user	bg,a	softtrap		! if (pcb_nsaved > 0)	 mov	T_WINOF, %o0		!	trap(T_WINOF);	/*	 * To get here, we must have tried to return from a previous	 * trap and discovered that it would cause a window underflow.	 * We then must have tried to pull the registers out of the	 * user stack (from the address in %fp==%i6) and discovered	 * that it was either unaligned or not loaded in memory, and	 * therefore we ran a trap(T_RWRET), which loaded one set of	 * registers into cpcb->pcb_pcb_rw[0] (if it had killed the	 * process due to a bad stack, we would not be here).	 *	 * We want to load pcb_rw[0] into the previous window, which	 * we know is currently invalid.  In other words, we want	 * %wim to be 1 << ((cwp + 2) % nwindows).	 */	wr	%g0, 0, %wim		! enable restores	mov	%g6, %l3		! save g6 in l3	mov	%l6, %g6		! set g6 = &u	st	%g0, [%g6 + PCB_NSAVED]	! clear cpcb->pcb_nsaved	restore				! enter window I	restore	%g0, 1, %l1		! enter window X, then %l1 = 1	rd	%psr, %l0	sll	%l1, %l0, %l1		! %wim = 1 << CWP;	wr	%l1, 0, %wim	and	%l0, 31, %l0	st	%l0, [%g6 + PCB_WIM]	! cpcb->pcb_wim = CWP;	nop				! unnecessary? old wim was 0...	save	%g0, %g0, %g0		! back to window I	LOADWIN(%g6 + PCB_RW)	save	%g0, %g0, %g0		! back to window T (trap window)	wr	%l0, 0, %psr		! cond codes, cond codes everywhere	mov	%l3, %g6		! restore g6	RETT! exported end marker for kernel gdb	.globl	_endtrapcode_endtrapcode:/* * init_tables(nwin) int nwin; * * Set up the uwtab and wmask tables. * We know nwin > 1. */init_tables:	/*	 * for (i = -nwin, j = nwin - 2; ++i < 0; j--)	 *	uwtab[i] = j;	 * (loop runs at least once)	 */	set	uwtab, %o3	sub	%g0, %o0, %o1		! i = -nwin + 1	inc	%o1	add	%o0, -2, %o2		! j = nwin - 2;0:	stb	%o2, [%o3 + %o1]	! uwtab[i] = j;1:	inccc	%o1			! ++i < 0?	bl	0b			! yes, continue loop	 dec	%o2			! in any case, j--	/*	 * (i now equals 0)	 * for (j = nwin - 1; i < nwin; i++, j--)	 *	uwtab[i] = j;	 * (loop runs at least twice)	 */	sub	%o0, 1, %o2		! j = nwin - 10:	stb	%o2, [%o3 + %o1]	! uwtab[i] = j	inc	%o1			! i++1:	cmp	%o1, %o0		! i < nwin?	bl	0b			! yes, continue	 dec	%o2			! in any case, j--	/*	 * We observe that, for i in 0..nwin-2, (i+1)%nwin == i+1;	 * for i==nwin-1, (i+1)%nwin == 0.	 * To avoid adding 1, we run i from 1 to nwin and set	 * wmask[i-1].	 *	 * for (i = j = 1; i < nwin; i++) {	 *	j <<= 1;	(j now == 1 << i)	 *	wmask[i - 1] = j;	 * }	 * (loop runs at least once)	 */	set	wmask - 1, %o3	mov	1, %o1			! i = 1;	mov	2, %o2			! j = 2;0:	stb	%o2, [%o3 + %o1]	! (wmask - 1)[i] = j;	inc	%o1			! i++	cmp	%o1, %o0		! i < nwin?	bl,a	0b			! yes, continue	 sll	%o2, 1, %o2		! (and j <<= 1)	/*	 * Now i==nwin, so we want wmask[i-1] = 1.	 */	mov	1, %o2			! j = 1;	retl	 stb	%o2, [%o3 + %o1]	! (wmask - 1)[i] = j;dostart:	rd	%psr, %l0		! paranoia: make sure ...	andn	%l0, PSR_ET, %l0	! we have traps off	wr	%l0, 0, %psr		! so that we can fiddle safely	nop; nop; nop	/*	 * Startup.	 *	 * W

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -