Page MenuHomeFreeBSD

D56414.diff
No OneTemporary

D56414.diff

Index: sys/conf/files.riscv
===================================================================
--- sys/conf/files.riscv
+++ sys/conf/files.riscv
@@ -88,6 +88,7 @@
riscv/riscv/timer.c standard
riscv/riscv/uio_machdep.c standard
riscv/riscv/unwind.c optional ddb | kdtrace_hooks | stack
+riscv/riscv/vector.c standard
riscv/riscv/vm_machdep.c standard
riscv/vmm/vmm.c optional vmm
riscv/vmm/vmm_aplic.c optional vmm
Index: sys/riscv/include/elf.h
===================================================================
--- sys/riscv/include/elf.h
+++ sys/riscv/include/elf.h
@@ -81,6 +81,7 @@
#define HWCAP_ISA_D HWCAP_ISA_BIT('d')
#define HWCAP_ISA_C HWCAP_ISA_BIT('c')
#define HWCAP_ISA_H HWCAP_ISA_BIT('h')
+#define HWCAP_ISA_V HWCAP_ISA_BIT('v')
#define HWCAP_ISA_G \
(HWCAP_ISA_I | HWCAP_ISA_M | HWCAP_ISA_A | HWCAP_ISA_F | HWCAP_ISA_D)
#define HWCAP_ISA_B HWCAP_ISA_BIT('b')
Index: sys/riscv/include/md_var.h
===================================================================
--- sys/riscv/include/md_var.h
+++ sys/riscv/include/md_var.h
@@ -46,6 +46,7 @@
extern bool has_sstc;
extern bool has_sscofpmf;
extern bool has_svpbmt;
+extern bool has_vector;
struct dumperinfo;
struct minidumpstate;
Index: sys/riscv/include/pcb.h
===================================================================
--- sys/riscv/include/pcb.h
+++ sys/riscv/include/pcb.h
@@ -51,6 +51,14 @@
#define PCB_FP_STARTED 0x1
#define PCB_FP_USERMASK 0x1
vm_offset_t pcb_onfault; /* Copyinout fault handler */
+ /* Vector state. */
+ uint64_t pcb_vsflags;
+#define PCB_VS_STARTED 0x1
+ uint64_t pcb_vstart;
+ uint64_t pcb_vl;
+ uint64_t pcb_vtype;
+ uint64_t pcb_vcsr;
+ void *pcb_vsaved; /* Vector registers area. */
};
#ifdef _KERNEL
Index: sys/riscv/include/riscvreg.h
===================================================================
--- sys/riscv/include/riscvreg.h
+++ sys/riscv/include/riscvreg.h
@@ -64,6 +64,12 @@
#define SSTATUS_SPIE_SHIFT 5
#define SSTATUS_SPP (1 << 8)
#define SSTATUS_SPP_SHIFT 8
+#define SSTATUS_VS_SHIFT 9
+#define SSTATUS_VS_OFF (0x0 << SSTATUS_VS_SHIFT)
+#define SSTATUS_VS_INITIAL (0x1 << SSTATUS_VS_SHIFT)
+#define SSTATUS_VS_CLEAN (0x2 << SSTATUS_VS_SHIFT)
+#define SSTATUS_VS_DIRTY (0x3 << SSTATUS_VS_SHIFT)
+#define SSTATUS_VS_MASK (0x3 << SSTATUS_VS_SHIFT)
#define SSTATUS_FS_SHIFT 13
#define SSTATUS_FS_OFF (0x0 << SSTATUS_FS_SHIFT)
#define SSTATUS_FS_INITIAL (0x1 << SSTATUS_FS_SHIFT)
Index: sys/riscv/include/vector.h
===================================================================
--- /dev/null
+++ sys/riscv/include/vector.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_VECTOR_H_
+#define _MACHINE_VECTOR_H_
+
+void vector_state_init(struct thread *td);
+void vector_state_store(struct thread *td);
+void vector_state_restore(struct thread *td);
+void vector_copy_thread(struct thread *td1, struct thread *td2);
+
+#endif /* !_MACHINE_VECTOR_H_ */
Index: sys/riscv/riscv/identcpu.c
===================================================================
--- sys/riscv/riscv/identcpu.c
+++ sys/riscv/riscv/identcpu.c
@@ -75,6 +75,7 @@
/* Supervisor-mode extension support. */
bool has_hyp;
+bool has_vector;
bool __read_frequently has_sstc;
bool __read_frequently has_sscofpmf;
bool has_svpbmt;
@@ -280,6 +281,7 @@
case 'h':
case 'i':
case 'm':
+ case 'v':
desc->isa_extensions |= HWCAP_ISA_BIT(isa[i]);
i++;
break;
@@ -402,6 +404,9 @@
return;
}
+ if (bootverbose)
+ printf("hart %d isa: %s\n", hart, isa);
+
/*
* The string is specified to be lowercase, but let's be
* certain.
@@ -462,6 +467,7 @@
UPDATE_CAP(mmu_caps, desc->mmu_caps);
/* Supervisor-mode extension support. */
+ UPDATE_CAP(has_vector, (desc->isa_extensions & HWCAP_ISA_V) != 0);
UPDATE_CAP(has_hyp, (desc->isa_extensions & HWCAP_ISA_H) != 0);
UPDATE_CAP(has_sstc, (desc->smode_extensions & SV_SSTC) != 0);
UPDATE_CAP(has_sscofpmf, (desc->smode_extensions & SV_SSCOFPMF) != 0);
@@ -605,7 +611,8 @@
"\04Double"
"\06Float"
"\10Hypervisor"
- "\15Mult/Div");
+ "\15Mult/Div"
+ "\26Vector");
}
if (SHOULD_PRINT(smode_extensions)) {
Index: sys/riscv/riscv/machdep.c
===================================================================
--- sys/riscv/riscv/machdep.c
+++ sys/riscv/riscv/machdep.c
@@ -299,6 +299,7 @@
thread0.td_pcb = (struct pcb *)(thread0.td_kstack +
thread0.td_kstack_pages * PAGE_SIZE) - 1;
thread0.td_pcb->pcb_fpflags = 0;
+ thread0.td_pcb->pcb_vsflags = 0;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}
Index: sys/riscv/riscv/swtch.S
===================================================================
--- sys/riscv/riscv/swtch.S
+++ sys/riscv/riscv/swtch.S
@@ -210,6 +210,17 @@
call _C_LABEL(pmap_activate_sw)
mv a0, s0
+ /* Is VS enabled for new thread? */
+ ld t0, TD_FRAME(a0)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_VS_MASK
+ and t3, t1, t2
+ beqz t3, 1f /* No, skip. */
+
+ call _C_LABEL(vector_state_restore)
+ mv a0, s0
+
+1:
/* Store the new curthread */
sd a0, PC_CURTHREAD(tp)
/* And the new pcb */
@@ -304,6 +315,33 @@
__fpe_state_save x13
1:
+ /*
+ * Is VS enabled and is it in dirty state
+ * for the old thread?
+ */
+ ld t0, TD_FRAME(a0)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_VS_MASK
+ and t3, t1, t2
+ li t2, SSTATUS_VS_DIRTY
+ bne t3, t2, 1f /* No, skip. */
+
+ /* Yes, mark VS clean and save registers. */
+ li t2, ~SSTATUS_VS_MASK
+ and t3, t1, t2
+ li t2, SSTATUS_VS_CLEAN
+ or t3, t3, t2
+ sd t3, (TF_SSTATUS)(t0)
+
+ mv s0, a0
+ mv s1, a1
+ mv s2, a2
+ call _C_LABEL(vector_state_store)
+ mv a0, s0
+ mv a1, s1
+ mv a2, s2
+1:
+
/* Activate the new thread's pmap */
mv s0, a0
mv s1, a1
@@ -321,6 +359,20 @@
ld t0, TD_LOCK(a1)
beq t0, s2, 1b
#endif
+
+ /* Is VS enabled for new thread? */
+ ld t0, TD_FRAME(a1)
+ ld t1, (TF_SSTATUS)(t0)
+ li t2, SSTATUS_VS_MASK
+ and t3, t1, t2
+ beqz t3, 1f /* No, skip. */
+
+ /* Restore vector registers. */
+ mv a0, a1
+ call _C_LABEL(vector_state_restore)
+ mv a1, s1
+1:
+
/*
* Restore the saved context.
*/
Index: sys/riscv/riscv/trap.c
===================================================================
--- sys/riscv/riscv/trap.c
+++ sys/riscv/riscv/trap.c
@@ -62,6 +62,8 @@
#include <machine/frame.h>
#include <machine/pcb.h>
#include <machine/pcpu.h>
+#include <machine/vector.h>
+#include <machine/md_var.h>
#include <machine/resource.h>
@@ -443,6 +445,17 @@
pcb->pcb_fpflags |= PCB_FP_STARTED;
break;
}
+ if (has_vector && (pcb->pcb_vsflags & PCB_VS_STARTED) == 0) {
+ /*
+ * Could be a vector trap. Enable VS usage
+ * for this thread and try again.
+ */
+ vector_state_init(td);
+ frame->tf_sstatus &= ~SSTATUS_VS_MASK;
+ frame->tf_sstatus |= SSTATUS_VS_CLEAN;
+ pcb->pcb_vsflags |= PCB_VS_STARTED;
+ break;
+ }
call_trapsignal(td, SIGILL, ILL_ILLTRP, (void *)frame->tf_sepc,
exception);
userret(td, frame);
Index: sys/riscv/riscv/vector.c
===================================================================
--- /dev/null
+++ sys/riscv/riscv/vector.c
@@ -0,0 +1,214 @@
+/*-
+ * Copyright (c) 2026 Ruslan Bukin <br@bsdpad.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+
+#include <vm/uma.h>
+
+#include <machine/vector.h>
+#include <machine/pcb.h>
+#include <machine/reg.h>
+
+static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx",
+ "Kernel contexts for Vector state");
+
+static void
+vector_enable(void)
+{
+ uint64_t reg;
+
+ reg = SSTATUS_VS_CLEAN;
+
+ csr_set(sstatus, reg);
+}
+
+static void
+vector_disable(void)
+{
+ uint64_t mask;
+
+ mask = SSTATUS_VS_MASK;
+
+ csr_clear(sstatus, mask);
+}
+
+void
+vector_state_store(struct thread *td)
+{
+ struct pcb *p;
+ void *datap;
+ uint64_t vl;
+
+ p = td->td_pcb;
+
+ KASSERT(p->pcb_vsaved != NULL, ("VS area is NULL"));
+
+ datap = p->pcb_vsaved;
+
+ vector_enable();
+
+ /* Store vector CSRs. */
+ __asm __volatile(
+ "csrr %0, vstart\n\t"
+ "csrr %1, vtype\n\t"
+ "csrr %2, vl\n\t"
+ "csrr %3, vcsr\n\t"
+ : "=r" (p->pcb_vstart), "=r" (p->pcb_vtype),
+ "=r" (p->pcb_vl), "=r" (p->pcb_vcsr) ::);
+
+ /* Store vector registers. */
+ __asm __volatile(
+ ".option push\n\t"
+ ".option arch, +zve32x\n\t"
+ "vsetvli %0, x0, e8, m8, ta, ma\n\t"
+ "vse8.v v0, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vse8.v v8, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vse8.v v16, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vse8.v v24, (%1)\n\t"
+ ".option pop\n\t"
+ : "=&r" (vl) : "r" (datap) : "memory");
+
+ vector_disable();
+}
+
+void
+vector_state_restore(struct thread *td)
+{
+ struct pcb *p;
+ void *datap;
+ uint64_t vl;
+
+ p = td->td_pcb;
+
+ KASSERT(p->pcb_vsaved != NULL, ("VS area is NULL"));
+
+ datap = p->pcb_vsaved;
+
+ vector_enable();
+
+ /* Restore vector registers. */
+ __asm __volatile(
+ ".option push\n\t"
+ ".option arch, +zve32x\n\t"
+ "vsetvli %0, x0, e8, m8, ta, ma\n\t"
+ "vle8.v v0, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vle8.v v8, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vle8.v v16, (%1)\n\t"
+ "add %1, %1, %0\n\t"
+ "vle8.v v24, (%1)\n\t"
+ ".option pop\n\t"
+ : "=&r" (vl) : "r" (datap) : "memory");
+
+ /* Restore vector CSRs. */
+ __asm __volatile(
+ ".option push\n\t"
+ ".option arch, +zve32x\n\t"
+ "vsetvl x0, %2, %1\n\t"
+ ".option pop\n\t"
+ "csrw vstart, %0\n\t"
+ "csrw vcsr, %3\n\t"
+ :: "r" (p->pcb_vstart), "r" (p->pcb_vtype),
+ "r" (p->pcb_vl), "r" (p->pcb_vcsr));
+
+ vector_disable();
+}
+
+static int
+vector_get_size(void)
+{
+ int len;
+
+ /* RISC-V has 32 vector registers of vlenb size each. */
+
+ vector_enable();
+ len = csr_read(vlenb) * 32;
+ vector_disable();
+
+ return (len);
+}
+
+void
+vector_state_init(struct thread *td)
+{
+ struct pcb *p;
+ int len;
+
+ p = td->td_pcb;
+
+ KASSERT(p->pcb_vsaved == NULL, ("vsaved is already initialized"));
+
+ len = vector_get_size();
+
+ p->pcb_vsaved = malloc(len, M_FPUKERN_CTX, M_WAITOK | M_ZERO);
+}
+
+void
+vector_copy_thread(struct thread *td1, struct thread *td2)
+{
+ struct pcb *p1;
+ struct pcb *p2;
+ int len;
+
+ /* Struct pcb already copied, now init the vector save area. */
+
+ p1 = td1->td_pcb;
+ p2 = td2->td_pcb;
+ p2->pcb_vsaved = NULL;
+
+ vector_state_init(td2);
+
+ len = vector_get_size();
+
+ memcpy(p2->pcb_vsaved, p1->pcb_vsaved, len);
+}
+
+static void
+vector_thread_dtor(void *arg __unused, struct thread *td)
+{
+ void *datap;
+
+ datap = td->td_pcb->pcb_vsaved;
+
+ free(datap, M_FPUKERN_CTX);
+}
+
+static void
+vector_init(const void *dummy __unused)
+{
+
+ EVENTHANDLER_REGISTER(thread_dtor, vector_thread_dtor, NULL,
+ EVENTHANDLER_PRI_ANY);
+}
+
+SYSINIT(vector, SI_SUB_SMP, SI_ORDER_ANY, vector_init, NULL);
Index: sys/riscv/riscv/vm_machdep.c
===================================================================
--- sys/riscv/riscv/vm_machdep.c
+++ sys/riscv/riscv/vm_machdep.c
@@ -53,6 +53,7 @@
#include <machine/pcb.h>
#include <machine/frame.h>
#include <machine/sbi.h>
+#include <machine/vector.h>
#if __riscv_xlen == 64
#define TP_OFFSET 16 /* sizeof(struct tcb) */
@@ -100,6 +101,14 @@
critical_exit();
}
+ /* Ensure the Vector state is saved before copying the pcb. */
+ if ((td1->td_pcb->pcb_vsflags & PCB_VS_STARTED) != 0) {
+ MPASS(td1 == curthread);
+ critical_enter();
+ vector_state_store(td1);
+ critical_exit();
+ }
+
cpu_set_pcb_frame(td2);
pcb2 = td2->td_pcb;
@@ -123,6 +132,9 @@
td2->td_pcb->pcb_ra = (uintptr_t)fork_trampoline;
td2->td_pcb->pcb_sp = (uintptr_t)td2->td_frame;
+ if ((td1->td_pcb->pcb_vsflags & PCB_VS_STARTED) != 0)
+ vector_copy_thread(td1, td2);
+
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_sstatus_ie = (SSTATUS_SIE);

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 20, 8:36 AM (20 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31828462
Default Alt Text
D56414.diff (14 KB)

Event Timeline