head_4xx.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 1,123 行 · 第 1/3 页
S
1,123 行
/* 0x0500 - External Interrupt Exception*/ START_EXCEPTION(0x0500, HardwareInterrupt) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL li r4,0 bl transfer_to_handler_GLOBAL(do_IRQ_intercept) .long do_IRQ .long ret_from_intercept/* 0x0600 - Alignment Exception*/ START_EXCEPTION(0x0600, Alignment) STND_EXCEPTION_PROLOG mfspr r4,SPRN_DEAR /* Grab the DEAR and save it */ stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */ FINISH_EXCEPTION(AlignmentException)/* 0x0700 - Program Exception*/ START_EXCEPTION(0x0700, ProgramCheck) STND_EXCEPTION_PROLOG mfspr r4,SPRN_ESR /* Grab the ESR, save it */ stw r4,_ESR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */ FINISH_EXCEPTION(ProgramCheckException)/* I'm stealing this unused vector location to build a standard exception * frame for Data TLB Access errors. The other Data TLB exceptions will bail * out to this point if they can't resolve the lightweight TLB fault. */ START_EXCEPTION(0x0800, DataAccess) STND_EXCEPTION_PROLOG mfspr r5,SPRN_ESR /* Grab the ESR, save it, pass arg3 */ stw r5,_ESR(r21) mfspr r4,SPRN_DEAR /* Grab the DEAR, save it, pass arg2 */ stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */ FINISH_EXCEPTION(do_page_fault) /* do_page_fault(regs, ESR, DEAR) */ STND_EXCEPTION(0x0900, Trap_09, UnknownException) STND_EXCEPTION(0x0A00, Trap_0A, UnknownException) STND_EXCEPTION(0x0B00, Trap_0B, UnknownException)/* 0x0C00 - System Call Exception*/ START_EXCEPTION(0x0C00, SystemCall) STND_EXCEPTION_PROLOG stw r3,ORIG_GPR3(r21) li r7,STND_EXC li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 /* Copy EE bit from the saved MSR */ FINISH_EXCEPTION(DoSyscall) STND_EXCEPTION(0x0D00, Trap_0D, UnknownException) STND_EXCEPTION(0x0E00, Trap_0E, UnknownException) STND_EXCEPTION(0x0F00, Trap_0F, UnknownException)/* 0x1000 - Programmable Interval Timer (PIT) Exception*/ START_EXCEPTION(0x1000, Decrementer) STND_EXCEPTION_PROLOG lis r0,TSR_PIS@h /* Set-up the PIT exception mask */ mtspr SPRN_TSR,r0 /* Clear the PIT exception */ addi r3,r1,STACK_FRAME_OVERHEAD li r7,STND_EXC li r20,MSR_KERNEL bl transfer_to_handler_GLOBAL(timer_interrupt_intercept) .long timer_interrupt .long ret_from_intercept#if 0/* NOTE: * FIT and WDT handlers are not implemented yet. *//* 0x1010 - Fixed Interval Timer (FIT) Exception*/ STND_EXCEPTION(0x1010, FITException, UnknownException)/* 0x1020 - Watchdog Timer (WDT) Exception*/ CRIT_EXCEPTION(0x1020, WDTException, UnknownException)#endif/* 0x1100 - Data TLB Miss Exception * As the name implies, translation is not in the MMU, so search the * page tables and fix it. The only purpose of this function is to * load TLB entries from the page table if they exist. */ START_EXCEPTION(0x1100, DTLBMiss) mtspr SPRG0, r20 /* Save some working registers */ mtspr SPRG1, r21#ifdef CONFIG_403GCX stw r22, 0(r0) stw r23, 4(r0) mfcr r21 mfspr r22, SPRN_PID stw r21, 8(r0) stw r22, 12(r0)#else mtspr SPRG4, r22 mtspr SPRG5, r23 mfcr r21 mfspr r22, SPRN_PID mtspr SPRG7, r21 mtspr SPRG6, r22#endif mfspr r20, SPRN_DEAR /* Get faulting address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ andis. r21, r20, 0x8000 beq 3f lis r21, swapper_pg_dir@h ori r21, r21, swapper_pg_dir@l li r23, 0 mtspr SPRN_PID, r23 /* TLB will have 0 TID */ b 4f /* Get the PGD for the current thread. */3: mfspr r21,SPRG3 lwz r21,PGDIR(r21)4: tophys(r21, r21) rlwimi r21, r20, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ lwz r21, 0(r21) /* Get L1 entry */ rlwinm. r22, r21, 0, 0, 19 /* Extract L2 (pte) base address */ beq 2f /* Bail if no table */ tophys(r22, r22) rlwimi r22, r20, 22, 20, 29 /* Compute PTE address */ lwz r21, 0(r22) /* Get Linux PTE */ andi. r23, r21, _PAGE_PRESENT beq 2f ori r21, r21, _PAGE_ACCESSED stw r21, 0(r22) /* Most of the Linux PTE is ready to load into the TLB LO. * We set ZSEL, where only the LS-bit determines user access. * 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. */ li r22, 0x0ce2 andc r21, r21, r22 /* Make sure 20, 21 are zero */ b finish_tlb_load2: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. */#ifdef CONFIG_403GCX lwz r22, 12(r0) lwz r21, 8(r0) mtspr SPRN_PID, r22 mtcr r21 lwz r23, 4(r0) lwz r22, 0(r0)#else mfspr r22, SPRG6 mfspr r21, SPRG7 mtspr SPRN_PID, r22 mtcr r21 mfspr r23, SPRG5 mfspr r22, SPRG4#endif mfspr r21, SPRG1 mfspr r20, SPRG0 b DataAccess/* 0x1200 - Instruction TLB Miss Exception * Nearly the same as above, except we get our information from different * registers and bailout to a different point. */ START_EXCEPTION(0x1200, ITLBMiss) mtspr SPRG0, r20 /* Save some working registers */ mtspr SPRG1, r21#ifdef CONFIG_403GCX stw r22, 0(r0) stw r23, 4(r0) mfcr r21 mfspr r22, SPRN_PID stw r21, 8(r0) stw r22, 12(r0)#else mtspr SPRG4, r22 mtspr SPRG5, r23 mfcr r21 mfspr r22, SPRN_PID mtspr SPRG7, r21 mtspr SPRG6, r22#endif mfspr r20, SRR0 /* Get faulting address */ /* If we are faulting a kernel address, we have to use the * kernel page tables. */ andis. r21, r20, 0x8000 beq 3f lis r21, swapper_pg_dir@h ori r21, r21, swapper_pg_dir@l li r23, 0 mtspr SPRN_PID, r23 /* TLB will have 0 TID */ b 4f /* Get the PGD for the current thread. */3: mfspr r21,SPRG3 lwz r21,PGDIR(r21)4: tophys(r21, r21) rlwimi r21, r20, 12, 20, 29 /* Create L1 (pgdir/pmd) address */ lwz r21, 0(r21) /* Get L1 entry */ rlwinm. r22, r21, 0, 0, 19 /* Extract L2 (pte) base address */ beq 2f /* Bail if no table */ tophys(r22, r22) rlwimi r22, r20, 22, 20, 29 /* Compute PTE address */ lwz r21, 0(r22) /* Get Linux PTE */ andi. r23, r21, _PAGE_PRESENT beq 2f ori r21, r21, _PAGE_ACCESSED stw r21, 0(r22) /* Most of the Linux PTE is ready to load into the TLB LO. * We set ZSEL, where only the LS-bit determines user access. * 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. */ li r22, 0x0ce2 andc r21, r21, r22 /* Make sure 20, 21 are zero */ b finish_tlb_load2: /* The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. */#ifdef CONFIG_403GCX lwz r22, 12(r0) lwz r21, 8(r0) mtspr SPRN_PID, r22 mtcr r21 lwz r23, 4(r0) lwz r22, 0(r0)#else mfspr r22, SPRG6 mfspr r21, SPRG7 mtspr SPRN_PID, r22 mtcr r21 mfspr r23, SPRG5 mfspr r22, SPRG4#endif mfspr r21, SPRG1 mfspr r20, SPRG0 b InstructionAccess STND_EXCEPTION(0x1300, Trap_13, UnknownException) STND_EXCEPTION(0x1400, Trap_14, UnknownException) STND_EXCEPTION(0x1500, Trap_15, UnknownException) STND_EXCEPTION(0x1600, Trap_16, UnknownException)#ifdef CONFIG_IBM405_ERR51 /* 405GP errata 51 */ START_EXCEPTION(0x1700, Trap_17) b DTLBMiss#else STND_EXCEPTION(0x1700, Trap_17, UnknownException)#endif STND_EXCEPTION(0x1800, Trap_18, UnknownException) STND_EXCEPTION(0x1900, Trap_19, UnknownException) STND_EXCEPTION(0x1A00, Trap_1A, UnknownException) STND_EXCEPTION(0x1B00, Trap_1B, UnknownException) STND_EXCEPTION(0x1C00, Trap_1C, UnknownException) STND_EXCEPTION(0x1D00, Trap_1D, UnknownException) STND_EXCEPTION(0x1E00, Trap_1E, UnknownException) STND_EXCEPTION(0x1F00, Trap_1F, UnknownException)/* 0x2000 - Debug Exception*/ START_EXCEPTION(0x2000, DebugTrap) b check_single_step_in_exceptionret_to_debug_exception: CRIT_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD li r7,CRIT_EXC; li r20,MSR_KERNEL FINISH_EXCEPTION(DebugException)/* Make sure the final interrupt handler has not spilled past the * end of its allotted space. */ .=0x2100/* 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 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 handlers_ MSR (the debug trap is * a critical exception, so we are using SPRN_SRR3 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. */check_single_step_in_exception: /* This first instruction was already executed by the exception * handler and must be the first instruction of every exception * handler. */ mtspr SPRN_SPRG0,r20 /* Save some working registers... */ mtspr SPRN_SPRG1,r21 mfcr r20 /* ..and the cr because we change it */ mfspr r21,SPRN_SRR3 /* MSR at the time of fault */ andi. r21,r21,MSR_PR bne+ 2f /* trapped from problem state */ mfspr r21,SPRN_SRR2 /* Faulting instruction address */ cmplwi r21,0x2100 bgt+ 2f /* address above exception vectors */ lis r21,DBSR_IC@h /* Remove the trap status */ mtspr SPRN_DBSR,r21 mfspr r21,SPRN_SRR3 rlwinm r21,r21,0,23,21 /* clear MSR_DE */ mtspr SPRN_SRR3, r21 /* restore MSR at rcfi without DE */ mtcrf 0xff,r20 /* restore registers */ mfspr r21,SPRN_SPRG1 mfspr r20,SPRN_SPRG0 sync rfci /* return to the exception handler */ b . /* prevent prefetch past rfci */2: mtcrf 0xff,r20 /* restore registers */ mfspr r21,SPRN_SPRG1 mfspr r20,SPRN_SPRG0 b ret_to_debug_exception
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?