head_44x.s
来自「Linux Kernel 2.6.9 for OMAP1710」· S 代码 · 共 894 行 · 第 1/2 页
S
894 行
EXC_XFER_EE_LITE(0x0c00, DoSyscall) /* Auxillary Processor Unavailable Interrupt */ EXCEPTION(0x2020, AuxillaryProcessorUnavailable, UnknownException, EXC_XFER_EE) /* Decrementer Interrupt */ START_EXCEPTION(Decrementer) NORMAL_EXCEPTION_PROLOG lis r0,TSR_DIS@h /* Setup the DEC interrupt mask */ mtspr SPRN_TSR,r0 /* Clear the DEC interrupt */ addi r3,r1,STACK_FRAME_OVERHEAD EXC_XFER_LITE(0x1000, timer_interrupt) /* Fixed Internal Timer Interrupt */ /* TODO: Add FIT support */ EXCEPTION(0x1010, FixedIntervalTimer, UnknownException, EXC_XFER_EE) /* Watchdog Timer Interrupt */ /* TODO: Add watchdog support */ CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException) /* Data TLB Error Interrupt */ START_EXCEPTION(DataTLBError) mtspr SPRG0, r10 /* Save some working registers */ mtspr SPRG1, r11 mtspr SPRG4W, r12 mtspr SPRG5W, r13 mfcr r11 mtspr SPRG7W, r11 mfspr r10, SPRN_DEAR /* Get faulting address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ andis. r11, r10, 0x8000 beq 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l mfspr r12,SPRN_MMUCR rlwinm r12,r12,0,0,23 /* Clear TID */ b 4f /* Get the PGD for the current thread */3: mfspr r11,SPRG3 lwz r11,PGDIR(r11) /* Load PID into MMUCR TID */ mfspr r12,SPRN_MMUCR mfspr r13,SPRN_PID /* Get PID */ rlwimi r12,r13,0,24,31 /* Set TID */4: mtspr SPRN_MMUCR,r12 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r11, r12, r11 /* Get pgd/pmd entry */ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ beq 2f /* Bail if no table */ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ lwz r11, 4(r12) /* Get pte entry */ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ beq 2f /* Bail if not present */ ori r11, r11, _PAGE_ACCESSED stw r11, 4(r12) /* Jump to common tlb load */ b finish_tlb_load2: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. */ mfspr r11, SPRG7R mtcr r11 mfspr r13, SPRG5R mfspr r12, SPRG4R mfspr r11, SPRG1 mfspr r10, SPRG0 b data_access /* Instruction TLB Error Interrupt */ /* * Nearly the same as above, except we get our * information from different registers and bailout * to a different point. */ START_EXCEPTION(InstructionTLBError) mtspr SPRG0, r10 /* Save some working registers */ mtspr SPRG1, r11 mtspr SPRG4W, r12 mtspr SPRG5W, r13 mfcr r11 mtspr SPRG7W, r11 mfspr r10, SRR0 /* Get faulting address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ andis. r11, r10, 0x8000 beq 3f lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l mfspr r12,SPRN_MMUCR rlwinm r12,r12,0,0,23 /* Clear TID */ b 4f /* Get the PGD for the current thread */3: mfspr r11,SPRG3 lwz r11,PGDIR(r11) /* Load PID into MMUCR TID */ mfspr r12,SPRN_MMUCR mfspr r13,SPRN_PID /* Get PID */ rlwimi r12,r13,0,24,31 /* Set TID */4: mtspr SPRN_MMUCR,r12 rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r11, r12, r11 /* Get pgd/pmd entry */ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ beq 2f /* Bail if no table */ rlwimi r12, r10, 23, 20, 28 /* Compute pte address */ lwz r11, 4(r12) /* Get pte entry */ andi. r13, r11, _PAGE_PRESENT /* Is the page present? */ beq 2f /* Bail if not present */ ori r11, r11, _PAGE_ACCESSED stw r11, 4(r12) /* Jump to common TLB load point */ b finish_tlb_load2: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. */ mfspr r11, SPRG7R mtcr r11 mfspr r13, SPRG5R mfspr r12, SPRG4R mfspr r11, SPRG1 mfspr r10, SPRG0 b InstructionStorage/* Check for a single step debug exception while in an exception * handler before state has been saved. This is to catch the case * where an instruction that we are trying to single step causes * an exception (eg ITLB/DTLB miss) and thus the first instruction of * the exception handler generates a single step debug exception. * * If we get a debug trap on the first instruction of an exception handler, * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). * The exception handler was handling a non-critical interrupt, so it will * save (and later restore) the MSR via SPRN_SRR1, which will still have * the MSR_DE bit set. */ /* Debug Interrupt */ START_EXCEPTION(Debug) CRITICAL_EXCEPTION_PROLOG /* * If this is a single step or branch-taken exception in an * exception entry sequence, it was probably meant to apply to * the code where the exception occurred (since exception entry * doesn't turn off DE automatically). We simulate the effect * of turning off DE on entry to an exception handler by turning * off DE in the CSRR1 value and clearing the debug status. */ mfspr r10,SPRN_DBSR /* check single-step/branch taken */ andis. r10,r10,(DBSR_IC|DBSR_BT)@h beq+ 1f andi. r0,r9,MSR_PR /* check supervisor */ beq 2f /* branch if we need to fix it up... */ /* continue normal handling for a critical exception... */1: mfspr r4,SPRN_DBSR addi r3,r1,STACK_FRAME_OVERHEAD EXC_XFER_TEMPLATE(DebugException, 0x2002, \ (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) /* here it looks like we got an inappropriate debug exception. */2: rlwinm r9,r9,0,~MSR_DE /* clear DE in the CSRR1 value */ mtspr SPRN_DBSR,r10 /* clear the IC/BT debug intr status */ /* restore state and get out */ lwz r10,_CCR(r11) lwz r0,GPR0(r11) lwz r1,GPR1(r11) mtcrf 0x80,r10 mtspr CSRR0,r12 mtspr CSRR1,r9 lwz r9,GPR9(r11) mtspr SPRG2,r8; /* SPRG2 only used in criticals */ lis r8,crit_save@ha; lwz r10,crit_r10@l(r8) lwz r11,crit_r11@l(r8) mfspr r8,SPRG2 rfci b ./* * Local functions */ /* * Data TLB exceptions will bail out to this point * if they can't resolve the lightweight TLB fault. */data_access: NORMAL_EXCEPTION_PROLOG mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ stw r5,_ESR(r11) mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ EXC_XFER_EE_LITE(0x0300, handle_page_fault)/* * Both the instruction and data TLB miss get to this * point to load the TLB. * r10 - EA of fault * r11 - available to use * r12 - Pointer to the 64-bit PTE * r13 - available to use * MMUCR - loaded with proper value when we get here * Upon exit, we reload everything and RFI. */finish_tlb_load: /* * We set execute, because we don't have the granularity to * properly set this at the page level (Linux problem). * If shared is set, we cause a zero PID->TID load. * Many of these bits are software only. Bits we don't set * here we (properly should) assume have the appropriate value. */ /* Load the next available TLB index */ lis r13, tlb_44x_index@ha lwz r13, tlb_44x_index@l(r13) /* Load the TLB high watermark */ lis r11, tlb_44x_hwater@ha lwz r11, tlb_44x_hwater@l(r11) /* Increment, rollover, and store TLB index */ addi r13, r13, 1 cmpw 0, r13, r11 /* reserve entries */ ble 7f li r13, 07: /* Store the next available TLB index */ lis r11, tlb_44x_index@ha stw r13, tlb_44x_index@l(r11) lwz r11, 0(r12) /* Get MS word of PTE */ lwz r12, 4(r12) /* Get LS word of PTE */ rlwimi r11, r12, 0, 0 , 19 /* Insert RPN */ tlbwe r11, r13, PPC44x_TLB_XLAT /* Write XLAT */ /* * Create PAGEID. This is the faulting address, * page size, and valid flag. */ li r11, PPC44x_TLB_VALID | PPC44x_TLB_4K rlwimi r10, r11, 0, 20, 31 /* Insert valid and page size */ tlbwe r10, r13, PPC44x_TLB_PAGEID /* Write PAGEID */ li r10, PPC44x_TLB_SR@l /* Set SR */ rlwimi r10, r12, 0, 30, 30 /* Set SW = _PAGE_RW */ rlwimi r10, r12, 29, 29, 29 /* SX = _PAGE_HWEXEC */ rlwimi r10, r12, 29, 28, 28 /* UR = _PAGE_USER */ rlwimi r11, r12, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ and r11, r12, r11 /* HWEXEC & USER */ rlwimi r10, r11, 0, 26, 26 /* UX = HWEXEC & USER */ rlwimi r12, r10, 0, 26, 31 /* Insert static perms */ rlwinm r12, r12, 0, 20, 15 /* Clear U0-U3 */ tlbwe r12, r13, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. */ mfspr r11, SPRG7R mtcr r11 mfspr r13, SPRG5R mfspr r12, SPRG4R mfspr r11, SPRG1 mfspr r10, SPRG0 rfi /* Force context change *//* * Global functions *//* * extern void giveup_altivec(struct task_struct *prev) * * The 44x core does not have an AltiVec unit. */_GLOBAL(giveup_altivec) blr/* * extern void giveup_fpu(struct task_struct *prev) * * The 44x core does not have an FPU. */_GLOBAL(giveup_fpu) blr/* * extern void abort(void) * * At present, this routine just applies a system reset. */_GLOBAL(abort) mfspr r13,SPRN_DBCR0 oris r13,r13,DBCR0_RST_SYSTEM@h mtspr SPRN_DBCR0,r13_GLOBAL(set_context)#ifdef CONFIG_BDI_SWITCH /* Context switch the PTE pointer for the Abatron BDI2000. * The PGDIR is the second parameter. */ lis r5, abatron_pteptrs@h ori r5, r5, abatron_pteptrs@l stw r4, 0x4(r5)#endif mtspr SPRN_PID,r3 isync /* Force context change */ blr/* * We put a few things here that have to be page-aligned. This stuff * goes at the beginning of the data segment, which is page-aligned. */ .data_GLOBAL(sdata)_GLOBAL(empty_zero_page) .space 4096/* * To support >32-bit physical addresses, we use an 8KB pgdir. */_GLOBAL(swapper_pg_dir) .space 8192 .section .bss/* Stack for handling critical exceptions from kernel mode */critical_stack_bottom: .space 4096critical_stack_top: .previous/* Stack for handling machine check exceptions from kernel mode */mcheck_stack_bottom: .space 4096mcheck_stack_top: .previous/* * This area is used for temporarily saving registers during the * critical and machine check exception prologs. It must always * follow the page aligned allocations, so it starts on a page * boundary, ensuring that all crit_save areas are in a single * page. *//* crit_save */_GLOBAL(crit_save) .space 4_GLOBAL(crit_r10) .space 4_GLOBAL(crit_r11) .space 4_GLOBAL(crit_sprg0) .space 4_GLOBAL(crit_sprg1) .space 4_GLOBAL(crit_sprg4) .space 4_GLOBAL(crit_sprg5) .space 4_GLOBAL(crit_sprg7) .space 4_GLOBAL(crit_pid) .space 4_GLOBAL(crit_srr0) .space 4_GLOBAL(crit_srr1) .space 4/* mcheck_save */_GLOBAL(mcheck_save) .space 4_GLOBAL(mcheck_r10) .space 4_GLOBAL(mcheck_r11) .space 4_GLOBAL(mcheck_sprg0) .space 4_GLOBAL(mcheck_sprg1) .space 4_GLOBAL(mcheck_sprg4) .space 4_GLOBAL(mcheck_sprg5) .space 4_GLOBAL(mcheck_sprg7) .space 4_GLOBAL(mcheck_pid) .space 4_GLOBAL(mcheck_srr0) .space 4_GLOBAL(mcheck_srr1) .space 4_GLOBAL(mcheck_csrr0) .space 4_GLOBAL(mcheck_csrr1) .space 4/* * This space gets a copy of optional info passed to us by the bootstrap * which is used to pass parameters into the kernel like root=/dev/sda1, etc. */_GLOBAL(cmd_line) .space 512/* * Room for two PTE pointers, usually the kernel and current user pointers * to their respective root page table. */abatron_pteptrs: .space 8
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?