From: Mahesh Salgaonkar <redacted>
The routine machine_check_pSeries_early() is only used on powernv, not
pseries. Hence rename machine_check_pSeries_early to
machine_check_powernv_early.
Reported-by: Paul Mackerras <redacted>
Signed-off-by: Mahesh Salgaonkar <redacted>
---
arch/powerpc/kernel/exceptions-64s.S | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
From: Mahesh Salgaonkar <redacted>
The current implementation of MCE early handling modifies CR0/1 registers
without saving its old values. Fix this by moving early check for
powersaving mode to machine_check_handle_early().
The power architecture 2.06 or later allows the possibility of getting
machine check while in nap/sleep/winkle. The last bit of HSPRG0 is set
to 1, if thread is woken up from winkle. Hence, clear the last bit of
HSPRG0 (r13) before MCE handler starts using it as paca pointer.
Also, the current code always puts the thread into nap state irrespective
of whatever idle state it woke up from. Fix that by looking at
paca->thread_idle_state and put the thread back into same state where it
came from.
Reported-by: Paul Mackerras <redacted>
Signed-off-by: Mahesh Salgaonkar <redacted>
---
arch/powerpc/kernel/exceptions-64s.S | 66 ++++++++++++++++++++--------------
1 file changed, 39 insertions(+), 27 deletions(-)
@@ -164,29 +164,14 @@ machine_check_pSeries_1:*vector*/SET_SCRATCH0(r13)/*saver13*/-#ifdef CONFIG_PPC_P7_NAP-BEGIN_FTR_SECTION-/*Runningnativeonarch2.06orlater,checkifweare-*wakingupfromnap.Weonlyhandlenostatelossand-*supervisorstateloss.Wedo-not-handlehypervisor-*statelossatthistime.+/*+*Runningnativeonarch2.06orlater,wemaywakeupfromwinkle+*insidemachinecheck.Ifyes,thenlastbitofHSPGR0wouldbeset+*to1.Henceclearitunconditionally.*/-mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-beq9f--mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-/*wakingupfrompowersave (nap)state*/-cmpwicr1,r13,2-/*TotallossofHVstateisfatal.let's just stay stuck here */-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-bgtcr1,.-9:-OPT_SET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE|CPU_FTR_ARCH_206)-#endif /* CONFIG_PPC_P7_NAP */+GET_PACA(r13)+clrrdir13,r13,1+SET_PACA(r13)EXCEPTION_PROLOG_0(PACA_EXMC)BEGIN_FTR_SECTIONbmachine_check_powernv_early
@@ -1362,25 +1347,52 @@ machine_check_handle_early:*Checkifthreadwasinpowersavingmode.Wecomeherewhenany*ofthefollowingistrue:*a.threadwasn't in power saving mode-*b.threadwasinpowersavingmodewithnostatelossor-*supervisorstateloss+*b.threadwasinpowersavingmodewithnostateloss,+*supervisorstatelossorhypervisorstateloss.*-*Gobacktonapagainif(b)istrue.+*Gobacktonap/sleep/winklemodeagainif(b)istrue.*/rlwinm.r11,r12,47-31,30,31/*Wasitinpowersavingmode?*/beq4f/*No,itwasn;t*//*Threadwasinpowersavingmode.Gobacktonapagain.*/cmpwir11,2-bne3f-/*Supervisorstateloss*/+blt3f+/*Supervisor/Hypervisorstatelossloss*/lir0,1stbr0,PACA_NAPSTATELOST(r13)3:blmachine_check_queue_eventMACHINE_CHECK_HANDLER_WINDUPGET_PACA(r13)+/*+*CheckwhatidlestatethisCPUwasinandgobacktosamemode+*again.+*/+lbzr3,PACA_THREAD_IDLE_STATE(r13)+cmpwir3,PNV_THREAD_NAP+bgt1fldr1,PACAR1(r13)lir3,PNV_THREAD_NAPbpower7_enter_nap_mode+/*Noreturn*/+1:+cmpwir3,PNV_THREAD_SLEEP+bgt2f+IDLE_STATE_ENTER_SEQ(PPC_SLEEP)+/*Noreturn*/++2:+/*+*Gobacktowinkle.Pleasenotethatthisthreadwaswokenupin+*machinecheckfromwinkleandhavenotrestoredtheper-subcore+*state.Hencebeforegoingbacktowinkle,setlastbitofHSPGR0+*to1.Thiswillmakesurethatifthisthreadgetswokenup+*againatresetvector0x100thenitwillgetchancetorestore+*thesubcorestate.+*/+orir13,r13,1+SET_PACA(r13)+IDLE_STATE_ENTER_SEQ(PPC_WINKLE)+/*Noreturn*/4:#endif/*
From: Shreyas B Prabhu <hidden> Date: 2016-02-25 07:45:15
On 02/25/2016 10:25 AM, Mahesh J Salgaonkar wrote:
quoted hunk
From: Mahesh Salgaonkar <redacted>
The current implementation of MCE early handling modifies CR0/1 registers
without saving its old values. Fix this by moving early check for
powersaving mode to machine_check_handle_early().
The power architecture 2.06 or later allows the possibility of getting
machine check while in nap/sleep/winkle. The last bit of HSPRG0 is set
to 1, if thread is woken up from winkle. Hence, clear the last bit of
HSPRG0 (r13) before MCE handler starts using it as paca pointer.
Also, the current code always puts the thread into nap state irrespective
of whatever idle state it woke up from. Fix that by looking at
paca->thread_idle_state and put the thread back into same state where it
came from.
Reported-by: Paul Mackerras <redacted>
Signed-off-by: Mahesh Salgaonkar <redacted>
---
arch/powerpc/kernel/exceptions-64s.S | 66 ++++++++++++++++++++--------------
1 file changed, 39 insertions(+), 27 deletions(-)
@@ -164,29 +164,14 @@ machine_check_pSeries_1:*vector*/SET_SCRATCH0(r13)/*saver13*/-#ifdef CONFIG_PPC_P7_NAP-BEGIN_FTR_SECTION-/*Runningnativeonarch2.06orlater,checkifweare-*wakingupfromnap.Weonlyhandlenostatelossand-*supervisorstateloss.Wedo-not-handlehypervisor-*statelossatthistime.+/*+*Runningnativeonarch2.06orlater,wemaywakeupfromwinkle+*insidemachinecheck.Ifyes,thenlastbitofHSPGR0wouldbeset+*to1.Henceclearitunconditionally.*/-mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-beq9f--mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-/*wakingupfrompowersave (nap)state*/-cmpwicr1,r13,2-/*TotallossofHVstateisfatal.let's just stay stuck here */-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-bgtcr1,.-9:-OPT_SET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE|CPU_FTR_ARCH_206)-#endif /* CONFIG_PPC_P7_NAP */+GET_PACA(r13)+clrrdir13,r13,1+SET_PACA(r13)EXCEPTION_PROLOG_0(PACA_EXMC)BEGIN_FTR_SECTIONbmachine_check_powernv_early
@@ -1362,25 +1347,52 @@ machine_check_handle_early:*Checkifthreadwasinpowersavingmode.Wecomeherewhenany*ofthefollowingistrue:*a.threadwasn't in power saving mode-*b.threadwasinpowersavingmodewithnostatelossor-*supervisorstateloss+*b.threadwasinpowersavingmodewithnostateloss,+*supervisorstatelossorhypervisorstateloss.*-*Gobacktonapagainif(b)istrue.+*Gobacktonap/sleep/winklemodeagainif(b)istrue.*/rlwinm.r11,r12,47-31,30,31/*Wasitinpowersavingmode?*/beq4f/*No,itwasn;t*//*Threadwasinpowersavingmode.Gobacktonapagain.*/cmpwir11,2-bne3f-/*Supervisorstateloss*/+blt3f+/*Supervisor/Hypervisorstatelossloss*/
loss repeated twice in comment
li r0,1
stb r0,PACA_NAPSTATELOST(r13)
3: bl machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
GET_PACA(r13)
+ /*
+ * Check what idle state this CPU was in and go back to same mode
+ * again.
+ */
+ lbz r3,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi r3,PNV_THREAD_NAP
+ bgt 1f
ld r1,PACAR1(r13)
li r3,PNV_THREAD_NAP
b power7_enter_nap_mode
You could call IDLE_STATE_ENTER_SEQ(PPC_NAP) here to keep it consistent
with what you do for sleep and winkle below. power7_enter_nap_mode is
only setting couple of PACA flags which are anyway set in your case.
Also what is the MSR at this point? I don't foresee any issue as long as
we are in real mode. That said, ISA says SF, HV and ME bits should be 1,
RI can be 0,1 and rest have to be 0 before entering low power mode.
+ /* No return */
+1:
+ cmpwi r3,PNV_THREAD_SLEEP
+ bgt 2f
+ IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
+ /* No return */
+
+2:
+ /*
+ * Go back to winkle. Please note that this thread was woken up in
+ * machine check from winkle and have not restored the per-subcore
+ * state. Hence before going back to winkle, set last bit of HSPGR0
+ * to 1. This will make sure that if this thread gets woken up
+ * again at reset vector 0x100 then it will get chance to restore
+ * the subcore state.
+ */
+ ori r13,r13,1
+ SET_PACA(r13)
Note PACA_THREAD_IDLE_STATE(r13) showing PNV_THREAD_WINKLE doesn't
necessarily mean we woke up from winkle. It only means we requested for
it. So here is possible you are setting last bit of HSPRG0 unnecessarily
in some cases. I don't believe this has any harmful effects though. It
will only result unnecessarily restoring SLB and few SPRs next time the
thread wakes up in reset vector.
+ IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
+ /* No return */
4:
#endif
/*
Overall this patch looks good to me.
Reviewed-by: Shreyas B. Prabhu <redacted>
On 02/25/2016 10:25 AM, Mahesh J Salgaonkar wrote:
quoted
From: Mahesh Salgaonkar <redacted>
The current implementation of MCE early handling modifies CR0/1 registers
without saving its old values. Fix this by moving early check for
powersaving mode to machine_check_handle_early().
The power architecture 2.06 or later allows the possibility of getting
machine check while in nap/sleep/winkle. The last bit of HSPRG0 is set
to 1, if thread is woken up from winkle. Hence, clear the last bit of
HSPRG0 (r13) before MCE handler starts using it as paca pointer.
Also, the current code always puts the thread into nap state irrespective
of whatever idle state it woke up from. Fix that by looking at
paca->thread_idle_state and put the thread back into same state where it
came from.
Reported-by: Paul Mackerras <redacted>
Signed-off-by: Mahesh Salgaonkar <redacted>
---
arch/powerpc/kernel/exceptions-64s.S | 66 ++++++++++++++++++++--------------
1 file changed, 39 insertions(+), 27 deletions(-)
@@ -164,29 +164,14 @@ machine_check_pSeries_1:*vector*/SET_SCRATCH0(r13)/*saver13*/-#ifdef CONFIG_PPC_P7_NAP-BEGIN_FTR_SECTION-/*Runningnativeonarch2.06orlater,checkifweare-*wakingupfromnap.Weonlyhandlenostatelossand-*supervisorstateloss.Wedo-not-handlehypervisor-*statelossatthistime.+/*+*Runningnativeonarch2.06orlater,wemaywakeupfromwinkle+*insidemachinecheck.Ifyes,thenlastbitofHSPGR0wouldbeset+*to1.Henceclearitunconditionally.*/-mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-beq9f--mfsprr13,SPRN_SRR1-rlwinm.r13,r13,47-31,30,31-/*wakingupfrompowersave (nap)state*/-cmpwicr1,r13,2-/*TotallossofHVstateisfatal.let's just stay stuck here */-OPT_GET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-bgtcr1,.-9:-OPT_SET_SPR(r13,SPRN_CFAR,CPU_FTR_CFAR)-END_FTR_SECTION_IFSET(CPU_FTR_HVMODE|CPU_FTR_ARCH_206)-#endif /* CONFIG_PPC_P7_NAP */+GET_PACA(r13)+clrrdir13,r13,1+SET_PACA(r13)EXCEPTION_PROLOG_0(PACA_EXMC)BEGIN_FTR_SECTIONbmachine_check_powernv_early
@@ -1362,25 +1347,52 @@ machine_check_handle_early:*Checkifthreadwasinpowersavingmode.Wecomeherewhenany*ofthefollowingistrue:*a.threadwasn't in power saving mode-*b.threadwasinpowersavingmodewithnostatelossor-*supervisorstateloss+*b.threadwasinpowersavingmodewithnostateloss,+*supervisorstatelossorhypervisorstateloss.*-*Gobacktonapagainif(b)istrue.+*Gobacktonap/sleep/winklemodeagainif(b)istrue.*/rlwinm.r11,r12,47-31,30,31/*Wasitinpowersavingmode?*/beq4f/*No,itwasn;t*//*Threadwasinpowersavingmode.Gobacktonapagain.*/cmpwir11,2-bne3f-/*Supervisorstateloss*/+blt3f+/*Supervisor/Hypervisorstatelossloss*/
loss repeated twice in comment
quoted
li r0,1
stb r0,PACA_NAPSTATELOST(r13)
3: bl machine_check_queue_event
MACHINE_CHECK_HANDLER_WINDUP
GET_PACA(r13)
+ /*
+ * Check what idle state this CPU was in and go back to same mode
+ * again.
+ */
+ lbz r3,PACA_THREAD_IDLE_STATE(r13)
+ cmpwi r3,PNV_THREAD_NAP
+ bgt 1f
ld r1,PACAR1(r13)
li r3,PNV_THREAD_NAP
b power7_enter_nap_mode
You could call IDLE_STATE_ENTER_SEQ(PPC_NAP) here to keep it consistent
with what you do for sleep and winkle below. power7_enter_nap_mode is
only setting couple of PACA flags which are anyway set in your case.
Yup I could do that. Will fix it in v2.
Also what is the MSR at this point? I don't foresee any issue as long as
we are in real mode. That said, ISA says SF, HV and ME bits should be 1,
RI can be 0,1 and rest have to be 0 before entering low power mode.
Machine check interrupts are taken in real mode and by the time we come
here ME bit is already set to 1. So we are good.
quoted
+ /* No return */
+1:
+ cmpwi r3,PNV_THREAD_SLEEP
+ bgt 2f
+ IDLE_STATE_ENTER_SEQ(PPC_SLEEP)
+ /* No return */
+
+2:
+ /*
+ * Go back to winkle. Please note that this thread was woken up in
+ * machine check from winkle and have not restored the per-subcore
+ * state. Hence before going back to winkle, set last bit of HSPGR0
+ * to 1. This will make sure that if this thread gets woken up
+ * again at reset vector 0x100 then it will get chance to restore
+ * the subcore state.
+ */
+ ori r13,r13,1
+ SET_PACA(r13)
Note PACA_THREAD_IDLE_STATE(r13) showing PNV_THREAD_WINKLE doesn't
necessarily mean we woke up from winkle. It only means we requested for
it. So here is possible you are setting last bit of HSPRG0 unnecessarily
in some cases.
Agree. But unlike reset vector, MCE can come with valid values in
CR[0-7] and we can't afford to trash them. For checking whether r13 has
its last bit set or not, it will end up trashing CR0 at least.
I don't believe this has any harmful effects though. It
will only result unnecessarily restoring SLB and few SPRs next time the
thread wakes up in reset vector.
I think we should be ok with that.
quoted
+ IDLE_STATE_ENTER_SEQ(PPC_WINKLE)
+ /* No return */
4:
#endif
/*
Overall this patch looks good to me.
Reviewed-by: Shreyas B. Prabhu <redacted>