📄 head_64.s
字号:
b .do_hash_page /* Try to handle as hpte fault */ .align 7 .globl instruction_access_commoninstruction_access_common: EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) ld r3,_NIP(r1) andis. r4,r12,0x5820 li r5,0x400 b .do_hash_page /* Try to handle as hpte fault *//* * Here is the common SLB miss user that is used when going to virtual * mode for SLB misses, that is currently not used */#ifdef __DISABLED__ .align 7 .globl slb_miss_user_commonslb_miss_user_common: mflr r10 std r3,PACA_EXGEN+EX_DAR(r13) stw r9,PACA_EXGEN+EX_CCR(r13) std r10,PACA_EXGEN+EX_LR(r13) std r11,PACA_EXGEN+EX_SRR0(r13) bl .slb_allocate_user ld r10,PACA_EXGEN+EX_LR(r13) ld r3,PACA_EXGEN+EX_R3(r13) lwz r9,PACA_EXGEN+EX_CCR(r13) ld r11,PACA_EXGEN+EX_SRR0(r13) mtlr r10 beq- slb_miss_fault andi. r10,r12,MSR_RI /* check for unrecoverable exception */ beq- unrecov_user_slb mfmsr r10.machine push.machine "power4" mtcrf 0x80,r9.machine pop clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ mtmsrd r10,1 mtspr SRR0,r11 mtspr SRR1,r12 ld r9,PACA_EXGEN+EX_R9(r13) ld r10,PACA_EXGEN+EX_R10(r13) ld r11,PACA_EXGEN+EX_R11(r13) ld r12,PACA_EXGEN+EX_R12(r13) ld r13,PACA_EXGEN+EX_R13(r13) rfid b .slb_miss_fault: EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) ld r4,PACA_EXGEN+EX_DAR(r13) li r5,0 std r4,_DAR(r1) std r5,_DSISR(r1) b handle_page_faultunrecov_user_slb: EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) DISABLE_INTS bl .save_nvgprs1: addi r3,r1,STACK_FRAME_OVERHEAD bl .unrecoverable_exception b 1b#endif /* __DISABLED__ *//* * r13 points to the PACA, r9 contains the saved CR, * r12 contain the saved SRR1, SRR0 is still ready for return * r3 has the faulting address * r9 - r13 are saved in paca->exslb. * r3 is saved in paca->slb_r3 * We assume we aren't going to take any exceptions during this procedure. */_GLOBAL(slb_miss_realmode) mflr r10 stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ bl .slb_allocate_realmode /* All done -- return from exception. */ ld r10,PACA_EXSLB+EX_LR(r13) ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */#ifdef CONFIG_PPC_ISERIESBEGIN_FW_FTR_SECTION ld r11,PACALPPACAPTR(r13) ld r11,LPPACASRR0(r11) /* get SRR0 value */END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)#endif /* CONFIG_PPC_ISERIES */ mtlr r10 andi. r10,r12,MSR_RI /* check for unrecoverable exception */ beq- unrecov_slb.machine push.machine "power4" mtcrf 0x80,r9 mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */.machine pop#ifdef CONFIG_PPC_ISERIESBEGIN_FW_FTR_SECTION mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)#endif /* CONFIG_PPC_ISERIES */ ld r9,PACA_EXSLB+EX_R9(r13) ld r10,PACA_EXSLB+EX_R10(r13) ld r11,PACA_EXSLB+EX_R11(r13) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid b . /* prevent speculative execution */unrecov_slb: EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) DISABLE_INTS bl .save_nvgprs1: addi r3,r1,STACK_FRAME_OVERHEAD bl .unrecoverable_exception b 1b .align 7 .globl hardware_interrupt_common .globl hardware_interrupt_entryhardware_interrupt_common: EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) FINISH_NAPhardware_interrupt_entry: DISABLE_INTSBEGIN_FTR_SECTION bl .ppc64_runlatch_onEND_FTR_SECTION_IFSET(CPU_FTR_CTRL) addi r3,r1,STACK_FRAME_OVERHEAD bl .do_IRQ b .ret_from_except_lite#ifdef CONFIG_PPC_970_NAPpower4_fixup_nap: andc r9,r9,r10 std r9,TI_LOCAL_FLAGS(r11) ld r10,_LINK(r1) /* make idle task do the */ std r10,_NIP(r1) /* equivalent of a blr */ blr#endif .align 7 .globl alignment_commonalignment_common: mfspr r10,SPRN_DAR std r10,PACA_EXGEN+EX_DAR(r13) mfspr r10,SPRN_DSISR stw r10,PACA_EXGEN+EX_DSISR(r13) EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN) ld r3,PACA_EXGEN+EX_DAR(r13) lwz r4,PACA_EXGEN+EX_DSISR(r13) std r3,_DAR(r1) std r4,_DSISR(r1) bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ENABLE_INTS bl .alignment_exception b .ret_from_except .align 7 .globl program_check_commonprogram_check_common: EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ENABLE_INTS bl .program_check_exception b .ret_from_except .align 7 .globl fp_unavailable_commonfp_unavailable_common: EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) bne 1f /* if from user, just load it up */ bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ENABLE_INTS bl .kernel_fp_unavailable_exception BUG_OPCODE1: b .load_up_fpu .align 7 .globl altivec_unavailable_commonaltivec_unavailable_common: EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN)#ifdef CONFIG_ALTIVECBEGIN_FTR_SECTION bne .load_up_altivec /* if from user, just load it up */END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)#endif bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ENABLE_INTS bl .altivec_unavailable_exception b .ret_from_except#ifdef CONFIG_ALTIVEC/* * load_up_altivec(unused, unused, tsk) * Disable VMX for the task which had it previously, * and save its vector registers in its thread_struct. * Enables the VMX for use in the kernel on return. * On SMP we know the VMX is free, since we give it up every * switch (ie, no lazy save of the vector registers). * On entry: r13 == 'current' && last_task_used_altivec != 'current' */_STATIC(load_up_altivec) mfmsr r5 /* grab the current MSR */ oris r5,r5,MSR_VEC@h mtmsrd r5 /* enable use of VMX now */ isync/* * For SMP, we don't do lazy VMX switching because it just gets too * horrendously complex, especially when a task switches from one CPU * to another. Instead we call giveup_altvec in switch_to. * VRSAVE isn't dealt with here, that is done in the normal context * switch code. Note that we could rely on vrsave value to eventually * avoid saving all of the VREGs here... */#ifndef CONFIG_SMP ld r3,last_task_used_altivec@got(r2) ld r4,0(r3) cmpdi 0,r4,0 beq 1f /* Save VMX state to last_task_used_altivec's THREAD struct */ addi r4,r4,THREAD SAVE_32VRS(0,r5,r4) mfvscr vr0 li r10,THREAD_VSCR stvx vr0,r10,r4 /* Disable VMX for last_task_used_altivec */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) lis r6,MSR_VEC@h andc r4,r4,r6 std r4,_MSR-STACK_FRAME_OVERHEAD(r5)1:#endif /* CONFIG_SMP */ /* Hack: if we get an altivec unavailable trap with VRSAVE * set to all zeros, we assume this is a broken application * that fails to set it properly, and thus we switch it to * all 1's */ mfspr r4,SPRN_VRSAVE cmpdi 0,r4,0 bne+ 1f li r4,-1 mtspr SPRN_VRSAVE,r41: /* enable use of VMX after return */ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ oris r12,r12,MSR_VEC@h std r12,_MSR(r1) li r4,1 li r10,THREAD_VSCR stw r4,THREAD_USED_VR(r5) lvx vr0,r10,r5 mtvscr vr0 REST_32VRS(0,r4,r5)#ifndef CONFIG_SMP /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ std r4,0(r3)#endif /* CONFIG_SMP */ /* restore registers and return */ b fast_exception_return#endif /* CONFIG_ALTIVEC *//* * Hash table stuff */ .align 7_GLOBAL(do_hash_page) std r3,_DAR(r1) std r4,_DSISR(r1) andis. r0,r4,0xa450 /* weird error? */ bne- handle_page_fault /* if not, try to insert a HPTE */BEGIN_FTR_SECTION andis. r0,r4,0x0020 /* Is it a segment table fault? */ bne- do_ste_alloc /* If so handle it */END_FTR_SECTION_IFCLR(CPU_FTR_SLB) /* * We need to set the _PAGE_USER bit if MSR_PR is set or if we are * accessing a userspace segment (even from the kernel). We assume * kernel addresses always have the high bit set. */ rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ rotldi r0,r3,15 /* Move high bit into MSR_PR posn */ orc r0,r12,r0 /* MSR_PR | ~high_bit */ rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ ori r4,r4,1 /* add _PAGE_PRESENT */ rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */ /* * On iSeries, we soft-disable interrupts here, then * hard-enable interrupts so that the hash_page code can spin on * the hash_table_lock without problems on a shared processor. */ DISABLE_INTS /* * r3 contains the faulting address * r4 contains the required access permissions * r5 contains the trap number * * at return r3 = 0 for success */ bl .hash_page /* build HPTE if possible */ cmpdi r3,0 /* see if hash_page succeeded */#ifdef DO_SOFT_DISABLEBEGIN_FW_FTR_SECTION /* * If we had interrupts soft-enabled at the point where the * DSI/ISI occurred, and an interrupt came in during hash_page, * handle it now. * We jump to ret_from_except_lite rather than fast_exception_return * because ret_from_except_lite will check for and handle pending * interrupts if necessary. */ beq 13fEND_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)#endifBEGIN_FW_FTR_SECTION /* * Here we have interrupts hard-disabled, so it is sufficient * to restore paca->{soft,hard}_enable and get out. */ beq fast_exc_return_irq /* Return from exception on success */END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) /* For a hash failure, we don't bother re-enabling interrupts */ ble- 12f /* * hash_page couldn't handle it, set soft interrupt enable back * to what it was before the trap. Note that .local_irq_restore * handles any interrupts pending at this point. */ ld r3,SOFTE(r1) bl .local_irq_restore b 11f/* Here we have a page fault that hash_page can't handle. */handle_page_fault: ENABLE_INTS11: ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD bl .do_page_fault cmpdi r3,0 beq+ 13f bl .save_nvgprs mr r5,r3 addi r3,r1,STACK_FRAME_OVERHEAD lwz r4,_DAR(r1) bl .bad_page_fault b .ret_from_except13: b .ret_from_except_lite/* We have a page fault that hash_page could handle but HV refused * the PTE insertion */12: bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD ld r4,_DAR(r1) bl .low_hash_fault b .ret_from_except /* here we have a segment miss */do_ste_alloc: bl .ste_allocate /* try to insert stab entry */ cmpdi r3,0 bne- handle_page_fault b fast_exception_return/* * r13 points to the PACA, r9 contains the saved CR, * r11 and r12 contain the saved SRR0 and SRR1. * r9 - r13 are saved in paca->exslb. * We assume we aren't going to take any exceptions during this procedure. * We assume (DAR >> 60) == 0xc. */ .align 7_GLOBAL(do_stab_bolted) stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ /* Hash to the primary group */ ld r10,PACASTABVIRT(r13) mfspr r11,SPRN_DAR srdi r11,r11,28 rldimi r10,r11,7,52 /* r10 = first ste of the group */ /* Calculate VSID */ /* This is a kernel address, so protovsid = ESID */ ASM_VSID_SCRAMBLE(r11, r9, 256M) rldic r9,r11,12,16 /* r9 = vsid << 12 */ /* Search the primary group for a free entry */1: ld r11,0(r10) /* Test valid bit of the current ste */ andi. r11,r11,0x80 beq 2f addi r10,r10,16 andi. r11,r10,0x70 bne 1b /* Stick for only searching the primary group for now. */ /* At least for now, we use a very simple random castout scheme */ /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ mftb r11 rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ ori r11,r11,0x10 /* r10 currently points to an ste one past the group of interest */ /* make it point to the randomly selected entry */ subi r10,r10,128 or r10,r10,r11 /* r10 is the entry to invalidate */ isync /* mark the entry invalid */ ld r11,0(r10) rldicl r11,r11,56,1 /* clear the valid bit */ rotldi r11,r11,8 std r11,0(r10) sync clrrdi r11,r11,28 /* Get the esid part of the ste */ slbie r112: std r9,8(r10) /* Store the vsid part of the ste */ eieio mfspr r11,SPRN_DAR /* Get the new esid */ clrrdi r11,r11,28 /* Permits a full 32b of ESID */ ori r11,r11,0x90 /* Turn on valid and kp */ std r11,0(r10) /* Put new entry back into the stab */ sync /* All done -- return from exception. */ lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ andi. r10,r12,MSR_RI beq- unrecov_slb mtcrf 0x80,r9 /* restore CR */ mfmsr r10 clrrdi r10,r10,2 mtmsrd r10,1 mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12 ld r9,PACA_EXSLB+EX_R9(r13) ld r10,PACA_EXSLB+EX_R10(r13) ld r11,PACA_EXSLB+EX_R11(r13) ld r12,PACA_EXSLB+EX_R12(r13) ld r13,PACA_EXSLB+EX_R13(r13) rfid b . /* prevent speculative execution *//* * Space for CPU0's segment table. * * On iSeries, the hypervisor must fill in at least one entry before * we get control (with relocate on). The address is given to the hv * as a page number (see xLparMap below), so this must be at a * fixed address (the linker can't compute (u64)&initial_stab >> * PAGE_SHIFT). */ . = STAB0_OFFSET /* 0x6000 */ .globl initial_stabinitial_stab: .space 4096#ifdef CONFIG_PPC_PSERIES/* * Data area reserved for FWNMI option. * This address (0x7000) is fixed by the RPA. */ .= 0x7000 .globl fwnmi_data_areafwnmi_data_area:#endif /* CONFIG_PPC_PSERIES */ /* iSeries does not use the FWNMI stuff, so it is safe to put * this here, even if we later allow kernels that will boot on * both pSeries and iSeries */#ifdef CONFIG_PPC_ISERIES . = LPARMAP_PHYS .globl xLparMapxLparMap:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -