📄 locore.s
字号:
_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 + -