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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
	ld	[%l4 + 20], %g1		! set new %g1	/* set up returnee's out registers, including its %sp */	ldd	[%l4 + 48], %i0	ldd	[%l4 + 56], %i2	ldd	[%l4 + 64], %i4	ldd	[%l4 + 72], %i6	/* load returnee's window, making the window above it be invalid */	restore	restore	%g0, 1, %l1		! move to inval window and set %l1 = 1	rd	%psr, %l0	sll	%l1, %l0, %l1	wr	%l1, 0, %wim		! %wim = 1 << (%psr & 31)	sethi	%hi(_cpcb), %l1	ld	[%l1 + %lo(_cpcb)], %l1	and	%l0, 31, %l0		! CWP = %psr & 31;	st	%l0, [%l1 + PCB_WIM]	! cpcb->pcb_wim = CWP;	save	%g0, %g0, %g0		! back to window to reload	LOADWIN(%sp)	save	%g0, %g0, %g0		! back to trap window	/* note, we have not altered condition codes; safe to just rett */	RETT#endif/* * syscall() builds a trap frame and calls syscall(). * sun_syscall is same but delivers sun system call number * XXX	should not have to save&reload ALL the registers just for *	ptrace... */#ifdef COMPAT_SUNOSsun_syscall:	TRAP_SETUP(-CCFSZ-80)	b	sys_merge	 mov	1, %o3			! third arg to syscall: sun compatsyscall:	TRAP_SETUP(-CCFSZ-80)	clr	%o3			! third arg to syscall: native bsdsys_merge:#elsesyscall:	TRAP_SETUP(-CCFSZ-80)#endif	wr	%l0, PSR_ET, %psr	std	%l0, [%sp + CCFSZ + 0]	! tf_psr, tf_pc	rd	%y, %l3	std	%l2, [%sp + CCFSZ + 8]	! tf_npc, tf_y	st	%g1, [%sp + CCFSZ + 20]	! tf_g[1]	std	%g2, [%sp + CCFSZ + 24]	! tf_g[2], tf_g[3]	std	%g4, [%sp + CCFSZ + 32]	! etc	std	%g6, [%sp + CCFSZ + 40]	mov	%g1, %o0		! (code)	std	%i0, [%sp + CCFSZ + 48]	add	%sp, CCFSZ, %o1		! (&tf)	std	%i2, [%sp + CCFSZ + 56]	mov	%l1, %o2		! (pc)	std	%i4, [%sp + CCFSZ + 64]	call	_syscall		! syscall(code, &tf, pc, suncompat)	 std	%i6, [%sp + CCFSZ + 72]	! now load em all up again, sigh	ldd	[%sp + CCFSZ + 0], %l0	! new %psr, new pc	ldd	[%sp + CCFSZ + 8], %l2	! new npc, new %y	wr	%l3, 0, %y	/* see `dostart' for the reason for this label */init_syscall_ret:	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/* * Interrupts.  Software interrupts must be cleared from the software * interrupt enable register.  Rather than calling ienab_bic for each, * we do them in-line before enabling traps. * * After preliminary setup work, the interrupt is passed to each * registered handler in turn.  These are expected to return nonzero if * they took care of the interrupt.  If a handler claims the interrupt, * we exit (hardware interrupts are latched in the requestor so we'll * just take another interrupt in the unlikely event of simultaneous * interrupts from two different devices at the same level).  If we go * through all the registered handlers and no one claims it, we report a * stray interrupt.  This is more or less done as: * *	for (ih = intrhand[intlev]; ih; ih = ih->ih_next) *		if ((*ih->ih_fun)(ih->ih_arg ? ih->ih_arg : &frame)) *			return; *	strayintr(&frame); * * Software interrupts are almost the same with three exceptions: * (1) we clear the interrupt from the software interrupt enable *     register before calling any handler (we have to clear it first *     to avoid an interrupt-losing race), * (2) we always call all the registered handlers (there is no way *     to tell if the single bit in the software interrupt register *     represents one or many requests) * (3) we never announce a stray interrupt (because of (1), another *     interrupt request can come in while we're in the handler.  If *     the handler deal with everything for both the original & the *     new request, we'll erroneously report a stray interrupt when *     we take the software interrupt for the new request. * * Inputs: *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l3 = interrupt level *	(software interrupt only) %l4 = bits to clear in interrupt register * * Internal: *	%l4, %l5: local variables *	%l6 = %y *	%l7 = %g1 *	%g2..%g7 go to stack * * An interrupt frame is built in the space for a full trapframe; * this contains the psr, pc, npc, and interrupt level. */	.comm	_intrhand, 15 * 8	! intrhand[0..14]; 0 => errorsoftintr:	sethi	%hi(IE_reg_addr), %l6	ldub	[%l6 + %lo(IE_reg_addr)], %l5	andn	%l5, %l4, %l5	stb	%l5, [%l6 + %lo(IE_reg_addr)]	INTR_SETUP(-CCFSZ-80)	std	%g2, [%sp + CCFSZ + 24]	! save registers	INCR(_cnt+V_INTR)		! cnt.v_intr++; (clobbers %o0,%o1)	mov	%g1, %l7	rd	%y, %l6	std	%g4, [%sp + CCFSZ + 32]	andn	%l0, PSR_PIL, %l4	! %l4 = psr & ~PSR_PIL |	sll	%l3, 8, %l5		!	intlev << IPLSHIFT	std	%g6, [%sp + CCFSZ + 40]	or	%l5, %l4, %l4		!			;	wr	%l4, 0, %psr		! the manual claims this	wr	%l4, PSR_ET, %psr	! song and dance is necessary	std	%l0, [%sp + CCFSZ + 0]	! set up intrframe/clockframe	sll	%l3, 2, %l5	set	_intrcnt, %l4		! intrcnt[intlev]++;	ld	[%l4 + %l5], %o0	std	%l2, [%sp + CCFSZ + 8]	inc	%o0	st	%o0, [%l4 + %l5]	set	_intrhand, %l4		! %l4 = intrhand[intlev];	ld	[%l4 + %l5], %l4	b	3f	 st	%fp, [%sp + CCFSZ + 16]1:	ld	[%l4], %o1	ld	[%l4 + 4], %o0	tst	%o0	bz,a	2f	 add	%sp, CCFSZ, %o02:	jmpl	%o1, %o7		!	(void)(*ih->ih_fun)(...)	 ld	[%l4 + 8], %l4		!	and ih = ih->ih_next3:	tst	%l4			! while ih != NULL	bnz	1b	 nop	mov	%l7, %g1	wr	%l6, 0, %y	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	ldd	[%sp + CCFSZ + 40], %g6	b	return_from_trap	 wr	%l0, 0, %psr	/*	 * _sparc_interrupt is exported for paranoia checking (see intr.c).	 */	.globl	_sparc_interrupt_sparc_interrupt:	INTR_SETUP(-CCFSZ-80)	std	%g2, [%sp + CCFSZ + 24]	! save registers	INCR(_cnt+V_INTR)		! cnt.v_intr++; (clobbers %o0,%o1)	mov	%g1, %l7	rd	%y, %l6	std	%g4, [%sp + CCFSZ + 32]	andn	%l0, PSR_PIL, %l4	! %l4 = psr & ~PSR_PIL |	sll	%l3, 8, %l5		!	intlev << IPLSHIFT	std	%g6, [%sp + CCFSZ + 40]	or	%l5, %l4, %l4		!			;	wr	%l4, 0, %psr		! the manual claims this	wr	%l4, PSR_ET, %psr	! song and dance is necessary	std	%l0, [%sp + CCFSZ + 0]	! set up intrframe/clockframe	sll	%l3, 2, %l5	set	_intrcnt, %l4		! intrcnt[intlev]++;	ld	[%l4 + %l5], %o0	std	%l2, [%sp + CCFSZ + 8]	! set up intrframe/clockframe	inc	%o0	st	%o0, [%l4 + %l5]	set	_intrhand, %l4		! %l4 = intrhand[intlev];	ld	[%l4 + %l5], %l4	b	3f	 st	%fp, [%sp + CCFSZ + 16]1:	ld	[%l4], %o1	ld	[%l4 + 4], %o0	tst	%o0	bz,a	2f	 add	%sp, CCFSZ, %o02:	jmpl	%o1, %o7		!	handled = (*ih->ih_fun)(...)	 ld	[%l4 + 8], %l4		!	and ih = ih->ih_next	tst	%o0	bnz	4f			! if (handled) break	 nop3:	tst	%l4	bnz	1b			! while (ih)	 nop	call	_strayintr		!	strayintr(&intrframe)	 add	%sp, CCFSZ, %o0	/* all done: restore registers and go return */4:	mov	%l7, %g1	wr	%l6, 0, %y	ldd	[%sp + CCFSZ + 24], %g2	ldd	[%sp + CCFSZ + 32], %g4	ldd	[%sp + CCFSZ + 40], %g6	b	return_from_trap	 wr	%l0, 0, %psr#ifdef notyet/* * Level 12 (ZS serial) interrupt.  Handle it quickly, schedule a * software interrupt, and get out.  Do the software interrupt directly * if we would just take it on the way out. * * Input: *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc * Internal: *	%l3 = zs device *	%l4, %l5 = temporary *	%l6 = rr3 (or temporary data) + 0x100 => need soft int *	%l7 = zs soft status */zshard:#endif /* notyet *//* * Level 15 interrupt.  An async memory error has occurred; * take care of it (typically by panicking, but hey...). *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc *	%l3 = 15 * 4 (why? just because!) * * Internal: *	%l4 = %y *	%l5 = %g1 *	%l6 = %g6 *	%l7 = %g7 *  g2, g3, g4, g5 go to stack * * This code is almost the same as that in mem_access_fault, * except that we already know the problem is not a `normal' fault, * and that we must be extra-careful with interrupt enables. */nmi:	INTR_SETUP(-CCFSZ-80)	INCR(_cnt+V_INTR)		! cnt.v_intr++; (clobbers %o0,%o1)	/*	 * Level 15 interrupts are nonmaskable, so with traps off,	 * disable all interrupts to prevent recursion.	 */	sethi	%hi(IE_reg_addr), %o0	ldub	[%o0 + %lo(IE_reg_addr)], %o1	andn	%o1, IE_ALLIE, %o1	stb	%o1, [%o0 + %lo(IE_reg_addr)]	wr	%l0, PSR_ET, %psr	! okay, turn traps on again	std	%g2, [%sp + CCFSZ + 0]	! save g2, g3	rd	%y, %l4			! save y	! must read the sync error register too.	set	AC_SYNC_ERR, %o0	lda	[%o0] ASI_CONTROL, %o1	! sync err reg	inc	4, %o0	lda	[%o0] ASI_CONTROL, %o2	! sync virt addr	std	%g4, [%sp + CCFSZ + 8]	! save g4,g5	mov	%g1, %l5		! save g1,g6,g7	mov	%g6, %l6	mov	%g7, %l7	inc	4, %o0	lda	[%o0] ASI_CONTROL, %o3	! async err reg	inc	4, %o0	lda	[%o0] ASI_CONTROL, %o4	! async virt addr	! and call C code	call	_memerr			! memerr(0, ser, sva, aer, ava)	clr	%o0	mov	%l5, %g1		! restore g1 through g7	ldd	[%sp + CCFSZ + 0], %g2	ldd	[%sp + CCFSZ + 8], %g4	wr	%l0, 0, %psr		! re-disable traps	mov	%l6, %g6	mov	%l7, %g7	! set IE_ALLIE again (safe, we disabled traps again above)	sethi	%hi(IE_reg_addr), %o0	ldub	[%o0 + %lo(IE_reg_addr)], %o1	or	%o1, IE_ALLIE, %o1	stb	%o1, [%o0 + %lo(IE_reg_addr)]	b	return_from_trap	 wr	%l4, 0, %y		! restore y/* * Window overflow trap handler. *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc */window_of:#ifdef TRIVIAL_WINDOW_OVERFLOW_HANDLER	/* a trivial version that assumes %sp is ok */	/* (for testing only!) */	save	%g0, %g0, %g0	std	%l0, [%sp + (0*8)]	rd	%psr, %l0	mov	1, %l1	sll	%l1, %l0, %l0	wr	%l0, 0, %wim	std	%l2, [%sp + (1*8)]	std	%l4, [%sp + (2*8)]	std	%l6, [%sp + (3*8)]	std	%i0, [%sp + (4*8)]	std	%i2, [%sp + (5*8)]	std	%i4, [%sp + (6*8)]	std	%i6, [%sp + (7*8)]	restore	RETT#else	/*	 * This is similar to TRAP_SETUP, but we do not want to spend	 * a lot of time, so we have separate paths for kernel and user.	 * We also know for sure that the window has overflowed.	 */	btst	PSR_PS, %l0	bz	winof_user	 sethi	%hi(clean_trap_window), %l7	/*	 * Overflow from kernel mode.  Call clean_trap_window to	 * do the dirty work, then just return, since we know prev	 * window is valid.  clean_trap_windows might dump all *user*	 * windows into the pcb, but we do not care: there is at	 * least one kernel window (a trap or interrupt frame!)	 * above us.	 */	jmpl	%l7 + %lo(clean_trap_window), %l4	 mov	%g7, %l7		! for clean_trap_window	wr	%l0, 0, %psr		! put back the @%*! cond. codes	nop				! (let them settle in)	RETTwinof_user:	/*	 * Overflow from user mode.	 * If clean_trap_window dumps the registers into the pcb,	 * rft_user will need to call trap(), so we need space for	 * a trap frame.  We also have to compute pcb_nw.	 *	 * SHOULD EXPAND IN LINE TO AVOID BUILDING TRAP FRAME ON	 * `EASY' SAVES	 */	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	ld	[%l6 + PCB_WIM], %l5	and	%l0, 31, %l3	sub	%l3, %l5, %l5 		/* l5 = CWP - pcb_wim */	set	uwtab, %l4	ldub	[%l4 + %l5], %l5	/* l5 = uwtab[l5] */	st	%l5, [%l6 + PCB_UW]	jmpl	%l7 + %lo(clean_trap_window), %l4	 mov	%g7, %l7		! for clean_trap_window	sethi	%hi(_cpcb), %l6	ld	[%l6 + %lo(_cpcb)], %l6	set	UPAGES*NBPG-CCFSZ-80, %l5	add	%l6, %l5, %sp		/* over to kernel stack */	CHECK_SP_REDZONE(%l6, %l5)	/*	 * Copy return_from_trap far enough to allow us	 * to jump directly to rft_user_or_recover_pcb_windows	 * (since we know that is where we are headed).	 */!	and	%l0, 31, %l3		! still set (clean_trap_window					! leaves this register alone)	set	wmask, %l6	ldub	[%l6 + %l3], %l5	! %l5 = 1 << ((CWP + 1) % nwindows)	b	rft_user_or_recover_pcb_windows	 rd	%wim, %l4		! (read %wim first)#endif /* end `real' version of window overflow trap handler *//* * Window underflow trap handler. *	%l0 = %psr *	%l1 = return pc *	%l2 = return npc * * A picture: * *	  T R I X *	0 0 0 1 0 0 0	(%wim) * [bit numbers increase towards the right; * `restore' moves right & `save' moves left] * * T is the current (Trap) window, R is the window that attempted * a `Restore' instruction, I is the Invalid window, and X is the * window we want to make invalid before we return. * * Since window R is valid, we cannot use rft_user to restore stuff * for us.  We have to duplicate its logic.  YUCK. * * Incidentally, TRIX are for kids.  Silly rabbit! */window_uf:#ifdef TRIVIAL_WINDOW_UNDERFLOW_HANDLER	wr	%g0, 0, %wim		! allow us to enter I	restore				! to R	nop	nop	restore				! to I	restore	%g0, 1, %l1		! to X	rd	%psr, %l0	sll	%l1, %l0, %l0	wr	%l0, 0, %wim	save	%g0, %g0, %g0		! back to I	LOADWIN(%sp)	save	%g0, %g0, %g0		! back to R	save	%g0, %g0, %g0		! back to T	RETT#else	wr	%g0, 0, %wim		! allow us to enter I	btst	PSR_PS, %l0	restore				! enter window R	bz	winuf_user	 restore			! enter window I	/*	 * Underflow from kernel mode.  Just recover the	 * registers and go (except that we have to update	 * the blasted user pcb fields).	 */	restore	%g0, 1, %l1		! enter window X, then set %l1 to 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

⌨️ 快捷键说明

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