[PATCH v3 06/11] powerpc/ptrace: Expose DEXCR and HDEXCR registers to ptrace
Benjamin Gray
bgray at linux.ibm.com
Fri Jun 16 13:48:41 AEST 2023
The DEXCR register is of interest when ptracing processes. Currently it
is static, but eventually will be dynamically controllable by a process.
If a process can control its own, then it is useful for it to be
ptrace-able to (e.g., for checkpoint-restore functionality).
It is also relevant to core dumps (the NPHIE aspect in particular),
which use the ptrace mechanism (or is it the other way around?) to
decide what to dump. The HDEXCR is useful here too, as the NPHIE aspect
may be set in the HDEXCR without being set in the DEXCR. Although the
HDEXCR is per-cpu and we don't track it in the task struct (it's useless
in normal operation), it would be difficult to imagine why a hypervisor
would set it to different values within a guest. A hypervisor cannot
safely set NPHIE differently at least, as that would break programs.
Expose a read-only view of the userspace DEXCR and HDEXCR to ptrace.
The HDEXCR is always readonly, and is useful for diagnosing the core
dumps (as the HDEXCR may set NPHIE without the DEXCR setting it).
Signed-off-by: Benjamin Gray <bgray at linux.ibm.com>
Reviewed-by: Russell Currey <ruscur at russell.cc>
---
v3: * Add ruscur reviewed-by
* Expose values as 64 bits
* DEXCR is no longer a config
v2: * New in v2
---
arch/powerpc/include/uapi/asm/elf.h | 1 +
arch/powerpc/kernel/ptrace/ptrace-decl.h | 1 +
arch/powerpc/kernel/ptrace/ptrace-view.c | 36 +++++++++++++++++++++++-
include/uapi/linux/elf.h | 1 +
4 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/uapi/asm/elf.h b/arch/powerpc/include/uapi/asm/elf.h
index dbc4a5b8d02d..e0d323c808dd 100644
--- a/arch/powerpc/include/uapi/asm/elf.h
+++ b/arch/powerpc/include/uapi/asm/elf.h
@@ -98,6 +98,7 @@
#define ELF_NEBB 3 /* includes ebbrr, ebbhr, bescr */
#define ELF_NPMU 5 /* includes siar, sdar, sier, mmcr2, mmcr0 */
#define ELF_NPKEY 3 /* includes amr, iamr, uamor */
+#define ELF_NDEXCR 2 /* includes dexcr, hdexcr */
typedef unsigned long elf_greg_t64;
typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
diff --git a/arch/powerpc/kernel/ptrace/ptrace-decl.h b/arch/powerpc/kernel/ptrace/ptrace-decl.h
index 463a63eb8cc7..998a84f64804 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-decl.h
+++ b/arch/powerpc/kernel/ptrace/ptrace-decl.h
@@ -57,6 +57,7 @@ enum powerpc_regset {
REGSET_TAR, /* TAR register */
REGSET_EBB, /* EBB registers */
REGSET_PMR, /* Performance Monitor Registers */
+ REGSET_DEXCR, /* DEXCR registers */
#endif
#ifdef CONFIG_PPC_MEM_KEYS
REGSET_PKEY, /* AMR register */
diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c
index 5fff0d04b23f..87a46edb3efb 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-view.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-view.c
@@ -454,7 +454,36 @@ static int pmu_set(struct task_struct *target, const struct user_regset *regset,
5 * sizeof(unsigned long));
return ret;
}
-#endif
+
+static int dexcr_active(struct task_struct *target, const struct user_regset *regset)
+{
+ if (!cpu_has_feature(CPU_FTR_ARCH_31))
+ return -ENODEV;
+
+ return regset->n;
+}
+
+static int dexcr_get(struct task_struct *target, const struct user_regset *regset,
+ struct membuf to)
+{
+ if (!cpu_has_feature(CPU_FTR_ARCH_31))
+ return -ENODEV;
+
+ /*
+ * The DEXCR is currently static across all CPUs, so we don't
+ * store the target's value anywhere, but the static value
+ * will also be correct.
+ */
+ membuf_store(&to, (unsigned long)(DEXCR_INIT & 0xFFFFFFFF));
+
+ /*
+ * Technically the HDEXCR is per-cpu, but a hypervisor can't reasonably
+ * change it between CPUs of the same guest.
+ */
+ return membuf_store(&to, (unsigned long)(mfspr(SPRN_HDEXCR_RO) & 0xFFFFFFFF));
+}
+
+#endif /* CONFIG_PPC_BOOK3S_64 */
#ifdef CONFIG_PPC_MEM_KEYS
static int pkey_active(struct task_struct *target, const struct user_regset *regset)
@@ -615,6 +644,11 @@ static const struct user_regset native_regsets[] = {
.size = sizeof(u64), .align = sizeof(u64),
.active = pmu_active, .regset_get = pmu_get, .set = pmu_set
},
+ [REGSET_DEXCR] = {
+ .core_note_type = NT_PPC_DEXCR, .n = ELF_NDEXCR,
+ .size = sizeof(u64), .align = sizeof(u64),
+ .active = dexcr_active, .regset_get = dexcr_get
+ },
#endif
#ifdef CONFIG_PPC_MEM_KEYS
[REGSET_PKEY] = {
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index ac3da855fb19..cfa31f1eb5d7 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -403,6 +403,7 @@ typedef struct elf64_shdr {
#define NT_PPC_TM_CPPR 0x10e /* TM checkpointed Program Priority Register */
#define NT_PPC_TM_CDSCR 0x10f /* TM checkpointed Data Stream Control Register */
#define NT_PPC_PKEY 0x110 /* Memory Protection Keys registers */
+#define NT_PPC_DEXCR 0x111 /* PowerPC DEXCR registers */
#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
--
2.40.1
More information about the Linuxppc-dev
mailing list