head_44x.s
来自「linux-2.4.29操作系统的源码」· S 代码 · 共 1,120 行 · 第 1/3 页
S
1,120 行
SAVE_GPR(7, r21); /* Save r7 on the stack */#define STND_EXCEPTION_PROLOG \ COMMON_PROLOG; \ mfspr r22,SPRN_SRR0; /* Faulting instruction address */\ lis r20,MSR_WE@h; \ mfspr r23,SPRN_SRR1; /* MSR at the time of fault */\ andc r23,r23,r20; /* disable processor wait state */\ COMMON_EPILOG;#define CRIT_EXCEPTION_PROLOG \ COMMON_PROLOG; \ mfspr r22,SPRN_CSRR0; /* Faulting instruction address */\ lis r20,MSR_WE@h; \ mfspr r23,SPRN_CSRR1; /* MSR at the time of fault */\ andc r23,r23,r20; /* disable processor wait state */\ COMMON_EPILOG;#define START_EXCEPTION(label) \ .align 5; \label:#define FINISH_EXCEPTION(n, func) \ bl transfer_to_handler; \ .long func; \ .long ret_from_except; \ .long n#define STND_EXCEPTION(n, label, func) \ START_EXCEPTION(label) \ STND_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r7,STND_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(n, func)#define CRIT_EXCEPTION(n, label, func) \ START_EXCEPTION(label) \ CRIT_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ li r7,CRIT_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(n, func)interrupt_base: /* Critical Input Interrupt */ CRIT_EXCEPTION(0x100, CriticalInput,UnknownException); /* Machine Check Interrupt */ /* TODO: provide bus error register status */ START_EXCEPTION(MachineCheck) COMMON_PROLOG; mfspr r22,__SPRN_MCSRR0 /* Faulting instruction address */ lis r20,MSR_WE@h mfspr r23,__SPRN_MCSRR1 /* MSR at the time of fault */ andc r23,r23,r20 /* disable processor wait state */ COMMON_EPILOG;#ifdef CONFIG_440A lis r20,MCSR_MCS@h mfspr r4,SPRN_MCSR /* We may want to access original MCSR as arg2 in the future. --ebs */ mtspr SPRN_MCSR,r20 /* Clear Machine Check Summary field */#endif mfspr r5,SPRN_ESR /* Grab the ESR, save it */ stw r5,_ESR(r21) addi r3,r1,STACK_FRAME_OVERHEAD li r7,MCHK_EXC li r20,MSR_KERNEL FINISH_EXCEPTION(0x200, MachineCheckException) /* Data Storage Interrupt */ START_EXCEPTION(DataStorage) mtspr SPRG0, r20 /* Save some working registers */ mtspr SPRG1, r21 mtspr SPRG4W, r22 mtspr SPRG5W, r23 mtspr SPRG6W, r24 mfcr r21 mtspr SPRG7W, r21 /* * Check if it was a store fault, if not then bail * because a user tried to access a kernel or * read-protected page. Otherwise, get the * offending address and handle it. */ mfspr r20, SPRN_ESR andis. r20, r20, ESR_DST@h beq 2f 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 mfspr r22,SPRN_MMUCR /* Set TID to 0 */ li r23,PPC44x_MMUCR_TID@l andc r22,r22,r23 mtspr SPRN_MMUCR,r22 b 4f /* Get the PGD for the current thread */3: mfspr r21,SPRG3 lwz r21,PGDIR(r21) /* Load MMUCR with our PID and STS=<current TS> */ mfspr r22,SPRN_MMUCR /* Get MMUCR */ lis r23,PPC44x_MMUCR_STS@h ori r23,r23,PPC44x_MMUCR_TID@l /* Create mask */ andc r22,r22,r23 /* Clear out TID/STS bits */ mfspr r23,SPRN_PID /* Get PID */ or r22,r22,r23 /* Set TID bits */ mfspr r24,SPRN_SRR1 /* Get SRR1 */ andi. r24,r24,MSR_IS@l /* TS=1? */ beq 4f /* If not, leave STS=0 */ oris r22,r22,PPC44x_MMUCR_STS@h /* Set STS=1 */ mtspr SPRN_MMUCR,r224: rlwinm r22, r20, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r21, r22, r21 /* Get pgd/pmd entry */ rlwinm. r22, r21, 0, 0, 20 /* Extract pt base address */ beq 2f /* Bail if no table */ rlwimi r22, r20, 23, 20, 28 /* Compute pte address */ lwz r21, 4(r22) /* Get pte entry */ andi. r23, r21, _PAGE_RW /* Is it writeable? */ beq 2f /* Bail if not */ /* Update 'changed'. */ ori r21, r21, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE stw r21, 4(r22) /* Update Linux page table */ /* FIXME: Staticly setting some permissions */ li r23, 0x003f /* Set UX,UW,UR,SX,SW,SR */ andi. r21,r21,0xffff /* Clear MS 16 bits */ /* FIXME: Force attributes */ ori r21,r21, 0x0100 /* Set G */ /* FIXME: Already set in PTE */ rlwimi r21,r23,0,26,31 /* Insert static perms */ lis r23,0xffff ori r23,r23,0x0fff /* Set U0-U3 mask */ and r21,r21,r23 /* Clear U0-U3 */ /* find the TLB index that caused the fault. It has to be here. */ tlbsx r24, 0, r20 tlbwe r21, r24, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. */ mfspr r21, SPRG7R mtcr r21 mfspr r24, SPRG6R mfspr r23, SPRG5R mfspr r22, SPRG4R mfspr r21, SPRG1 mfspr r20, SPRG0 rfi /* Force context change */2: /* * The bailout. Restore registers to pre-exception conditions * and call the heavyweights to help us out. */ mfspr r21, SPRG7R mtcr r21 mfspr r24, SPRG6R mfspr r23, SPRG5R mfspr r22, SPRG4R mfspr r21, SPRG1 mfspr r20, SPRG0 b data_access /* Instruction Storage Interrupt */ START_EXCEPTION(InstructionStorage) STND_EXCEPTION_PROLOG mfspr r5,SPRN_ESR /* Grab the ESR, save it */ stw r5,_ESR(r21) mr r4,r22 /* Pass SRR0 as arg2 */ li r5,0 /* Pass zero as arg3 */ 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(0x400, do_page_fault)/* do_page_fault(regs, SRR0, SRR1) */ /* External Input Interrupt */ START_EXCEPTION(ExternalInput) 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 .long 0x500 /* Alignment Interrupt */ START_EXCEPTION(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(0x600, AlignmentException) /* Program Interrupt */ START_EXCEPTION(Program) 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(0x700, ProgramCheckException) /* Floating Point Unavailable Interrupt */ STND_EXCEPTION(0x2010, FloatingPointUnavailable,UnknownException); /* System Call Interrupt */ START_EXCEPTION(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(0xc00, DoSyscall) /* Auxillary Processor Unavailable */ STND_EXCEPTION(0x2020, AuxillaryProcessorUnavailable,UnknownException); /* Decrementer Interrupt */ START_EXCEPTION(Decrementer) STND_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 li r7,STND_EXC li r20,MSR_KERNEL bl transfer_to_handler_GLOBAL(timer_interrupt_intercept) .long timer_interrupt .long ret_from_intercept .long 0x1000 /* Fixed Internal Timer Interrupt */ /* TODO: Add FIT support */ STND_EXCEPTION(0x1010, FixedIntervalTimer,UnknownException); /* Watchdog Timer Interrupt */ /* TODO: Add watchdog support */ CRIT_EXCEPTION(0x1020, WatchdogTimer,UnknownException); /* Data TLB Error Interrupt */ START_EXCEPTION(DataTLBError) mtspr SPRG0, r20 /* Save some working registers */ mtspr SPRG1, r21 mtspr SPRG4W, r22 mtspr SPRG5W, r23 mtspr SPRG6W, r24 mfcr r21 mtspr SPRG7W, r21 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 mfspr r22,SPRN_MMUCR /* Set TID to 0 */ li r23,PPC44x_MMUCR_TID@l andc r22,r22,r23 mtspr SPRN_MMUCR,r22 b 4f /* Get the PGD for the current thread */3: mfspr r21,SPRG3 lwz r21,PGDIR(r21) /* Load PID into MMUCR TID */ li r23,PPC44x_MMUCR_TID@l /* Create mask */ andc r22,r22,r23 /* Clear out TID/STS bits */ mfspr r23,SPRN_PID /* Get PID */ or r22,r22,r23 mtspr SPRN_MMUCR,r224: rlwinm r22, r20, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r21, r22, r21 /* Get pgd/pmd entry */ rlwinm. r22, r21, 0, 0, 20 /* Extract pt base address */ beq 2f /* Bail if no table */ rlwimi r22, r20, 23, 20, 28 /* Compute pte address */ lwz r21, 4(r22) /* Get pte entry */ andi. r23, r21, _PAGE_PRESENT /* Is the page present? */ beq 2f /* Bail if not present */ ori r21, r21, _PAGE_ACCESSED stw r21, 4(r22) /* 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 r21, SPRG7R mtcr r21 mfspr r24, SPRG6R mfspr r23, SPRG5R mfspr r22, SPRG4R mfspr r21, SPRG1 mfspr r20, 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, r20 /* Save some working registers */ mtspr SPRG1, r21 mtspr SPRG4W, r22 mtspr SPRG5W, r23 mtspr SPRG6W, r24 mfcr r21 mtspr SPRG7W, r21 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 mfspr r22,SPRN_MMUCR /* Set TID to 0 */ li r23,PPC44x_MMUCR_TID@l andc r22,r22,r23 mtspr SPRN_MMUCR,r22 b 4f /* Get the PGD for the current thread */3: mfspr r21,SPRG3 lwz r21,PGDIR(r21)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?