entry.s
来自「linux-2.6.15.6」· S 代码 · 共 2,410 行 · 第 1/4 页
S
2,410 行
* cr25 contains a pointer to the current user address * space page directory. * * sr3 will contain the space id of the user address space * of the current running thread while that thread is * running in the kernel. */ /* * register number allocations. Note that these are all * in the shadowed registers */ t0 = r1 /* temporary register 0 */ va = r8 /* virtual address for which the trap occured */ t1 = r9 /* temporary register 1 */ pte = r16 /* pte/phys page # */ prot = r17 /* prot bits */ spc = r24 /* space for which the trap occured */ ptp = r25 /* page directory/page table pointer */#ifdef CONFIG_64BITdtlb_miss_20w: space_adjust spc,va,t0 get_pgd spc,ptp space_check spc,t0,dtlb_fault L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot rfir nopdtlb_check_alias_20w: do_alias spc,t0,t1,va,pte,prot,dtlb_fault idtlbt pte,prot rfir nopnadtlb_miss_20w: space_adjust spc,va,t0 get_pgd spc,ptp space_check spc,t0,nadtlb_fault L3_ptep ptp,pte,t0,va,nadtlb_check_flush_20w update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot rfir nopnadtlb_check_flush_20w: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate /* Insert a "flush only" translation */ depdi,z 7,7,3,prot depdi 1,10,1,prot /* Get rid of prot bits and convert to page addr for idtlbt */ depdi 0,63,12,pte extrd,u pte,56,52,pte idtlbt pte,prot rfir nop#elsedtlb_miss_11: get_pgd spc,ptp space_check spc,t0,dtlb_fault L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 update_ptep ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ rfir nopdtlb_check_alias_11: /* Check to see if fault is in the temporary alias region */ cmpib,<>,n 0,spc,dtlb_fault /* forward */ ldil L%(TMPALIAS_MAP_START),t0 copy va,t1 depwi 0,31,23,t1 cmpb,<>,n t0,t1,dtlb_fault /* forward */ ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot depw,z prot,8,7,prot /* * OK, it is in the temp alias region, check whether "from" or "to". * Check "subtle" note in pacache.S re: r23/r26. */ extrw,u,= va,9,1,r0 or,tr %r23,%r0,pte /* If "from" use "from" page */ or %r26,%r0,pte /* else "to", use "to" page */ idtlba pte,(va) idtlbp prot,(va) rfir nopnadtlb_miss_11: get_pgd spc,ptp space_check spc,t0,nadtlb_fault L2_ptep ptp,pte,t0,va,nadtlb_check_flush_11 update_ptep ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ rfir nopnadtlb_check_flush_11: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate /* Insert a "flush only" translation */ zdepi 7,7,3,prot depi 1,10,1,prot /* Get rid of prot bits and convert to page addr for idtlba */ depi 0,31,12,pte extru pte,24,25,pte mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ rfir nopdtlb_miss_20: space_adjust spc,va,t0 get_pgd spc,ptp space_check spc,t0,dtlb_fault L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 idtlbt pte,prot rfir nopdtlb_check_alias_20: do_alias spc,t0,t1,va,pte,prot,dtlb_fault idtlbt pte,prot rfir nopnadtlb_miss_20: get_pgd spc,ptp space_check spc,t0,nadtlb_fault L2_ptep ptp,pte,t0,va,nadtlb_check_flush_20 update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 idtlbt pte,prot rfir nopnadtlb_check_flush_20: bb,>=,n pte,_PAGE_FLUSH_BIT,nadtlb_emulate /* Insert a "flush only" translation */ depdi,z 7,7,3,prot depdi 1,10,1,prot /* Get rid of prot bits and convert to page addr for idtlbt */ depdi 0,63,12,pte extrd,u pte,56,32,pte idtlbt pte,prot rfir nop#endifnadtlb_emulate: /* * Non access misses can be caused by fdc,fic,pdc,lpa,probe and * probei instructions. We don't want to fault for these * instructions (not only does it not make sense, it can cause * deadlocks, since some flushes are done with the mmap * semaphore held). If the translation doesn't exist, we can't * insert a translation, so have to emulate the side effects * of the instruction. Since we don't insert a translation * we can get a lot of faults during a flush loop, so it makes * sense to try to do it here with minimum overhead. We only * emulate fdc,fic,pdc,probew,prober instructions whose base * and index registers are not shadowed. We defer everything * else to the "slow" path. */ mfctl %cr19,%r9 /* Get iir */ /* PA 2.0 Arch Ref. Book pg 382 has a good description of the insn bits. Checks for fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw */ /* Checks for fdc,fdce,pdc,"fic,4f" only */ ldi 0x280,%r16 and %r9,%r16,%r17 cmpb,<>,n %r16,%r17,nadtlb_probe_check bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ BL get_register,%r25 extrw,u %r9,15,5,%r8 /* Get index register # */ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ copy %r1,%r24 BL get_register,%r25 extrw,u %r9,10,5,%r8 /* Get base register # */ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ BL set_register,%r25 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */nadtlb_nullify: mfctl %ipsw,%r8 ldil L%PSW_N,%r9 or %r8,%r9,%r8 /* Set PSW_N */ mtctl %r8,%ipsw rfir nop /* When there is no translation for the probe address then we must nullify the insn and return zero in the target regsiter. This will indicate to the calling code that it does not have write/read privileges to this address. This should technically work for prober and probew in PA 1.1, and also probe,r and probe,w in PA 2.0 WARNING: USE ONLY NON-SHADOW REGISTERS WITH PROBE INSN! THE SLOW-PATH EMULATION HAS NOT BEEN WRITTEN YET. */nadtlb_probe_check: ldi 0x80,%r16 and %r9,%r16,%r17 cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/ BL get_register,%r25 /* Find the target register */ extrw,u %r9,31,5,%r8 /* Get target register */ CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ BL set_register,%r25 copy %r0,%r1 /* Write zero to target register */ b nadtlb_nullify /* Nullify return insn */ nop#ifdef CONFIG_64BITitlb_miss_20w: /* * I miss is a little different, since we allow users to fault * on the gateway page which is in the kernel address space. */ space_adjust spc,va,t0 get_pgd spc,ptp space_check spc,t0,itlb_fault L3_ptep ptp,pte,t0,va,itlb_fault update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot iitlbt pte,prot rfir nop#elseitlb_miss_11: get_pgd spc,ptp space_check spc,t0,itlb_fault L2_ptep ptp,pte,t0,va,itlb_fault update_ptep ptp,pte,t0,t1 make_insert_tlb_11 spc,pte,prot mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 iitlba pte,(%sr1,va) iitlbp prot,(%sr1,va) mtsp t0, %sr1 /* Restore sr1 */ rfir nopitlb_miss_20: get_pgd spc,ptp space_check spc,t0,itlb_fault L2_ptep ptp,pte,t0,va,itlb_fault update_ptep ptp,pte,t0,t1 make_insert_tlb spc,pte,prot f_extend pte,t0 iitlbt pte,prot rfir nop#endif#ifdef CONFIG_64BITdbit_trap_20w: space_adjust spc,va,t0 get_pgd spc,ptp space_check spc,t0,dbit_fault L3_ptep ptp,pte,t0,va,dbit_fault#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nolock_20w load32 PA(pa_dbit_lock),t0dbit_spin_20w: ldcw 0(t0),t1 cmpib,= 0,t1,dbit_spin_20w nopdbit_nolock_20w:#endif update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot idtlbt pte,prot#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nounlock_20w ldi 1,t1 stw t1,0(t0)dbit_nounlock_20w:#endif rfir nop#elsedbit_trap_11: get_pgd spc,ptp space_check spc,t0,dbit_fault L2_ptep ptp,pte,t0,va,dbit_fault#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nolock_11 load32 PA(pa_dbit_lock),t0dbit_spin_11: ldcw 0(t0),t1 cmpib,= 0,t1,dbit_spin_11 nopdbit_nolock_11:#endif update_dirty ptp,pte,t1 make_insert_tlb_11 spc,pte,prot mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ mtsp spc,%sr1 idtlba pte,(%sr1,va) idtlbp prot,(%sr1,va) mtsp t1, %sr1 /* Restore sr1 */#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nounlock_11 ldi 1,t1 stw t1,0(t0)dbit_nounlock_11:#endif rfir nopdbit_trap_20: get_pgd spc,ptp space_check spc,t0,dbit_fault L2_ptep ptp,pte,t0,va,dbit_fault#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nolock_20 load32 PA(pa_dbit_lock),t0dbit_spin_20: ldcw 0(t0),t1 cmpib,= 0,t1,dbit_spin_20 nopdbit_nolock_20:#endif update_dirty ptp,pte,t1 make_insert_tlb spc,pte,prot f_extend pte,t1 idtlbt pte,prot#ifdef CONFIG_SMP CMPIB=,n 0,spc,dbit_nounlock_20 ldi 1,t1 stw t1,0(t0)dbit_nounlock_20:#endif rfir nop#endif .import handle_interruption,codekernel_bad_space: b intr_save ldi 31,%r8 /* Use an unused code */dbit_fault: b intr_save ldi 20,%r8itlb_fault: b intr_save ldi 6,%r8nadtlb_fault: b intr_save ldi 17,%r8dtlb_fault: b intr_save ldi 15,%r8 /* Register saving semantics for system calls: %r1 clobbered by system call macro in userspace %r2 saved in PT_REGS by gateway page %r3 - %r18 preserved by C code (saved by signal code) %r19 - %r20 saved in PT_REGS by gateway page %r21 - %r22 non-standard syscall args stored in kernel stack by gateway page %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page %r27 - %r30 saved in PT_REGS by gateway page %r31 syscall return pointer */ /* Floating point registers (FIXME: what do we do with these?) %fr0 - %fr3 status/exception, not preserved %fr4 - %fr7 arguments %fr8 - %fr11 not preserved by C code %fr12 - %fr21 preserved by C code %fr22 - %fr31 not preserved by C code */ .macro reg_save regs STREG %r3, PT_GR3(\regs) STREG %r4, PT_GR4(\regs) STREG %r5, PT_GR5(\regs) STREG %r6, PT_GR6(\regs) STREG %r7, PT_GR7(\regs) STREG %r8, PT_GR8(\regs) STREG %r9, PT_GR9(\regs) STREG %r10,PT_GR10(\regs) STREG %r11,PT_GR11(\regs) STREG %r12,PT_GR12(\regs) STREG %r13,PT_GR13(\regs) STREG %r14,PT_GR14(\regs) STREG %r15,PT_GR15(\regs) STREG %r16,PT_GR16(\regs) STREG %r17,PT_GR17(\regs) STREG %r18,PT_GR18(\regs) .endm .macro reg_restore regs LDREG PT_GR3(\regs), %r3 LDREG PT_GR4(\regs), %r4 LDREG PT_GR5(\regs), %r5 LDREG PT_GR6(\regs), %r6 LDREG PT_GR7(\regs), %r7 LDREG PT_GR8(\regs), %r8 LDREG PT_GR9(\regs), %r9 LDREG PT_GR10(\regs),%r10 LDREG PT_GR11(\regs),%r11 LDREG PT_GR12(\regs),%r12 LDREG PT_GR13(\regs),%r13 LDREG PT_GR14(\regs),%r14 LDREG PT_GR15(\regs),%r15 LDREG PT_GR16(\regs),%r16 LDREG PT_GR17(\regs),%r17 LDREG PT_GR18(\regs),%r18 .endm .export sys_fork_wrapper .export child_returnsys_fork_wrapper: LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1 ldo TASK_REGS(%r1),%r1 reg_save %r1 mfctl %cr27, %r3 STREG %r3, PT_CR27(%r1) STREG %r2,-RP_OFFSET(%r30) ldo FRAME_SIZE(%r30),%r30#ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */#endif /* These are call-clobbered registers and therefore also syscall-clobbered (we hope). */ STREG %r2,PT_GR19(%r1) /* save for child */ STREG %r30,PT_GR21(%r1) LDREG PT_GR30(%r1),%r25 copy %r1,%r24 BL sys_clone,%r2 ldi SIGCHLD,%r26 LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?