powerpc/32s: Refactor update of user segment registers
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Thu, 3 Jun 2021 08:41:37 +0000 (08:41 +0000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 16 Jun 2021 14:09:07 +0000 (00:09 +1000)
KUEP implements the update of user segment registers.

Move it into mmu-hash.h in order to use it from other places.

And inline kuep_lock() and kuep_unlock(). Inlining kuep_lock() is
important for system_call_exception(), otherwise system_call_exception()
has to save into stack the system call parameters that are used just
after, and doing that takes more instructions than kuep_lock() itself.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/24591ca480d14a62ef910e38a5273d551262c4a2.1622708530.git.christophe.leroy@csgroup.eu
arch/powerpc/include/asm/book3s/32/kup.h
arch/powerpc/include/asm/book3s/32/mmu-hash.h
arch/powerpc/include/asm/kup.h
arch/powerpc/mm/book3s32/kuep.c

index c1f7c2e625a6564a4a13db5707e6a864b4ee9d53..83aa0dde50d6400a227545c43d774afdd4348fdd 100644 (file)
@@ -7,6 +7,27 @@
 
 #ifndef __ASSEMBLY__
 
+static __always_inline bool kuep_is_disabled(void)
+{
+       return !IS_ENABLED(CONFIG_PPC_KUEP);
+}
+
+static inline void kuep_lock(void)
+{
+       if (kuep_is_disabled())
+               return;
+
+       update_user_segments(mfsr(0) | SR_NX);
+}
+
+static inline void kuep_unlock(void)
+{
+       if (kuep_is_disabled())
+               return;
+
+       update_user_segments(mfsr(0) & ~SR_NX);
+}
+
 #ifdef CONFIG_PPC_KUAP
 
 #include <linux/sched.h>
index b85f8e114a9c0f52f15f78251ed43db90d1afa19..cc0284bbac86f670144226d405b760409c9bf418 100644 (file)
@@ -102,6 +102,33 @@ extern s32 patch__hash_page_B, patch__hash_page_C;
 extern s32 patch__flush_hash_A0, patch__flush_hash_A1, patch__flush_hash_A2;
 extern s32 patch__flush_hash_B;
 
+#include <asm/reg.h>
+#include <asm/task_size_32.h>
+
+#define UPDATE_TWO_USER_SEGMENTS(n) do {               \
+       if (TASK_SIZE > ((n) << 28))                    \
+               mtsr(val1, (n) << 28);                  \
+       if (TASK_SIZE > (((n) + 1) << 28))              \
+               mtsr(val2, ((n) + 1) << 28);            \
+       val1 = (val1 + 0x222) & 0xf0ffffff;             \
+       val2 = (val2 + 0x222) & 0xf0ffffff;             \
+} while (0)
+
+static __always_inline void update_user_segments(u32 val)
+{
+       int val1 = val;
+       int val2 = (val + 0x111) & 0xf0ffffff;
+
+       UPDATE_TWO_USER_SEGMENTS(0);
+       UPDATE_TWO_USER_SEGMENTS(2);
+       UPDATE_TWO_USER_SEGMENTS(4);
+       UPDATE_TWO_USER_SEGMENTS(6);
+       UPDATE_TWO_USER_SEGMENTS(8);
+       UPDATE_TWO_USER_SEGMENTS(10);
+       UPDATE_TWO_USER_SEGMENTS(12);
+       UPDATE_TWO_USER_SEGMENTS(14);
+}
+
 #endif /* !__ASSEMBLY__ */
 
 /* We happily ignore the smaller BATs on 601, we don't actually use
index ec96232529ac27f3d0e29a16a7df7b14d3c588a3..4b94d42937774dbc57c2ac99ba21fac3cf9f34d2 100644 (file)
@@ -46,10 +46,7 @@ void setup_kuep(bool disabled);
 static inline void setup_kuep(bool disabled) { }
 #endif /* CONFIG_PPC_KUEP */
 
-#if defined(CONFIG_PPC_KUEP) && defined(CONFIG_PPC_BOOK3S_32)
-void kuep_lock(void);
-void kuep_unlock(void);
-#else
+#ifndef CONFIG_PPC_BOOK3S_32
 static inline void kuep_lock(void) { }
 static inline void kuep_unlock(void) { }
 #endif
index 6eafe7b2b0318c4890bde16af40e0ce989c3edac..919595f47e25f9faaf7e12bc0cb7cfea8c23ef15 100644 (file)
@@ -1,43 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include <asm/kup.h>
-#include <asm/reg.h>
-#include <asm/task_size_32.h>
-#include <asm/mmu.h>
-
-#define KUEP_UPDATE_TWO_USER_SEGMENTS(n) do {          \
-       if (TASK_SIZE > ((n) << 28))                    \
-               mtsr(val1, (n) << 28);                  \
-       if (TASK_SIZE > (((n) + 1) << 28))              \
-               mtsr(val2, ((n) + 1) << 28);            \
-       val1 = (val1 + 0x222) & 0xf0ffffff;             \
-       val2 = (val2 + 0x222) & 0xf0ffffff;             \
-} while (0)
-
-static __always_inline void kuep_update(u32 val)
-{
-       int val1 = val;
-       int val2 = (val + 0x111) & 0xf0ffffff;
-
-       KUEP_UPDATE_TWO_USER_SEGMENTS(0);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(2);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(4);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(6);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(8);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(10);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(12);
-       KUEP_UPDATE_TWO_USER_SEGMENTS(14);
-}
-
-void kuep_lock(void)
-{
-       kuep_update(mfsr(0) | SR_NX);
-}
-
-void kuep_unlock(void)
-{
-       kuep_update(mfsr(0) & ~SR_NX);
-}
 
 void __init setup_kuep(bool disabled)
 {