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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
	/*	 * The window we wanted to push could not be pushed.	 * Instead, save ALL user windows into the pcb.	 * We will notice later that we did this, when we	 * get ready to return from our trap or syscall.	 *	 * The code here is run rarely and need not be optimal.	 */ctw_invalid:	/*	 * Reread cpcb->pcb_uw.  We decremented this earlier,	 * so it is off by one.	 */	ld	[%g6 + PCB_UW], %g7	! (number of user windows) - 1	add	%g6, PCB_RW, %g5	/* save g7+1 windows, starting with the current one */1:					! do {	std	%l0, [%g5 + (0*8)]	!	rw->rw_local[0] = l0;	std	%l2, [%g5 + (1*8)]	!	...	std	%l4, [%g5 + (2*8)]	std	%l6, [%g5 + (3*8)]	std	%i0, [%g5 + (4*8)]	std	%i2, [%g5 + (5*8)]	std	%i4, [%g5 + (6*8)]	std	%i6, [%g5 + (7*8)]	deccc	%g7			!	if (n > 0) save(), rw++;	bge,a	1b			! } while (--n >= 0);	 save	%g5, 64, %g5	/* stash sp for bottommost window */	st	%sp, [%g5 + 64 + (7*8)]	/* set up new wim */	rd	%psr, %g7		! g7 = (junk << 5) + new_cwp;	mov	1, %g5			! g5 = 1 << new_cwp;	sll	%g5, %g7, %g5	wr	%g5, 0, %wim		! wim = g5;	and	%g7, 31, %g7	st	%g7, [%g6 + PCB_WIM]	! cpcb->pcb_wim = new_cwp;	/* fix up pcb fields */	ld	[%g6 + PCB_UW], %g7	! n = cpcb->pcb_uw;	add	%g7, 1, %g5	st	%g5, [%g6 + PCB_NSAVED]	! cpcb->pcb_nsaved = n + 1;	st	%g0, [%g6 + PCB_UW]	! cpcb->pcb_uw = 0;	/* return to trap window */1:	deccc	%g7			! do {	bge	1b			!	restore();	 restore			! } while (--n >= 0);	mov	%l5, %g5		! restore g5, g6, & g7, and return	mov	%l6, %g6	jmp	%l4 + 8	 mov	%l7, %g7	/* NOTREACHED *//* * Each memory access (text or data) fault, from user or kernel mode, * comes here.  We read the error register and figure out what has * happened. * * This cannot be done from C code since we must not enable traps (and * hence may not use the `save' instruction) until we have decided that * the error is or is not an asynchronous one that showed up after a * synchronous error, but which must be handled before the sync err. * * Most memory faults are user mode text or data faults, which can cause * signal delivery or ptracing, for which we must build a full trapframe. * It does not seem worthwhile to work to avoid this in the other cases, * so we store all the %g registers on the stack immediately. * * On entry: *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l3 = T_TEXTFAULT or T_DATAFAULT * * Internal: *	%l4 = %y, until we call mem_access_fault (then onto trapframe) *	%l5 = IE_reg_addr, if async mem error * * We know about the layout of the error registers here. *	addr	reg *	----	--- *	a	AC_SYNC_ERR *	a+4	AC_SYNC_VA *	a+8	AC_ASYNC_ERR *	a+12	AC_ASYNC_VA */memfault:	TRAP_SETUP(-CCFSZ-80)	INCR(_cnt+V_FAULTS)		! cnt.v_faults++ (clobbers %o0,%o1)	st	%g1, [%sp + CCFSZ + 20]	! save g1	rd	%y, %l4			! save y#if AC_SYNC_ERR + 4 != AC_SYNC_VA || \    AC_SYNC_ERR + 8 != AC_ASYNC_ERR || AC_SYNC_ERR + 12 != AC_ASYNC_VA	help help help		! I, I, I wanna be a lifeguard#endif	set	AC_SYNC_ERR, %o0	std	%g2, [%sp + CCFSZ + 24]	! save g2, g3	lda	[%o0] ASI_CONTROL, %o1	! sync err reg	inc	4, %o0	std	%g4, [%sp + CCFSZ + 32]	! (sneak g4,g5 in here)	lda	[%o0] ASI_CONTROL, %o2	! sync virt addr	btst	SER_MEMERR, %o1		! memory error?	std	%g6, [%sp + CCFSZ + 40]	bz,a	normal_mem_fault	! no, just a regular fault 	 wr	%l0, PSR_ET, %psr	! (and reenable traps)	/*	 * We got a synchronous memory error.  It could be one that	 * happened because there were two stores in a row, and the	 * first went into the write buffer, and the second caused this	 * synchronous trap; so there could now be a pending async error.	 * This is in fact the case iff the two va's differ.	 */	inc	4, %o0	lda	[%o0] ASI_CONTROL, %o3	! async err reg	inc	4, %o0	lda	[%o0] ASI_CONTROL, %o4	! async virt addr	cmp	%o2, %o4	be,a	1f			! no, not an async err	 wr	%l0, PSR_ET, %psr	! (and reenable traps)	/*	 * Handle the async error; ignore the sync error for now	 * (we may end up getting it again, but so what?).	 * This code is essentially the same as that at `nmi' below,	 * but the register usage is different and we cannot merge.	 */	sethi	%hi(IE_reg_addr), %l5	! ienab_bic(IE_ALLIE);	ldub	[%l5 + %lo(IE_reg_addr)], %o0	andn	%o0, IE_ALLIE, %o0	stb	%o0, [%l5 + %lo(IE_reg_addr)]	/*	 * Now reenable traps and call C code.	 * %o1 through %o4 still hold the error reg contents.	 * If memerr() returns, return from the trap.	 */	wr	%l0, PSR_ET, %psr	call	_memerr			! memerr(0, ser, sva, aer, ava)	 clr	%o0	ld	[%sp + CCFSZ + 20], %g1	! restore g1 through g7	wr	%l0, 0, %psr		! and disable traps, 3 instr delay	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	ldd	[%sp + CCFSZ + 40], %g6	/* now safe to set IE_ALLIE again */	ldub	[%l5 + %lo(IE_reg_addr)], %o1	or	%o1, IE_ALLIE, %o1	stb	%o1, [%l5 + %lo(IE_reg_addr)]	b	return_from_trap	 wr	%l4, 0, %y		! restore y	/*	 * Trap was a synchronous memory error.	 * %o1 through %o4 still hold the error reg contents.	 */1:	call	_memerr			! memerr(1, ser, sva, aer, ava)	 mov	1, %o0	ld	[%sp + CCFSZ + 20], %g1	! restore g1 through g7	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	ldd	[%sp + CCFSZ + 40], %g6	wr	%l4, 0, %y		! restore y	b	return_from_trap	 wr	%l0, 0, %psr	/* NOTREACHED */normal_mem_fault:	/*	 * Trap was some other error; call C code to deal with it.	 * Must finish trap frame (psr,pc,npc,%y,%o0..%o7) in case	 * we decide to deliver a signal or ptrace the process.	 * %g1..%g7 were already set up above.	 */	std	%l0, [%sp + CCFSZ + 0]	! set tf.tf_psr, tf.tf_pc	mov	%l3, %o0		! (argument: type)	st	%l2, [%sp + CCFSZ + 8]	! set tf.tf_npc	st	%l4, [%sp + CCFSZ + 12]	! set tf.tf_y	mov	%l1, %o3		! (argument: pc)	std	%i0, [%sp + CCFSZ + 48]	! tf.tf_out[0], etc	std	%i2, [%sp + CCFSZ + 56]	mov	%l0, %o4		! (argument: psr)	std	%i4, [%sp + CCFSZ + 64]	std	%i6, [%sp + CCFSZ + 72]	call	_mem_access_fault	! mem_access_fault(type, ser, sva,					!		pc, psr, &tf);	 add	%sp, CCFSZ, %o5		! (argument: &tf)	ldd	[%sp + CCFSZ + 0], %l0	! load new values	ldd	[%sp + CCFSZ + 8], %l2	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	ldd	[%sp + CCFSZ + 56], %i2	ldd	[%sp + CCFSZ + 64], %i4	ldd	[%sp + CCFSZ + 72], %i6	b	return_from_trap	! go return	 wr	%l0, 0, %psr		! (but first disable traps again)/* * fp_exception has to check to see if we are trying to save * the FP state, and if so, continue to save the FP state. * * We do not even bother checking to see if we were in kernel mode, * since users have no access to the special_fp_store instruction. * * This whole idea was stolen from Sprite. */fp_exception:	set	special_fp_store, %l4	! see if we came from the special one	cmp	%l1, %l4		! pc == special_fp_store?	bne	slowtrap		! no, go handle per usual	 EMPTY	sethi	%hi(savefpcont), %l4	! yes, "return" to the special code	or	%lo(savefpcont), %l4, %l4	jmp	%l4	 rett	%l4 + 4/* * slowtrap() builds a trap frame and calls trap(). * This is called `slowtrap' because it *is*.... * We have to build a full frame for ptrace(), for instance. * * Registers: *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l3 = trap code */slowtrap:	TRAP_SETUP(-CCFSZ-80)	/*	 * Phew, ready to enable traps and call C code.	 */	mov	%l3, %o0		! put type in %o0 for laterLslowtrap_reenter:	wr	%l0, PSR_ET, %psr	! traps on again	std	%l0, [%sp + CCFSZ]	! tf.tf_psr = psr; tf.tf_pc = ret_pc;	rd	%y, %l3	std	%l2, [%sp + CCFSZ + 8]	! tf.tf_npc = return_npc; tf.tf_y = %y;	st	%g1, [%sp + CCFSZ + 20]	std	%g2, [%sp + CCFSZ + 24]	std	%g4, [%sp + CCFSZ + 32]	std	%g6, [%sp + CCFSZ + 40]	std	%i0, [%sp + CCFSZ + 48]	mov	%l0, %o1		! (psr)	std	%i2, [%sp + CCFSZ + 56]	mov	%l1, %o2		! (pc)	std	%i4, [%sp + CCFSZ + 64]	add	%sp, CCFSZ, %o3		! (&tf)	call	_trap			! trap(type, psr, pc, &tf)	 std	%i6, [%sp + CCFSZ + 72]	ldd	[%sp + CCFSZ], %l0	! load new values	ldd	[%sp + CCFSZ + 8], %l2	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	ldd	[%sp + CCFSZ + 56], %i2	ldd	[%sp + CCFSZ + 64], %i4	ldd	[%sp + CCFSZ + 72], %i6	b	return_from_trap	 wr	%l0, 0, %psr/* * Do a `software' trap by re-entering the trap code, possibly first * switching from interrupt stack to kernel stack.  This is used for * scheduling and signal ASTs (which generally occur from softclock or * tty or net interrupts) and register window saves (which might occur * from anywhere). * * The current window is the trap window, and it is by definition clean. * We enter with the trap type in %o0.  All we have to do is jump to * Lslowtrap_reenter above, but maybe after switching stacks.... */softtrap:	sethi	%hi(_eintstack), %l7	cmp	%sp, %l7	bge	Lslowtrap_reenter	 EMPTY	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	set	UPAGES*NBPG - CCFSZ - 80, %l5	add	%l6, %l5, %l7	SET_SP_REDZONE(%l6, %l5)	b	Lslowtrap_reenter	 mov	%l7, %sp#ifdef KGDB/* * bpt is entered on all breakpoint traps. * If this is a kernel breakpoint, we do not want to call trap(). * Among other reasons, this way we can set breakpoints in trap(). */bpt:	btst	PSR_PS, %l0		! breakpoint from kernel?	bz	slowtrap		! no, go do regular trap	 nop	/*	 * Build a trap frame for kgdb_trap_glue to copy.	 * Enable traps but set ipl high so that we will not	 * see interrupts from within breakpoints.	 */	TRAP_SETUP(-CCFSZ-80)	or	%l0, PSR_PIL, %l4	! splhigh()	wr	%l4, 0, %psr		! the manual claims that this	wr	%l4, PSR_ET, %psr	! song and dance is necessary	std	%l0, [%sp + CCFSZ + 0]	! tf.tf_psr, tf.tf_pc	mov	%l3, %o0		! trap type arg for kgdb_trap_glue	rd	%y, %l3	std	%l2, [%sp + CCFSZ + 8]	! tf.tf_npc, tf.tf_y	rd	%wim, %l3	st	%l3, [%sp + CCFSZ + 16]	! tf.tf_wim (a kgdb-only r/o field)	st	%g1, [%sp + CCFSZ + 20]	! tf.tf_global[1]	std	%g2, [%sp + CCFSZ + 24]	! etc	std	%g4, [%sp + CCFSZ + 32]	std	%g6, [%sp + CCFSZ + 40]	std	%i0, [%sp + CCFSZ + 48]	! tf.tf_in[0..1]	std	%i2, [%sp + CCFSZ + 56]	! etc	std	%i4, [%sp + CCFSZ + 64]	std	%i6, [%sp + CCFSZ + 72]	/*	 * Now call kgdb_trap_glue(); if it returns, call trap().	 */	mov	%o0, %l3		! gotta save trap type	call	_kgdb_trap_glue		! kgdb_trap_glue(type, &trapframe)	 add	%sp, CCFSZ, %o1		! (&trapframe)	/*	 * Use slowtrap to call trap---but first erase our tracks	 * (put the registers back the way they were).	 */	mov	%l3, %o0		! slowtrap will need trap type	ld	[%sp + CCFSZ + 12], %l3	wr	%l3, 0, %y	ld	[%sp + CCFSZ + 20], %g1	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	b	Lslowtrap_reenter	 ldd	[%sp + CCFSZ + 40], %g6/* * Enter kernel breakpoint.  Write all the windows (not including the * current window) into the stack, so that backtrace works.  Copy the * supplied trap frame to the kgdb stack and switch stacks. * * kgdb_trap_glue(type, tf0) *	int type; *	struct trapframe *tf0; */	.globl	_kgdb_trap_glue_kgdb_trap_glue:	save	%sp, -CCFSZ, %sp	call	_write_all_windows	 mov	%sp, %l4		! %l4 = current %sp	/* copy trapframe to top of kgdb stack */	set	_kgdb_stack + KGDB_STACK_SIZE - 80, %l0					! %l0 = tfcopy -> end_of_kgdb_stack	mov	80, %l11:	ldd	[%i1], %l2	inc	8, %i1	deccc	8, %l1	std	%l2, [%l0]	bg	1b	 inc	8, %l0#ifdef DEBUG	/* save old red zone and then turn it off */	sethi	%hi(_redzone), %l7	ld	[%l7 + %lo(_redzone)], %l6	st	%g0, [%l7 + %lo(_redzone)]#endif	/* switch to kgdb stack */	add	%l0, -CCFSZ-80, %sp	/* if (kgdb_trap(type, tfcopy)) kgdb_rett(tfcopy); */	mov	%i0, %o0	call	_kgdb_trap	add	%l0, -80, %o1	tst	%o0	bnz,a	kgdb_rett	 add	%l0, -80, %g1	/*	 * kgdb_trap() did not handle the trap at all so the stack is	 * still intact.  A simple `restore' will put everything back,	 * after we reset the stack pointer.	 */	mov	%l4, %sp#ifdef DEBUG	st	%l6, [%l7 + %lo(_redzone)]	! restore red zone#endif	ret	restore/* * Return from kgdb trap.  This is sort of special. * * We know that kgdb_trap_glue wrote the window above it, so that we will * be able to (and are sure to have to) load it up.  We also know that we * came from kernel land and can assume that the %fp (%i6) we load here * is proper.  We must also be sure not to lower ipl (it is at splhigh()) * until we have traps disabled, due to the SPARC taking traps at the * new ipl before noticing that PSR_ET has been turned off.  We are on * the kgdb stack, so this could be disastrous. * * Note that the trapframe argument in %g1 points into the current stack * frame (current window).  We abandon this window when we move %g1->tf_psr * into %psr, but we will not have loaded the new %sp yet, so again traps * must be disabled. */kgdb_rett:	rd	%psr, %g4		! turn off traps	wr	%g4, PSR_ET, %psr	/* use the three-instruction delay to do something useful */	ld	[%g1], %g2		! pick up new %psr	ld	[%g1 + 12], %g3		! set %y	wr	%g3, 0, %y#ifdef DEBUG	st	%l6, [%l7 + %lo(_redzone)] ! and restore red zone#endif	wr	%g0, 0, %wim		! enable window changes	nop; nop; nop	/* now safe to set the new psr (changes CWP, leaves traps disabled) */	wr	%g2, 0, %psr		! set rett psr (including cond codes)	/* 3 instruction delay before we can use the new window *//*1*/	ldd	[%g1 + 24], %g2		! set new %g2, %g3/*2*/	ldd	[%g1 + 32], %g4		! set new %g4, %g5/*3*/	ldd	[%g1 + 40], %g6		! set new %g6, %g7	/* now we can use the new window */	mov	%g1, %l4	ld	[%l4 + 4], %l1		! get new pc	ld	[%l4 + 8], %l2		! get new npc

⌨️ 快捷键说明

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