Re: [PATCH v8 5/5] powernv/pseries: consolidate code for mce early handling.
From: Mahesh Jagannath Salgaonkar <hidden>
Date: 2018-08-27 10:32:36
On 08/23/2018 02:32 PM, Nicholas Piggin wrote:
On Thu, 23 Aug 2018 14:13:13 +0530 Mahesh Jagannath Salgaonkar [off-list ref] wrote:quoted
On 08/20/2018 05:04 PM, Nicholas Piggin wrote:quoted
On Sun, 19 Aug 2018 22:38:39 +0530 Mahesh J Salgaonkar [off-list ref] wrote:quoted
From: Mahesh Salgaonkar <redacted> Now that other platforms also implements real mode mce handler, lets consolidate the code by sharing existing powernv machine check early code. Rename machine_check_powernv_early to machine_check_common_early and reuse the code. Signed-off-by: Mahesh Salgaonkar <redacted> --- arch/powerpc/kernel/exceptions-64s.S | 155 ++++++---------------------------- 1 file changed, 28 insertions(+), 127 deletions(-)diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 12f056179112..2f85a7baf026 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S@@ -243,14 +243,13 @@ EXC_REAL_BEGIN(machine_check, 0x200, 0x100) SET_SCRATCH0(r13) /* save r13 */ EXCEPTION_PROLOG_0(PACA_EXMC) BEGIN_FTR_SECTION - b machine_check_powernv_early + b machine_check_common_early FTR_SECTION_ELSE b machine_check_pSeries_0 ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) EXC_REAL_END(machine_check, 0x200, 0x100) EXC_VIRT_NONE(0x4200, 0x100) -TRAMP_REAL_BEGIN(machine_check_powernv_early) -BEGIN_FTR_SECTION +TRAMP_REAL_BEGIN(machine_check_common_early) EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200) /* * Register contents:@@ -306,7 +305,9 @@ BEGIN_FTR_SECTION /* Save r9 through r13 from EXMC save area to stack frame. */ EXCEPTION_PROLOG_COMMON_2(PACA_EXMC) mfmsr r11 /* get MSR value */ +BEGIN_FTR_SECTION ori r11,r11,MSR_ME /* turn on ME bit */ +END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) ori r11,r11,MSR_RI /* turn on RI bit */ LOAD_HANDLER(r12, machine_check_handle_early) 1: mtspr SPRN_SRR0,r12@@ -325,7 +326,6 @@ BEGIN_FTR_SECTION andc r11,r11,r10 /* Turn off MSR_ME */ b 1b b . /* prevent speculative execution */ -END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) TRAMP_REAL_BEGIN(machine_check_pSeries) .globl machine_check_fwnmi@@ -333,7 +333,7 @@ machine_check_fwnmi: SET_SCRATCH0(r13) /* save r13 */ EXCEPTION_PROLOG_0(PACA_EXMC) BEGIN_FTR_SECTION - b machine_check_pSeries_early + b machine_check_common_early END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) machine_check_pSeries_0: EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST_PR, 0x200)@@ -346,103 +346,6 @@ machine_check_pSeries_0: TRAMP_KVM_SKIP(PACA_EXMC, 0x200) -TRAMP_REAL_BEGIN(machine_check_pSeries_early) -BEGIN_FTR_SECTION - EXCEPTION_PROLOG_1(PACA_EXMC, NOTEST, 0x200) - mr r10,r1 /* Save r1 */ - lhz r11,PACA_IN_MCE(r13) - cmpwi r11,0 /* Are we in nested machine check */ - bne 0f /* Yes, we are. */ - /* First machine check entry */ - ld r1,PACAMCEMERGSP(r13) /* Use MC emergency stack */ -0: subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ - addi r11,r11,1 /* increment paca->in_mce */ - sth r11,PACA_IN_MCE(r13) - /* Limit nested MCE to level 4 to avoid stack overflow */ - cmpwi r11,MAX_MCE_DEPTH - bgt 1f /* Check if we hit limit of 4 */ - mfspr r11,SPRN_SRR0 /* Save SRR0 */ - mfspr r12,SPRN_SRR1 /* Save SRR1 */ - EXCEPTION_PROLOG_COMMON_1() - EXCEPTION_PROLOG_COMMON_2(PACA_EXMC) - EXCEPTION_PROLOG_COMMON_3(0x200) - addi r3,r1,STACK_FRAME_OVERHEAD - BRANCH_LINK_TO_FAR(machine_check_early) /* Function call ABI */ - ld r12,_MSR(r1) - andi. r11,r12,MSR_PR /* See if coming from user. */ - bne 2f /* continue in V mode if we are. */ - - /* - * At this point we are not sure about what context we come from. - * We may be in the middle of swithing stack. r1 may not be valid. - * Hence stay on emergency stack, call machine_check_exception and - * return from the interrupt. - * But before that, check if this is an un-recoverable exception. - * If yes, then stay on emergency stack and panic. - */ - andi. r11,r12,MSR_RI - beq 1f - - /* - * Check if we have successfully handled/recovered from error, if not - * then stay on emergency stack and panic. - */ - cmpdi r3,0 /* see if we handled MCE successfully */ - beq 1f /* if !handled then panic */ - - /* Stay on emergency stack and return from interrupt. */ - LOAD_HANDLER(r10,mce_return) - mtspr SPRN_SRR0,r10 - ld r10,PACAKMSR(r13) - mtspr SPRN_SRR1,r10 - RFI_TO_KERNEL - b . - -1: LOAD_HANDLER(r10,unrecover_mce) - mtspr SPRN_SRR0,r10 - ld r10,PACAKMSR(r13) - /* - * We are going down. But there are chances that we might get hit by - * another MCE during panic path and we may run into unstable state - * with no way out. Hence, turn ME bit off while going down, so that - * when another MCE is hit during panic path, hypervisor will - * power cycle the lpar, instead of getting into MCE loop. - */ - li r3,MSR_ME - andc r10,r10,r3 /* Turn off MSR_ME */ - mtspr SPRN_SRR1,r10 - RFI_TO_KERNEL - b . - - /* Move original SRR0 and SRR1 into the respective regs */ -2: ld r9,_MSR(r1) - mtspr SPRN_SRR1,r9 - ld r3,_NIP(r1) - mtspr SPRN_SRR0,r3 - ld r9,_CTR(r1) - mtctr r9 - ld r9,_XER(r1) - mtxer r9 - ld r9,_LINK(r1) - mtlr r9 - REST_GPR(0, r1) - REST_8GPRS(2, r1) - REST_GPR(10, r1) - ld r11,_CCR(r1) - mtcr r11 - /* Decrement paca->in_mce. */ - lhz r12,PACA_IN_MCE(r13) - subi r12,r12,1 - sth r12,PACA_IN_MCE(r13) - REST_GPR(11, r1) - REST_2GPRS(12, r1) - /* restore original r1. */ - ld r1,GPR1(r1) - SET_SCRATCH0(r13) /* save r13 */ - EXCEPTION_PROLOG_0(PACA_EXMC) - b machine_check_pSeries_0 -END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) - EXC_COMMON_BEGIN(machine_check_common) /* * Machine check is different because we use a different@@ -541,6 +444,9 @@ EXC_COMMON_BEGIN(machine_check_handle_early) bl machine_check_early std r3,RESULT(r1) /* Save result */ ld r12,_MSR(r1) +BEGIN_FTR_SECTION + b 4f +END_FTR_SECTION_IFCLR(CPU_FTR_HVMODE) #ifdef CONFIG_PPC_P7_NAP /*@@ -564,10 +470,11 @@ EXC_COMMON_BEGIN(machine_check_handle_early) */ rldicl. r11,r12,4,63 /* See if MC hit while in HV mode. */ beq 5f - andi. r11,r12,MSR_PR /* See if coming from user. */ +4: andi. r11,r12,MSR_PR /* See if coming from user. */ bne 9f /* continue in V mode if we are. */ 5: +BEGIN_FTR_SECTION #ifdef CONFIG_KVM_BOOK3S_64_HANDLER /* * We are coming from kernel context. Check if we are coming from@@ -578,6 +485,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) cmpwi r11,0 /* Check if coming from guest */ bne 9f /* continue if we are. */ #endif +END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)Put these inside the ifdef?quoted
/* * At this point we are not sure about what context we come from. * Queue up the MCE event and return from the interrupt.@@ -611,6 +519,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early) cmpdi r3,0 /* see if we handled MCE successfully */ beq 1b /* if !handled then panic */ +BEGIN_FTR_SECTION /* * Return from MC interrupt. * Queue up the MCE event so that we can log it later, while@@ -619,10 +528,24 @@ EXC_COMMON_BEGIN(machine_check_handle_early) bl machine_check_queue_event MACHINE_CHECK_HANDLER_WINDUP RFI_TO_USER_OR_KERNEL +FTR_SECTION_ELSE + /* + * pSeries: Return from MC interrupt. Before that stay on emergency + * stack and call machine_check_exception to log the MCE event. + */ + LOAD_HANDLER(r10,mce_return) + mtspr SPRN_SRR0,r10 + ld r10,PACAKMSR(r13) + mtspr SPRN_SRR1,r10 + RFI_TO_KERNEL + b . +ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)Do you still need mce_return? Why can't you consolidate it as well? ... Hmm, okay so now I look back at patch 2, I don't think you should call machine_check_exception there. You're supposed to call machine_check_queue_event here and it will be handled by irq work.machine_check_queue_event does not handle RTAS mce event.Yes it would need a bit of work.quoted
Also, we need to call fwnmi_release_errinfo() as early as possible which is why I am calling machine_check_exception() in mce_return path for pSeries. Otherwise if we get another MCE before calling fwnmi_release_errinfo() then lpar will get rebooted without any logs getting printed.I think you can call that in your early handler, but then defer the printing to the irq work. Although hmm, maybe that's less of a problem now we do nmi_enter in machine check exception so I think printk will use an NMI safe buffer. We have to be careful actually of soft irq state if we take a machine check in an un-reconciled state or in the middle of the irq replay code I'm not actually sure we do the right thing, but that would be a bug in existing code too. And we definitely have MSR[RI] vs DAR/DSISR bugs in existing code, sigh. I don't know... maybe just push what you have and we'll try to do some more fixes and cleanups on top of that.
Sure. I will respin the next version addressing your other minor comments. Will work on more improvements as separate change. Thanks, -Mahesh.