Skip to content

Commit

Permalink
powerpc/32s: Refactor update of user segment registers
Browse files Browse the repository at this point in the history
[ Upstream commit 91bb308 ]

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
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
chleroy authored and Sasha Levin committed Aug 26, 2021
1 parent efe40fd commit 33bd580
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 41 deletions.
21 changes: 21 additions & 0 deletions arch/powerpc/include/asm/book3s/32/kup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
27 changes: 27 additions & 0 deletions arch/powerpc/include/asm/book3s/32/mmu-hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions arch/powerpc/include/asm/kup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 0 additions & 37 deletions arch/powerpc/mm/book3s32/kuep.c
Original file line number Diff line number Diff line change
@@ -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)
{
Expand Down

0 comments on commit 33bd580

Please sign in to comment.