Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108611923
D43309.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D43309.diff
View Options
diff --git a/sys/arm64/arm64/vfp.c b/sys/arm64/arm64/vfp.c
--- a/sys/arm64/arm64/vfp.c
+++ b/sys/arm64/arm64/vfp.c
@@ -30,12 +30,14 @@
#ifdef VFP
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/elf.h>
#include <sys/eventhandler.h>
#include <sys/limits.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/smp.h>
#include <vm/uma.h>
@@ -918,6 +920,145 @@
}
SYSINIT(sve, SI_SUB_SMP, SI_ORDER_ANY, sve_init, NULL);
+static bool
+get_arm64_sve(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ struct svereg_header *header;
+ struct pcb *pcb;
+ size_t buf_size;
+ uint16_t sve_flags;
+
+ pcb = td->td_pcb;
+
+ /* If there is no SVE support in HW then we don't support NT_ARM_SVE */
+ if (pcb->pcb_sve_len == 0)
+ return (false);
+
+ sve_flags = 0;
+ if ((pcb->pcb_fpflags & PCB_FP_SVEVALID) == 0) {
+ /* If SVE hasn't been used yet provide the VFP registers */
+ buf_size = sizeof(struct fpreg);
+ sve_flags |= SVEREG_FLAG_FP;
+ } else {
+ /* We have SVE registers */
+ buf_size = sve_buf_size(td);
+ sve_flags |= SVEREG_FLAG_SVE;
+ KASSERT(pcb->pcb_svesaved != NULL, ("%s: no saved sve",
+ __func__));
+ }
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(struct svereg_header) + buf_size,
+ ("%s: invalid size", __func__));
+
+ if (td == curthread && (pcb->pcb_fpflags & PCB_FP_STARTED) != 0)
+ vfp_save_state(td, pcb);
+
+ header = buf;
+ memset(header, 0, sizeof(*header));
+
+ header->sve_size = sizeof(struct svereg_header) + buf_size;
+ header->sve_maxsize = sizeof(struct svereg_header) +
+ sve_max_buf_size();
+ header->sve_vec_len = pcb->pcb_sve_len;
+ header->sve_max_vec_len = sve_max_vector_len;
+ header->sve_flags = sve_flags;
+
+ if ((sve_flags & SVEREG_FLAG_REGS_MASK) == SVEREG_FLAG_FP) {
+ struct fpreg *fpregs;
+
+ fpregs = (void *)(&header[1]);
+ memcpy(fpregs->fp_q, pcb->pcb_fpustate.vfp_regs,
+ sizeof(fpregs->fp_q));
+ fpregs->fp_cr = pcb->pcb_fpustate.vfp_fpcr;
+ fpregs->fp_sr = pcb->pcb_fpustate.vfp_fpsr;
+ } else {
+ memcpy((void *)(&header[1]), pcb->pcb_svesaved,
+ buf_size);
+ }
+ }
+ *sizep = sizeof(struct svereg_header) + buf_size;
+
+ return (true);
+}
+
+static bool
+set_arm64_sve(struct regset *rs, struct thread *td, void *buf, size_t size)
+{
+ struct svereg_header *header;
+ struct pcb *pcb;
+ size_t buf_size;
+ uint16_t sve_flags;
+
+ pcb = td->td_pcb;
+
+ /* If there is no SVE support in HW then we don't support NT_ARM_SVE */
+ if (pcb->pcb_sve_len == 0)
+ return (false);
+
+ sve_flags = 0;
+ if ((pcb->pcb_fpflags & PCB_FP_SVEVALID) == 0) {
+ /*
+ * If the SVE state is invalid it provide the FP registers.
+ * This may be beause it hasn't been used, or it has but
+ * was switched out in a system call.
+ */
+ buf_size = sizeof(struct fpreg);
+ sve_flags |= SVEREG_FLAG_FP;
+ } else {
+ /* We have SVE registers */
+ MPASS(pcb->pcb_svesaved != NULL);
+ buf_size = sve_buf_size(td);
+ sve_flags |= SVEREG_FLAG_SVE;
+ KASSERT(pcb->pcb_svesaved != NULL, ("%s: no saved sve",
+ __func__));
+ }
+
+ if (size != sizeof(struct svereg_header) + buf_size)
+ return (false);
+
+ header = buf;
+ /* Sanity checks on the header */
+ if (header->sve_size != sizeof(struct svereg_header) + buf_size)
+ return (false);
+
+ if (header->sve_maxsize != sizeof(struct svereg_header) +
+ sve_max_buf_size())
+ return (false);
+
+ if (header->sve_vec_len != pcb->pcb_sve_len)
+ return (false);
+
+ if (header->sve_max_vec_len != sve_max_vector_len)
+ return (false);
+
+ if (header->sve_flags != sve_flags)
+ return (false);
+
+ if ((sve_flags & SVEREG_FLAG_REGS_MASK) == SVEREG_FLAG_FP) {
+ struct fpreg *fpregs;
+
+ fpregs = (void *)(&header[1]);
+ memcpy(pcb->pcb_fpustate.vfp_regs, fpregs->fp_q,
+ sizeof(fpregs->fp_q));
+ pcb->pcb_fpustate.vfp_fpcr = fpregs->fp_cr;
+ pcb->pcb_fpustate.vfp_fpsr = fpregs->fp_sr;
+ } else {
+ /* Restore the SVE registers */
+ memcpy(pcb->pcb_svesaved, (void *)(&header[1]), buf_size);
+ }
+
+ return (true);
+}
+
+static struct regset regset_arm64_sve = {
+ .note = NT_ARM_SVE,
+ .get = get_arm64_sve,
+ .set = set_arm64_sve,
+};
+ELF_REGSET(regset_arm64_sve);
+
struct fpu_kern_ctx *
fpu_kern_alloc_ctx(u_int flags)
{
diff --git a/sys/arm64/include/reg.h b/sys/arm64/include/reg.h
--- a/sys/arm64/include/reg.h
+++ b/sys/arm64/include/reg.h
@@ -63,6 +63,19 @@
int dummy;
};
+#define SVEREG_FLAG_REGS_MASK 0x0001
+#define SVEREG_FLAG_FP 0x0000
+#define SVEREG_FLAG_SVE 0x0001
+
+struct svereg_header {
+ __uint32_t sve_size;
+ __uint32_t sve_maxsize;
+ __uint16_t sve_vec_len;
+ __uint16_t sve_max_vec_len;
+ __uint16_t sve_flags;
+ __uint16_t sve_reserved;
+};
+
struct dbreg {
__uint8_t db_debug_ver;
__uint8_t db_nbkpts;
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -826,6 +826,7 @@
#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
#define NT_ARM_VFP 0x400 /* ARM VFP registers */
#define NT_ARM_TLS 0x401 /* ARM TLS register */
+#define NT_ARM_SVE 0x405 /* ARM SVE registers */
#define NT_ARM_ADDR_MASK 0x406 /* arm64 address mask (e.g. for TBI) */
/* GNU note types. */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 9:21 PM (8 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16213328
Default Alt Text
D43309.diff (5 KB)
Attached To
Mode
D43309: arm64: Support SVE in ptrace and core dumps
Attached
Detach File
Event Timeline
Log In to Comment