Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F153127046
D56414.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D56414.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D56414: riscv: vector extension support
Attached
Detach File
Event Timeline
Log In to Comment