* [PATCH v2 01/24] arm64/sysreg: add system register POR_EL{0,1}
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 02/24] arm64/sysreg: update CPACR_EL1 register Joey Gouly
` (22 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Add POR_EL{0,1} according to DDI0601 2023-03.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/include/asm/sysreg.h | 13 +++++++++++++
arch/arm64/tools/sysreg | 12 ++++++++++++
2 files changed, 25 insertions(+)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 38296579a4fd..cc2d61fd45c3 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -994,6 +994,19 @@
#define PIRx_ELx_PERM(idx, perm) ((perm) << ((idx) * 4))
+/*
+ * Permission Overlay Extension (POE) permission encodings.
+ */
+#define POE_NONE UL(0x0)
+#define POE_R UL(0x1)
+#define POE_X UL(0x2)
+#define POE_RX UL(0x3)
+#define POE_W UL(0x4)
+#define POE_RW UL(0x5)
+#define POE_XW UL(0x6)
+#define POE_RXW UL(0x7)
+#define POE_MASK UL(0xf)
+
#define ARM64_FEATURE_FIELD_BITS 4
/* Defined for compatibility only, do not add new users. */
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 76ce150e7347..dd91d0639bab 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -2504,6 +2504,18 @@ Sysreg PIR_EL2 3 4 10 2 3
Fields PIRx_ELx
EndSysreg
+Sysreg POR_EL0 3 3 10 2 4
+Fields PIRx_ELx
+EndSysreg
+
+Sysreg POR_EL1 3 0 10 2 4
+Fields PIRx_ELx
+EndSysreg
+
+Sysreg POR_EL12 3 5 10 2 4
+Fields PIRx_ELx
+EndSysreg
+
Sysreg LORSA_EL1 3 0 10 4 0
Res0 63:52
Field 51:16 SA
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 02/24] arm64/sysreg: update CPACR_EL1 register
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
2023-10-27 18:08 ` [PATCH v2 01/24] arm64/sysreg: add system register POR_EL{0,1} Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 03/24] arm64: cpufeature: add Permission Overlay Extension cpucap Joey Gouly
` (21 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Add E0POE bit that traps accesses to POR_EL0 from EL0.
Updated according to DDI0601 2023-03.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/tools/sysreg | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index dd91d0639bab..6952987f8363 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -1741,7 +1741,8 @@ Field 0 M
EndSysreg
SysregFields CPACR_ELx
-Res0 63:29
+Res0 63:30
+Field 29 E0POE
Field 28 TTA
Res0 27:26
Field 25:24 SMEN
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 03/24] arm64: cpufeature: add Permission Overlay Extension cpucap
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
2023-10-27 18:08 ` [PATCH v2 01/24] arm64/sysreg: add system register POR_EL{0,1} Joey Gouly
2023-10-27 18:08 ` [PATCH v2 02/24] arm64/sysreg: update CPACR_EL1 register Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 04/24] arm64: disable trapping of POR_EL0 to EL2 Joey Gouly
` (20 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
This indicates if the system supports POE. This is a CPUCAP_BOOT_CPU_FEATURE
as the boot CPU will enable POE if it has it, so secondary CPUs must also
have this feature.
Add a new config option: ARM64_POE
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/Kconfig | 16 ++++++++++++++++
arch/arm64/kernel/cpufeature.c | 9 +++++++++
arch/arm64/tools/cpucaps | 1 +
3 files changed, 26 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b10515c0200b..1f1a12e28c3f 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2060,6 +2060,22 @@ config ARM64_EPAN
if the cpu does not implement the feature.
endmenu # "ARMv8.7 architectural features"
+menu "ARMv8.9 architectural features"
+config ARM64_POE
+ prompt "Permission Overlay Extension"
+ def_bool y
+ help
+ The Permission Overlay Extension is used to implement Memory
+ Protection Keys. Memory Protection Keys provides a mechanism for
+ enforcing page-based protections, but without requiring modification
+ of the page tables when an application changes protection domains.
+
+ For details, see Documentation/core-api/protection-keys.rst
+
+ If unsure, say y.
+
+endmenu # "ARMv8.9 architectural features"
+
config ARM64_SVE
bool "ARM Scalable Vector Extension support"
default y
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 444a73c2e638..f1c1f348a31d 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2719,6 +2719,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature,
ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
},
+#ifdef CONFIG_ARM64_POE
+ {
+ .desc = "Stage-1 Permission Overlay Extension (S1POE)",
+ .capability = ARM64_HAS_S1POE,
+ .type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
+ .matches = has_cpuid_feature,
+ ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, S1POE, IMP)
+ },
+#endif
{},
};
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index c3f06fdef609..b8348e40f6d9 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -43,6 +43,7 @@ HAS_NO_FPSIMD
HAS_NO_HW_PREFETCH
HAS_PAN
HAS_S1PIE
+HAS_S1POE
HAS_RAS_EXTN
HAS_RNG
HAS_SB
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 04/24] arm64: disable trapping of POR_EL0 to EL2
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (2 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 03/24] arm64: cpufeature: add Permission Overlay Extension cpucap Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 05/24] arm64: context switch POR_EL0 register Joey Gouly
` (19 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Allow EL0 or EL1 to access POR_EL0 without being trapped to EL2.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/el2_setup.h | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index b7afaa026842..df5614be4b70 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -184,12 +184,20 @@
.Lset_pie_fgt_\@:
mrs_s x1, SYS_ID_AA64MMFR3_EL1
ubfx x1, x1, #ID_AA64MMFR3_EL1_S1PIE_SHIFT, #4
- cbz x1, .Lset_fgt_\@
+ cbz x1, .Lset_poe_fgt_\@
/* Disable trapping of PIR_EL1 / PIRE0_EL1 */
orr x0, x0, #HFGxTR_EL2_nPIR_EL1
orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1
+.Lset_poe_fgt_\@:
+ mrs_s x1, SYS_ID_AA64MMFR3_EL1
+ ubfx x1, x1, #ID_AA64MMFR3_EL1_S1POE_SHIFT, #4
+ cbz x1, .Lset_fgt_\@
+
+ /* Disable trapping of POR_EL0 */
+ orr x0, x0, #HFGxTR_EL2_nPOR_EL0
+
.Lset_fgt_\@:
msr_s SYS_HFGRTR_EL2, x0
msr_s SYS_HFGWTR_EL2, x0
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 05/24] arm64: context switch POR_EL0 register
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (3 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 04/24] arm64: disable trapping of POR_EL0 to EL2 Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 06/24] KVM: arm64: Save/restore POE registers Joey Gouly
` (18 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
POR_EL0 is a register that can be modified by userspace directly,
so it must be context switched.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/cpufeature.h | 6 ++++++
arch/arm64/include/asm/processor.h | 1 +
arch/arm64/include/asm/sysreg.h | 3 +++
arch/arm64/kernel/process.c | 19 +++++++++++++++++++
4 files changed, 29 insertions(+)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 5bba39376055..019af90a3cf4 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -831,6 +831,12 @@ static inline bool system_supports_tlb_range(void)
cpus_have_const_cap(ARM64_HAS_TLB_RANGE);
}
+static inline bool system_supports_poe(void)
+{
+ return IS_ENABLED(CONFIG_ARM64_POE) &&
+ alternative_has_cap_unlikely(ARM64_HAS_S1POE);
+}
+
int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index e5bc54522e71..b3ad719c2d0c 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -179,6 +179,7 @@ struct thread_struct {
u64 sctlr_user;
u64 svcr;
u64 tpidr2_el0;
+ u64 por_el0;
};
static inline unsigned int thread_get_vl(struct thread_struct *thread,
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index cc2d61fd45c3..32270823a40b 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -1007,6 +1007,9 @@
#define POE_RXW UL(0x7)
#define POE_MASK UL(0xf)
+/* Initial value for Permission Overlay Extension for EL0 */
+#define POR_EL0_INIT POE_RXW
+
#define ARM64_FEATURE_FIELD_BITS 4
/* Defined for compatibility only, do not add new users. */
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 0fcc4eb1a7ab..9caed797fc47 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -271,12 +271,19 @@ static void flush_tagged_addr_state(void)
clear_thread_flag(TIF_TAGGED_ADDR);
}
+static void flush_poe(void)
+{
+ if (system_supports_poe())
+ write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0);
+}
+
void flush_thread(void)
{
fpsimd_flush_thread();
tls_thread_flush();
flush_ptrace_hw_breakpoint(current);
flush_tagged_addr_state();
+ flush_poe();
}
void arch_release_task_struct(struct task_struct *tsk)
@@ -498,6 +505,17 @@ static void erratum_1418040_new_exec(void)
preempt_enable();
}
+static void permission_overlay_switch(struct task_struct *next)
+{
+ if (system_supports_poe()) {
+ current->thread.por_el0 = read_sysreg_s(SYS_POR_EL0);
+ if (current->thread.por_el0 != next->thread.por_el0) {
+ write_sysreg_s(next->thread.por_el0, SYS_POR_EL0);
+ isb();
+ }
+ }
+}
+
/*
* __switch_to() checks current->thread.sctlr_user as an optimisation. Therefore
* this function must be called with preemption disabled and the update to
@@ -533,6 +551,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
ssbs_thread_switch(next);
erratum_1418040_thread_switch(next);
ptrauth_thread_switch_user(next);
+ permission_overlay_switch(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 06/24] KVM: arm64: Save/restore POE registers
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (4 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 05/24] arm64: context switch POR_EL0 register Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 07/24] arm64: enable the Permission Overlay Extension for EL0 Joey Gouly
` (17 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Define the new system registers that POE introduces and context switch them.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oliver.upton@linux.dev>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/kvm_arm.h | 4 ++--
arch/arm64/include/asm/kvm_host.h | 4 ++++
arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 10 ++++++++++
arch/arm64/kvm/sys_regs.c | 2 ++
4 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 5882b2415596..4022e69e17fd 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -344,14 +344,14 @@
*/
#define __HFGRTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51))
#define __HFGRTR_EL2_MASK GENMASK(49, 0)
-#define __HFGRTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
+#define __HFGRTR_EL2_nMASK (GENMASK(60, 59) | GENMASK(55, 54) | BIT(50))
#define __HFGWTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51) | \
BIT(46) | BIT(42) | BIT(40) | BIT(28) | \
GENMASK(26, 25) | BIT(21) | BIT(18) | \
GENMASK(15, 14) | GENMASK(10, 9) | BIT(2))
#define __HFGWTR_EL2_MASK GENMASK(49, 0)
-#define __HFGWTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
+#define __HFGWTR_EL2_nMASK (GENMASK(60, 59) | GENMASK(55, 54) | BIT(50))
#define __HFGITR_EL2_RES0 GENMASK(63, 57)
#define __HFGITR_EL2_MASK GENMASK(54, 0)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index af06ccb7ee34..205653bc5c2c 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -365,6 +365,10 @@ enum vcpu_sysreg {
PIR_EL1, /* Permission Indirection Register 1 (EL1) */
PIRE0_EL1, /* Permission Indirection Register 0 (EL1) */
+ /* Permission Overlay Extension registers */
+ POR_EL1, /* Permission Overlay Register 1 (EL1) */
+ POR_EL0, /* Permission Overlay Register 0 (EL0) */
+
/* 32bit specific registers. */
DACR32_EL2, /* Domain Access Control Register */
IFSR32_EL2, /* Instruction Fault Status Register */
diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
index bb6b571ec627..22f07ee43e7e 100644
--- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
+++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
@@ -19,6 +19,9 @@
static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
{
ctxt_sys_reg(ctxt, MDSCR_EL1) = read_sysreg(mdscr_el1);
+
+ if (system_supports_poe())
+ ctxt_sys_reg(ctxt, POR_EL0) = read_sysreg_s(SYS_POR_EL0);
}
static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
@@ -59,6 +62,8 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR);
ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0);
}
+ if (system_supports_poe())
+ ctxt_sys_reg(ctxt, POR_EL1) = read_sysreg_el1(SYS_POR);
ctxt_sys_reg(ctxt, PAR_EL1) = read_sysreg_par();
ctxt_sys_reg(ctxt, TPIDR_EL1) = read_sysreg(tpidr_el1);
@@ -89,6 +94,9 @@ static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt)
static inline void __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
{
write_sysreg(ctxt_sys_reg(ctxt, MDSCR_EL1), mdscr_el1);
+
+ if (system_supports_poe())
+ write_sysreg_s(ctxt_sys_reg(ctxt, POR_EL0), SYS_POR_EL0);
}
static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt)
@@ -135,6 +143,8 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR);
write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0);
}
+ if (system_supports_poe())
+ write_sysreg_el1(ctxt_sys_reg(ctxt, POR_EL1), SYS_POR);
write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1);
write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1);
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e92ec810d449..7d66cc7e104c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2124,6 +2124,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
{ SYS_DESC(SYS_PIRE0_EL1), access_vm_reg, reset_unknown, PIRE0_EL1 },
{ SYS_DESC(SYS_PIR_EL1), access_vm_reg, reset_unknown, PIR_EL1 },
+ { SYS_DESC(SYS_POR_EL1), NULL, reset_unknown, POR_EL1 },
{ SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
{ SYS_DESC(SYS_LORSA_EL1), trap_loregion },
@@ -2203,6 +2204,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ PMU_SYS_REG(PMOVSSET_EL0),
.access = access_pmovs, .reg = PMOVSSET_EL0 },
+ { SYS_DESC(SYS_POR_EL0), NULL, reset_unknown, POR_EL0 },
{ SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
{ SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 },
{ SYS_DESC(SYS_TPIDR2_EL0), undef_access },
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 07/24] arm64: enable the Permission Overlay Extension for EL0
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (5 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 06/24] KVM: arm64: Save/restore POE registers Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 08/24] arm64: add POIndex defines Joey Gouly
` (16 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Expose a HWCAP and ID_AA64MMFR3_EL1_S1POE to userspace, so they can be used to
check if the CPU supports the feature.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
Documentation/arch/arm64/elf_hwcaps.rst | 3 +++
arch/arm64/include/asm/hwcap.h | 1 +
arch/arm64/include/uapi/asm/hwcap.h | 1 +
arch/arm64/kernel/cpufeature.c | 14 ++++++++++++++
arch/arm64/kernel/cpuinfo.c | 1 +
5 files changed, 20 insertions(+)
diff --git a/Documentation/arch/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst
index 76ff9d7398fd..85f6e9babc7f 100644
--- a/Documentation/arch/arm64/elf_hwcaps.rst
+++ b/Documentation/arch/arm64/elf_hwcaps.rst
@@ -308,6 +308,9 @@ HWCAP2_MOPS
HWCAP2_HBC
Functionality implied by ID_AA64ISAR2_EL1.BC == 0b0001.
+HWCAP2_POE
+ Functionality implied by ID_AA64MMFR3_EL1.S1POE == 0b0001.
+
4. Unused AT_HWCAP bits
-----------------------
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 521267478d18..196f21b7d11b 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -139,6 +139,7 @@
#define KERNEL_HWCAP_SME_F16F16 __khwcap2_feature(SME_F16F16)
#define KERNEL_HWCAP_MOPS __khwcap2_feature(MOPS)
#define KERNEL_HWCAP_HBC __khwcap2_feature(HBC)
+#define KERNEL_HWCAP_POE __khwcap2_feature(POE)
/*
* This yields a mask that user programs can use to figure out what
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 53026f45a509..8809ff35d6e4 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -104,5 +104,6 @@
#define HWCAP2_SME_F16F16 (1UL << 42)
#define HWCAP2_MOPS (1UL << 43)
#define HWCAP2_HBC (1UL << 44)
+#define HWCAP2_POE (1UL << 46)
#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f1c1f348a31d..c79f43dfb2be 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -400,6 +400,8 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64mmfr3[] = {
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_POE),
+ FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_S1POE_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_S1PIE_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR3_EL1_TCRX_SHIFT, 4, 0),
ARM64_FTR_END,
@@ -2220,6 +2222,14 @@ static void cpu_enable_mops(const struct arm64_cpu_capabilities *__unused)
sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_MSCEn);
}
+#ifdef CONFIG_ARM64_POE
+static void cpu_enable_poe(const struct arm64_cpu_capabilities *__unused)
+{
+ sysreg_clear_set(REG_TCR2_EL1, 0, TCR2_EL1x_E0POE);
+ sysreg_clear_set(CPACR_EL1, 0, CPACR_ELx_E0POE);
+}
+#endif
+
/* Internal helper functions to match cpu capability type */
static bool
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
@@ -2725,6 +2735,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.capability = ARM64_HAS_S1POE,
.type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
.matches = has_cpuid_feature,
+ .cpu_enable = cpu_enable_poe,
ARM64_CPUID_FIELDS(ID_AA64MMFR3_EL1, S1POE, IMP)
},
#endif
@@ -2874,6 +2885,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(ID_AA64SMFR0_EL1, BI32I32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_BI32I32),
HWCAP_CAP(ID_AA64SMFR0_EL1, F32F32, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_F32F32),
#endif /* CONFIG_ARM64_SME */
+#ifdef CONFIG_ARM64_POE
+ HWCAP_CAP(ID_AA64MMFR3_EL1, S1POE, IMP, CAP_HWCAP, KERNEL_HWCAP_POE),
+#endif
{},
};
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 98fda8500535..5b44e8ab9ab8 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -127,6 +127,7 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_SME_F16F16] = "smef16f16",
[KERNEL_HWCAP_MOPS] = "mops",
[KERNEL_HWCAP_HBC] = "hbc",
+ [KERNEL_HWCAP_POE] = "poe",
};
#ifdef CONFIG_COMPAT
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 08/24] arm64: add POIndex defines
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (6 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 07/24] arm64: enable the Permission Overlay Extension for EL0 Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 09/24] arm64: define VM_PKEY_BIT* for arm64 Joey Gouly
` (15 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
The 3-bit POIndex is stored in the PTE at bits 60..62.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/pgtable-hwdef.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index e4944d517c99..fe270fa39110 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -178,6 +178,16 @@
#define PTE_PI_IDX_2 53 /* PXN */
#define PTE_PI_IDX_3 54 /* UXN */
+/*
+ * POIndex[2:0] encoding (Permission Overlay Extension)
+ */
+#define PTE_PO_IDX_0 (_AT(pteval_t, 1) << 60)
+#define PTE_PO_IDX_1 (_AT(pteval_t, 1) << 61)
+#define PTE_PO_IDX_2 (_AT(pteval_t, 1) << 62)
+
+#define PTE_PO_IDX_MASK GENMASK_ULL(62, 60)
+
+
/*
* Memory Attribute override for Stage-2 (MemAttr[3:0])
*/
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 09/24] arm64: define VM_PKEY_BIT* for arm64
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (7 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 08/24] arm64: add POIndex defines Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 10/24] arm64: mask out POIndex when modifying a PTE Joey Gouly
` (14 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Define the VM_PKEY_BIT* values for arm64, and convert them into the arm64
specific pgprot values.
Move the current values for x86 and PPC into arch/*.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/mman.h | 8 +++++++-
arch/arm64/include/asm/page.h | 10 ++++++++++
arch/arm64/mm/mmap.c | 9 +++++++++
arch/powerpc/include/asm/page.h | 11 +++++++++++
arch/x86/include/asm/page.h | 10 ++++++++++
fs/proc/task_mmu.c | 2 ++
include/linux/mm.h | 13 -------------
7 files changed, 49 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
index 5966ee4a6154..ecb2d18dc4d7 100644
--- a/arch/arm64/include/asm/mman.h
+++ b/arch/arm64/include/asm/mman.h
@@ -7,7 +7,7 @@
#include <uapi/asm/mman.h>
static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
- unsigned long pkey __always_unused)
+ unsigned long pkey)
{
unsigned long ret = 0;
@@ -17,6 +17,12 @@ static inline unsigned long arch_calc_vm_prot_bits(unsigned long prot,
if (system_supports_mte() && (prot & PROT_MTE))
ret |= VM_MTE;
+#if defined(CONFIG_ARCH_HAS_PKEYS)
+ ret |= pkey & 0x1 ? VM_PKEY_BIT0 : 0;
+ ret |= pkey & 0x2 ? VM_PKEY_BIT1 : 0;
+ ret |= pkey & 0x4 ? VM_PKEY_BIT2 : 0;
+#endif
+
return ret;
}
#define arch_calc_vm_prot_bits(prot, pkey) arch_calc_vm_prot_bits(prot, pkey)
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
index 2312e6ee595f..aabfda2516d2 100644
--- a/arch/arm64/include/asm/page.h
+++ b/arch/arm64/include/asm/page.h
@@ -49,6 +49,16 @@ int pfn_is_map_memory(unsigned long pfn);
#define VM_DATA_DEFAULT_FLAGS (VM_DATA_FLAGS_TSK_EXEC | VM_MTE_ALLOWED)
+#if defined(CONFIG_ARCH_HAS_PKEYS)
+/* A protection key is a 3-bit value */
+# define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_2
+# define VM_PKEY_BIT0 VM_HIGH_ARCH_2
+# define VM_PKEY_BIT1 VM_HIGH_ARCH_3
+# define VM_PKEY_BIT2 VM_HIGH_ARCH_4
+# define VM_PKEY_BIT3 0
+# define VM_PKEY_BIT4 0
+#endif
+
#include <asm-generic/getorder.h>
#endif
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index 8f5b7ce857ed..df4ece982375 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -98,6 +98,15 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags)
if (vm_flags & VM_MTE)
prot |= PTE_ATTRINDX(MT_NORMAL_TAGGED);
+#ifdef CONFIG_ARCH_HAS_PKEYS
+ if (vm_flags & VM_PKEY_BIT0)
+ prot |= PTE_PO_IDX_0;
+ if (vm_flags & VM_PKEY_BIT1)
+ prot |= PTE_PO_IDX_1;
+ if (vm_flags & VM_PKEY_BIT2)
+ prot |= PTE_PO_IDX_2;
+#endif
+
return __pgprot(prot);
}
EXPORT_SYMBOL(vm_get_page_prot);
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index e5fcc79b5bfb..a5e75ec333ad 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -330,6 +330,17 @@ static inline unsigned long kaslr_offset(void)
}
#include <asm-generic/memory_model.h>
+
+#if defined(CONFIG_ARCH_HAS_PKEYS)
+# define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0
+/* A protection key is a 5-bit value */
+# define VM_PKEY_BIT0 VM_HIGH_ARCH_0
+# define VM_PKEY_BIT1 VM_HIGH_ARCH_1
+# define VM_PKEY_BIT2 VM_HIGH_ARCH_2
+# define VM_PKEY_BIT3 VM_HIGH_ARCH_3
+# define VM_PKEY_BIT4 VM_HIGH_ARCH_4
+#endif /* CONFIG_ARCH_HAS_PKEYS */
+
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_PAGE_H */
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index d18e5c332cb9..b770db1a21e7 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -87,5 +87,15 @@ static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#if defined(CONFIG_ARCH_HAS_PKEYS)
+# define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0
+/* A protection key is a 4-bit value */
+# define VM_PKEY_BIT0 VM_HIGH_ARCH_0
+# define VM_PKEY_BIT1 VM_HIGH_ARCH_1
+# define VM_PKEY_BIT2 VM_HIGH_ARCH_2
+# define VM_PKEY_BIT3 VM_HIGH_ARCH_3
+# define VM_PKEY_BIT4 0
+#endif /* CONFIG_ARCH_HAS_PKEYS */
+
#endif /* __KERNEL__ */
#endif /* _ASM_X86_PAGE_H */
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 3dd5be96691b..fcd94a39bb30 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -689,7 +689,9 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
[ilog2(VM_PKEY_BIT0)] = "",
[ilog2(VM_PKEY_BIT1)] = "",
[ilog2(VM_PKEY_BIT2)] = "",
+#if VM_PKEY_BIT3
[ilog2(VM_PKEY_BIT3)] = "",
+#endif
#if VM_PKEY_BIT4
[ilog2(VM_PKEY_BIT4)] = "",
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bf5d0b1b16f4..84ee022bf43e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -328,19 +328,6 @@ extern unsigned int kobjsize(const void *objp);
#define VM_HIGH_ARCH_5 BIT(VM_HIGH_ARCH_BIT_5)
#endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */
-#ifdef CONFIG_ARCH_HAS_PKEYS
-# define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0
-# define VM_PKEY_BIT0 VM_HIGH_ARCH_0 /* A protection key is a 4-bit value */
-# define VM_PKEY_BIT1 VM_HIGH_ARCH_1 /* on x86 and 5-bit value on ppc64 */
-# define VM_PKEY_BIT2 VM_HIGH_ARCH_2
-# define VM_PKEY_BIT3 VM_HIGH_ARCH_3
-#ifdef CONFIG_PPC
-# define VM_PKEY_BIT4 VM_HIGH_ARCH_4
-#else
-# define VM_PKEY_BIT4 0
-#endif
-#endif /* CONFIG_ARCH_HAS_PKEYS */
-
#ifdef CONFIG_X86_USER_SHADOW_STACK
/*
* VM_SHADOW_STACK should not be set with VM_SHARED because of lack of
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 10/24] arm64: mask out POIndex when modifying a PTE
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (8 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 09/24] arm64: define VM_PKEY_BIT* for arm64 Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 11/24] arm64: enable ARCH_HAS_PKEYS on arm64 Joey Gouly
` (13 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
When a PTE is modified, the POIndex must be masked off so that it can be modified.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/pgtable.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 7f7d9b1df4e5..6c57ebe8e349 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -820,7 +820,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
*/
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
PTE_PROT_NONE | PTE_VALID | PTE_WRITE | PTE_GP |
- PTE_ATTRINDX_MASK;
+ PTE_ATTRINDX_MASK | PTE_PO_IDX_MASK;
+
/* preserve the hardware dirty information */
if (pte_hw_dirty(pte))
pte = set_pte_bit(pte, __pgprot(PTE_DIRTY));
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 11/24] arm64: enable ARCH_HAS_PKEYS on arm64
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (9 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 10/24] arm64: mask out POIndex when modifying a PTE Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 12/24] arm64: handle PKEY/POE faults Joey Gouly
` (12 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Enable the ARCH_HAS_PKEYS config, but provide dummy
functions for the entire interface.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/Kconfig | 2 ++
arch/arm64/include/asm/pkeys.h | 54 ++++++++++++++++++++++++++++++++++
arch/arm64/mm/mmu.c | 7 +++++
3 files changed, 63 insertions(+)
create mode 100644 arch/arm64/include/asm/pkeys.h
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1f1a12e28c3f..68cfcbd95c8e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -2064,6 +2064,8 @@ menu "ARMv8.9 architectural features"
config ARM64_POE
prompt "Permission Overlay Extension"
def_bool y
+ select ARCH_USES_HIGH_VMA_FLAGS
+ select ARCH_HAS_PKEYS
help
The Permission Overlay Extension is used to implement Memory
Protection Keys. Memory Protection Keys provides a mechanism for
diff --git a/arch/arm64/include/asm/pkeys.h b/arch/arm64/include/asm/pkeys.h
new file mode 100644
index 000000000000..5761fb48fd53
--- /dev/null
+++ b/arch/arm64/include/asm/pkeys.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Arm Ltd.
+ *
+ * Based on arch/x86/include/asm/pkeys.h
+*/
+
+#ifndef _ASM_ARM64_PKEYS_H
+#define _ASM_ARM64_PKEYS_H
+
+#define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2)
+
+#define arch_max_pkey() 0
+
+int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
+ unsigned long init_val);
+
+static inline bool arch_pkeys_enabled(void)
+{
+ return false;
+}
+
+static inline int vma_pkey(struct vm_area_struct *vma)
+{
+ return -1;
+}
+
+static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
+ int prot, int pkey)
+{
+ return -1;
+}
+
+static inline int execute_only_pkey(struct mm_struct *mm)
+{
+ return -1;
+}
+
+static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
+{
+ return false;
+}
+
+static inline int mm_pkey_alloc(struct mm_struct *mm)
+{
+ return -1;
+}
+
+static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
+{
+ return -EINVAL;
+}
+
+#endif /* _ASM_ARM64_PKEYS_H */
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 47781bec6171..11765791b880 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1487,3 +1487,10 @@ void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte
{
set_pte_at(vma->vm_mm, addr, ptep, pte);
}
+
+#ifdef CONFIG_ARCH_HAS_PKEYS
+int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long init_val)
+{
+ return -ENOSPC;
+}
+#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 12/24] arm64: handle PKEY/POE faults
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (10 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 11/24] arm64: enable ARCH_HAS_PKEYS on arm64 Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 13/24] arm64: stop using generic mm_hooks.h Joey Gouly
` (11 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
If a memory fault occurs that is due to an overlay/pkey fault, report that to
userspace with a SEGV_PKUERR.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/traps.h | 1 +
arch/arm64/kernel/traps.c | 12 ++++++++--
arch/arm64/mm/fault.c | 44 +++++++++++++++++++++++++++++++---
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index d66dfb3a72dd..dae51eccfc19 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,6 +26,7 @@ try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn)
void force_signal_inject(int signal, int code, unsigned long address, unsigned long err);
void arm64_notify_segfault(unsigned long addr);
void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
+void arm64_force_sig_fault_pkey(int signo, int code, unsigned long far, const char *str, int pkey);
void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8b70759cdbb9..b68682c284a2 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -263,16 +263,24 @@ static void arm64_show_signal(int signo, const char *str)
__show_regs(regs);
}
-void arm64_force_sig_fault(int signo, int code, unsigned long far,
- const char *str)
+void arm64_force_sig_fault_pkey(int signo, int code, unsigned long far,
+ const char *str, int pkey)
{
arm64_show_signal(signo, str);
if (signo == SIGKILL)
force_sig(SIGKILL);
+ else if (code == SEGV_PKUERR)
+ force_sig_pkuerr((void __user *)far, pkey);
else
force_sig_fault(signo, code, (void __user *)far);
}
+void arm64_force_sig_fault(int signo, int code, unsigned long far,
+ const char *str)
+{
+ arm64_force_sig_fault_pkey(signo, code, far, str, 0);
+}
+
void arm64_force_sig_mceerr(int code, unsigned long far, short lsb,
const char *str)
{
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 2e5d1e238af9..655dd80f0ec0 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -23,6 +23,7 @@
#include <linux/sched/debug.h>
#include <linux/highmem.h>
#include <linux/perf_event.h>
+#include <linux/pkeys.h>
#include <linux/preempt.h>
#include <linux/hugetlb.h>
@@ -497,6 +498,23 @@ static void do_bad_area(unsigned long far, unsigned long esr,
#define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000)
#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000)
+static bool fault_from_pkey(unsigned long esr, struct vm_area_struct *vma,
+ unsigned int mm_flags)
+{
+ unsigned long iss2 = ESR_ELx_ISS2(esr);
+
+ if (!arch_pkeys_enabled())
+ return false;
+
+ if (iss2 & ESR_ELx_Overlay)
+ return true;
+
+ return !arch_vma_access_permitted(vma,
+ mm_flags & FAULT_FLAG_WRITE,
+ mm_flags & FAULT_FLAG_INSTRUCTION,
+ mm_flags & FAULT_FLAG_REMOTE);
+}
+
static vm_fault_t __do_page_fault(struct mm_struct *mm,
struct vm_area_struct *vma, unsigned long addr,
unsigned int mm_flags, unsigned long vm_flags,
@@ -688,9 +706,29 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
* Something tried to access memory that isn't in our memory
* map.
*/
- arm64_force_sig_fault(SIGSEGV,
- fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
- far, inf->name);
+ int fault_kind;
+ /*
+ * The pkey value that we return to userspace can be different
+ * from the pkey that caused the fault.
+ *
+ * 1. T1 : mprotect_key(foo, PAGE_SIZE, pkey=4);
+ * 2. T1 : set AMR to deny access to pkey=4, touches, page
+ * 3. T1 : faults...
+ * 4. T2: mprotect_key(foo, PAGE_SIZE, pkey=5);
+ * 5. T1 : enters fault handler, takes mmap_lock, etc...
+ * 6. T1 : reaches here, sees vma_pkey(vma)=5, when we really
+ * faulted on a pte with its pkey=4.
+ */
+ int pkey = vma_pkey(vma);
+
+ if (fault_from_pkey(esr, vma, mm_flags))
+ fault_kind = SEGV_PKUERR;
+ else
+ fault_kind = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR;
+
+ arm64_force_sig_fault_pkey(SIGSEGV,
+ fault_kind,
+ far, inf->name, pkey);
}
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 13/24] arm64: stop using generic mm_hooks.h
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (11 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 12/24] arm64: handle PKEY/POE faults Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 14/24] arm64: implement PKEYS support Joey Gouly
` (10 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
These functions will be extended to support pkeys.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/mmu_context.h | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index a6fb325424e7..c0eeed54225e 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -20,7 +20,6 @@
#include <asm/cpufeature.h>
#include <asm/daifflags.h>
#include <asm/proc-fns.h>
-#include <asm-generic/mm_hooks.h>
#include <asm/cputype.h>
#include <asm/sysreg.h>
#include <asm/tlbflush.h>
@@ -209,6 +208,20 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
return 0;
}
+static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
+{
+ return 0;
+}
+
+static inline void arch_exit_mmap(struct mm_struct *mm)
+{
+}
+
+static inline void arch_unmap(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+}
+
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
static inline void update_saved_ttbr0(struct task_struct *tsk,
struct mm_struct *mm)
@@ -298,6 +311,12 @@ static inline unsigned long mm_untag_mask(struct mm_struct *mm)
return -1UL >> 8;
}
+static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
+ bool write, bool execute, bool foreign)
+{
+ return true;
+}
+
#include <asm-generic/mmu_context.h>
#endif /* !__ASSEMBLY__ */
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 14/24] arm64: implement PKEYS support
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (12 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 13/24] arm64: stop using generic mm_hooks.h Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 15/24] arm64: add POE signal support Joey Gouly
` (9 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Implement the PKEYS interface, using the Permission Overlay Extension.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/mmu.h | 2 +
arch/arm64/include/asm/mmu_context.h | 32 ++++++++++++-
arch/arm64/include/asm/pgtable.h | 23 +++++++++-
arch/arm64/include/asm/pkeys.h | 68 +++++++++++++++++++++++++---
arch/arm64/include/asm/por.h | 33 ++++++++++++++
arch/arm64/mm/mmu.c | 35 +++++++++++++-
6 files changed, 184 insertions(+), 9 deletions(-)
create mode 100644 arch/arm64/include/asm/por.h
diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 94b68850cb9f..ed2cd66347d8 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -25,6 +25,8 @@ typedef struct {
refcount_t pinned;
void *vdso;
unsigned long flags;
+
+ u8 pkey_allocation_map;
} mm_context_t;
/*
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index c0eeed54225e..aa739b87d49b 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -15,6 +15,7 @@
#include <linux/sched/hotplug.h>
#include <linux/mm_types.h>
#include <linux/pgtable.h>
+#include <linux/pkeys.h>
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
@@ -205,11 +206,24 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
atomic64_set(&mm->context.id, 0);
refcount_set(&mm->context.pinned, 0);
+
+ // pkey 0 is the default, so always reserve it.
+ mm->context.pkey_allocation_map = 0x1;
+
return 0;
}
+static inline void arch_dup_pkeys(struct mm_struct *oldmm,
+ struct mm_struct *mm)
+{
+ /* Duplicate the oldmm pkey state in mm: */
+ mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
+}
+
static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
{
+ arch_dup_pkeys(oldmm, mm);
+
return 0;
}
@@ -311,10 +325,26 @@ static inline unsigned long mm_untag_mask(struct mm_struct *mm)
return -1UL >> 8;
}
+/*
+ * We only want to enforce protection keys on the current process
+ * because we effectively have no access to POR_EL0 for other
+ * processes or any way to tell *which * POR_EL0 in a threaded
+ * process we could use.
+ *
+ * So do not enforce things if the VMA is not from the current
+ * mm, or if we are in a kernel thread.
+ */
static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
bool write, bool execute, bool foreign)
{
- return true;
+ if (!arch_pkeys_enabled())
+ return true;
+
+ /* allow access if the VMA is not one from this process */
+ if (foreign || vma_is_foreign(vma))
+ return true;
+
+ return por_el0_allows_pkey(vma_pkey(vma), write, execute);
}
#include <asm-generic/mmu_context.h>
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6c57ebe8e349..8a1ff6ed917d 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -30,6 +30,7 @@
#include <asm/cmpxchg.h>
#include <asm/fixmap.h>
+#include <asm/por.h>
#include <linux/mmdebug.h>
#include <linux/mm_types.h>
#include <linux/sched.h>
@@ -143,6 +144,24 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
#define pte_accessible(mm, pte) \
(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
+static inline bool por_el0_allows_pkey(u8 pkey, bool write, bool execute)
+{
+ u64 por;
+
+ if (!system_supports_poe())
+ return true;
+
+ por = read_sysreg_s(SYS_POR_EL0);
+
+ if (write)
+ return por_elx_allows_write(por, pkey);
+
+ if (execute)
+ return por_elx_allows_exec(por, pkey);
+
+ return por_elx_allows_read(por, pkey);
+}
+
/*
* p??_access_permitted() is true for valid user mappings (PTE_USER
* bit set, subject to the write permission check). For execute-only
@@ -151,7 +170,9 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
* PTE_VALID bit set.
*/
#define pte_access_permitted(pte, write) \
- (((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) && (!(write) || pte_write(pte)))
+ (((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) && \
+ (!(write) || pte_write(pte)) && \
+ por_el0_allows_pkey(FIELD_GET(PTE_PO_IDX_MASK, pte_val(pte)), write, false))
#define pmd_access_permitted(pmd, write) \
(pte_access_permitted(pmd_pte(pmd), (write)))
#define pud_access_permitted(pud, write) \
diff --git a/arch/arm64/include/asm/pkeys.h b/arch/arm64/include/asm/pkeys.h
index 5761fb48fd53..a80c654da93d 100644
--- a/arch/arm64/include/asm/pkeys.h
+++ b/arch/arm64/include/asm/pkeys.h
@@ -10,7 +10,7 @@
#define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2)
-#define arch_max_pkey() 0
+#define arch_max_pkey() 7
int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
unsigned long init_val);
@@ -22,33 +22,89 @@ static inline bool arch_pkeys_enabled(void)
static inline int vma_pkey(struct vm_area_struct *vma)
{
- return -1;
+ return (vma->vm_flags & ARCH_VM_PKEY_FLAGS) >> VM_PKEY_SHIFT;
}
static inline int arch_override_mprotect_pkey(struct vm_area_struct *vma,
int prot, int pkey)
{
- return -1;
+ if (pkey != -1)
+ return pkey;
+
+ return vma_pkey(vma);
}
static inline int execute_only_pkey(struct mm_struct *mm)
{
+ // Execute-only mappings are handled by EPAN/FEAT_PAN3.
+ WARN_ON_ONCE(!cpus_have_final_cap(ARM64_HAS_EPAN));
+
return -1;
}
+#define mm_pkey_allocation_map(mm) (mm->context.pkey_allocation_map)
+#define mm_set_pkey_allocated(mm, pkey) do { \
+ mm_pkey_allocation_map(mm) |= (1U << pkey); \
+} while (0)
+#define mm_set_pkey_free(mm, pkey) do { \
+ mm_pkey_allocation_map(mm) &= ~(1U << pkey); \
+} while (0)
+
static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)
{
- return false;
+ /*
+ * "Allocated" pkeys are those that have been returned
+ * from pkey_alloc() or pkey 0 which is allocated
+ * implicitly when the mm is created.
+ */
+ if (pkey < 0)
+ return false;
+ if (pkey >= arch_max_pkey())
+ return false;
+
+ return mm_pkey_allocation_map(mm) & (1U << pkey);
}
+/*
+ * Returns a positive, 3-bit key on success, or -1 on failure.
+ */
static inline int mm_pkey_alloc(struct mm_struct *mm)
{
- return -1;
+ /*
+ * Note: this is the one and only place we make sure
+ * that the pkey is valid as far as the hardware is
+ * concerned. The rest of the kernel trusts that
+ * only good, valid pkeys come out of here.
+ */
+ u8 all_pkeys_mask = ((1U << arch_max_pkey()) - 1);
+ int ret;
+
+ if (!arch_pkeys_enabled())
+ return -1;
+
+ /*
+ * Are we out of pkeys? We must handle this specially
+ * because ffz() behavior is undefined if there are no
+ * zeros.
+ */
+ if (mm_pkey_allocation_map(mm) == all_pkeys_mask)
+ return -1;
+
+ ret = ffz(mm_pkey_allocation_map(mm));
+
+ mm_set_pkey_allocated(mm, ret);
+
+ return ret;
}
static inline int mm_pkey_free(struct mm_struct *mm, int pkey)
{
- return -EINVAL;
+ if (!mm_pkey_is_allocated(mm, pkey))
+ return -EINVAL;
+
+ mm_set_pkey_free(mm, pkey);
+
+ return 0;
}
#endif /* _ASM_ARM64_PKEYS_H */
diff --git a/arch/arm64/include/asm/por.h b/arch/arm64/include/asm/por.h
new file mode 100644
index 000000000000..90484dae9920
--- /dev/null
+++ b/arch/arm64/include/asm/por.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Arm Ltd.
+*/
+
+#ifndef _ASM_ARM64_POR_H
+#define _ASM_ARM64_POR_H
+
+#define POR_BITS_PER_PKEY 4
+#define POR_ELx_IDX(por_elx, idx) (((por_elx) >> (idx * POR_BITS_PER_PKEY)) & 0xf)
+
+static inline bool por_elx_allows_read(u64 por, u8 pkey)
+{
+ u8 perm = POR_ELx_IDX(por, pkey);
+
+ return perm & POE_R;
+}
+
+static inline bool por_elx_allows_write(u64 por, u8 pkey)
+{
+ u8 perm = POR_ELx_IDX(por, pkey);
+
+ return perm & POE_W;
+}
+
+static inline bool por_elx_allows_exec(u64 por, u8 pkey)
+{
+ u8 perm = POR_ELx_IDX(por, pkey);
+
+ return perm & POE_X;
+}
+
+#endif /* _ASM_ARM64_POR_H */
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 11765791b880..eccf5a95ff30 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -25,6 +25,7 @@
#include <linux/vmalloc.h>
#include <linux/set_memory.h>
#include <linux/kfence.h>
+#include <linux/pkeys.h>
#include <asm/barrier.h>
#include <asm/cputype.h>
@@ -1491,6 +1492,38 @@ void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte
#ifdef CONFIG_ARCH_HAS_PKEYS
int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, unsigned long init_val)
{
- return -ENOSPC;
+ u64 new_por = POE_RXW;
+ u64 old_por;
+ u64 pkey_shift;
+
+ if (!arch_pkeys_enabled())
+ return -ENOSPC;
+
+ /*
+ * This code should only be called with valid 'pkey'
+ * values originating from in-kernel users. Complain
+ * if a bad value is observed.
+ */
+ if (WARN_ON_ONCE(pkey >= arch_max_pkey()))
+ return -EINVAL;
+
+ /* Set the bits we need in POR: */
+ if (init_val & PKEY_DISABLE_ACCESS)
+ new_por = POE_X;
+ else if (init_val & PKEY_DISABLE_WRITE)
+ new_por = POE_RX;
+
+ /* Shift the bits in to the correct place in POR for pkey: */
+ pkey_shift = pkey * POR_BITS_PER_PKEY;
+ new_por <<= pkey_shift;
+
+ /* Get old POR and mask off any old bits in place: */
+ old_por = read_sysreg_s(SYS_POR_EL0);
+ old_por &= ~(POE_MASK << pkey_shift);
+
+ /* Write old part along with new part: */
+ write_sysreg_s(old_por | new_por, SYS_POR_EL0);
+
+ return 0;
}
#endif
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 15/24] arm64: add POE signal support
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (13 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 14/24] arm64: implement PKEYS support Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-30 19:10 ` Mark Brown
2023-10-27 18:08 ` [PATCH v2 16/24] arm64: enable PKEY support for CPUs with S1POE Joey Gouly
` (8 subsequent siblings)
23 siblings, 1 reply; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Add PKEY support to signals, by saving and restoring POR_EL0 from the stackframe.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/uapi/asm/sigcontext.h | 7 ++++
arch/arm64/kernel/signal.c | 51 ++++++++++++++++++++++++
2 files changed, 58 insertions(+)
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index f23c1dc3f002..cef85eeaf541 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -98,6 +98,13 @@ struct esr_context {
__u64 esr;
};
+#define POE_MAGIC 0x504f4530
+
+struct poe_context {
+ struct _aarch64_ctx head;
+ __u64 por_el0;
+};
+
/*
* extra_context: describes extra space in the signal frame for
* additional structures that don't fit in sigcontext.__reserved[].
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 0e8beb3349ea..379f364005bf 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -62,6 +62,7 @@ struct rt_sigframe_user_layout {
unsigned long zt_offset;
unsigned long extra_offset;
unsigned long end_offset;
+ unsigned long poe_offset;
};
#define BASE_SIGFRAME_SIZE round_up(sizeof(struct rt_sigframe), 16)
@@ -182,6 +183,8 @@ struct user_ctxs {
u32 za_size;
struct zt_context __user *zt;
u32 zt_size;
+ struct poe_context __user *poe;
+ u32 poe_size;
};
static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
@@ -227,6 +230,20 @@ static int restore_fpsimd_context(struct user_ctxs *user)
return err ? -EFAULT : 0;
}
+static int restore_poe_context(struct user_ctxs *user)
+{
+ u64 por_el0;
+ int err = 0;
+
+ if (user->poe_size != sizeof(*user->poe))
+ return -EINVAL;
+
+ __get_user_error(por_el0, &(user->poe->por_el0), err);
+ if (!err)
+ write_sysreg_s(por_el0, SYS_POR_EL0);
+
+ return err;
+}
#ifdef CONFIG_ARM64_SVE
@@ -590,6 +607,7 @@ static int parse_user_sigframe(struct user_ctxs *user,
user->tpidr2 = NULL;
user->za = NULL;
user->zt = NULL;
+ user->poe = NULL;
if (!IS_ALIGNED((unsigned long)base, 16))
goto invalid;
@@ -640,6 +658,17 @@ static int parse_user_sigframe(struct user_ctxs *user,
/* ignore */
break;
+ case POE_MAGIC:
+ if (!system_supports_poe())
+ goto invalid;
+
+ if (user->poe)
+ goto invalid;
+
+ user->poe = (struct poe_context __user *)head;
+ user->poe_size = size;
+ break;
+
case SVE_MAGIC:
if (!system_supports_sve() && !system_supports_sme())
goto invalid;
@@ -812,6 +841,9 @@ static int restore_sigframe(struct pt_regs *regs,
if (err == 0 && system_supports_sme2() && user.zt)
err = restore_zt_context(&user);
+ if (err == 0 && system_supports_poe() && user.poe)
+ err = restore_poe_context(&user);
+
return err;
}
@@ -928,6 +960,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user,
}
}
+ if (system_supports_poe()) {
+ err = sigframe_alloc(user, &user->poe_offset,
+ sizeof(struct poe_context));
+ if (err)
+ return err;
+ }
+
return sigframe_alloc_end(user);
}
@@ -968,6 +1007,15 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user,
__put_user_error(current->thread.fault_code, &esr_ctx->esr, err);
}
+ if (system_supports_poe() && err == 0 && user->poe_offset) {
+ struct poe_context __user *poe_ctx =
+ apply_user_offset(user, user->poe_offset);
+
+ __put_user_error(POE_MAGIC, &poe_ctx->head.magic, err);
+ __put_user_error(sizeof(*poe_ctx), &poe_ctx->head.size, err);
+ __put_user_error(read_sysreg_s(SYS_POR_EL0), &poe_ctx->por_el0, err);
+ }
+
/* Scalable Vector Extension state (including streaming), if present */
if ((system_supports_sve() || system_supports_sme()) &&
err == 0 && user->sve_offset) {
@@ -1119,6 +1167,9 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
sme_smstop();
}
+ if (system_supports_poe())
+ write_sysreg_s(POR_EL0_INIT, SYS_POR_EL0);
+
if (ka->sa.sa_flags & SA_RESTORER)
sigtramp = ka->sa.sa_restorer;
else
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v2 15/24] arm64: add POE signal support
2023-10-27 18:08 ` [PATCH v2 15/24] arm64: add POE signal support Joey Gouly
@ 2023-10-30 19:10 ` Mark Brown
0 siblings, 0 replies; 28+ messages in thread
From: Mark Brown @ 2023-10-30 19:10 UTC (permalink / raw)
To: Joey Gouly
Cc: linux-arm-kernel, akpm, aneesh.kumar, catalin.marinas,
dave.hansen, maz, oliver.upton, shuah, will, kvmarm,
linux-fsdevel, linux-mm, linux-kselftest, James Morse,
Suzuki K Poulose, Zenghui Yu
[-- Attachment #1: Type: text/plain, Size: 190 bytes --]
On Fri, Oct 27, 2023 at 07:08:41PM +0100, Joey Gouly wrote:
> Add PKEY support to signals, by saving and restoring POR_EL0 from the stackframe.
Reviewed-by: Mark Brown <broonie@kernel.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v2 16/24] arm64: enable PKEY support for CPUs with S1POE
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (14 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 15/24] arm64: add POE signal support Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 17/24] arm64: enable POE and PIE to coexist Joey Gouly
` (7 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Now that PKEYs support has been implemented, enable it for CPUs that
support S1POE.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/pkeys.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/pkeys.h b/arch/arm64/include/asm/pkeys.h
index a80c654da93d..23c473300058 100644
--- a/arch/arm64/include/asm/pkeys.h
+++ b/arch/arm64/include/asm/pkeys.h
@@ -17,7 +17,7 @@ int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
static inline bool arch_pkeys_enabled(void)
{
- return false;
+ return system_supports_poe();
}
static inline int vma_pkey(struct vm_area_struct *vma)
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 17/24] arm64: enable POE and PIE to coexist
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (15 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 16/24] arm64: enable PKEY support for CPUs with S1POE Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 18/24] kselftest/arm64: move get_header() Joey Gouly
` (6 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Set the EL0/userspace indirection encodings to be the overlay enabled
variants of the permissions.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/pgtable-prot.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index eed814b00a38..06fb944ef252 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -141,10 +141,10 @@ extern bool arm64_use_ng_mappings;
#define PIE_E0 ( \
PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_X_O) | \
- PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX) | \
- PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX) | \
- PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R) | \
- PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW))
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_RX_O) | \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RWX_O) | \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY), PIE_R_O) | \
+ PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED), PIE_RW_O))
#define PIE_E1 ( \
PIRx_ELx_PERM(pte_pi_index(_PAGE_EXECONLY), PIE_NONE_O) | \
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 18/24] kselftest/arm64: move get_header()
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (16 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 17/24] arm64: enable POE and PIE to coexist Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 19/24] selftests: mm: move fpregs printing Joey Gouly
` (5 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Put this function in the header so that it can be used by other tests, without
needing to link to testcases.c.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
.../arm64/signal/testcases/testcases.c | 23 -----------------
.../arm64/signal/testcases/testcases.h | 25 +++++++++++++++++--
2 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
index 9f580b55b388..fe950b6bca6b 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.c
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
@@ -6,29 +6,6 @@
#include "testcases.h"
-struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
- size_t resv_sz, size_t *offset)
-{
- size_t offs = 0;
- struct _aarch64_ctx *found = NULL;
-
- if (!head || resv_sz < HDR_SZ)
- return found;
-
- while (offs <= resv_sz - HDR_SZ &&
- head->magic != magic && head->magic) {
- offs += head->size;
- head = GET_RESV_NEXT_HEAD(head);
- }
- if (head->magic == magic) {
- found = head;
- if (offset)
- *offset = offs;
- }
-
- return found;
-}
-
bool validate_extra_context(struct extra_context *extra, char **err,
void **extra_data, size_t *extra_size)
{
diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.h b/tools/testing/selftests/arm64/signal/testcases/testcases.h
index a08ab0d6207a..d33154c9a4bd 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.h
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.h
@@ -87,8 +87,29 @@ struct fake_sigframe {
bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err);
-struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
- size_t resv_sz, size_t *offset);
+static inline struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
+ size_t resv_sz, size_t *offset)
+{
+ size_t offs = 0;
+ struct _aarch64_ctx *found = NULL;
+
+ if (!head || resv_sz < HDR_SZ)
+ return found;
+
+ while (offs <= resv_sz - HDR_SZ &&
+ head->magic != magic && head->magic) {
+ offs += head->size;
+ head = GET_RESV_NEXT_HEAD(head);
+ }
+ if (head->magic == magic) {
+ found = head;
+ if (offset)
+ *offset = offs;
+ }
+
+ return found;
+}
+
static inline struct _aarch64_ctx *get_terminator(struct _aarch64_ctx *head,
size_t resv_sz,
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 19/24] selftests: mm: move fpregs printing
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (17 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 18/24] kselftest/arm64: move get_header() Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 20/24] selftests: mm: make protection_keys test work on arm64 Joey Gouly
` (4 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
arm64's fpregs are not at a constant offset from sigcontext. Since this is
not an important part of the test, don't print the fpregs pointer on arm64.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
---
tools/testing/selftests/mm/pkey-powerpc.h | 1 +
tools/testing/selftests/mm/pkey-x86.h | 2 ++
tools/testing/selftests/mm/protection_keys.c | 6 ++++++
3 files changed, 9 insertions(+)
diff --git a/tools/testing/selftests/mm/pkey-powerpc.h b/tools/testing/selftests/mm/pkey-powerpc.h
index ae5df26104e5..6275d0f474b3 100644
--- a/tools/testing/selftests/mm/pkey-powerpc.h
+++ b/tools/testing/selftests/mm/pkey-powerpc.h
@@ -9,6 +9,7 @@
#endif
#define REG_IP_IDX PT_NIP
#define REG_TRAPNO PT_TRAP
+#define MCONTEXT_FPREGS
#define gregs gp_regs
#define fpregs fp_regs
#define si_pkey_offset 0x20
diff --git a/tools/testing/selftests/mm/pkey-x86.h b/tools/testing/selftests/mm/pkey-x86.h
index 814758e109c0..b9170a26bfcb 100644
--- a/tools/testing/selftests/mm/pkey-x86.h
+++ b/tools/testing/selftests/mm/pkey-x86.h
@@ -15,6 +15,8 @@
#endif
+#define MCONTEXT_FPREGS
+
#ifndef PKEY_DISABLE_ACCESS
# define PKEY_DISABLE_ACCESS 0x1
#endif
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index 48dc151f8fca..b3dbd76ea27c 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -314,7 +314,9 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
ucontext_t *uctxt = vucontext;
int trapno;
unsigned long ip;
+#ifdef MCONTEXT_FPREGS
char *fpregs;
+#endif
#if defined(__i386__) || defined(__x86_64__) /* arch */
u32 *pkey_reg_ptr;
int pkey_reg_offset;
@@ -330,7 +332,9 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
+#ifdef MCONTEXT_FPREGS
fpregs = (char *) uctxt->uc_mcontext.fpregs;
+#endif
dprintf2("%s() trapno: %d ip: 0x%016lx info->si_code: %s/%d\n",
__func__, trapno, ip, si_code_str(si->si_code),
@@ -359,7 +363,9 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
#endif /* arch */
dprintf1("siginfo: %p\n", si);
+#ifdef MCONTEXT_FPREGS
dprintf1(" fpregs: %p\n", fpregs);
+#endif
if ((si->si_code == SEGV_MAPERR) ||
(si->si_code == SEGV_ACCERR) ||
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 20/24] selftests: mm: make protection_keys test work on arm64
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (18 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 19/24] selftests: mm: move fpregs printing Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 21/24] kselftest/arm64: add HWCAP test for FEAT_S1POE Joey Gouly
` (3 subsequent siblings)
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
The encoding of the pkey register differs on arm64, than on x86/ppc. On those
platforms, a bit in the register is used to disable permissions, for arm64, a
bit enabled in the register indicates that the permission is allowed.
This drops two asserts of the form:
assert(read_pkey_reg() <= orig_pkey_reg);
Because on arm64 this doesn't hold, due to the encoding.
The pkey must be reset to both access allow and write allow in the signal
handler. pkey_access_allow() works currently for PowerPC as the
PKEY_DISABLE_ACCESS and PKEY_DISABLE_WRITE have overlapping bits set.
Access to the uc_mcontext is abstracted, as arm64 has a different structure.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
---
.../arm64/signal/testcases/testcases.h | 3 +
tools/testing/selftests/mm/Makefile | 2 +-
tools/testing/selftests/mm/pkey-arm64.h | 138 ++++++++++++++++++
tools/testing/selftests/mm/pkey-helpers.h | 8 +
tools/testing/selftests/mm/pkey-powerpc.h | 2 +
tools/testing/selftests/mm/pkey-x86.h | 2 +
tools/testing/selftests/mm/protection_keys.c | 23 +--
7 files changed, 167 insertions(+), 11 deletions(-)
create mode 100644 tools/testing/selftests/mm/pkey-arm64.h
diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.h b/tools/testing/selftests/arm64/signal/testcases/testcases.h
index d33154c9a4bd..e445027d5ec2 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.h
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.h
@@ -25,6 +25,9 @@
#define HDR_SZ \
sizeof(struct _aarch64_ctx)
+#define GET_UC_RESV_HEAD(uc) \
+ (struct _aarch64_ctx *)(&(uc->uc_mcontext.__reserved))
+
#define GET_SF_RESV_HEAD(sf) \
(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
index 6a9fc5693145..f50987233f55 100644
--- a/tools/testing/selftests/mm/Makefile
+++ b/tools/testing/selftests/mm/Makefile
@@ -95,7 +95,7 @@ TEST_GEN_FILES += $(BINARIES_64)
endif
else
-ifneq (,$(findstring $(ARCH),ppc64))
+ifneq (,$(filter $(ARCH),arm64 ppc64))
TEST_GEN_FILES += protection_keys
endif
diff --git a/tools/testing/selftests/mm/pkey-arm64.h b/tools/testing/selftests/mm/pkey-arm64.h
new file mode 100644
index 000000000000..3a5d8ba69bb7
--- /dev/null
+++ b/tools/testing/selftests/mm/pkey-arm64.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023 Arm Ltd.
+*/
+
+#ifndef _PKEYS_ARM64_H
+#define _PKEYS_ARM64_H
+
+#include "vm_util.h"
+/* for signal frame parsing */
+#include "../arm64/signal/testcases/testcases.h"
+
+#ifndef SYS_mprotect_key
+# define SYS_mprotect_key 288
+#endif
+#ifndef SYS_pkey_alloc
+# define SYS_pkey_alloc 289
+# define SYS_pkey_free 290
+#endif
+#define MCONTEXT_IP(mc) mc.pc
+#define MCONTEXT_TRAPNO(mc) -1
+
+#define PKEY_MASK 0xf
+
+#define POE_X 0x2
+#define POE_RX 0x3
+#define POE_RWX 0x7
+
+#define NR_PKEYS 7
+#define NR_RESERVED_PKEYS 1 /* pkey-0 */
+
+#define PKEY_ALLOW_ALL 0x77777777
+
+#define PKEY_BITS_PER_PKEY 4
+#define PAGE_SIZE sysconf(_SC_PAGESIZE)
+#undef HPAGE_SIZE
+#define HPAGE_SIZE default_huge_page_size()
+
+/* 4-byte instructions * 16384 = 64K page */
+#define __page_o_noops() asm(".rept 16384 ; nop; .endr")
+
+static inline u64 __read_pkey_reg(void)
+{
+ u64 pkey_reg = 0;
+
+ // POR_EL0
+ asm volatile("mrs %0, S3_3_c10_c2_4" : "=r" (pkey_reg));
+
+ return pkey_reg;
+}
+
+static inline void __write_pkey_reg(u64 pkey_reg)
+{
+ u64 por = pkey_reg;
+
+ dprintf4("%s() changing %016llx to %016llx\n",
+ __func__, __read_pkey_reg(), pkey_reg);
+
+ // POR_EL0
+ asm volatile("msr S3_3_c10_c2_4, %0\nisb" :: "r" (por) :);
+
+ dprintf4("%s() pkey register after changing %016llx to %016llx\n",
+ __func__, __read_pkey_reg(), pkey_reg);
+}
+
+static inline int cpu_has_pkeys(void)
+{
+ /* No simple way to determine this */
+ return 1;
+}
+
+static inline u32 pkey_bit_position(int pkey)
+{
+ return pkey * PKEY_BITS_PER_PKEY;
+}
+
+static inline int get_arch_reserved_keys(void)
+{
+ return NR_RESERVED_PKEYS;
+}
+
+void expect_fault_on_read_execonly_key(void *p1, int pkey)
+{
+}
+
+void *malloc_pkey_with_mprotect_subpage(long size, int prot, u16 pkey)
+{
+ return PTR_ERR_ENOTSUP;
+}
+
+#define set_pkey_bits set_pkey_bits
+static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
+{
+ u32 shift = pkey_bit_position(pkey);
+ u64 new_val = POE_RWX;
+
+ /* mask out bits from pkey in old value */
+ reg &= ~((u64)PKEY_MASK << shift);
+
+ if (flags & PKEY_DISABLE_ACCESS)
+ new_val = POE_X;
+ else if (flags & PKEY_DISABLE_WRITE)
+ new_val = POE_RX;
+
+ /* OR in new bits for pkey */
+ reg |= new_val << shift;
+
+ return reg;
+}
+
+#define get_pkey_bits get_pkey_bits
+static inline u64 get_pkey_bits(u64 reg, int pkey)
+{
+ u32 shift = pkey_bit_position(pkey);
+ /*
+ * shift down the relevant bits to the lowest two, then
+ * mask off all the other higher bits
+ */
+ u32 perm = (reg >> shift) & PKEY_MASK;
+
+ if (perm == POE_X)
+ return PKEY_DISABLE_ACCESS;
+ if (perm == POE_RX)
+ return PKEY_DISABLE_WRITE;
+ return 0;
+}
+
+static void aarch64_write_signal_pkey(ucontext_t *uctxt, u64 pkey)
+{
+ struct _aarch64_ctx *ctx = GET_UC_RESV_HEAD(uctxt);
+ struct poe_context *poe_ctx =
+ (struct poe_context *) get_header(ctx, POE_MAGIC,
+ sizeof(uctxt->uc_mcontext), NULL);
+ if (poe_ctx)
+ poe_ctx->por_el0 = pkey;
+}
+
+#endif /* _PKEYS_ARM64_H */
diff --git a/tools/testing/selftests/mm/pkey-helpers.h b/tools/testing/selftests/mm/pkey-helpers.h
index 92f3be3dd8e5..07d131f98043 100644
--- a/tools/testing/selftests/mm/pkey-helpers.h
+++ b/tools/testing/selftests/mm/pkey-helpers.h
@@ -91,12 +91,17 @@ void record_pkey_malloc(void *ptr, long size, int prot);
#include "pkey-x86.h"
#elif defined(__powerpc64__) /* arch */
#include "pkey-powerpc.h"
+#elif defined(__aarch64__) /* arch */
+#include "pkey-arm64.h"
#else /* arch */
#error Architecture not supported
#endif /* arch */
+#ifndef PKEY_MASK
#define PKEY_MASK (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
+#endif
+#ifndef set_pkey_bits
static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
{
u32 shift = pkey_bit_position(pkey);
@@ -106,7 +111,9 @@ static inline u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
reg |= (flags & PKEY_MASK) << shift;
return reg;
}
+#endif
+#ifndef get_pkey_bits
static inline u64 get_pkey_bits(u64 reg, int pkey)
{
u32 shift = pkey_bit_position(pkey);
@@ -116,6 +123,7 @@ static inline u64 get_pkey_bits(u64 reg, int pkey)
*/
return ((reg >> shift) & PKEY_MASK);
}
+#endif
extern u64 shadow_pkey_reg;
diff --git a/tools/testing/selftests/mm/pkey-powerpc.h b/tools/testing/selftests/mm/pkey-powerpc.h
index 6275d0f474b3..3d0c0bdae5bc 100644
--- a/tools/testing/selftests/mm/pkey-powerpc.h
+++ b/tools/testing/selftests/mm/pkey-powerpc.h
@@ -8,6 +8,8 @@
# define SYS_pkey_free 385
#endif
#define REG_IP_IDX PT_NIP
+#define MCONTEXT_IP(mc) mc.gp_regs[REG_IP_IDX]
+#define MCONTEXT_TRAPNO(mc) mc.gp_regs[REG_TRAPNO]
#define REG_TRAPNO PT_TRAP
#define MCONTEXT_FPREGS
#define gregs gp_regs
diff --git a/tools/testing/selftests/mm/pkey-x86.h b/tools/testing/selftests/mm/pkey-x86.h
index b9170a26bfcb..5f28e26a2511 100644
--- a/tools/testing/selftests/mm/pkey-x86.h
+++ b/tools/testing/selftests/mm/pkey-x86.h
@@ -15,6 +15,8 @@
#endif
+#define MCONTEXT_IP(mc) mc.gregs[REG_IP_IDX]
+#define MCONTEXT_TRAPNO(mc) mc.gregs[REG_TRAPNO]
#define MCONTEXT_FPREGS
#ifndef PKEY_DISABLE_ACCESS
diff --git a/tools/testing/selftests/mm/protection_keys.c b/tools/testing/selftests/mm/protection_keys.c
index b3dbd76ea27c..14883d551531 100644
--- a/tools/testing/selftests/mm/protection_keys.c
+++ b/tools/testing/selftests/mm/protection_keys.c
@@ -147,7 +147,7 @@ void abort_hooks(void)
* will then fault, which makes sure that the fault code handles
* execute-only memory properly.
*/
-#ifdef __powerpc64__
+#if defined(__powerpc64__) || defined(__aarch64__)
/* This way, both 4K and 64K alignment are maintained */
__attribute__((__aligned__(65536)))
#else
@@ -212,7 +212,6 @@ void pkey_disable_set(int pkey, int flags)
unsigned long syscall_flags = 0;
int ret;
int pkey_rights;
- u64 orig_pkey_reg = read_pkey_reg();
dprintf1("START->%s(%d, 0x%x)\n", __func__,
pkey, flags);
@@ -242,8 +241,6 @@ void pkey_disable_set(int pkey, int flags)
dprintf1("%s(%d) pkey_reg: 0x%016llx\n",
__func__, pkey, read_pkey_reg());
- if (flags)
- pkey_assert(read_pkey_reg() >= orig_pkey_reg);
dprintf1("END<---%s(%d, 0x%x)\n", __func__,
pkey, flags);
}
@@ -253,7 +250,6 @@ void pkey_disable_clear(int pkey, int flags)
unsigned long syscall_flags = 0;
int ret;
int pkey_rights = hw_pkey_get(pkey, syscall_flags);
- u64 orig_pkey_reg = read_pkey_reg();
pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
@@ -273,8 +269,6 @@ void pkey_disable_clear(int pkey, int flags)
dprintf1("%s(%d) pkey_reg: 0x%016llx\n", __func__,
pkey, read_pkey_reg());
- if (flags)
- assert(read_pkey_reg() <= orig_pkey_reg);
}
void pkey_write_allow(int pkey)
@@ -330,8 +324,8 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
__func__, __LINE__,
__read_pkey_reg(), shadow_pkey_reg);
- trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
- ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
+ trapno = MCONTEXT_TRAPNO(uctxt->uc_mcontext);
+ ip = MCONTEXT_IP(uctxt->uc_mcontext);
#ifdef MCONTEXT_FPREGS
fpregs = (char *) uctxt->uc_mcontext.fpregs;
#endif
@@ -395,6 +389,8 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext)
#elif defined(__powerpc64__) /* arch */
/* restore access and let the faulting instruction continue */
pkey_access_allow(siginfo_pkey);
+#elif defined(__aarch64__)
+ aarch64_write_signal_pkey(uctxt, PKEY_ALLOW_ALL);
#endif /* arch */
pkey_faults++;
dprintf1("<<<<==================================================\n");
@@ -908,7 +904,9 @@ void expected_pkey_fault(int pkey)
* test program continue. We now have to restore it.
*/
if (__read_pkey_reg() != 0)
-#else /* arch */
+#elif defined(__aarch64__)
+ if (__read_pkey_reg() != PKEY_ALLOW_ALL)
+#else
if (__read_pkey_reg() != shadow_pkey_reg)
#endif /* arch */
pkey_assert(0);
@@ -1498,6 +1496,11 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
lots_o_noops_around_write(&scratch);
do_not_expect_pkey_fault("executing on PROT_EXEC memory");
expect_fault_on_read_execonly_key(p1, pkey);
+
+ // Reset back to PROT_EXEC | PROT_READ for architectures that support
+ // non-PKEY execute-only permissions.
+ ret = mprotect_pkey(p1, PAGE_SIZE, PROT_EXEC | PROT_READ, (u64)pkey);
+ pkey_assert(!ret);
}
void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey)
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 21/24] kselftest/arm64: add HWCAP test for FEAT_S1POE
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (19 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 20/24] selftests: mm: make protection_keys test work on arm64 Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-30 19:18 ` Mark Brown
2023-10-27 18:08 ` [PATCH v2 22/24] kselftest/arm64: parse POE_MAGIC in a signal frame Joey Gouly
` (2 subsequent siblings)
23 siblings, 1 reply; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Check that when POE is enabled, the POR_EL0 register is accessible.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
---
tools/testing/selftests/arm64/abi/hwcap.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c
index e3d262831d91..64bb49fe3f5c 100644
--- a/tools/testing/selftests/arm64/abi/hwcap.c
+++ b/tools/testing/selftests/arm64/abi/hwcap.c
@@ -101,6 +101,12 @@ static void pmull_sigill(void)
asm volatile(".inst 0x0ee0e000" : : : );
}
+static void poe_sigill(void)
+{
+ /* mrs x0, POR_EL0 */
+ asm volatile("mrs x0, S3_3_C10_C2_4" : : : "x0");
+}
+
static void rng_sigill(void)
{
asm volatile("mrs x0, S3_3_C2_C4_0" : : : "x0");
@@ -379,6 +385,13 @@ static const struct hwcap_data {
.cpuinfo = "pmull",
.sigill_fn = pmull_sigill,
},
+ {
+ .name = "POE",
+ .at_hwcap = AT_HWCAP2,
+ .hwcap_bit = HWCAP2_POE,
+ .cpuinfo = "poe",
+ .sigill_fn = poe_sigill,
+ },
{
.name = "RNG",
.at_hwcap = AT_HWCAP2,
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v2 21/24] kselftest/arm64: add HWCAP test for FEAT_S1POE
2023-10-27 18:08 ` [PATCH v2 21/24] kselftest/arm64: add HWCAP test for FEAT_S1POE Joey Gouly
@ 2023-10-30 19:18 ` Mark Brown
0 siblings, 0 replies; 28+ messages in thread
From: Mark Brown @ 2023-10-30 19:18 UTC (permalink / raw)
To: Joey Gouly
Cc: linux-arm-kernel, akpm, aneesh.kumar, catalin.marinas,
dave.hansen, maz, oliver.upton, shuah, will, kvmarm,
linux-fsdevel, linux-mm, linux-kselftest, James Morse,
Suzuki K Poulose, Zenghui Yu
[-- Attachment #1: Type: text/plain, Size: 326 bytes --]
On Fri, Oct 27, 2023 at 07:08:47PM +0100, Joey Gouly wrote:
> + {
> + .name = "POE",
> + .at_hwcap = AT_HWCAP2,
> + .hwcap_bit = HWCAP2_POE,
> + .cpuinfo = "poe",
> + .sigill_fn = poe_sigill,
> + },
We should set sigill_reliable here - there's a trap for the POR_EL0 so
the test must fail if the hwcap isn't available.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v2 22/24] kselftest/arm64: parse POE_MAGIC in a signal frame
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (20 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 21/24] kselftest/arm64: add HWCAP test for FEAT_S1POE Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-30 19:19 ` Mark Brown
2023-10-27 18:08 ` [PATCH v2 23/24] kselftest/arm64: Add test case for POR_EL0 signal frame records Joey Gouly
2023-10-27 18:08 ` [PATCH v2 24/24] KVM: selftests: get-reg-list: add Permission Overlay registers Joey Gouly
23 siblings, 1 reply; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Teach the signal frame parsing about the new POE frame, avoids warning when it
is generated.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
---
tools/testing/selftests/arm64/signal/testcases/testcases.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c
index fe950b6bca6b..5dda753870aa 100644
--- a/tools/testing/selftests/arm64/signal/testcases/testcases.c
+++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c
@@ -161,6 +161,10 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
if (head->size != sizeof(struct esr_context))
*err = "Bad size for esr_context";
break;
+ case POE_MAGIC:
+ if (head->size != sizeof(struct poe_context))
+ *err = "Bad size for poe_context";
+ break;
case TPIDR2_MAGIC:
if (head->size != sizeof(struct tpidr2_context))
*err = "Bad size for tpidr2_context";
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v2 22/24] kselftest/arm64: parse POE_MAGIC in a signal frame
2023-10-27 18:08 ` [PATCH v2 22/24] kselftest/arm64: parse POE_MAGIC in a signal frame Joey Gouly
@ 2023-10-30 19:19 ` Mark Brown
0 siblings, 0 replies; 28+ messages in thread
From: Mark Brown @ 2023-10-30 19:19 UTC (permalink / raw)
To: Joey Gouly
Cc: linux-arm-kernel, akpm, aneesh.kumar, catalin.marinas,
dave.hansen, maz, oliver.upton, shuah, will, kvmarm,
linux-fsdevel, linux-mm, linux-kselftest, James Morse,
Suzuki K Poulose, Zenghui Yu
[-- Attachment #1: Type: text/plain, Size: 203 bytes --]
On Fri, Oct 27, 2023 at 07:08:48PM +0100, Joey Gouly wrote:
> Teach the signal frame parsing about the new POE frame, avoids warning when it
> is generated.
Reviewed-by: Mark Brown <broonie@kernel.org>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v2 23/24] kselftest/arm64: Add test case for POR_EL0 signal frame records
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (21 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 22/24] kselftest/arm64: parse POE_MAGIC in a signal frame Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
2023-10-27 18:08 ` [PATCH v2 24/24] KVM: selftests: get-reg-list: add Permission Overlay registers Joey Gouly
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Ensure that we get signal context for POR_EL0 if and only if POE is present
on the system.
Copied from the TPIDR2 test.
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
---
.../testing/selftests/arm64/signal/.gitignore | 1 +
.../arm64/signal/testcases/poe_siginfo.c | 86 +++++++++++++++++++
2 files changed, 87 insertions(+)
create mode 100644 tools/testing/selftests/arm64/signal/testcases/poe_siginfo.c
diff --git a/tools/testing/selftests/arm64/signal/.gitignore b/tools/testing/selftests/arm64/signal/.gitignore
index 839e3a252629..6bcb27bd506b 100644
--- a/tools/testing/selftests/arm64/signal/.gitignore
+++ b/tools/testing/selftests/arm64/signal/.gitignore
@@ -5,6 +5,7 @@ sme_*
ssve_*
sve_*
tpidr2_*
+poe_siginfo
za_*
zt_*
!*.[ch]
diff --git a/tools/testing/selftests/arm64/signal/testcases/poe_siginfo.c b/tools/testing/selftests/arm64/signal/testcases/poe_siginfo.c
new file mode 100644
index 000000000000..d890029304c4
--- /dev/null
+++ b/tools/testing/selftests/arm64/signal/testcases/poe_siginfo.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Arm Limited
+ *
+ * Verify that the POR_EL0 register context in signal frames is set up as
+ * expected.
+ */
+
+#include <signal.h>
+#include <ucontext.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+#include <asm/sigcontext.h>
+
+#include "test_signals_utils.h"
+#include "testcases.h"
+
+static union {
+ ucontext_t uc;
+ char buf[1024 * 128];
+} context;
+
+#define SYS_POR_EL0 "S3_3_C10_C2_4"
+
+static uint64_t get_por_el0(void)
+{
+ uint64_t val;
+
+ asm volatile (
+ "mrs %0, " SYS_POR_EL0 "\n"
+ : "=r"(val)
+ :
+ : "cc");
+
+ return val;
+}
+
+int poe_present(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
+{
+ struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context);
+ struct poe_context *poe_ctx;
+ size_t offset;
+ bool in_sigframe;
+ bool have_poe;
+ __u64 orig_poe;
+
+ have_poe = getauxval(AT_HWCAP2) & HWCAP2_POE;
+ if (have_poe)
+ orig_poe = get_por_el0();
+
+ if (!get_current_context(td, &context.uc, sizeof(context)))
+ return 1;
+
+ poe_ctx = (struct poe_context *)
+ get_header(head, POE_MAGIC, td->live_sz, &offset);
+
+ in_sigframe = poe_ctx != NULL;
+
+ fprintf(stderr, "POR_EL0 sigframe %s on system %s POE\n",
+ in_sigframe ? "present" : "absent",
+ have_poe ? "with" : "without");
+
+ td->pass = (in_sigframe == have_poe);
+
+ /*
+ * Check that the value we read back was the one present at
+ * the time that the signal was triggered.
+ */
+ if (have_poe && poe_ctx) {
+ if (poe_ctx->por_el0 != orig_poe) {
+ fprintf(stderr, "POR_EL0 in frame is %llx, was %llx\n",
+ poe_ctx->por_el0, orig_poe);
+ td->pass = false;
+ }
+ }
+
+ return 0;
+}
+
+struct tdescr tde = {
+ .name = "POR_EL0",
+ .descr = "Validate that POR_EL0 is present as expected",
+ .timeout = 3,
+ .run = poe_present,
+};
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v2 24/24] KVM: selftests: get-reg-list: add Permission Overlay registers
2023-10-27 18:08 [PATCH v2 00/20] Permission Overlay Extension Joey Gouly
` (22 preceding siblings ...)
2023-10-27 18:08 ` [PATCH v2 23/24] kselftest/arm64: Add test case for POR_EL0 signal frame records Joey Gouly
@ 2023-10-27 18:08 ` Joey Gouly
23 siblings, 0 replies; 28+ messages in thread
From: Joey Gouly @ 2023-10-27 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Cc: akpm, aneesh.kumar, broonie, catalin.marinas, dave.hansen,
joey.gouly, maz, oliver.upton, shuah, will, kvmarm, linux-fsdevel,
linux-mm, linux-kselftest, James Morse, Suzuki K Poulose,
Zenghui Yu
Add new system registers:
- POR_EL1
- POR_EL0
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oliver.upton@linux.dev>
Cc: Shuah Khan <shuah@kernel.org>
---
tools/testing/selftests/kvm/aarch64/get-reg-list.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list.c b/tools/testing/selftests/kvm/aarch64/get-reg-list.c
index 709d7d721760..ac661ebf6859 100644
--- a/tools/testing/selftests/kvm/aarch64/get-reg-list.c
+++ b/tools/testing/selftests/kvm/aarch64/get-reg-list.c
@@ -40,6 +40,18 @@ static struct feature_id_reg feat_id_regs[] = {
ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */
4,
1
+ },
+ {
+ ARM64_SYS_REG(3, 0, 10, 2, 4), /* POR_EL1 */
+ ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */
+ 16,
+ 1
+ },
+ {
+ ARM64_SYS_REG(3, 3, 10, 2, 4), /* POR_EL0 */
+ ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */
+ 16,
+ 1
}
};
@@ -468,6 +480,7 @@ static __u64 base_regs[] = {
ARM64_SYS_REG(3, 0, 10, 2, 0), /* MAIR_EL1 */
ARM64_SYS_REG(3, 0, 10, 2, 2), /* PIRE0_EL1 */
ARM64_SYS_REG(3, 0, 10, 2, 3), /* PIR_EL1 */
+ ARM64_SYS_REG(3, 0, 10, 2, 4), /* POR_EL1 */
ARM64_SYS_REG(3, 0, 10, 3, 0), /* AMAIR_EL1 */
ARM64_SYS_REG(3, 0, 12, 0, 0), /* VBAR_EL1 */
ARM64_SYS_REG(3, 0, 12, 1, 1), /* DISR_EL1 */
@@ -475,6 +488,7 @@ static __u64 base_regs[] = {
ARM64_SYS_REG(3, 0, 13, 0, 4), /* TPIDR_EL1 */
ARM64_SYS_REG(3, 0, 14, 1, 0), /* CNTKCTL_EL1 */
ARM64_SYS_REG(3, 2, 0, 0, 0), /* CSSELR_EL1 */
+ ARM64_SYS_REG(3, 3, 10, 2, 4), /* POR_EL0 */
ARM64_SYS_REG(3, 3, 13, 0, 2), /* TPIDR_EL0 */
ARM64_SYS_REG(3, 3, 13, 0, 3), /* TPIDRRO_EL0 */
ARM64_SYS_REG(3, 3, 14, 0, 1), /* CNTPCT_EL0 */
--
2.25.1
^ permalink raw reply related [flat|nested] 28+ messages in thread