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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 3 页
字号:
set1:	movzbl	P_PRIORITY(%eax),%edx	shrl	$2,%edx	btsl	%edx,_whichqs		# set q full bit	shll	$3,%edx	addl	$_qs,%edx		# locate q hdr	movl	%edx,P_FORW(%eax)	# link process on tail of q	movl	P_BACK(%edx),%ecx	movl	%ecx,P_BACK(%eax)	movl	%eax,P_BACK(%edx)	movl	%eax,P_FORW(%ecx)	retset2:	.asciz	"setrunqueue"/* * Remrq(p) * * Call should be made at spl6(). */	ALIGN32ENTRY(remrq)	movl	4(%esp),%eax	movzbl	P_PRIORITY(%eax),%edx	shrl	$2,%edx	btrl	%edx,_whichqs		# clear full bit, panic if clear already	jb	rem1	pushl	$rem3	call	_panicrem1:	pushl	%edx	movl	P_FORW(%eax),%ecx	# unlink process	movl	P_BACK(%eax),%edx	movl	%edx,P_BACK(%ecx)	movl	P_BACK(%eax),%ecx	movl	P_FORW(%eax),%edx	movl	%edx,P_FORW(%ecx)	popl	%edx	movl	$_qs,%ecx	shll	$3,%edx	addl	%edx,%ecx	cmpl	P_FORW(%ecx),%ecx	# q still has something?	je	rem2	shrl	$3,%edx			# yes, set bit as still full	btsl	%edx,_whichqsrem2:	movl	$0,P_BACK(%eax)		# zap reverse link to indicate off list	retrem3:	.asciz	"remrq"sw0:	.asciz	"Xswitch"/* * When no processes are on the runq, Swtch branches to idle * to wait for something to come ready. */	.globl	Idle	ALIGN32Idle:idle:	call	_spl0	cmpl	$0,_whichqs	jne	sw1	hlt		# wait for interrupt	jmp	idle	.align 4 /* ..so that profiling doesn't lump Idle with Xswitch().. */badsw:	pushl	$sw0	call	_panic	/*NOTREACHED*//* * Swtch() */	ALIGN32ENTRY(Xswitch)	incl	_cnt+V_SWTCH	/* switch to new process. first, save context as needed */	movl	_curproc,%ecx	/* if no process to save, don't bother */	cmpl	$0,%ecx	je	sw1	movl	P_ADDR(%ecx),%ecx	movl	(%esp),%eax		# Hardware registers	movl	%eax, PCB_EIP(%ecx)	movl	%ebx, PCB_EBX(%ecx)	movl	%esp, PCB_ESP(%ecx)	movl	%ebp, PCB_EBP(%ecx)	movl	%esi, PCB_ESI(%ecx)	movl	%edi, PCB_EDI(%ecx)#ifdef NPX	/* have we used fp, and need a save? */	mov	_curproc,%eax	cmp	%eax,_npxproc	jne	1f	pushl	%ecx			/* h/w bugs make saving complicated */	leal	PCB_SAVEFPU(%ecx),%eax	pushl	%eax	call	_npxsave		/* do it in a big C function */	popl	%eax	popl	%ecx1:#endif	movl	_CMAP2,%eax		# save temporary map PTE	movl	%eax,PCB_CMAP2(%ecx)	# in our context	movl	$0,_curproc		#  out of process	# movw	_cpl, %ax	# movw	%ax, PCB_IML(%ecx)	# save ipl	/* save is done, now choose a new process or idle */sw1:	movl	_whichqs,%edi2:	cli	bsfl	%edi,%eax		# find a full q	jz	idle			# if none, idle	# XX update whichqs?swfnd:	btrl	%eax,%edi		# clear q full status	jnb	2b		# if it was clear, look for another	movl	%eax,%ebx		# save which one we are using	shll	$3,%eax	addl	$_qs,%eax		# select q	movl	%eax,%esi#ifdef	DIAGNOSTIC	cmpl	P_FORW(%eax),%eax # linked to self? (e.g. not on list)	je	badsw			# not possible#endif	movl	P_FORW(%eax),%ecx	# unlink from front of process q	movl	P_FORW(%ecx),%edx	movl	%edx,P_FORW(%eax)	movl	P_BACK(%ecx),%eax	movl	%eax,P_BACK(%edx)	cmpl	P_FORW(%ecx),%esi	# q empty	je	3f	btsl	%ebx,%edi		# nope, set to indicate full3:	movl	%edi,_whichqs		# update q status	movl	$0,%eax	movl	%eax,_want_resched#ifdef	DIAGNOSTIC	cmpl	%eax,P_WCHAN(%ecx)	jne	badsw	cmpb	$ SRUN,P_STAT(%ecx)	jne	badsw#endif	movl	%eax,P_BACK(%ecx)	/* isolate process to run */	movl	P_ADDR(%ecx),%edx	movl	PCB_CR3(%edx),%ebx	/* switch address space */	movl	%ebx,%cr3	/* restore context */	movl	PCB_EBX(%edx), %ebx	movl	PCB_ESP(%edx), %esp	movl	PCB_EBP(%edx), %ebp	movl	PCB_ESI(%edx), %esi	movl	PCB_EDI(%edx), %edi	movl	PCB_EIP(%edx), %eax	movl	%eax, (%esp)	movl	PCB_CMAP2(%edx),%eax	# get temporary map	movl	%eax,_CMAP2		# reload temporary map PTE	movl	%ecx,_curproc		# into next process	movl	%edx,_curpcb	/* pushl	PCB_IML(%edx)	call	_splx	popl	%eax*/	movl	%edx,%eax		# return (1);	ret	.globl	_mvesp	ALIGN32_mvesp:	movl	%esp,%eax	ret/* * struct proc *switch_to_inactive(p) ; struct proc *p; * * At exit of a process, move off the address space of the * process and onto a "safe" one. Then, on a temporary stack * return and run code that disposes of the old state. * Since this code requires a parameter from the "old" stack, * pass it back as a return value. */	ALIGN32ENTRY(switch_to_inactive)	popl	%edx			# old pc	popl	%eax			# arg, our return value	movl	_IdlePTD,%ecx	movl	%ecx,%cr3		# good bye address space #write buffer?	movl	$tmpstk-4,%esp		# temporary stack, compensated for call	jmp	%edx			# return, execute remainder of cleanup/* * savectx(pcb, altreturn) * Update pcb, saving current processor state and arranging * for alternate return ala longjmp in Xswitch if altreturn is true. */	ALIGN32ENTRY(savectx)	movl	4(%esp), %ecx	movw	_cpl, %ax	movw	%ax,  PCB_IML(%ecx)	movl	(%esp), %eax		movl	%eax, PCB_EIP(%ecx)	movl	%ebx, PCB_EBX(%ecx)	movl	%esp, PCB_ESP(%ecx)	movl	%ebp, PCB_EBP(%ecx)	movl	%esi, PCB_ESI(%ecx)	movl	%edi, PCB_EDI(%ecx)#ifdef NPX	/*	 * If npxproc == NULL, then the npx h/w state is irrelevant and the	 * state had better already be in the pcb.  This is true for forks	 * but not for dumps (the old book-keeping with FP flags in the pcb	 * always lost for dumps because the dump pcb has 0 flags).	 *	 * If npxproc != NULL, then we have to save the npx h/w state to	 * npxproc's pcb and copy it to the requested pcb, or save to the	 * requested pcb and reload.  Copying is easier because we would	 * have to handle h/w bugs for reloading.  We used to lose the	 * parent's npx state for forks by forgetting to reload.	 */	mov	_npxproc,%eax	testl	%eax,%eax  	je	1f	pushl	%ecx	movl	P_ADDR(%eax),%eax	leal	PCB_SAVEFPU(%eax),%eax	pushl	%eax	pushl	%eax	call	_npxsave	popl	%eax	popl	%eax	popl	%ecx	pushl	%ecx	pushl	$108+8*2	/* XXX h/w state size + padding */	leal	PCB_SAVEFPU(%ecx),%ecx	pushl	%ecx	pushl	%eax	call	_bcopy	addl	$12,%esp	popl	%ecx1:#endif	movl	_CMAP2, %edx		# save temporary map PTE	movl	%edx, PCB_CMAP2(%ecx)	# in our context	cmpl	$0, 8(%esp)	je	1f	movl	%esp, %edx		# relocate current sp relative to pcb	subl	$_kstack, %edx		#   (sp is relative to kstack):	addl	%edx, %ecx		#   pcb += sp - kstack;	movl	%eax, (%ecx)		# write return pc at (relocated) sp@	# this mess deals with replicating register state gcc hides	movl	12(%esp),%eax	movl	%eax,12(%ecx)	movl	16(%esp),%eax	movl	%eax,16(%ecx)	movl	20(%esp),%eax	movl	%eax,20(%ecx)	movl	24(%esp),%eax	movl	%eax,24(%ecx)1:	xorl	%eax, %eax		# return 0	ret/* * addupc(int pc, struct uprof *up, int ticks): * update profiling information for the user process. */	ALIGN32ENTRY(addupc)	pushl %ebp	movl %esp,%ebp	movl 12(%ebp),%edx		/* up */	movl 8(%ebp),%eax		/* pc */	subl PR_OFF(%edx),%eax		/* pc -= up->pr_off */	jl L1				/* if (pc < 0) return */	shrl $1,%eax			/* praddr = pc >> 1 */	imull PR_SCALE(%edx),%eax	/* praddr *= up->pr_scale */	shrl $15,%eax			/* praddr = praddr << 15 */	andl $-2,%eax			/* praddr &= ~1 */	cmpl PR_SIZE(%edx),%eax		/* if (praddr > up->pr_size) return */	ja L1/*	addl %eax,%eax			/* praddr -> word offset */	addl PR_BASE(%edx),%eax		/* praddr += up-> pr_base */	movl 16(%ebp),%ecx		/* ticks */	movl _curpcb,%edx	movl $proffault,PCB_ONFAULT(%edx)	addl %ecx,(%eax)		/* storage location += ticks */	movl $0,PCB_ONFAULT(%edx)L1:	leave	ret	ALIGN32proffault:	/* if we get a fault, then kill profiling all together */	movl $0,PCB_ONFAULT(%edx)	/* squish the fault handler */ 	movl 12(%ebp),%ecx	movl $0,PR_SCALE(%ecx)		/* up->pr_scale = 0 */	leave	ret.data	ALIGN32	.globl	_cyloffset, _curpcb_cyloffset:	.long	0	.globl	_proc0paddr_proc0paddr:	.long	0LF:	.asciz "Xswitch %x".text # To be done:	.globl _astoff_astoff:	ret#define	IDTVEC(name)	.align 4; .globl _X/**/name; _X/**/name:#define	PANIC(msg)	xorl %eax,%eax; movl %eax,_waittime; pushl 1f; \			call _panic; 1: .asciz msg#define	PRINTF(n,msg)	pushal ; nop ; pushl 1f; call _printf; MSG(msg) ; \			 popl %eax ; popal#define	MSG(msg)	.data; 1: .asciz msg; .text	.text/* * Trap and fault vector routines */ #define	TRAP(a)		pushl $(a) ; jmp alltraps#ifdef KGDB#define	BPTTRAP(a)	pushl $(a) ; jmp bpttraps#else#define	BPTTRAP(a)	TRAP(a)#endifIDTVEC(div)	pushl $0; TRAP(T_DIVIDE)IDTVEC(dbg)	pushl $0; BPTTRAP(T_TRCTRAP)IDTVEC(nmi)	pushl $0; TRAP(T_NMI)IDTVEC(bpt)	pushl $0; BPTTRAP(T_BPTFLT)IDTVEC(ofl)	pushl $0; TRAP(T_OFLOW)IDTVEC(bnd)	pushl $0; TRAP(T_BOUND)IDTVEC(ill)	pushl $0; TRAP(T_PRIVINFLT)IDTVEC(dna)	pushl $0; TRAP(T_DNA)IDTVEC(dble)	TRAP(T_DOUBLEFLT)	/*PANIC("Double Fault");*/IDTVEC(fpusegm)	pushl $0; TRAP(T_FPOPFLT)IDTVEC(tss)	TRAP(T_TSSFLT)	/*PANIC("TSS not valid");*/IDTVEC(missing)	TRAP(T_SEGNPFLT)IDTVEC(stk)	TRAP(T_STKFLT)IDTVEC(prot)	TRAP(T_PROTFLT)IDTVEC(page)	TRAP(T_PAGEFLT)IDTVEC(rsvd)	pushl $0; TRAP(T_RESERVED)IDTVEC(fpu)#ifdef NPX	/*	 * Handle like an interrupt so that we can call npxintr to clear the	 * error.  It would be better to handle npx interrupts as traps but	 * this is difficult for nested interrupts.	 */	pushl	$0		/* dummy error code */	pushl	$T_ASTFLT	pushal	nop			/* silly, the bug is for popal and it only				 * bites when the next instruction has a				 * complicated address mode */	pushl	%ds	pushl	%es		/* now the stack frame is a trap frame */	movl	$KDSEL,%eax	movl	%ax,%ds	movl	%ax,%es	pushl	_cpl	pushl	$0		/* dummy unit to finish building intr frame */	incl	_cnt+V_TRAP	call	_npxintr	jmp	doreti#else	pushl $0; TRAP(T_ARITHTRAP)#endif	/* 17 - 31 reserved for future exp */IDTVEC(rsvd0)	pushl $0; TRAP(17)IDTVEC(rsvd1)	pushl $0; TRAP(18)IDTVEC(rsvd2)	pushl $0; TRAP(19)IDTVEC(rsvd3)	pushl $0; TRAP(20)IDTVEC(rsvd4)	pushl $0; TRAP(21)IDTVEC(rsvd5)	pushl $0; TRAP(22)IDTVEC(rsvd6)	pushl $0; TRAP(23)IDTVEC(rsvd7)	pushl $0; TRAP(24)IDTVEC(rsvd8)	pushl $0; TRAP(25)IDTVEC(rsvd9)	pushl $0; TRAP(26)IDTVEC(rsvd10)	pushl $0; TRAP(27)IDTVEC(rsvd11)	pushl $0; TRAP(28)IDTVEC(rsvd12)	pushl $0; TRAP(29)IDTVEC(rsvd13)	pushl $0; TRAP(30)IDTVEC(rsvd14)	pushl $0; TRAP(31)	ALIGN32alltraps:	pushal	nop	push %ds	push %es	# movw	$KDSEL,%ax	movw	$0x10,%ax	movw	%ax,%ds	movw	%ax,%escalltrap:	incl	_cnt+V_TRAP	call	_trap	/*	 * Return through doreti to handle ASTs.  Have to change trap frame	 * to interrupt frame.	 */	movl	$T_ASTFLT,4+4+32(%esp)	/* new trap type (err code not used) */	pushl	_cpl	pushl	$0			/* dummy unit */	jmp	doreti#ifdef KGDB/* * This code checks for a kgdb trap, then falls through * to the regular trap code. */	ALIGN32bpttraps:	pushal	nop	push	%es	push	%ds	# movw	$KDSEL,%ax	movw	$0x10,%ax	movw	%ax,%ds	movw	%ax,%es	movzwl	52(%esp),%eax	test	$3,%eax		jne	calltrap	call	_kgdb_trap_glue			jmp	calltrap#endif/* * Call gate entry for syscall */	ALIGN32IDTVEC(syscall)	pushfl	# only for stupid carry bit and more stupid wait3 cc kludge	pushal	# only need eax,ecx,edx - trap resaves others	nop	movl	$KDSEL,%eax		# switch to kernel segments	movl	%ax,%ds	movl	%ax,%es	incl	_cnt+V_SYSCALL  # kml 3/25/93	call	_syscall	/*	 * Return through doreti to handle ASTs.  Have to change syscall frame	 * to interrupt frame.	 *	 * XXX - we should have set up the frame earlier to avoid the	 * following popal/pushal (not much can be done to avoid shuffling	 * the flags).  Consistent frames would simplify things all over.	 */	movl	32+0(%esp),%eax	/* old flags, shuffle to above cs:eip */	movl	32+4(%esp),%ebx	/* `int' frame should have been ef, eip, cs */	movl	32+8(%esp),%ecx	movl	%ebx,32+0(%esp)	movl	%ecx,32+4(%esp)	movl	%eax,32+8(%esp)	popal	nop	pushl	$0		/* dummy error code */	pushl	$T_ASTFLT	pushal	nop	movl	__udatasel,%eax	/* switch back to user segments */	push	%eax		/* XXX - better to preserve originals? */	push	%eax	pushl	_cpl	pushl	$0	jmp	doreti	ALIGN32ENTRY(htonl)ENTRY(ntohl)	movl	4(%esp),%eax	xchgb	%al,%ah	roll	$16,%eax	xchgb	%al,%ah	ret	ALIGN32ENTRY(htons)ENTRY(ntohs)	movzwl	4(%esp),%eax	xchgb	%al,%ah	ret#include "vector.s"#include "i386/isa/icu.s"

⌨️ 快捷键说明

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