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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
 *	Handle an interrupt from kernel mode. *	Interrupts use the standard kernel stack. *	switch_exit sets up a kernel stack after exit so interrupts won't fail. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- */#define KINTR_REG_OFFSET	(STAND_FRAME_SIZE)#define KINTR_SR_OFFSET		(STAND_FRAME_SIZE + KERN_REG_SIZE)#define KINTR_MULT_LO_OFFSET	(STAND_FRAME_SIZE + KERN_REG_SIZE + 4)#define KINTR_MULT_HI_OFFSET	(STAND_FRAME_SIZE + KERN_REG_SIZE + 8)#define	KINTR_FRAME_SIZE	(STAND_FRAME_SIZE + KERN_REG_SIZE + 12)NNON_LEAF(MachKernIntr, KINTR_FRAME_SIZE, ra)	.set	noat	subu	sp, sp, KINTR_FRAME_SIZE	# allocate stack frame	.mask	0x80000000, (STAND_RA_OFFSET - KINTR_FRAME_SIZE)/* * Save the relevant kernel registers onto the stack. * We don't need to save s0 - s8, sp and gp because * the compiler does it for us. */	sw	AT, KINTR_REG_OFFSET + 0(sp)	sw	v0, KINTR_REG_OFFSET + 4(sp)	sw	v1, KINTR_REG_OFFSET + 8(sp)	sw	a0, KINTR_REG_OFFSET + 12(sp)	mflo	v0	mfhi	v1	sw	a1, KINTR_REG_OFFSET + 16(sp)	sw	a2, KINTR_REG_OFFSET + 20(sp)	sw	a3, KINTR_REG_OFFSET + 24(sp)	sw	t0, KINTR_REG_OFFSET + 28(sp)	mfc0	a0, MACH_COP_0_STATUS_REG	# First arg is the status reg.	sw	t1, KINTR_REG_OFFSET + 32(sp)	sw	t2, KINTR_REG_OFFSET + 36(sp)	sw	t3, KINTR_REG_OFFSET + 40(sp)	sw	t4, KINTR_REG_OFFSET + 44(sp)	mfc0	a1, MACH_COP_0_CAUSE_REG	# Second arg is the cause reg.	sw	t5, KINTR_REG_OFFSET + 48(sp)	sw	t6, KINTR_REG_OFFSET + 52(sp)	sw	t7, KINTR_REG_OFFSET + 56(sp)	sw	t8, KINTR_REG_OFFSET + 60(sp)	mfc0	a2, MACH_COP_0_EXC_PC		# Third arg is the pc.	sw	t9, KINTR_REG_OFFSET + 64(sp)	sw	ra, KINTR_REG_OFFSET + 68(sp)	sw	v0, KINTR_MULT_LO_OFFSET(sp)	sw	v1, KINTR_MULT_HI_OFFSET(sp)	sw	a0, KINTR_SR_OFFSET(sp)/* * Call the interrupt handler. */	jal	interrupt	sw	a2, STAND_RA_OFFSET(sp)		# for debugging/* * Restore registers and return from the interrupt. */	lw	a0, KINTR_SR_OFFSET(sp)	lw	t0, KINTR_MULT_LO_OFFSET(sp)	lw	t1, KINTR_MULT_HI_OFFSET(sp)	mtc0	a0, MACH_COP_0_STATUS_REG	# Restore the SR, disable intrs	mtlo	t0	mthi	t1	lw	k0, STAND_RA_OFFSET(sp)	lw	AT, KINTR_REG_OFFSET + 0(sp)	lw	v0, KINTR_REG_OFFSET + 4(sp)	lw	v1, KINTR_REG_OFFSET + 8(sp)	lw	a0, KINTR_REG_OFFSET + 12(sp)	lw	a1, KINTR_REG_OFFSET + 16(sp)	lw	a2, KINTR_REG_OFFSET + 20(sp)	lw	a3, KINTR_REG_OFFSET + 24(sp)	lw	t0, KINTR_REG_OFFSET + 28(sp)	lw	t1, KINTR_REG_OFFSET + 32(sp)	lw	t2, KINTR_REG_OFFSET + 36(sp)	lw	t3, KINTR_REG_OFFSET + 40(sp)	lw	t4, KINTR_REG_OFFSET + 44(sp)	lw	t5, KINTR_REG_OFFSET + 48(sp)	lw	t6, KINTR_REG_OFFSET + 52(sp)	lw	t7, KINTR_REG_OFFSET + 56(sp)	lw	t8, KINTR_REG_OFFSET + 60(sp)	lw	t9, KINTR_REG_OFFSET + 64(sp)	lw	ra, KINTR_REG_OFFSET + 68(sp)	addu	sp, sp, KINTR_FRAME_SIZE	j	k0				# Now return from the	rfe					#  interrupt.	.set	atEND(MachKernIntr)/*---------------------------------------------------------------------------- * * MachUserIntr -- * *	Handle an interrupt from user mode. *	Note: we save minimal state in the u.u_pcb struct and use the standard *	kernel stack since there has to be a u page if we came from user mode. *	If there is a pending software interrupt, then save the remaining state *	and call softintr(). This is all because if we call switch() inside *	interrupt(), not all the user registers have been saved in u.u_pcb. * * Results: * 	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- */NNON_LEAF(MachUserIntr, STAND_FRAME_SIZE, ra)	.set	noat	.mask	0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)/* * Save the relevant user registers into the u.u_pcb struct. * We don't need to save s0 - s8 because * the compiler does it for us. */	sw	AT, UADDR+U_PCB_REGS+(AST * 4)	sw	v0, UADDR+U_PCB_REGS+(V0 * 4)	sw	v1, UADDR+U_PCB_REGS+(V1 * 4)	sw	a0, UADDR+U_PCB_REGS+(A0 * 4)	mflo	v0	mfhi	v1	sw	a1, UADDR+U_PCB_REGS+(A1 * 4)	sw	a2, UADDR+U_PCB_REGS+(A2 * 4)	sw	a3, UADDR+U_PCB_REGS+(A3 * 4)	sw	t0, UADDR+U_PCB_REGS+(T0 * 4)	mfc0	a0, MACH_COP_0_STATUS_REG	# First arg is the status reg.	sw	t1, UADDR+U_PCB_REGS+(T1 * 4)	sw	t2, UADDR+U_PCB_REGS+(T2 * 4)	sw	t3, UADDR+U_PCB_REGS+(T3 * 4)	sw	t4, UADDR+U_PCB_REGS+(T4 * 4)	mfc0	a1, MACH_COP_0_CAUSE_REG	# Second arg is the cause reg.	sw	t5, UADDR+U_PCB_REGS+(T5 * 4)	sw	t6, UADDR+U_PCB_REGS+(T6 * 4)	sw	t7, UADDR+U_PCB_REGS+(T7 * 4)	sw	t8, UADDR+U_PCB_REGS+(T8 * 4)	mfc0	a2, MACH_COP_0_EXC_PC		# Third arg is the pc.	sw	t9, UADDR+U_PCB_REGS+(T9 * 4)	sw	gp, UADDR+U_PCB_REGS+(GP * 4)	sw	sp, UADDR+U_PCB_REGS+(SP * 4)	sw	ra, UADDR+U_PCB_REGS+(RA * 4)	li	sp, KERNELSTACK - STAND_FRAME_SIZE	# switch to kernel SP	sw	v0, UADDR+U_PCB_REGS+(MULLO * 4)	sw	v1, UADDR+U_PCB_REGS+(MULHI * 4)	sw	a0, UADDR+U_PCB_REGS+(SR * 4)	sw	a2, UADDR+U_PCB_REGS+(PC * 4) #	la	gp, _gp				# switch to kernel GP	.set	at	and	t0, a0, ~MACH_SR_COP_1_BIT	# Turn off the FPU.	.set	noat	mtc0	t0, MACH_COP_0_STATUS_REG/* * Call the interrupt handler. */	jal	interrupt	sw	a2, STAND_RA_OFFSET(sp)		# for debugging/* * Restore registers and return from the interrupt. */	lw	a0, UADDR+U_PCB_REGS+(SR * 4)	lw	v0, astpending			# any pending interrupts?	mtc0	a0, MACH_COP_0_STATUS_REG	# Restore the SR, disable intrs	bne	v0, zero, 1f			# dont restore, call softintr	lw	t0, UADDR+U_PCB_REGS+(MULLO * 4)	lw	t1, UADDR+U_PCB_REGS+(MULHI * 4)	lw	k0, UADDR+U_PCB_REGS+(PC * 4)	lw	AT, UADDR+U_PCB_REGS+(AST * 4)	lw	v0, UADDR+U_PCB_REGS+(V0 * 4)	lw	v1, UADDR+U_PCB_REGS+(V1 * 4)	lw	a0, UADDR+U_PCB_REGS+(A0 * 4)	lw	a1, UADDR+U_PCB_REGS+(A1 * 4)	lw	a2, UADDR+U_PCB_REGS+(A2 * 4)	lw	a3, UADDR+U_PCB_REGS+(A3 * 4)	mtlo	t0	mthi	t1	lw	t0, UADDR+U_PCB_REGS+(T0 * 4)	lw	t1, UADDR+U_PCB_REGS+(T1 * 4)	lw	t2, UADDR+U_PCB_REGS+(T2 * 4)	lw	t3, UADDR+U_PCB_REGS+(T3 * 4)	lw	t4, UADDR+U_PCB_REGS+(T4 * 4)	lw	t5, UADDR+U_PCB_REGS+(T5 * 4)	lw	t6, UADDR+U_PCB_REGS+(T6 * 4)	lw	t7, UADDR+U_PCB_REGS+(T7 * 4)	lw	t8, UADDR+U_PCB_REGS+(T8 * 4)	lw	t9, UADDR+U_PCB_REGS+(T9 * 4)	lw	gp, UADDR+U_PCB_REGS+(GP * 4)	lw	sp, UADDR+U_PCB_REGS+(SP * 4)	lw	ra, UADDR+U_PCB_REGS+(RA * 4)	j	k0				# Now return from the	rfe					#  interrupt.1:/* * We have pending software interrupts; save remaining user state in u.u_pcb. */	sw	s0, UADDR+U_PCB_REGS+(S0 * 4)	sw	s1, UADDR+U_PCB_REGS+(S1 * 4)	sw	s2, UADDR+U_PCB_REGS+(S2 * 4)	sw	s3, UADDR+U_PCB_REGS+(S3 * 4)	sw	s4, UADDR+U_PCB_REGS+(S4 * 4)	sw	s5, UADDR+U_PCB_REGS+(S5 * 4)	sw	s6, UADDR+U_PCB_REGS+(S6 * 4)	sw	s7, UADDR+U_PCB_REGS+(S7 * 4)	sw	s8, UADDR+U_PCB_REGS+(S8 * 4)	li	t0, MACH_HARD_INT_MASK | MACH_SR_INT_ENA_CUR/* * Call the software interrupt handler. */	jal	softintr	mtc0	t0, MACH_COP_0_STATUS_REG	# enable interrupts (spl0)/* * Restore user registers and return. NOTE: interrupts are enabled. */	lw	a0, UADDR+U_PCB_REGS+(SR * 4)	lw	t0, UADDR+U_PCB_REGS+(MULLO * 4)	lw	t1, UADDR+U_PCB_REGS+(MULHI * 4)	mtc0	a0, MACH_COP_0_STATUS_REG	# this should disable interrupts	mtlo	t0	mthi	t1	lw	k0, UADDR+U_PCB_REGS+(PC * 4)	lw	AT, UADDR+U_PCB_REGS+(AST * 4)	lw	v0, UADDR+U_PCB_REGS+(V0 * 4)	lw	v1, UADDR+U_PCB_REGS+(V1 * 4)	lw	a0, UADDR+U_PCB_REGS+(A0 * 4)	lw	a1, UADDR+U_PCB_REGS+(A1 * 4)	lw	a2, UADDR+U_PCB_REGS+(A2 * 4)	lw	a3, UADDR+U_PCB_REGS+(A3 * 4)	lw	t0, UADDR+U_PCB_REGS+(T0 * 4)	lw	t1, UADDR+U_PCB_REGS+(T1 * 4)	lw	t2, UADDR+U_PCB_REGS+(T2 * 4)	lw	t3, UADDR+U_PCB_REGS+(T3 * 4)	lw	t4, UADDR+U_PCB_REGS+(T4 * 4)	lw	t5, UADDR+U_PCB_REGS+(T5 * 4)	lw	t6, UADDR+U_PCB_REGS+(T6 * 4)	lw	t7, UADDR+U_PCB_REGS+(T7 * 4)	lw	s0, UADDR+U_PCB_REGS+(S0 * 4)	lw	s1, UADDR+U_PCB_REGS+(S1 * 4)	lw	s2, UADDR+U_PCB_REGS+(S2 * 4)	lw	s3, UADDR+U_PCB_REGS+(S3 * 4)	lw	s4, UADDR+U_PCB_REGS+(S4 * 4)	lw	s5, UADDR+U_PCB_REGS+(S5 * 4)	lw	s6, UADDR+U_PCB_REGS+(S6 * 4)	lw	s7, UADDR+U_PCB_REGS+(S7 * 4)	lw	t8, UADDR+U_PCB_REGS+(T8 * 4)	lw	t9, UADDR+U_PCB_REGS+(T9 * 4)	lw	gp, UADDR+U_PCB_REGS+(GP * 4)	lw	sp, UADDR+U_PCB_REGS+(SP * 4)	lw	s8, UADDR+U_PCB_REGS+(S8 * 4)	lw	ra, UADDR+U_PCB_REGS+(RA * 4)	j	k0	rfe	.set	atEND(MachUserIntr)#if 0/*---------------------------------------------------------------------------- * * MachTLBModException -- * *	Handle a TLB modified exception. *	The BaddVAddr, Context, and EntryHi registers contain the failed *	virtual address. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- */NLEAF(MachTLBModException)	.set	noat	tlbp					# find the TLB entry	mfc0	k0, MACH_COP_0_TLB_LOW		# get the physical address	mfc0	k1, MACH_COP_0_TLB_INDEX	# check to be sure its valid	or	k0, k0, VMMACH_TLB_MOD_BIT	# update TLB	blt	k1, zero, 4f			# not found!!!	mtc0	k0, MACH_COP_0_TLB_LOW	li	k1, MACH_CACHED_MEMORY_ADDR	subu	k0, k0, k1	srl	k0, k0, VMMACH_TLB_PHYS_PAGE_SHIFT	la	k1, pmap_attributes	addu	k0, k0, k1	lbu	k1, 0(k0)			# fetch old value	nop	or	k1, k1, 1			# set modified bit	sb	k1, 0(k0)			# save new value	mfc0	k0, MACH_COP_0_EXC_PC		# get return address	nop	j	k0	rfe4:	break	0				# panic	.set	atEND(MachTLBModException)#endif/*---------------------------------------------------------------------------- * * MachTLBMissException -- * *	Handle a TLB miss exception from kernel mode. *	The BaddVAddr, Context, and EntryHi registers contain the failed *	virtual address. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- */NLEAF(MachTLBMissException)	.set	noat	mfc0	k0, MACH_COP_0_BAD_VADDR	# get the fault address	li	k1, VM_MIN_KERNEL_ADDRESS	# compute index	subu	k0, k0, k1	lw	k1, Sysmapsize			# index within range?	srl	k0, k0, PGSHIFT	sltu	k1, k0, k1	beq	k1, zero, 1f			# No. check for valid stack	nop	lw	k1, Sysmap	sll	k0, k0, 2			# compute offset from index	addu	k1, k1, k0	lw	k0, 0(k1)			# get PTE entry	mfc0	k1, MACH_COP_0_EXC_PC		# get return address	mtc0	k0, MACH_COP_0_TLB_LOW		# save PTE entry	and	k0, k0, PG_V			# check for valid entry	beq	k0, zero, MachKernGenException	# PTE invalid	nop	tlbwr					# update TLB	j	k1	rfe1:	subu	k0, sp, UADDR + 0x200		# check to see if we have a	sltiu	k0, UPAGES*NBPG - 0x200		#  valid kernel stack	bne	k0, zero, MachKernGenException	# Go panic	nop	la	a0, start - START_FRAME - 8	# set sp to a valid place	sw	sp, 24(a0)	move	sp, a0	la	a0, 1f	mfc0	a2, MACH_COP_0_STATUS_REG	mfc0	a3, MACH_COP_0_CAUSE_REG	mfc0	a1, MACH_COP_0_EXC_PC	sw	a2, 16(sp)	sw	a3, 20(sp)	sw	sp, 24(sp)	move	a2, ra	jal	printf	mfc0	a3, MACH_COP_0_BAD_VADDR	.data1:	.asciiz	"ktlbmiss: PC %x RA %x ADR %x\nSR %x CR %x SP %x\n"	.text	la	sp, start - START_FRAME		# set sp to a valid place	PANIC("kernel stack overflow")	.set	atEND(MachTLBMissException)/* * Set/clear software interrupt routines. */LEAF(setsoftclock)	mfc0	v0, MACH_COP_0_CAUSE_REG	# read cause register	nop	or	v0, v0, MACH_SOFT_INT_MASK_0	# set soft clock interrupt	mtc0	v0, MACH_COP_0_CAUSE_REG	# save it	j	ra	nopEND(setsoftclock)LEAF(clearsoftclock)	mfc0	v0, MACH_COP_0_CAUSE_REG	# read cause register	nop	and	v0, v0, ~MACH_SOFT_INT_MASK_0	# clear soft clock interrupt	mtc0	v0, MACH_COP_0_CAUSE_REG	# save it	j	ra	nopEND(clearsoftclock)LEAF(setsoftnet)	mfc0	v0, MACH_COP_0_CAUSE_REG	# read cause register	nop	or	v0, v0, MACH_SOFT_INT_MASK_1	# set soft net interrupt	mtc0	v0, MACH_COP_0_CAUSE_REG	# save it	j	ra	nopEND(setsoftnet)LEAF(clearsoftnet)	mfc0	v0, MACH_COP_0_CAUSE_REG	# read cause register	nop	and	v0, v0, ~MACH_SOFT_INT_MASK_1	# clear soft net interrupt	mtc0	v0, MACH_COP_0_CAUSE_REG	# save it	j	ra	nopEND(clearsoftnet)/* * Set/change interrupt priority routines. */LEAF(MachEnableIntr)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	nop	or	v0, v0, MACH_SR_INT_ENA_CUR	mtc0	v0, MACH_COP_0_STATUS_REG	# enable all interrupts	j	ra	nopEND(MachEnableIntr)LEAF(spl0)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	nop	or	t0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)	mtc0	t0, MACH_COP_0_STATUS_REG	# enable all interrupts	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(spl0)LEAF(splsoftclock)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~MACH_SOFT_INT_MASK_0	# disable soft clock	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(splsoftclock)LEAF(Mach_spl0)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~(MACH_INT_MASK_0|MACH_SOFT_INT_MASK_1|MACH_SOFT_INT_MASK_0)	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(Mach_spl0)LEAF(Mach_spl1)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~(MACH_INT_MASK_1|MACH_SOFT_INT_MASK_0|MACH_SOFT_INT_MASK_1)	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(Mach_spl1)LEAF(Mach_spl2)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~(MACH_INT_MASK_2|MACH_SOFT_INT_MASK_1|MACH_SOFT_INT_MASK_0)	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(Mach_spl2)LEAF(Mach_spl3)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~(MACH_INT_MASK_3|MACH_SOFT_INT_MASK_1|MACH_SOFT_INT_MASK_0)	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(Mach_spl3)/* * We define an alternate entry point after mcount is called so it * can be used in mcount without causeing a recursive loop. */LEAF(splhigh)ALEAF(_splhigh)	mfc0	v0, MACH_COP_0_STATUS_REG	# read status register	li	t0, ~MACH_SR_INT_ENA_CUR	# disable all interrupts	and	t0, t0, v0	mtc0	t0, MACH_COP_0_STATUS_REG	# save it	j	ra	and	v0, v0, (MACH_INT_MASK | MACH_SR_INT_ENA_CUR)END(splhigh)/*

⌨️ 快捷键说明

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