powerpc/powernv/idle: Restore AMR/UAMOR/AMOR after idle [Linux 5.2]

powerpc/powernv/idle: Restore AMR/UAMOR/AMOR after idle [Linux 5.2]

This Linux kernel change "powerpc/powernv/idle: Restore AMR/UAMOR/AMOR after idle" is included in the Linux 5.2 release. This change is authored by Michael Ellerman <mpe [at] ellerman.id.au> on Thu Apr 18 16:51:17 2019 +1000. The commit for this change in Linux stable tree is 53a712b (patch).

powerpc/powernv/idle: Restore AMR/UAMOR/AMOR after idle

In order to implement KUAP (Kernel Userspace Access Protection) on
Power9 we will be using the AMR, and therefore indirectly the
UAMOR/AMOR.

So save/restore these regs in the idle code.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

There are 27 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/powerpc/kernel/idle_book3s.S | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index 3617800..4a860d3 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -170,8 +170,11 @@ core_idle_lock_held:
    bne-    core_idle_lock_held
    blr

-/* Reuse an unused pt_regs slot for IAMR */
+/* Reuse some unused pt_regs slots for AMR/IAMR/UAMOR/UAMOR */
+#define PNV_POWERSAVE_AMR  _TRAP
 #define PNV_POWERSAVE_IAMR _DAR
+#define PNV_POWERSAVE_UAMOR    _DSISR
+#define PNV_POWERSAVE_AMOR RESULT

 /*
  * Pass requested state in r3:
@@ -205,8 +208,16 @@ pnv_powersave_common:
    SAVE_NVGPRS(r1)

 BEGIN_FTR_SECTION
+   mfspr   r4, SPRN_AMR
    mfspr   r5, SPRN_IAMR
+   mfspr   r6, SPRN_UAMOR
+   std r4, PNV_POWERSAVE_AMR(r1)
    std r5, PNV_POWERSAVE_IAMR(r1)
+   std r6, PNV_POWERSAVE_UAMOR(r1)
+BEGIN_FTR_SECTION_NESTED(42)
+   mfspr   r7, SPRN_AMOR
+   std r7, PNV_POWERSAVE_AMOR(r1)
+END_FTR_SECTION_NESTED_IFSET(CPU_FTR_HVMODE, 42)
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)

    mfcr    r5
@@ -935,12 +946,20 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
    REST_GPR(2, r1)

 BEGIN_FTR_SECTION
-   /* IAMR was saved in pnv_powersave_common() */
+   /* These regs were saved in pnv_powersave_common() */
+   ld  r4, PNV_POWERSAVE_AMR(r1)
    ld  r5, PNV_POWERSAVE_IAMR(r1)
+   ld  r6, PNV_POWERSAVE_UAMOR(r1)
+   mtspr   SPRN_AMR, r4
    mtspr   SPRN_IAMR, r5
+   mtspr   SPRN_UAMOR, r6
+BEGIN_FTR_SECTION_NESTED(42)
+   ld  r7, PNV_POWERSAVE_AMOR(r1)
+   mtspr   SPRN_AMOR, r7
+END_FTR_SECTION_NESTED_IFSET(CPU_FTR_HVMODE, 42)
    /*
-    * We don't need an isync here because the upcoming mtmsrd is
-    * execution synchronizing.
+    * We don't need an isync here after restoring IAMR because the upcoming
+    * mtmsrd is execution synchronizing.
     */
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)

Leave a Reply

Your email address will not be published. Required fields are marked *