Accessing thread_info flags can cause an SLB fault, so it must not
be done with MSR[RI]=0, which leads to SLB unrecoverable fault error.

Signed-off-by: Nicholas Piggin <npig...@gmail.com>
---
 arch/powerpc/kernel/syscall_64.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kernel/syscall_64.c b/arch/powerpc/kernel/syscall_64.c
index 87d95b455b83..a56ae78f2d1d 100644
--- a/arch/powerpc/kernel/syscall_64.c
+++ b/arch/powerpc/kernel/syscall_64.c
@@ -313,12 +313,18 @@ notrace unsigned long 
interrupt_exit_kernel_prepare(struct pt_regs *regs, unsign
 {
        unsigned long *ti_flagsp = &current_thread_info()->flags;
        unsigned long flags;
+       unsigned long ret = 0;
 
        if (IS_ENABLED(CONFIG_PPC_BOOK3S) && unlikely(!(regs->msr & MSR_RI)))
                unrecoverable_exception(regs);
        BUG_ON(regs->msr & MSR_PR);
        BUG_ON(!FULL_REGS(regs));
 
+       if (unlikely(*ti_flagsp & _TIF_EMULATE_STACK_STORE)) {
+               clear_bits(_TIF_EMULATE_STACK_STORE, ti_flagsp);
+               ret = 1;
+       }
+
        local_irq_save(flags);
 
        if (regs->softe == IRQS_ENABLED) {
@@ -370,10 +376,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct 
pt_regs *regs, unsign
         */
        kuap_restore_amr(regs);
 
-       if (unlikely(*ti_flagsp & _TIF_EMULATE_STACK_STORE)) {
-               clear_bits(_TIF_EMULATE_STACK_STORE, ti_flagsp);
-               return 1;
-       }
-       return 0;
+       return ret;
 }
 #endif
-- 
2.23.0

Reply via email to