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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
 * Call should be made at spl6(), and p->p_stat should be SRUN */ENTRY(setrunqueue)	movl	sp@(4),a0	tstl	a0@(P_BACK)	jeq	Lset1	movl	#Lset2,sp@-	jbsr	_panicLset1:	clrl	d0	movb	a0@(P_PRIORITY),d0	lsrb	#2,d0	movl	_whichqs,d1	bset	d0,d1	movl	d1,_whichqs	lslb	#3,d0	addl	#_qs,d0	movl	d0,a0@(P_FORW)	movl	d0,a1	movl	a1@(P_BACK),a0@(P_BACK)	movl	a0,a1@(P_BACK)	movl	a0@(P_BACK),a1	movl	a0,a1@(P_FORW)	rtsLset2:	.asciz	"setrunqueue"	.even/* * Remrq(p) * * Call should be made at spl6(). */ENTRY(remrq)	movl	sp@(4),a0	clrl	d0	movb	a0@(P_PRIORITY),d0	lsrb	#2,d0	movl	_whichqs,d1	bclr	d0,d1	jne	Lrem1	movl	#Lrem3,sp@-	jbsr	_panicLrem1:	movl	d1,_whichqs	movl	a0@(P_FORW),a1	movl	a0@(P_BACK),a1@(P_BACK)	movl	a0@(P_BACK),a1	movl	a0@(P_FORW),a1@(P_FORW)	movl	#_qs,a1	movl	d0,d1	lslb	#3,d1	addl	d1,a1	cmpl	a1@(P_FORW),a1	jeq	Lrem2	movl	_whichqs,d1	bset	d0,d1	movl	d1,_whichqsLrem2:	clrl	a0@(P_BACK)	rtsLrem3:	.asciz	"remrq"Lsw0:	.asciz	"switch"	.even	.globl	_curpcb	.globl	_masterpaddr	| XXX compatibility (debuggers)	.data_masterpaddr:			| XXX compatibility (debuggers)_curpcb:	.long	0mdpflag:	.byte	0		| copy of proc md_flags low byte	.align	2	.comm	nullpcb,SIZEOF_PCB	.text/* * At exit of a process, do a switch for the last time. * The mapping of the pcb at p->p_addr has already been deleted, * and the memory for the pcb+stack has been freed. * The ipl is high enough to prevent the memory from being reallocated. */ENTRY(switch_exit)	movl	#nullpcb,_curpcb	| save state into garbage pcb	lea	tmpstk,sp		| goto a tmp stack	jra	_cpu_switch/* * When no processes are on the runq, Swtch branches to Idle * to wait for something to come ready. */	.globl	idleidle:	stop	#PSL_LOWIPLIdle:	movw	#PSL_HIGHIPL,sr	tstl	_whichqs	jeq	idle	movw	#PSL_LOWIPL,sr	jra	Lsw1Lbadsw:	movl	#Lsw0,sp@-	jbsr	_panic	/*NOTREACHED*//* * cpu_switch() * * NOTE: On the mc68851 (318/319/330) we attempt to avoid flushing the * entire ATC.  The effort involved in selective flushing may not be * worth it, maybe we should just flush the whole thing? * * NOTE 2: With the new VM layout we now no longer know if an inactive * user's PTEs have been changed (formerly denoted by the SPTECHG p_flag * bit).  For now, we just always flush the full ATC. */ENTRY(cpu_switch)	movl	_curpcb,a0		| current pcb	movw	sr,a0@(PCB_PS)		| save sr before changing ipl#ifdef notyet	movl	_curproc,sp@-		| remember last proc running#endif	clrl	_curproc	addql	#1,_cnt+V_SWTCHLsw1:	/*	 * Find the highest-priority queue that isn't empty,	 * then take the first proc from that queue.	 */	clrl	d0	lea	_whichqs,a0	movl	a0@,d1Lswchk:	btst	d0,d1	jne	Lswfnd	addqb	#1,d0	cmpb	#32,d0	jne	Lswchk	jra	IdleLswfnd:	movw	#PSL_HIGHIPL,sr		| lock out interrupts	movl	a0@,d1			| and check again...	bclr	d0,d1	jeq	Lsw1			| proc moved, rescan	movl	d1,a0@			| update whichqs	moveq	#1,d1			| double check for higher priority	lsll	d0,d1			| process (which may have snuck in	subql	#1,d1			| while we were finding this one)	andl	a0@,d1	jeq	Lswok			| no one got in, continue	movl	a0@,d1	bset	d0,d1			| otherwise put this one back	movl	d1,a0@	jra	Lsw1			| and rescanLswok:	movl	d0,d1	lslb	#3,d1			| convert queue number to index	addl	#_qs,d1			| locate queue (q)	movl	d1,a1	cmpl	a1@(P_FORW),a1		| anyone on queue?	jeq	Lbadsw			| no, panic	movl	a1@(P_FORW),a0		| p = q->p_forw	movl	a0@(P_FORW),a1@(P_FORW)	| q->p_forw = p->p_forw	movl	a0@(P_FORW),a1		| q = p->p_forw	movl	a0@(P_BACK),a1@(P_BACK)	| q->p_back = p->p_back	cmpl	a0@(P_FORW),d1		| anyone left on queue?	jeq	Lsw2			| no, skip	movl	_whichqs,d1	bset	d0,d1			| yes, reset bit	movl	d1,_whichqsLsw2:	movl	a0,_curproc	clrl	_want_resched#ifdef notyet	movl	sp@+,a1	cmpl	a0,a1			| switching to same proc?	jeq	Lswdone			| yes, skip save and restore#endif	/*	 * Save state of previous process in its pcb.	 */	movl	_curpcb,a1	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers	movl	usp,a2			| grab USP (a2 has been saved)	movl	a2,a1@(PCB_USP)		| and save it#ifdef FPCOPROC	lea	a1@(PCB_FPCTX),a2	| pointer to FP save area	fsave	a2@			| save FP state	tstb	a2@			| null state frame?	jeq	Lswnofpsave		| yes, all done	fmovem	fp0-fp7,a2@(216)	| save FP general registers	fmovem	fpcr/fpsr/fpi,a2@(312)	| save FP control registersLswnofpsave:#endif#ifdef DIAGNOSTIC	tstl	a0@(P_WCHAN)	jne	Lbadsw	cmpb	#SRUN,a0@(P_STAT)	jne	Lbadsw#endif	clrl	a0@(P_BACK)		| clear back link	movb	a0@(P_MDFLAG+3),mdpflag	| low byte of p_md.md_flags	movl	a0@(P_ADDR),a1		| get p_addr	movl	a1,_curpcb	/* see if pmap_activate needs to be called; should remove this */	movl	a0@(P_VMSPACE),a0	| vmspace = p->p_vmspace#ifdef DIAGNOSTIC	tstl	a0			| map == VM_MAP_NULL?	jeq	Lbadsw			| panic#endif	lea	a0@(VM_PMAP),a0		| pmap = &vmspace.vm_pmap	tstl	a0@(PM_STCHG)		| pmap->st_changed?	jeq	Lswnochg		| no, skip	pea	a1@			| push pcb (at p_addr)	pea	a0@			| push pmap	jbsr	_pmap_activate		| pmap_activate(pmap, pcb)	addql	#8,sp	movl	_curpcb,a1		| restore p_addrLswnochg:	movl	#PGSHIFT,d1	movl	a1,d0	lsrl	d1,d0			| convert p_addr to page number	lsll	#2,d0			| and now to Sysmap offset	addl	_Sysmap,d0		| add Sysmap base to get PTE addr#ifdef notdef	movw	#PSL_HIGHIPL,sr		| go crit while changing PTEs#endif	lea	tmpstk,sp		| now goto a tmp stack for NMI	movl	d0,a0			| address of new context	movl	_Umap,a2		| address of PTEs for kstack	moveq	#UPAGES-1,d0		| sizeof kstackLres1:	movl	a0@+,d1			| get PTE	andl	#~PG_PROT,d1		| mask out old protection	orl	#PG_RW+PG_V,d1		| ensure valid and writable	movl	d1,a2@+			| load it up	dbf	d0,Lres1		| til done#if defined(HP380)	cmpl	#-2,_mmutype		| 68040?	jne	Lres1a			| no, skip	.word	0xf518			| yes, pflusha	movl	a1@(PCB_USTP),d0	| get USTP	moveq	#PGSHIFT,d1	lsll	d1,d0			| convert to addr	.long	0x4e7b0806		| movc d0,urp	jra	LcxswdoneLres1a:#endif	movl	#CACHE_CLR,d0	movc	d0,cacr			| invalidate cache(s)#if defined(HP330) || defined(HP360) || defined(HP370)	tstl	_mmutype		| HP MMU?	jeq	Lhpmmu4			| yes, skip	pflusha				| flush entire TLB	movl	a1@(PCB_USTP),d0	| get USTP	moveq	#PGSHIFT,d1	lsll	d1,d0			| convert to addr	lea	_protorp,a0		| CRP prototype	movl	d0,a0@(4)		| stash USTP	pmove	a0@,crp			| load new user root pointer	jra	Lcxswdone		| thats itLhpmmu4:	#endif#if defined(HP320) || defined(HP350)	MMUADDR(a0)	movl	a0@(MMUTBINVAL),d1	| invalidate TLB	tstl	_ectype			| got external VAC?	jle	Lnocache1		| no, skip	andl	#~MMU_CEN,a0@(MMUCMD)	| toggle cache enable	orl	#MMU_CEN,a0@(MMUCMD)	| to clear data cacheLnocache1:	movl	a1@(PCB_USTP),a0@(MMUUSTP) | context switch#endifLcxswdone:	moveml	a1@(PCB_REGS),#0xFCFC	| and registers	movl	a1@(PCB_USP),a0	movl	a0,usp			| and USP#ifdef FPCOPROC	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area	tstb	a0@			| null state frame?	jeq	Lresfprest		| yes, easy#if defined(HP380)	cmpl	#-2,_mmutype		| 68040?	jne	Lresnot040		| no, skip	clrl	sp@-			| yes...	frestore sp@+			| ...magic!Lresnot040:#endif	fmovem	a0@(312),fpcr/fpsr/fpi	| restore FP control registers	fmovem	a0@(216),fp0-fp7	| restore FP general registersLresfprest:	frestore a0@			| restore state#endif	movw	a1@(PCB_PS),sr		| no, restore PS	moveq	#1,d0			| return 1 (for alternate returns)	rts/* * savectx(pcb, altreturn) * Update pcb, saving current processor state and arranging * for alternate return ala longjmp in switch if altreturn is true. */ENTRY(savectx)	movl	sp@(4),a1	movw	sr,a1@(PCB_PS)	movl	usp,a0			| grab USP	movl	a0,a1@(PCB_USP)		| and save it	moveml	#0xFCFC,a1@(PCB_REGS)	| save non-scratch registers#ifdef FPCOPROC	lea	a1@(PCB_FPCTX),a0	| pointer to FP save area	fsave	a0@			| save FP state	tstb	a0@			| null state frame?	jeq	Lsvnofpsave		| yes, all done	fmovem	fp0-fp7,a0@(216)	| save FP general registers	fmovem	fpcr/fpsr/fpi,a0@(312)	| save FP control registersLsvnofpsave:#endif	tstl	sp@(8)			| altreturn?	jeq	Lsavedone	movl	sp,d0			| relocate current sp relative to a1	subl	#_kstack,d0		|   (sp is relative to kstack):	addl	d0,a1			|   a1 += sp - kstack;	movl	sp@,a1@			| write return pc at (relocated) sp@Lsavedone:	moveq	#0,d0			| return 0	rts/* * {fu,su},{byte,sword,word} */ALTENTRY(fuiword, _fuword)ENTRY(fuword)	movl	sp@(4),a0		| address to read	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	movsl	a0@,d0			| do read from user space	nop	jra	LfsdoneENTRY(fusword)	movl	sp@(4),a0	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	moveq	#0,d0	movsw	a0@,d0			| do read from user space	nop	jra	Lfsdone/* Just like fusword, but tells trap code not to page in. */ENTRY(fuswintr)	movl	sp@(4),a0	movl	_curpcb,a1	movl	#_fswintr,a1@(PCB_ONFAULT)	moveq	#0,d0	movsw	a0@,d0	nop	jra	LfsdoneALTENTRY(fuibyte, _fubyte)ENTRY(fubyte)	movl	sp@(4),a0		| address to read	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	moveq	#0,d0	movsb	a0@,d0			| do read from user space	nop	jra	LfsdoneLfserr:	moveq	#-1,d0			| error indicatorLfsdone:	clrl	a1@(PCB_ONFAULT) 	| clear fault address	rts/* Just like Lfserr, but the address is different (& exported). */	.globl	_fswintr_fswintr:	moveq	#-1,d0	jra	Lfsdone/* * Write a longword in user instruction space. * Largely the same as suword but with a final i-cache purge on those * machines with split caches. */ENTRY(suiword)	movl	sp@(4),a0		| address to write	movl	sp@(8),d0		| value to put there	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	movsl	d0,a0@			| do write to user space	nop	moveq	#0,d0			| indicate no fault#if defined(HP380)	cmpl	#-2,_mmutype		| 68040?	jne	Lsuicpurge		| no, skip	.word	0xf498			| cinva ic (XXX overkill)	jra	LfsdoneLsuicpurge:#endif	movl	#IC_CLEAR,d1	movc	d1,cacr			| invalidate i-cache	jra	LfsdoneENTRY(suword)	movl	sp@(4),a0		| address to write	movl	sp@(8),d0		| value to put there	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	movsl	d0,a0@			| do write to user space	nop	moveq	#0,d0			| indicate no fault	jra	LfsdoneENTRY(susword)	movl	sp@(4),a0		| address to write	movw	sp@(10),d0		| value to put there	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	movsw	d0,a0@			| do write to user space	nop	moveq	#0,d0			| indicate no fault	jra	LfsdoneENTRY(suswintr)	movl	sp@(4),a0	movw	sp@(10),d0	movl	_curpcb,a1	movl	#_fswintr,a1@(PCB_ONFAULT)	movsw	d0,a0@	nop	moveq	#0,d0	jra	LfsdoneALTENTRY(suibyte, _subyte)ENTRY(subyte)	movl	sp@(4),a0		| address to write	movb	sp@(11),d0		| value to put there	movl	_curpcb,a1		| current pcb	movl	#Lfserr,a1@(PCB_ONFAULT) | where to return to on a fault	movsb	d0,a0@			| do write to user space	nop	moveq	#0,d0			| indicate no fault	jra	Lfsdone#if defined(HP380)ENTRY(suline)	movl	sp@(4),a0		| address to write	movl	_curpcb,a1		| current pcb	movl	#Lslerr,a1@(PCB_ONFAULT) | where to return to on a fault	movl	sp@(8),a1		| address of line	movl	a1@+,d0			| get lword	movsl	d0,a0@+			| put lword	nop				| sync	movl	a1@+,d0			| get lword	movsl	d0,a0@+			| put lword	nop				| sync	movl	a1@+,d0			| get lword	movsl	d0,a0@+			| put lword	nop				| sync	movl	a1@+,d0			| get lword	movsl	d0,a0@+			| put lword	nop				| sync	moveq	#0,d0			| indicate no fault	jra	LsldoneLslerr:	moveq	#-1,d0Lsldone:	movl	_curpcb,a1		| current pcb	clrl	a1@(PCB_ONFAULT) 	| clear fault address	rts#endif/* * Invalidate entire TLB. */ENTRY(TBIA)__TBIA:#if defined(HP380)	cmpl	#-2,_mmutype		| 68040?	jne	Lmotommu3		| no, skip	.word	0xf518			| yes, pflusha	rtsLmotommu3:#endif#if defined(HP330) || defined(HP360) || defined(HP370)	tstl	_mmutype		| HP MMU?	jeq	Lhpmmu6			| yes, skip

⌨️ 快捷键说明

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