📄 locore.s
字号:
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(LUNA2) 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) 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 pointerLcxswdone: 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(LUNA2) 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(LUNA2) 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(LUNA2)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(LUNA2) cmpl #-2,_mmutype | 68040? jne Lmotommu3 | no, skip .word 0xf518 | yes, pflusha rtsLmotommu3:#endif pflusha | flush entire TLB movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rts/* * Invalidate any TLB entry for given VA (TB Invalidate Single) */ENTRY(TBIS)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush entire TLB#endif#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne Lmotommu4 | no, skip movl sp@(4),a0 movc dfc,d1 moveq #1,d0 | user space movc d0,dfc .word 0xf508 | pflush a0@ moveq #5,d0 | super space movc d0,dfc .word 0xf508 | pflush a0@ movc d1,dfc rtsLmotommu4:#endif movl sp@(4),a0 | get addr to flush pflush #0,#0,a0@ | flush address from both sides movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip data cache rts/* * Invalidate supervisor side of TLB */ENTRY(TBIAS)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush everything#endif#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne Lmotommu5 | no, skip .word 0xf518 | yes, pflusha (for now) XXX rtsLmotommu5:#endif pflush #4,#4 | flush supervisor TLB entries movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rts/* * Invalidate user side of TLB */ENTRY(TBIAU)#ifdef DEBUG tstl fulltflush | being conservative? jne __TBIA | yes, flush everything#endif#if defined(LUNA2) cmpl #-2,_mmutype | 68040? jne Lmotommu6 | no, skip .word 0xf518 | yes, pflusha (for now) XXX rtsLmotommu6:#endif pflush #0,#4 | flush user TLB entries movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rts/* * Invalidate instruction cache */ENTRY(ICIA)#if defined(LUNA2)ENTRY(ICPA) cmpl #-2,_mmutype | 68040 jne Lmotommu7 | no, skip .word 0xf498 | cinva ic rtsLmotommu7:#endif movl #IC_CLEAR,d0 movc d0,cacr | invalidate i-cache rts/* * Invalidate data cache. * NOTE: we do not flush 68030 on-chip cache as there are no aliasing * problems with DC_WA. The only cases we have to worry about are context * switch and TLB changes, both of which are handled "in-line" in resume * and TBI*. */ENTRY(DCIA)__DCIA:#if defined(LUNA2) cmpl #-2,_mmutype | 68040 jne Lmotommu8 | no, skip /* XXX implement */ rtsLmotommu8:#endif rtsENTRY(DCIS)__DCIS:#if defined(LUNA2) cmpl #-2,_mmutype | 68040 jne Lmotommu9 | no, skip /* XXX implement */ rtsLmotommu9:#endif rtsENTRY(DCIU)__DCIU:#if defined(LUNA2) cmpl #-2,_mmutype | 68040 jne LmotommuA | no, skip /* XXX implement */ rtsLmotommuA:#endif rts#if defined(LUNA2)ENTRY(ICPL) movl sp@(4),a0 | address .word 0xf488 | cinvl ic,a0@ rtsENTRY(ICPP) movl sp@(4),a0 | address .word 0xf490 | cinvp ic,a0@ rtsENTRY(DCPL) movl sp@(4),a0 | address .word 0xf448 | cinvl dc,a0@ rtsENTRY(DCPP) movl sp@(4),a0 | address .word 0xf450 | cinvp dc,a0@ rtsENTRY(DCPA) .word 0xf458 | cinva dc rtsENTRY(DCFL) movl sp@(4),a0 | address .word 0xf468 | cpushl dc,a0@ rtsENTRY(DCFP) movl sp@(4),a0 | address .word 0xf470 | cpushp dc,a0@ rts#endifENTRY(PCIA)#if defined(LUNA2)ENTRY(DCFA) cmpl #-2,_mmutype | 68040 jne LmotommuB | no, skip .word 0xf478 | cpusha dc rtsLmotommuB:#endif movl #DC_CLEAR,d0 movc d0,cacr | invalidate on-chip d-cache rts#if 0 /****************************************************************//* external cache control */ENTRY(ecacheon) rtsENTRY(ecacheoff) rts#endif /****************************************************************//* * Get callers current SP value. * Note that simply taking the address of a local variable in a C function * doesn't work because callee saved registers may be outside the stack frame
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -