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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
/* * Now running on new u struct. * Restore registers and return. */	lw	v0, UADDR+U_PCB_CONTEXT+44	# restore kernel context	lw	ra, UADDR+U_PCB_CONTEXT+40	lw	s0, UADDR+U_PCB_CONTEXT+0	lw	s1, UADDR+U_PCB_CONTEXT+4	lw	s2, UADDR+U_PCB_CONTEXT+8	lw	s3, UADDR+U_PCB_CONTEXT+12	lw	s4, UADDR+U_PCB_CONTEXT+16	lw	s5, UADDR+U_PCB_CONTEXT+20	lw	s6, UADDR+U_PCB_CONTEXT+24	lw	s7, UADDR+U_PCB_CONTEXT+28	lw	sp, UADDR+U_PCB_CONTEXT+32	lw	s8, UADDR+U_PCB_CONTEXT+36	mtc0	v0, MACH_COP_0_STATUS_REG	j	ra	li	v0, 1				# possible return to 'savectx()'END(cpu_switch)/* * {fu,su},{ibyte,isword,iword}, fetch or store a byte, short or word to * user text space. * {fu,su},{byte,sword,word}, fetch or store a byte, short or word to * user data space. */LEAF(fuword)ALEAF(fuiword)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	lw	v0, 0(a0)		# fetch word	j	ra	sw	zero, UADDR+U_PCB_ONFAULTEND(fuword)LEAF(fusword)ALEAF(fuisword)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	lhu	v0, 0(a0)		# fetch short	j	ra	sw	zero, UADDR+U_PCB_ONFAULTEND(fusword)LEAF(fubyte)ALEAF(fuibyte)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	lbu	v0, 0(a0)		# fetch byte	j	ra	sw	zero, UADDR+U_PCB_ONFAULTEND(fubyte)LEAF(suword)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	sw	a1, 0(a0)		# store word	sw	zero, UADDR+U_PCB_ONFAULT	j	ra	move	v0, zeroEND(suword)/* * Have to flush instruction cache afterwards. */LEAF(suiword)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	sw	a1, 0(a0)		# store word	sw	zero, UADDR+U_PCB_ONFAULT	move	v0, zero	b	MachFlushICache		# NOTE: this should not clobber v0!	li	a1, 4			# size of wordEND(suiword)/* * Will have to flush the instruction cache if byte merging is done in hardware. */LEAF(susword)ALEAF(suisword)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	sh	a1, 0(a0)		# store short	sw	zero, UADDR+U_PCB_ONFAULT	j	ra	move	v0, zeroEND(susword)LEAF(subyte)ALEAF(suibyte)	blt	a0, zero, fswberr	# make sure address is in user space	li	v0, FSWBERR	sw	v0, UADDR+U_PCB_ONFAULT	sb	a1, 0(a0)		# store byte	sw	zero, UADDR+U_PCB_ONFAULT	j	ra	move	v0, zeroEND(subyte)LEAF(fswberr)	j	ra	li	v0, -1END(fswberr)/* * fuswintr and suswintr are just like fusword and susword except that if * the page is not in memory or would cause a trap, then we return an error. * The important thing is to prevent sleep() and switch(). */LEAF(fuswintr)	blt	a0, zero, fswintrberr	# make sure address is in user space	li	v0, FSWINTRBERR	sw	v0, UADDR+U_PCB_ONFAULT	lhu	v0, 0(a0)		# fetch short	j	ra	sw	zero, UADDR+U_PCB_ONFAULTEND(fuswintr)LEAF(suswintr)	blt	a0, zero, fswintrberr	# make sure address is in user space	li	v0, FSWINTRBERR	sw	v0, UADDR+U_PCB_ONFAULT	sh	a1, 0(a0)		# store short	sw	zero, UADDR+U_PCB_ONFAULT	j	ra	move	v0, zeroEND(suswintr)LEAF(fswintrberr)	j	ra	li	v0, -1END(fswintrberr)/* * Insert 'p' after 'q'. *	_insque(p, q) *		caddr_t p, q; */LEAF(_insque)	lw	v0, 0(a1)		# v0 = q->next	sw	a1, 4(a0)		# p->prev = q	sw	v0, 0(a0)		# p->next = q->next	sw	a0, 4(v0)		# q->next->prev = p	j	ra	sw	a0, 0(a1)		# q->next = pEND(_insque)/* * Remove item 'p' from queue. *	_remque(p) *		caddr_t p; */LEAF(_remque)	lw	v0, 0(a0)		# v0 = p->next	lw	v1, 4(a0)		# v1 = p->prev	nop	sw	v0, 0(v1)		# p->prev->next = p->next	j	ra	sw	v1, 4(v0)		# p->next->prev = p->prevEND(_remque)/* * This code is copied to the UTLB exception vector address to * handle user level TLB translation misses. * NOTE: This code must be relocatable!!! */	.globl	MachUTLBMissMachUTLBMiss:	.set	noat	mfc0	k0, MACH_COP_0_BAD_VADDR	# get the virtual address	lw	k1, UADDR+U_PCB_SEGTAB		# get the current segment table	bltz	k0, 1f				# R3000 chip bug	srl	k0, k0, SEGSHIFT		# compute segment table index	sll	k0, k0, 2	addu	k1, k1, k0	mfc0	k0, MACH_COP_0_BAD_VADDR	# get the virtual address	lw	k1, 0(k1)			# get pointer to segment map	srl	k0, k0, PGSHIFT - 2		# compute segment map index	andi	k0, k0, (NPTEPG - 1) << 2	beq	k1, zero, 2f			# invalid segment map	addu	k1, k1, k0			# index into segment map	lw	k0, 0(k1)			# get page PTE	nop	beq	k0, zero, 2f			# dont load invalid entries	mtc0	k0, MACH_COP_0_TLB_LOW	mfc0	k1, MACH_COP_0_EXC_PC		# get return address	tlbwr					# update TLB	j	k1	rfe1:	mfc0	k1, MACH_COP_0_EXC_PC		# get return address	nop	j	k1	rfe2:	j	SlowFault			# handle the rest	nop	.set	at	.globl	MachUTLBMissEndMachUTLBMissEnd:/* * This code is copied to the general exception vector address to * handle all execptions except RESET and UTLBMiss. * NOTE: This code must be relocatable!!! */	.globl	MachExceptionMachException:/* * Find out what mode we came from and jump to the proper handler. */	.set	noat	mfc0	k0, MACH_COP_0_STATUS_REG	# Get the status register	mfc0	k1, MACH_COP_0_CAUSE_REG	# Get the cause register value.	and	k0, k0, MACH_SR_KU_PREV		# test for user mode	sll	k0, k0, 3			# shift user bit for cause index	and	k1, k1, MACH_CR_EXC_CODE	# Mask out the cause bits.	or	k1, k1, k0			# change index to user table1:	la	k0, machExceptionTable		# get base of the jump table	addu	k0, k0, k1			# Get the address of the						#  function entry.  Note that						#  the cause is already						#  shifted left by 2 bits so						#  we dont have to shift.	lw	k0, 0(k0)			# Get the function address	nop	j	k0				# Jump to the function.	nop	.set	at	.globl	MachExceptionEndMachExceptionEnd:/* * We couldn't find a TLB entry. * Find out what mode we came from and call the appropriate handler. */SlowFault:	.set	noat	mfc0	k0, MACH_COP_0_STATUS_REG	nop	and	k0, k0, MACH_SR_KU_PREV	bne	k0, zero, MachUserGenException	nop	.set	at/* * Fall though ... *//*---------------------------------------------------------------------------- * * MachKernGenException -- * *	Handle an exception from kernel mode. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- *//* * The kernel exception stack contains 18 saved general registers, * the status register and the multiply lo and high registers. * In addition, we set this up for linkage conventions. */#define KERN_REG_SIZE		(18 * 4)#define KERN_REG_OFFSET		(STAND_FRAME_SIZE)#define KERN_SR_OFFSET		(STAND_FRAME_SIZE + KERN_REG_SIZE)#define KERN_MULT_LO_OFFSET	(STAND_FRAME_SIZE + KERN_REG_SIZE + 4)#define KERN_MULT_HI_OFFSET	(STAND_FRAME_SIZE + KERN_REG_SIZE + 8)#define	KERN_EXC_FRAME_SIZE	(STAND_FRAME_SIZE + KERN_REG_SIZE + 12)NNON_LEAF(MachKernGenException, KERN_EXC_FRAME_SIZE, ra)	.set	noat#ifdef KADB	la	k0, kdbpcb			# save registers for kadb	sw	s0, (S0 * 4)(k0)	sw	s1, (S1 * 4)(k0)	sw	s2, (S2 * 4)(k0)	sw	s3, (S3 * 4)(k0)	sw	s4, (S4 * 4)(k0)	sw	s5, (S5 * 4)(k0)	sw	s6, (S6 * 4)(k0)	sw	s7, (S7 * 4)(k0)	sw	s8, (S8 * 4)(k0)	sw	gp, (GP * 4)(k0)	sw	sp, (SP * 4)(k0)#endif	subu	sp, sp, KERN_EXC_FRAME_SIZE	.mask	0x80000000, (STAND_RA_OFFSET - KERN_EXC_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, KERN_REG_OFFSET + 0(sp)	sw	v0, KERN_REG_OFFSET + 4(sp)	sw	v1, KERN_REG_OFFSET + 8(sp)	sw	a0, KERN_REG_OFFSET + 12(sp)	mflo	v0	mfhi	v1	sw	a1, KERN_REG_OFFSET + 16(sp)	sw	a2, KERN_REG_OFFSET + 20(sp)	sw	a3, KERN_REG_OFFSET + 24(sp)	sw	t0, KERN_REG_OFFSET + 28(sp)	mfc0	a0, MACH_COP_0_STATUS_REG	# First arg is the status reg.	sw	t1, KERN_REG_OFFSET + 32(sp)	sw	t2, KERN_REG_OFFSET + 36(sp)	sw	t3, KERN_REG_OFFSET + 40(sp)	sw	t4, KERN_REG_OFFSET + 44(sp)	mfc0	a1, MACH_COP_0_CAUSE_REG	# Second arg is the cause reg.	sw	t5, KERN_REG_OFFSET + 48(sp)	sw	t6, KERN_REG_OFFSET + 52(sp)	sw	t7, KERN_REG_OFFSET + 56(sp)	sw	t8, KERN_REG_OFFSET + 60(sp)	mfc0	a2, MACH_COP_0_BAD_VADDR	# Third arg is the fault addr.	sw	t9, KERN_REG_OFFSET + 64(sp)	sw	ra, KERN_REG_OFFSET + 68(sp)	sw	v0, KERN_MULT_LO_OFFSET(sp)	sw	v1, KERN_MULT_HI_OFFSET(sp)	mfc0	a3, MACH_COP_0_EXC_PC		# Fourth arg is the pc.	sw	a0, KERN_SR_OFFSET(sp)/* * Call the exception handler. */	jal	trap	sw	a3, STAND_RA_OFFSET(sp)		# for debugging/* * Restore registers and return from the exception. * v0 contains the return address. */	lw	a0, KERN_SR_OFFSET(sp)	lw	t0, KERN_MULT_LO_OFFSET(sp)	lw	t1, KERN_MULT_HI_OFFSET(sp)	mtc0	a0, MACH_COP_0_STATUS_REG	# Restore the SR, disable intrs	mtlo	t0	mthi	t1	move	k0, v0	lw	AT, KERN_REG_OFFSET + 0(sp)	lw	v0, KERN_REG_OFFSET + 4(sp)	lw	v1, KERN_REG_OFFSET + 8(sp)	lw	a0, KERN_REG_OFFSET + 12(sp)	lw	a1, KERN_REG_OFFSET + 16(sp)	lw	a2, KERN_REG_OFFSET + 20(sp)	lw	a3, KERN_REG_OFFSET + 24(sp)	lw	t0, KERN_REG_OFFSET + 28(sp)	lw	t1, KERN_REG_OFFSET + 32(sp)	lw	t2, KERN_REG_OFFSET + 36(sp)	lw	t3, KERN_REG_OFFSET + 40(sp)	lw	t4, KERN_REG_OFFSET + 44(sp)	lw	t5, KERN_REG_OFFSET + 48(sp)	lw	t6, KERN_REG_OFFSET + 52(sp)	lw	t7, KERN_REG_OFFSET + 56(sp)	lw	t8, KERN_REG_OFFSET + 60(sp)	lw	t9, KERN_REG_OFFSET + 64(sp)	lw	ra, KERN_REG_OFFSET + 68(sp)	addu	sp, sp, KERN_EXC_FRAME_SIZE	j	k0				# Now return from the	rfe					#  exception.	.set	atEND(MachKernGenException)/*---------------------------------------------------------------------------- * * MachUserGenException -- * *	Handle an exception from user mode. * * Results: * 	None. * * Side effects: *	None. * *---------------------------------------------------------------------------- */NNON_LEAF(MachUserGenException, STAND_FRAME_SIZE, ra)	.set	noat	.mask	0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)/* * Save all of the registers except for the kernel temporaries in u.u_pcb. */	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	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)	mfhi	v1	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	a0, MACH_COP_0_STATUS_REG	# First arg is the status 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	s0, UADDR+U_PCB_REGS+(S0 * 4)	mfc0	a1, MACH_COP_0_CAUSE_REG	# Second arg is the cause reg.	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)	mfc0	a2, MACH_COP_0_BAD_VADDR	# Third arg is the fault addr	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	t8, UADDR+U_PCB_REGS+(T8 * 4)	mfc0	a3, MACH_COP_0_EXC_PC		# Fourth 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	s8, UADDR+U_PCB_REGS+(S8 * 4)	li	sp, KERNELSTACK - STAND_FRAME_SIZE	# switch to kernel SP	sw	ra, UADDR+U_PCB_REGS+(RA * 4)	sw	v0, UADDR+U_PCB_REGS+(MULLO * 4)	sw	v1, UADDR+U_PCB_REGS+(MULHI * 4)	sw	a0, UADDR+U_PCB_REGS+(SR * 4) #	la	gp, _gp				# switch to kernel GP	sw	a3, UADDR+U_PCB_REGS+(PC * 4)	sw	a3, STAND_RA_OFFSET(sp)		# for debugging	.set	at	and	t0, a0, ~MACH_SR_COP_1_BIT	# Turn off the FPU.	.set	noat/* * Call the exception handler. */	jal	trap	mtc0	t0, MACH_COP_0_STATUS_REG/* * 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(MachUserGenException)/*---------------------------------------------------------------------------- * * MachKernIntr -- *

⌨️ 快捷键说明

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