@@ -31,4 +31,11 @@ static inline bool por_elx_allows_exec(u64 por, u8 pkey)
return perm & POE_X;
}
+static inline u64 por_elx_set_pkey_perms(u64 por, u8 pkey, u64 perms)
+{
+ u64 shift = POR_ELx_PERM_SHIFT(pkey);
+
+ return (por & ~(POE_MASK << shift)) | (perms << shift);
+}
+
#endif /* _ASM_ARM64_POR_H */
@@ -1578,8 +1578,8 @@ void __cpu_replace_ttbr1(pgd_t *pgdp, bool cnp)
#ifdef CONFIG_ARCH_HAS_PKEYS
int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long init_val)
{
- u64 new_por;
- u64 old_por;
+ u64 new_perms;
+ u64 por;
if (!system_supports_poe())
return -ENOSPC;
@@ -1593,25 +1593,19 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long i
return -EINVAL;
/* Set the bits we need in POR: */
- new_por = POE_RWX;
+ new_perms = POE_RWX;
if (init_val & PKEY_DISABLE_WRITE)
- new_por &= ~POE_W;
+ new_perms &= ~POE_W;
if (init_val & PKEY_DISABLE_ACCESS)
- new_por &= ~POE_RW;
+ new_perms &= ~POE_RW;
if (init_val & PKEY_DISABLE_READ)
- new_por &= ~POE_R;
+ new_perms &= ~POE_R;
if (init_val & PKEY_DISABLE_EXECUTE)
- new_por &= ~POE_X;
+ new_perms &= ~POE_X;
- /* Shift the bits in to the correct place in POR for pkey: */
- new_por = POR_ELx_PERM_PREP(pkey, new_por);
-
- /* Get old POR and mask off any old bits in place: */
- old_por = read_sysreg_s(SYS_POR_EL0);
- old_por &= ~(POE_MASK << POR_ELx_PERM_SHIFT(pkey));
-
- /* Write old part along with new part: */
- write_sysreg_s(old_por | new_por, SYS_POR_EL0);
+ por = read_sysreg_s(SYS_POR_EL0);
+ por = por_elx_set_pkey_perms(por, pkey, new_perms);
+ write_sysreg_s(por, SYS_POR_EL0);
return 0;
}
Introduce a helper that sets the permissions of a given pkey (POIndex) in the POR_ELx format, and make use of it in arch_set_user_pkey_access(). Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com> --- arch/arm64/include/asm/por.h | 7 +++++++ arch/arm64/mm/mmu.c | 26 ++++++++++---------------- 2 files changed, 17 insertions(+), 16 deletions(-)