summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm/book3s/32
diff options
context:
space:
mode:
authorChristophe Leroy <christophe.leroy@csgroup.eu>2021-06-03 08:41:37 +0000
committerMichael Ellerman <mpe@ellerman.id.au>2021-06-17 00:09:07 +1000
commit91bb30822a2e1d7900f9f42e9e92647a9015f979 (patch)
tree65b175ba7614d99c0cfe3a49a1f4504cca0d7e4a /arch/powerpc/include/asm/book3s/32
parent91ec66719d4c5c0e7b4e32585b01881660d1bc53 (diff)
downloadlinux-stable-91bb30822a2e1d7900f9f42e9e92647a9015f979.tar.gz
linux-stable-91bb30822a2e1d7900f9f42e9e92647a9015f979.tar.bz2
linux-stable-91bb30822a2e1d7900f9f42e9e92647a9015f979.zip
powerpc/32s: Refactor update of user segment registers
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
Diffstat (limited to 'arch/powerpc/include/asm/book3s/32')
-rw-r--r--arch/powerpc/include/asm/book3s/32/kup.h21
-rw-r--r--arch/powerpc/include/asm/book3s/32/mmu-hash.h27
2 files changed, 48 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/book3s/32/kup.h b/arch/powerpc/include/asm/book3s/32/kup.h
index c1f7c2e625a6..83aa0dde50d6 100644
--- a/arch/powerpc/include/asm/book3s/32/kup.h
+++ b/arch/powerpc/include/asm/book3s/32/kup.h
@@ -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>
diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
index b85f8e114a9c..cc0284bbac86 100644
--- a/arch/powerpc/include/asm/book3s/32/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
@@ -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