Movatterモバイル変換
[0]ホーム
This is the mail archive of thelibc-alpha@sourceware.orgmailing list for theglibc project.
[PATCH v2 19/28] arm64/sve: ptrace and ELF coredump support
- From: Dave Martin <Dave dot Martin at arm dot com>
- To: linux-arm-kernel at lists dot infradead dot org
- Cc: Catalin Marinas <catalin dot marinas at arm dot com>,Will Deacon <will dot deacon at arm dot com>,Ard Biesheuvel <ard dot biesheuvel at linaro dot org>,Alex Bennée <alex dot bennee at linaro dot org>,Szabolcs Nagy <szabolcs dot nagy at arm dot com>,Richard Sandiford <richard dot sandiford at arm dot com>,kvmarm at lists dot cs dot columbia dot edu,libc-alpha at sourceware dot org,linux-arch at vger dot kernel dot org,gdb at sourceware dot org,Alan Hayward <alan dot hayward at arm dot com>,Yao Qi <Yao dot Qi at arm dot com>,Oleg Nesterov <oleg at redhat dot com>,Alexander Viro <viro at zeniv dot linux dot org dot uk>
- Date: Thu, 31 Aug 2017 18:00:51 +0100
- Subject: [PATCH v2 19/28] arm64/sve: ptrace and ELF coredump support
- Authentication-results: sourceware.org; auth=none
- References: <1504198860-12951-1-git-send-email-Dave.Martin@arm.com>
This patch defines and implements a new regset NT_ARM_SVE, whichdescribes a thread's SVE register state. This allows a debugger tomanipulate the SVE state, as well as being included in ELFcoredumps for post-mortem debugging.Because the regset size and layout are dependent on the thread'scurrent vector length, it is not possible to define a C struct todescribe the regset contents as is done for existing regsets.Instead, and for the same reasons, NT_ARM_SVE is based on thefreeform variable-layout approach used for the SVE signal frame.Additionally, to reduce debug overhead when debugging threads thatmight or might not have live SVE register state, NT_ARM_SVE may bepresented in one of two different formats: the old structuser_fpsimd_state format is embedded for describing the state of athread with no live SVE state, whereas a new variable-layoutstructure is embedded for describing live SVE state. This avoids adebugger needing to poll NT_PRFPREG in addition to NT_ARM_SVE, andallows existing userspace code to handle the non-SVE case withouttoo much modification.For this to work, NT_ARM_SVE is defined with a fixed-format headerof type struct user_sve_header, which the recipient can use tofigure out the content, size and layout of the reset of the regset.Accessor macros are defined to allow the vector-length-dependentparts of the regset to be manipulated.Signed-off-by: Alan Hayward <alan.hayward@arm.com>Signed-off-by: Dave Martin <Dave.Martin@arm.com>Cc: Alex Bennée <alex.bennee@linaro.org>---Changes since v1----------------Other changes related to Alex Bennée's comments:* Migrate to SVE_VQ_BYTES instead of magic numbers.Requested by Alex Bennée:* Thin out BUG_ON()s:Redundant BUG_ON()s and ones that just check invariants are removed.Important sanity-checks are migrated to WARN_ON()s, with someminimal best-effort patch-up code.Other:* [ABI fix] Bail out with -EIO if attempting to set theSVE regs for an unsupported VL, instead of misparsing the regset data.* Replace some in-kernel open-coded arithmetic with ALIGN()/DIV_ROUND_UP().--- arch/arm64/include/asm/fpsimd.h | 13 +- arch/arm64/include/uapi/asm/ptrace.h | 135 ++++++++++++++++++ arch/arm64/kernel/fpsimd.c | 40 +++++- arch/arm64/kernel/ptrace.c | 270 +++++++++++++++++++++++++++++++++-- include/uapi/linux/elf.h | 1 + 5 files changed, 449 insertions(+), 10 deletions(-)diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.hindex 6c22624..2723cca 100644--- a/arch/arm64/include/asm/fpsimd.h+++ b/arch/arm64/include/asm/fpsimd.h@@ -38,13 +38,16 @@ struct fpsimd_state { __uint128_t vregs[32]; u32 fpsr; u32 fpcr;+/*+ * For ptrace compatibility, pad to next 128-bit+ * boundary here if extending this struct.+ */ }; }; /* the id of the last cpu to have restored this state */ unsigned int cpu; }; - #if defined(__KERNEL__) && defined(CONFIG_COMPAT) /* Masks for extracting the FPSR and FPCR from the FPSCR */ #define VFP_FPSCR_STAT_MASK0xf800009f@@ -89,6 +92,10 @@ extern void sve_alloc(struct task_struct *task); extern void fpsimd_release_thread(struct task_struct *task); extern void fpsimd_dup_sve(struct task_struct *dst, struct task_struct const *src);+extern void fpsimd_sync_to_sve(struct task_struct *task);+extern void sve_sync_to_fpsimd(struct task_struct *task);+extern void sve_sync_from_fpsimd_zeropad(struct task_struct *task);+ extern int sve_set_vector_length(struct task_struct *task, unsigned long vl, unsigned long flags); @@ -103,6 +110,10 @@ static void __maybe_unused sve_alloc(struct task_struct *task) { } static void __maybe_unused fpsimd_release_thread(struct task_struct *task) { } static void __maybe_unused fpsimd_dup_sve(struct task_struct *dst, struct task_struct const *src) { }+static void __maybe_unused sve_sync_to_fpsimd(struct task_struct *task) { }+static void __maybe_unused sve_sync_from_fpsimd_zeropad(+struct task_struct *task) { }+ static void __maybe_unused sve_init_vq_map(void) { } static void __maybe_unused sve_update_vq_map(void) { } static int __maybe_unused sve_verify_vq_map(void) { return 0; }diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.hindex d1ff83d..1915ab0 100644--- a/arch/arm64/include/uapi/asm/ptrace.h+++ b/arch/arm64/include/uapi/asm/ptrace.h@@ -22,6 +22,7 @@ #include <linux/types.h> #include <asm/hwcap.h>+#include <asm/sigcontext.h> /*@@ -63,6 +64,8 @@ #ifndef __ASSEMBLY__ +#include <linux/prctl.h>+ /* * User structures for general purpose, floating point and debug registers. */@@ -90,6 +93,138 @@ struct user_hwdebug_state { }dbg_regs[16]; }; +/* SVE/FP/SIMD state (NT_ARM_SVE) */++struct user_sve_header {+__u32 size; /* total meaningful regset content in bytes */+__u32 max_size; /* maxmium possible size for this thread */+__u16 vl; /* current vector length */+__u16 max_vl; /* maximum possible vector length */+__u16 flags;+__u16 __reserved;+};++/* Definitions for user_sve_header.flags: */+#define SVE_PT_REGS_MASK(1 << 0)++/* Flags: must be kept in sync with prctl interface in <linux/ptrace.h> */+#define SVE_PT_REGS_FPSIMD0+#define SVE_PT_REGS_SVESVE_PT_REGS_MASK++#define SVE_PT_VL_INHERIT(PR_SVE_VL_INHERIT >> 16)+#define SVE_PT_VL_ONEXEC(PR_SVE_SET_VL_ONEXEC >> 16)+++/*+ * The remainder of the SVE state follows struct user_sve_header. The+ * total size of the SVE state (including header) depends on the+ * metadata in the header: SVE_PT_SIZE(vq, flags) gives the total size+ * of the state in bytes, including the header.+ *+ * Refer to <asm/sigcontext.h> for details of how to pass the correct+ * "vq" argument to these macros.+ */++/* Offset from the start of struct user_sve_header to the register data */+#define SVE_PT_REGS_OFFSET\+((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1))\+/ SVE_VQ_BYTES * SVE_VQ_BYTES)++/*+ * The register data content and layout depends on the value of the+ * flags field.+ */++/*+ * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD case:+ *+ * The payload starts at offset SVE_PT_FPSIMD_OFFSET, and is of type+ * struct user_fpsimd_state. Additional data might be appended in the+ * future: use SVE_PT_FPSIMD_SIZE(vq, flags) to compute the total size.+ * SVE_PT_FPSIMD_SIZE(vq, flags) will never be less than+ * sizeof(struct user_fpsimd_state).+ */++#define SVE_PT_FPSIMD_OFFSETSVE_PT_REGS_OFFSET++#define SVE_PT_FPSIMD_SIZE(vq, flags)(sizeof(struct user_fpsimd_state))++/*+ * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE case:+ *+ * The payload starts at offset SVE_PT_SVE_OFFSET, and is of size+ * SVE_PT_SVE_SIZE(vq, flags).+ *+ * Additional macros describe the contents and layout of the payload.+ * For each, SVE_PT_SVE_x_OFFSET(args) is the start offset relative to+ * the start of struct user_sve_header, and SVE_PT_SVE_x_SIZE(args) is+ * the size in bytes:+ *+ *xtypedescription+ *----------------+ *ZREGS\+ *ZREG|+ *PREGS| refer to <asm/sigcontext.h>+ *PREG|+ *FFR/+ *+ *FPSRuint32_tFPSR+ *FPCRuint32_tFPCR+ *+ * Additional data might be appended in the future.+ */++#define SVE_PT_SVE_ZREG_SIZE(vq)SVE_SIG_ZREG_SIZE(vq)+#define SVE_PT_SVE_PREG_SIZE(vq)SVE_SIG_PREG_SIZE(vq)+#define SVE_PT_SVE_FFR_SIZE(vq)SVE_SIG_FFR_SIZE(vq)+#define SVE_PT_SVE_FPSR_SIZEsizeof(__u32)+#define SVE_PT_SVE_FPCR_SIZEsizeof(__u32)++#define __SVE_SIG_TO_PT(offset) \+((offset) - SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)++#define SVE_PT_SVE_OFFSETSVE_PT_REGS_OFFSET++#define SVE_PT_SVE_ZREGS_OFFSET \+__SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET)+#define SVE_PT_SVE_ZREG_OFFSET(vq, n) \+__SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n))+#define SVE_PT_SVE_ZREGS_SIZE(vq) \+(SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)++#define SVE_PT_SVE_PREGS_OFFSET(vq) \+__SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))+#define SVE_PT_SVE_PREG_OFFSET(vq, n) \+__SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n))+#define SVE_PT_SVE_PREGS_SIZE(vq) \+(SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - \+SVE_PT_SVE_PREGS_OFFSET(vq))++#define SVE_PT_SVE_FFR_OFFSET(vq) \+__SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))++#define SVE_PT_SVE_FPSR_OFFSET(vq)\+((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) +\+(SVE_VQ_BYTES - 1))\+/ SVE_VQ_BYTES * SVE_VQ_BYTES)+#define SVE_PT_SVE_FPCR_OFFSET(vq) \+(SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)++/*+ * Any future extension appended after FPCR must be aligned to the next+ * 128-bit boundary.+ */++#define SVE_PT_SVE_SIZE(vq, flags)\+((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE\+- SVE_PT_SVE_OFFSET + (SVE_VQ_BYTES - 1))\+/ SVE_VQ_BYTES * SVE_VQ_BYTES)++#define SVE_PT_SIZE(vq, flags)\+ (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ?\+ SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags)\+: SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))+ #endif /* __ASSEMBLY__ */ #endif /* _UAPI__ASM_PTRACE_H */diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.cindex fff9fcf..361c019 100644--- a/arch/arm64/kernel/fpsimd.c+++ b/arch/arm64/kernel/fpsimd.c@@ -303,6 +303,37 @@ void sve_alloc(struct task_struct *task) BUG_ON(!task->thread.sve_state); } +void fpsimd_sync_to_sve(struct task_struct *task)+{+if (!test_tsk_thread_flag(task, TIF_SVE))+fpsimd_to_sve(task);+}++void sve_sync_to_fpsimd(struct task_struct *task)+{+if (test_tsk_thread_flag(task, TIF_SVE))+sve_to_fpsimd(task);+}++void sve_sync_from_fpsimd_zeropad(struct task_struct *task)+{+unsigned int vq;+void *sst = task->thread.sve_state;+struct fpsimd_state const *fst = &task->thread.fpsimd_state;+unsigned int i;++if (!test_tsk_thread_flag(task, TIF_SVE))+return;++vq = sve_vq_from_vl(task->thread.sve_vl);++memset(sst, 0, SVE_SIG_REGS_SIZE(vq));++for (i = 0; i < 32; ++i)+memcpy(ZREG(sst, vq, i), &fst->vregs[i],+ sizeof(fst->vregs[i]));+}+ /* * Handle SVE state across fork(): *@@ -459,10 +490,17 @@ static void __init sve_efi_setup(void) * This is evidence of a crippled system and we are returning void, * so no attempt is made to handle this situation here. */-BUG_ON(!sve_vl_valid(sve_max_vl));+if (!sve_vl_valid(sve_max_vl))+goto fail;+ efi_sve_state = __alloc_percpu( SVE_SIG_REGS_SIZE(sve_vq_from_vl(sve_max_vl)), SVE_VQ_BYTES); if (!efi_sve_state)+goto fail;++return;++fail: panic("Cannot allocate percpu memory for EFI SVE save/restore"); } diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.cindex 9cbb612..5ef4735b 100644--- a/arch/arm64/kernel/ptrace.c+++ b/arch/arm64/kernel/ptrace.c@@ -32,6 +32,7 @@ #include <linux/security.h> #include <linux/init.h> #include <linux/signal.h>+#include <linux/string.h> #include <linux/uaccess.h> #include <linux/perf_event.h> #include <linux/hw_breakpoint.h>@@ -40,6 +41,7 @@ #include <linux/elf.h> #include <asm/compat.h>+#include <asm/cpufeature.h> #include <asm/debug-monitors.h> #include <asm/pgtable.h> #include <asm/stacktrace.h>@@ -618,33 +620,66 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset, /* * TODO: update fp accessors for lazy context switching (sync/flush hwstate) */-static int fpr_get(struct task_struct *target, const struct user_regset *regset,- unsigned int pos, unsigned int count,- void *kbuf, void __user *ubuf)+static int __fpr_get(struct task_struct *target,+ const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ void *kbuf, void __user *ubuf, unsigned int start_pos) { struct user_fpsimd_state *uregs;++sve_sync_to_fpsimd(target);+ uregs = &target->thread.fpsimd_state.user_fpsimd; +return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs,+ start_pos, start_pos + sizeof(*uregs));+}++static int fpr_get(struct task_struct *target, const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ void *kbuf, void __user *ubuf)+{ if (target == current) fpsimd_preserve_current_state(); -return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);+return __fpr_get(target, regset, pos, count, kbuf, ubuf, 0); } -static int fpr_set(struct task_struct *target, const struct user_regset *regset,- unsigned int pos, unsigned int count,- const void *kbuf, const void __user *ubuf)+static int __fpr_set(struct task_struct *target,+ const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ const void *kbuf, const void __user *ubuf,+ unsigned int start_pos) { int ret; struct user_fpsimd_state newstate = target->thread.fpsimd_state.user_fpsimd; -ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);+sve_sync_to_fpsimd(target);++ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate,+ start_pos, start_pos + sizeof(newstate)); if (ret) return ret; target->thread.fpsimd_state.user_fpsimd = newstate;++return ret;+}++static int fpr_set(struct task_struct *target, const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ const void *kbuf, const void __user *ubuf)+{+int ret;++ret = __fpr_set(target, regset, pos, count, kbuf, ubuf, 0);+if (ret)+return ret;++sve_sync_from_fpsimd_zeropad(target); fpsimd_flush_task_state(target);+ return ret; } @@ -702,6 +737,210 @@ static int system_call_set(struct task_struct *target, return ret; } +#ifdef CONFIG_ARM64_SVE++static void sve_init_header_from_task(struct user_sve_header *header,+ struct task_struct *target)+{+unsigned int vq;++memset(header, 0, sizeof(*header));++header->flags = test_tsk_thread_flag(target, TIF_SVE) ?+SVE_PT_REGS_SVE : SVE_PT_REGS_FPSIMD;+if (test_tsk_thread_flag(target, TIF_SVE_VL_INHERIT))+header->flags |= SVE_PT_VL_INHERIT;++header->vl = target->thread.sve_vl;+vq = sve_vq_from_vl(header->vl);++if (WARN_ON(!sve_vl_valid(sve_max_vl)))+header->max_vl = header->vl;++header->size = SVE_PT_SIZE(vq, header->flags);+header->max_size = SVE_PT_SIZE(sve_vq_from_vl(header->max_vl),+ SVE_PT_REGS_SVE);+}++static unsigned int sve_size_from_header(struct user_sve_header const *header)+{+return ALIGN(header->size, SVE_VQ_BYTES);+}++static unsigned int sve_get_size(struct task_struct *target,+ const struct user_regset *regset)+{+struct user_sve_header header;++if (!system_supports_sve())+return 0;++sve_init_header_from_task(&header, target);+return sve_size_from_header(&header);+}++static int sve_get(struct task_struct *target,+ const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ void *kbuf, void __user *ubuf)+{+int ret;+struct user_sve_header header;+unsigned int vq;+unsigned long start, end;++if (!system_supports_sve())+return -EINVAL;++/* Header */+sve_init_header_from_task(&header, target);+vq = sve_vq_from_vl(header.vl);++ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &header,+ 0, sizeof(header));+if (ret)+return ret;++if (target == current)+fpsimd_preserve_current_state();++/* Registers: FPSIMD-only case */++BUILD_BUG_ON(SVE_PT_FPSIMD_OFFSET != sizeof(header));+if ((header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD)+return __fpr_get(target, regset, pos, count, kbuf, ubuf,+ SVE_PT_FPSIMD_OFFSET);++/* Otherwise: full SVE case */++BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header));+start = SVE_PT_SVE_OFFSET;+end = SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq);+ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,+ target->thread.sve_state,+ start, end);+if (ret)+return ret;++start = end;+end = SVE_PT_SVE_FPSR_OFFSET(vq);+ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,+ start, end);+if (ret)+return ret;++/*+ * Copy fpsr, and fpcr which must follow contiguously in+ * struct fpsimd_state:+ */+start = end;+end = SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE;+ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,+ &target->thread.fpsimd_state.fpsr,+ start, end);+if (ret)+return ret;++start = end;+end = sve_size_from_header(&header);+return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,+start, end);+}++static int sve_set(struct task_struct *target,+ const struct user_regset *regset,+ unsigned int pos, unsigned int count,+ const void *kbuf, const void __user *ubuf)+{+int ret;+struct user_sve_header header;+unsigned int vq;+unsigned long start, end;++if (!system_supports_sve())+return -EINVAL;++/* Header */+if (count < sizeof(header))+return -EINVAL;+ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &header,+ 0, sizeof(header));+if (ret)+goto out;++/*+ * Apart from PT_SVE_REGS_MASK, all PT_SVE_* flags are consumed by+ * sve_set_vector_length(), which will also validate them for us:+ */+ret = sve_set_vector_length(target, header.vl,+ header.flags & ~SVE_PT_REGS_MASK);+if (ret)+goto out;++/* Actual VL set may be less than the user asked for: */+vq = sve_vq_from_vl(target->thread.sve_vl);++/* Registers: FPSIMD-only case */++BUILD_BUG_ON(SVE_PT_FPSIMD_OFFSET != sizeof(header));+if ((header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) {+sve_sync_to_fpsimd(target);++ret = __fpr_set(target, regset, pos, count, kbuf, ubuf,+SVE_PT_FPSIMD_OFFSET);+clear_tsk_thread_flag(target, TIF_SVE);+goto out;+}++/* Otherwise: full SVE case */++/*+ * If setting a different VL from the requested VL and there is+ * register data, the data layout will be wrong: don't even+ * try to set the registers in this case.+ */+if (count && vq != sve_vq_from_vl(header.vl)) {+ret = -EIO;+goto out;+}++sve_alloc(target);+fpsimd_sync_to_sve(target);+set_tsk_thread_flag(target, TIF_SVE);++BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header));+start = SVE_PT_SVE_OFFSET;+end = SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq);+ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,+ target->thread.sve_state,+ start, end);+if (ret)+goto out;++start = end;+end = SVE_PT_SVE_FPSR_OFFSET(vq);+ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,+start, end);+if (ret)+goto out;++/*+ * Copy fpsr, and fpcr which must follow contiguously in+ * struct fpsimd_state:+ */+start = end;+end = SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE;+ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,+ &target->thread.fpsimd_state.fpsr,+ start, end);++out:+fpsimd_flush_task_state(target);+return ret;+}++#endif /* CONFIG_ARM64_SVE */+ enum aarch64_regset { REGSET_GPR, REGSET_FPR,@@ -711,6 +950,9 @@ enum aarch64_regset { REGSET_HW_WATCH, #endif REGSET_SYSTEM_CALL,+#ifdef CONFIG_ARM64_SVE+REGSET_SVE,+#endif }; static const struct user_regset aarch64_regsets[] = {@@ -768,6 +1010,18 @@ static const struct user_regset aarch64_regsets[] = { .get = system_call_get, .set = system_call_set, },+#ifdef CONFIG_ARM64_SVE+[REGSET_SVE] = { /* Scalable Vector Extension */+.core_note_type = NT_ARM_SVE,+.n = DIV_ROUND_UP(SVE_PT_SIZE(SVE_VQ_MAX, SVE_PT_REGS_SVE),+ SVE_VQ_BYTES),+.size = SVE_VQ_BYTES,+.align = SVE_VQ_BYTES,+.get = sve_get,+.set = sve_set,+.get_size = sve_get_size,+},+#endif }; static const struct user_regset_view user_aarch64_view = {diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.hindex b5280db..735b8f4 100644--- a/include/uapi/linux/elf.h+++ b/include/uapi/linux/elf.h@@ -416,6 +416,7 @@ typedef struct elf64_shdr { #define NT_ARM_HW_BREAK0x402/* ARM hardware breakpoint registers */ #define NT_ARM_HW_WATCH0x403/* ARM hardware watchpoint registers */ #define NT_ARM_SYSTEM_CALL0x404/* ARM system call number */+#define NT_ARM_SVE0x405/* ARM Scalable Vector Extension registers */ #define NT_METAG_CBUF0x500/* Metag catch buffer registers */ #define NT_METAG_RPIPE0x501/* Metag read pipeline state */ #define NT_METAG_TLS0x502/* Metag TLS pointer */-- 2.1.4
[8]ページ先頭