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

📄 locore.s

📁 早期freebsd实现
💻 S
📖 第 1 页 / 共 5 页
字号:
_esigcode:/* * Primitives */ #ifdef __STDC__#define EXPORT(name)		.globl _ ## name; _ ## name:#else#define EXPORT(name)		.globl _/**/name; _/**/name:#endif#ifdef GPROF#if __GNUC__ >= 2#define		ENTRY(name)		EXPORT(name) link a6,\#0; jbsr mcount; unlk a6#else#define		ENTRY(name)		EXPORT(name) link a6,#0; jbsr mcount; unlk a6#endif#define ALTENTRY(name, rname) ENTRY(name); jra rname+12#else#define		ENTRY(name)		EXPORT(name)#define ALTENTRY(name, rname)		ENTRY(name)#endif/* * For gcc2 */ENTRY(__main)	rts/* * copypage(fromaddr, toaddr) * * Optimized version of bcopy for a single page-aligned NBPG byte copy. */ENTRY(copypage)	movl	sp@(4),a0		| source address	movl	sp@(8),a1		| destination address	movl	#NBPG/32,d0		| number of 32 byte chunks#if defined(LUNA2)	cmpl	#-2,_mmutype		| 68040?	jne	Lmlloop			| no, use movlLm16loop:	.long	0xf6209000		| move16 a0@+,a1@+	.long	0xf6209000		| move16 a0@+,a1@+	subql	#1,d0	jne	Lm16loop	rts#endifLmlloop:	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	movl	a0@+,a1@+	subql	#1,d0	jne	Lmlloop	rts/* * copyinstr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from the user address space into * the kernel address space. * * NOTE: maxlength must be < 64K (due to use of DBcc) */ENTRY(copyinstr)	movl	_curpcb,a0		| current pcb	movl	#Lcisflt1,a0@(PCB_ONFAULT) | set up to catch faults	movl	sp@(4),a0		| a0 = fromaddr	movl	sp@(8),a1		| a1 = toaddr	moveq	#0,d0	movw	sp@(14),d0		| d0 = maxlength	jlt	Lcisflt1		| negative count, error	jeq	Lcisdone		| zero count, all done	subql	#1,d0			| set up for dbeqLcisloop:	movsb	a0@+,d1			| grab a byte	nop	movb	d1,a1@+			| copy it	dbeq	d0,Lcisloop		| if !null and more, continue	jne	Lcisflt2		| ran out of room, error	moveq	#0,d0			| got a null, all doneLcisdone:	tstl	sp@(16)			| return length desired?	jeq	Lcisret			| no, just return	subl	sp@(4),a0		| determine how much was copied	movl	sp@(16),a1		| return location	movl	a0,a1@			| stash itLcisret:	movl	_curpcb,a0		| current pcb	clrl	a0@(PCB_ONFAULT) 	| clear fault addr	rtsLcisflt1:	moveq	#EFAULT,d0		| copy fault	jra	LcisdoneLcisflt2:	moveq	#ENAMETOOLONG,d0	| ran out of space	jra	Lcisdone	/* * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from the kernel * address space to the user address space. * NOTE: maxlength must be < 64K */ENTRY(copyoutstr)	movl	_curpcb,a0		| current pcb	movl	#Lcosflt1,a0@(PCB_ONFAULT) | set up to catch faults	movl	sp@(4),a0		| a0 = fromaddr	movl	sp@(8),a1		| a1 = toaddr	moveq	#0,d0	movw	sp@(14),d0		| d0 = maxlength	jlt	Lcosflt1		| negative count, error	jeq	Lcosdone		| zero count, all done	subql	#1,d0			| set up for dbeqLcosloop:	movb	a0@+,d1			| grab a byte	movsb	d1,a1@+			| copy it	nop	dbeq	d0,Lcosloop		| if !null and more, continue	jne	Lcosflt2		| ran out of room, error	moveq	#0,d0			| got a null, all doneLcosdone:	tstl	sp@(16)			| return length desired?	jeq	Lcosret			| no, just return	subl	sp@(4),a0		| determine how much was copied	movl	sp@(16),a1		| return location	movl	a0,a1@			| stash itLcosret:	movl	_curpcb,a0		| current pcb	clrl	a0@(PCB_ONFAULT) 	| clear fault addr	rtsLcosflt1:	moveq	#EFAULT,d0		| copy fault	jra	LcosdoneLcosflt2:	moveq	#ENAMETOOLONG,d0	| ran out of space	jra	Lcosdone	/* * copystr(fromaddr, toaddr, maxlength, &lencopied) * * Copy a null terminated string from one point to another in * the kernel address space. * * NOTE: maxlength must be < 64K (due to use of DBcc) */ENTRY(copystr)	movl	sp@(4),a0		| a0 = fromaddr	movl	sp@(8),a1		| a1 = toaddr	moveq	#0,d0	movw	sp@(14),d0		| d0 = maxlength	jlt	Lcsflt1			| negative count, error	jeq	Lcsdone			| zero count, all done	subql	#1,d0			| set up for dbeqLcsloop:	movb	a0@+,a1@+		| copy a byte	dbeq	d0,Lcsloop		| if !null and more, continue	jne	Lcsflt2			| ran out of room, error	moveq	#0,d0			| got a null, all doneLcsdone:	tstl	sp@(16)			| return length desired?	jeq	Lcsret			| no, just return	subl	sp@(4),a0		| determine how much was copied	movl	sp@(16),a1		| return location	movl	a0,a1@			| stash itLcsret:	rtsLcsflt1:	moveq	#EFAULT,d0		| copy fault	jra	LcsdoneLcsflt2:	moveq	#ENAMETOOLONG,d0	| ran out of space	jra	Lcsdone	/*  * Copyin(from_user, to_kernel, len) * Copyout(from_kernel, to_user, len) * * Copy specified amount of data between kernel and user space. * * XXX both use the DBcc instruction which has 16-bit limitation so only * 64k units can be copied, where "unit" is either a byte or a longword * depending on alignment.  To be safe, assume it can copy at most * 64k bytes.  Don't make MAXBSIZE or MAXPHYS larger than 64k without * fixing this code! */ENTRY(copyin)	movl	sp@(12),d0		| get size#ifdef MAPPEDCOPY	.globl	_mappedcopysize,_mappedcopyin	cmpl	_mappedcopysize,d0	| size >= mappedcopysize	jcc	_mappedcopyin		| yes, go do it the new way#endif	movl	d2,sp@-			| scratch register	movl	_curpcb,a0		| current pcb	movl	#Lciflt,a0@(PCB_ONFAULT) | set up to catch faults	tstl	d0			| check count	jlt	Lciflt			| negative, error	jeq	Lcidone			| zero, done	movl	sp@(8),a0		| src address	movl	sp@(12),a1		| dest address	movl	a0,d2	btst	#0,d2			| src address odd?	jeq	Lcieven			| no, go check dest	movsb	a0@+,d1			| yes, get a byte	nop	movb	d1,a1@+			| put a byte	subql	#1,d0			| adjust count	jeq	Lcidone			| exit if doneLcieven:	movl	a1,d2	btst	#0,d2			| dest address odd?	jne	Lcibloop		| yes, must copy by bytes	movl	d0,d2			| no, get count	lsrl	#2,d2			| convert to longwords	jeq	Lcibloop		| no longwords, copy bytesLcilloop:	movsl	a0@+,d1			| get a long	nop	movl	d1,a1@+			| put a long	subql	#1,d2	jne	Lcilloop		| til done	andl	#3,d0			| what remains	jeq	Lcidone			| all doneLcibloop:	movsb	a0@+,d1			| get a byte	nop	movb	d1,a1@+			| put a byte	subql	#1,d0	jne	Lcibloop		| til doneLcidone:	movl	_curpcb,a0		| current pcb	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher	movl	sp@+,d2			| restore scratch reg	rtsLciflt:	moveq	#EFAULT,d0		| got a fault	jra	LcidoneENTRY(copyout)	movl	sp@(12),d0		| get size#ifdef MAPPEDCOPY	.globl	_mappedcopysize,_mappedcopyout	cmpl	_mappedcopysize,d0	| size >= mappedcopysize	jcc	_mappedcopyout		| yes, go do it the new way#endif	movl	d2,sp@-			| scratch register	movl	_curpcb,a0		| current pcb	movl	#Lcoflt,a0@(PCB_ONFAULT) | catch faults	tstl	d0			| check count	jlt	Lcoflt			| negative, error	jeq	Lcodone			| zero, done	movl	sp@(8),a0		| src address	movl	sp@(12),a1		| dest address	movl	a0,d2	btst	#0,d2			| src address odd?	jeq	Lcoeven			| no, go check dest	movb	a0@+,d1			| yes, get a byte	movsb	d1,a1@+			| put a byte	nop	subql	#1,d0			| adjust count	jeq	Lcodone			| exit if doneLcoeven:	movl	a1,d2	btst	#0,d2			| dest address odd?	jne	Lcobloop		| yes, must copy by bytes	movl	d0,d2			| no, get count	lsrl	#2,d2			| convert to longwords	jeq	Lcobloop		| no longwords, copy bytesLcolloop:	movl	a0@+,d1			| get a long	movsl	d1,a1@+			| put a long	nop	subql	#1,d2	jne	Lcolloop		| til done	andl	#3,d0			| what remains	jeq	Lcodone			| all doneLcobloop:	movb	a0@+,d1			| get a byte	movsb	d1,a1@+			| put a byte	nop	subql	#1,d0	jne	Lcobloop		| til doneLcodone:	movl	_curpcb,a0		| current pcb	clrl	a0@(PCB_ONFAULT) 	| clear fault catcher	movl	sp@+,d2			| restore scratch reg	rtsLcoflt:	moveq	#EFAULT,d0		| got a fault	jra	Lcodone/* * non-local gotos */ENTRY(setjmp)	movl	sp@(4),a0	| savearea pointer	moveml	#0xFCFC,a0@	| save d2-d7/a2-a7	movl	sp@,a0@(48)	| and return address	moveq	#0,d0		| return 0	rtsENTRY(longjmp)	movl	sp@(4),a0	moveml	a0@+,#0xFCFC	movl	a0@,sp@	moveq	#1,d0	rts/* * The following primitives manipulate the run queues.  _whichqs tells which * of the 32 queues _qs have processes in them.  Setrunqueue puts processes * into queues, Remrq removes them from queues.  The running process is on * no queue, other processes are on a queue related to p->p_priority, divided * by 4 actually to shrink the 0-127 range of priorities into the 32 available * queues. */	.globl	_whichqs,_qs,_cnt,_panic	.globl	_curproc,_want_resched/* * Setrunqueue(p) * * 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

⌨️ 快捷键说明

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