Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142742527
D45512.id139568.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
38 KB
Referenced Files
None
Subscribers
None
D45512.id139568.diff
View Options
Index: lib/Makefile
===================================================================
--- lib/Makefile
+++ lib/Makefile
@@ -206,7 +206,8 @@
SUBDIR.${MK_PMC}+= libipt
.endif
-.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64"
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64" || \
+ ${MACHINE_CPUARCH} == "riscv"
SUBDIR.${MK_BHYVE}+= libvmmapi
.endif
Index: lib/libvmmapi/riscv/Makefile.inc
===================================================================
--- /dev/null
+++ lib/libvmmapi/riscv/Makefile.inc
@@ -0,0 +1 @@
+SRCS+= vmmapi_machdep.c
Index: lib/libvmmapi/riscv/vmmapi_machdep.c
===================================================================
--- /dev/null
+++ lib/libvmmapi/riscv/vmmapi_machdep.c
@@ -0,0 +1,117 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ *
+ * 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 NETAPP, INC ``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 NETAPP, INC 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/types.h>
+#include <sys/ioctl.h>
+
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+#include <machine/vmm_snapshot.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "vmmapi.h"
+#include "internal.h"
+
+const char *vm_capstrmap[] = {
+ [VM_CAP_MAX] = NULL,
+};
+
+#define VM_MD_IOCTLS \
+ VM_ATTACH_APLIC, \
+ VM_ASSERT_IRQ, \
+ VM_DEASSERT_IRQ, \
+ VM_RAISE_MSI
+
+const cap_ioctl_t vm_ioctl_cmds[] = {
+ VM_COMMON_IOCTLS,
+ VM_MD_IOCTLS,
+};
+size_t vm_ioctl_ncmds = nitems(vm_ioctl_cmds);
+
+int
+vm_attach_aplic(struct vmctx *ctx, uint64_t mem_start, size_t mem_size)
+{
+ struct vm_aplic_descr aplic;
+
+ bzero(&aplic, sizeof(aplic));
+ aplic.mem_start = mem_start;
+ aplic.mem_size = mem_size;
+
+ return (ioctl(ctx->fd, VM_ATTACH_APLIC, &aplic));
+}
+
+int
+vm_assert_irq(struct vmctx *ctx, uint32_t irq)
+{
+ struct vm_irq vi;
+
+ bzero(&vi, sizeof(vi));
+ vi.irq = irq;
+
+ return (ioctl(ctx->fd, VM_ASSERT_IRQ, &vi));
+}
+
+int
+vm_deassert_irq(struct vmctx *ctx, uint32_t irq)
+{
+ struct vm_irq vi;
+
+ bzero(&vi, sizeof(vi));
+ vi.irq = irq;
+
+ return (ioctl(ctx->fd, VM_DEASSERT_IRQ, &vi));
+}
+
+int
+vm_raise_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg,
+ int bus, int slot, int func)
+{
+ struct vm_msi vmsi;
+
+ bzero(&vmsi, sizeof(vmsi));
+ vmsi.addr = addr;
+ vmsi.msg = msg;
+ vmsi.bus = bus;
+ vmsi.slot = slot;
+ vmsi.func = func;
+
+ return (ioctl(ctx->fd, VM_RAISE_MSI, &vmsi));
+}
+
+int
+vm_inject_exception(struct vcpu *vcpu, uint64_t scause)
+{
+ struct vm_exception vmexc;
+
+ bzero(&vmexc, sizeof(vmexc));
+ vmexc.scause = scause;
+
+ return (vcpu_ioctl(vcpu, VM_INJECT_EXCEPTION, &vmexc));
+}
Index: lib/libvmmapi/vmmapi.h
===================================================================
--- lib/libvmmapi/vmmapi.h
+++ lib/libvmmapi/vmmapi.h
@@ -161,12 +161,17 @@
int vm_reinit(struct vmctx *ctx);
int vm_raise_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg,
int bus, int slot, int func);
-#ifdef __aarch64__
+#if defined(__aarch64__)
int vm_attach_vgic(struct vmctx *ctx, uint64_t dist_start, size_t dist_size,
uint64_t redist_start, size_t redist_size);
+int vm_inject_exception(struct vcpu *vcpu, uint64_t esr, uint64_t far);
+#elif defined(__riscv)
+int vm_attach_aplic(struct vmctx *ctx, uint64_t mem_start, size_t mem_size);
+int vm_inject_exception(struct vcpu *vcpu, uint64_t scause);
+#endif
+#if defined(__aarch64__) || defined(__riscv)
int vm_assert_irq(struct vmctx *ctx, uint32_t irq);
int vm_deassert_irq(struct vmctx *ctx, uint32_t irq);
-int vm_inject_exception(struct vcpu *vcpu, uint64_t esr, uint64_t far);
#endif
#ifdef __amd64__
int vm_apicid2vcpu(struct vmctx *ctx, int apicid);
Index: usr.sbin/Makefile.riscv
===================================================================
--- /dev/null
+++ usr.sbin/Makefile.riscv
@@ -0,0 +1,2 @@
+SUBDIR+= bhyve
+SUBDIR+= bhyvectl
Index: usr.sbin/bhyve/pci_emul.c
===================================================================
--- usr.sbin/bhyve/pci_emul.c
+++ usr.sbin/bhyve/pci_emul.c
@@ -135,7 +135,7 @@
* change this address without changing it in OVMF.
*/
#define PCI_EMUL_MEMBASE32 0xc0000000
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(__riscv)
#define PCI_EMUL_IOBASE 0xdf000000UL
#define PCI_EMUL_IOLIMIT 0xe0000000UL
#define PCI_EMUL_MEMBASE32 0xa0000000UL
Index: usr.sbin/bhyve/pci_irq.h
===================================================================
--- usr.sbin/bhyve/pci_irq.h
+++ usr.sbin/bhyve/pci_irq.h
@@ -36,6 +36,8 @@
#include "amd64/pci_irq_machdep.h"
#elif defined(__aarch64__)
#include "aarch64/pci_irq_machdep.h"
+#elif defined(__riscv)
+#include "riscv/pci_irq_machdep.h"
#else
#error Unsupported platform
#endif
Index: usr.sbin/bhyve/riscv/Makefile.inc
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/Makefile.inc
@@ -0,0 +1,7 @@
+SRCS+= \
+ fdt.c
+
+.PATH: ${BHYVE_SYSDIR}/sys/riscv/vmm
+SRCS+= vmm_instruction_emul.c
+
+BHYVE_FDT_SUPPORT=
Index: usr.sbin/bhyve/riscv/bhyverun_machdep.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/bhyverun_machdep.c
@@ -0,0 +1,363 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ * Copyright (c) 2024 Ruslan Bukin <br@bsdpad.com>
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * 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 NETAPP, INC ``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 NETAPP, INC 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/mman.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "config.h"
+#include "debug.h"
+#include "fdt.h"
+#include "mem.h"
+#include "pci_emul.h"
+#include "pci_irq.h"
+#include "uart_emul.h"
+
+/* Start of mem + 32M */
+#define FDT_BASE 0x2000000
+#define FDT_SIZE (64 * 1024)
+
+/* Start of lowmem + 64K */
+#define UART_MMIO_BASE 0x10000
+#define UART_MMIO_SIZE 0x1000
+#define UART_INTR 1
+
+#define APLIC_MEM_BASE 0x2f000000
+#define APLIC_MEM_SIZE 0x10000
+
+#define PCIE_INTA 2
+#define PCIE_INTB 3
+#define PCIE_INTC 4
+#define PCIE_INTD 5
+
+void
+bhyve_init_config(void)
+{
+ init_config();
+
+ /* Set default values prior to option parsing. */
+ set_config_bool("acpi_tables", false);
+ set_config_bool("acpi_tables_in_memory", false);
+ set_config_value("memory.size", "256M");
+}
+
+void
+bhyve_usage(int code)
+{
+ const char *progname;
+
+ progname = getprogname();
+
+ fprintf(stderr,
+ "Usage: %s [-CDHhSW]\n"
+ " %*s [-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n]]\n"
+ " %*s [-k config_file] [-m mem] [-o var=value]\n"
+ " %*s [-p vcpu:hostcpu] [-r file] [-s pci] [-U uuid] vmname\n"
+ " -C: include guest memory in core file\n"
+ " -c: number of CPUs and/or topology specification\n"
+ " -D: destroy on power-off\n"
+ " -h: help\n"
+ " -k: key=value flat config file\n"
+ " -m: memory size\n"
+ " -o: set config 'var' to 'value'\n"
+ " -p: pin 'vcpu' to 'hostcpu'\n"
+ " -S: guest memory cannot be swapped\n"
+ " -s: <slot,driver,configinfo> PCI slot config\n"
+ " -U: UUID\n"
+ " -W: force virtio to use single-vector MSI\n",
+ progname, (int)strlen(progname), "", (int)strlen(progname), "",
+ (int)strlen(progname), "");
+ exit(code);
+}
+
+void
+bhyve_optparse(int argc, char **argv)
+{
+ const char *optstr;
+ int c;
+
+ optstr = "hCDSWk:f:o:p:c:s:m:U:";
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'c':
+ if (bhyve_topology_parse(optarg) != 0) {
+ errx(EX_USAGE, "invalid cpu topology '%s'",
+ optarg);
+ }
+ break;
+ case 'C':
+ set_config_bool("memory.guest_in_core", true);
+ break;
+ case 'D':
+ set_config_bool("destroy_on_poweroff", true);
+ break;
+ case 'k':
+ bhyve_parse_simple_config_file(optarg);
+ break;
+ case 'm':
+ set_config_value("memory.size", optarg);
+ break;
+ case 'o':
+ if (!bhyve_parse_config_option(optarg)) {
+ errx(EX_USAGE,
+ "invalid configuration option '%s'",
+ optarg);
+ }
+ break;
+ case 'p':
+ if (bhyve_pincpu_parse(optarg) != 0) {
+ errx(EX_USAGE,
+ "invalid vcpu pinning configuration '%s'",
+ optarg);
+ }
+ break;
+ case 's':
+ if (strncmp(optarg, "help", strlen(optarg)) == 0) {
+ pci_print_supported_devices();
+ exit(0);
+ } else if (pci_parse_slot(optarg) != 0)
+ exit(4);
+ else
+ break;
+ case 'S':
+ set_config_bool("memory.wired", true);
+ break;
+ case 'U':
+ set_config_value("uuid", optarg);
+ break;
+ case 'W':
+ set_config_bool("virtio_msix", false);
+ break;
+ case 'h':
+ bhyve_usage(0);
+ default:
+ bhyve_usage(1);
+ }
+ }
+}
+
+void
+bhyve_init_vcpu(struct vcpu *vcpu __unused)
+{
+}
+
+void
+bhyve_start_vcpu(struct vcpu *vcpu, bool bsp __unused)
+{
+ int error;
+
+ /* Set hart ID. */
+ error = vm_set_register(vcpu, VM_REG_GUEST_A0, vcpu_id(vcpu));
+
+ assert(error == 0);
+
+ fbsdrun_addcpu(vcpu_id(vcpu));
+}
+
+/*
+ * Load the specified boot code at the beginning of high memory.
+ */
+static void
+load_bootrom(struct vmctx *ctx, const char *path, uint64_t *elrp)
+{
+ struct stat sb;
+ void *data, *gptr;
+ vm_paddr_t loadaddr;
+ off_t size;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ err(1, "open(%s)", path);
+ if (fstat(fd, &sb) != 0)
+ err(1, "fstat(%s)", path);
+
+ size = sb.st_size;
+
+ loadaddr = vm_get_highmem_base(ctx);
+ gptr = vm_map_gpa(ctx, loadaddr, round_page(size));
+
+ data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED)
+ err(1, "mmap(%s)", path);
+ (void)close(fd);
+ memcpy(gptr, data, size);
+
+ if (munmap(data, size) != 0)
+ err(1, "munmap(%s)", path);
+
+ *elrp = loadaddr;
+}
+
+static void
+mmio_uart_intr_assert(void *arg)
+{
+ struct vmctx *ctx = arg;
+
+ vm_assert_irq(ctx, UART_INTR);
+}
+
+static void
+mmio_uart_intr_deassert(void *arg)
+{
+ struct vmctx *ctx = arg;
+
+ vm_deassert_irq(ctx, UART_INTR);
+}
+
+static int
+mmio_uart_mem_handler(struct vcpu *vcpu __unused, int dir, uint64_t addr,
+ int size __unused, uint64_t *val, void *arg1, long arg2)
+{
+ struct uart_ns16550_softc *sc = arg1;
+ long reg;
+
+ reg = addr - arg2;
+ if (dir == MEM_F_WRITE)
+ uart_ns16550_write(sc, reg, *val);
+ else
+ *val = uart_ns16550_read(sc, reg);
+
+ return (0);
+}
+
+static bool
+init_mmio_uart(struct vmctx *ctx)
+{
+ struct uart_ns16550_softc *sc;
+ struct mem_range mr;
+ const char *path;
+ int error;
+
+ path = get_config_value("console");
+ if (path == NULL)
+ return (false);
+
+ sc = uart_ns16550_init(mmio_uart_intr_assert, mmio_uart_intr_deassert,
+ ctx);
+ if (uart_ns16550_tty_open(sc, path) != 0) {
+ EPRINTLN("Unable to initialize backend '%s' for mmio uart",
+ path);
+ assert(0);
+ }
+
+ bzero(&mr, sizeof(struct mem_range));
+ mr.name = "uart";
+ mr.base = UART_MMIO_BASE;
+ mr.size = UART_MMIO_SIZE;
+ mr.flags = MEM_F_RW;
+ mr.handler = mmio_uart_mem_handler;
+ mr.arg1 = sc;
+ mr.arg2 = mr.base;
+ error = register_mem(&mr);
+ assert(error == 0);
+
+ return (true);
+}
+
+static vm_paddr_t
+fdt_gpa(struct vmctx *ctx)
+{
+ return (vm_get_highmem_base(ctx) + FDT_BASE);
+}
+
+int
+bhyve_init_platform(struct vmctx *ctx, struct vcpu *bsp)
+{
+ const char *bootrom;
+ uint64_t elr;
+ int error;
+ int pcie_intrs[4] = {PCIE_INTA, PCIE_INTB, PCIE_INTC, PCIE_INTD};
+
+ bootrom = get_config_value("bootrom");
+ if (bootrom == NULL) {
+ warnx("no bootrom specified");
+ return (ENOENT);
+ }
+ load_bootrom(ctx, bootrom, &elr);
+ error = vm_set_register(bsp, VM_REG_GUEST_SEPC, elr);
+ if (error != 0) {
+ warn("vm_set_register(GUEST_SEPC)");
+ return (error);
+ }
+
+ error = fdt_init(ctx, guest_ncpus, fdt_gpa(ctx), FDT_SIZE);
+ if (error != 0)
+ return (error);
+
+ fdt_add_aplic(APLIC_MEM_BASE, APLIC_MEM_SIZE);
+ error = vm_attach_aplic(ctx, APLIC_MEM_BASE, APLIC_MEM_SIZE);
+ if (error != 0) {
+ warn("vm_attach_aplic()");
+ return (error);
+ }
+
+ if (init_mmio_uart(ctx))
+ fdt_add_uart(UART_MMIO_BASE, UART_MMIO_SIZE, UART_INTR);
+
+ pci_irq_init(pcie_intrs);
+ fdt_add_pcie(pcie_intrs);
+
+ return (0);
+}
+
+int
+bhyve_init_platform_late(struct vmctx *ctx, struct vcpu *bsp)
+{
+ int error;
+
+ fdt_finalize();
+
+ /* Set hart ID. */
+ error = vm_set_register(bsp, VM_REG_GUEST_A0, 0);
+ assert(error == 0);
+
+ /* Set FDT base address. */
+ error = vm_set_register(bsp, VM_REG_GUEST_A1, fdt_gpa(ctx));
+ assert(error == 0);
+
+ return (0);
+}
Index: usr.sbin/bhyve/riscv/fdt.h
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/fdt.h
@@ -0,0 +1,45 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 The FreeBSD Foundation
+ *
+ * This software was developed by Andrew Turner under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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 _FDT_H_
+#define _FDT_H_
+
+#include <sys/types.h>
+
+struct vmctx;
+
+int fdt_init(struct vmctx *ctx, int ncpu, vm_paddr_t addrp,
+ vm_size_t size);
+void fdt_add_aplic(uint64_t dist_base, uint64_t dist_size);
+void fdt_add_pcie(int intrs[static 4]);
+void fdt_add_uart(uint64_t uart_base, uint64_t uart_size, int intr);
+void fdt_finalize(void);
+
+#endif /* _FDT_H_ */
Index: usr.sbin/bhyve/riscv/fdt.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/fdt.c
@@ -0,0 +1,326 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 The FreeBSD Foundation
+ * Copyright (c) 2024 Ruslan Bukin <br@bsdpad.com>
+ *
+ * This software was developed by Andrew Turner under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * 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 <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <libfdt.h>
+#include <vmmapi.h>
+
+#include "config.h"
+#include "bhyverun.h"
+#include "fdt.h"
+
+#define SET_PROP_U32(prop, idx, val) \
+ ((uint32_t *)(prop))[(idx)] = cpu_to_fdt32(val)
+#define SET_PROP_U64(prop, idx, val) \
+ ((uint64_t *)(prop))[(idx)] = cpu_to_fdt64(val)
+
+#define IRQ_TYPE_LEVEL_HIGH 4
+#define IRQ_TYPE_LEVEL_LOW 8
+
+static void *fdtroot;
+static uint32_t aplic_phandle = 0;
+static uint32_t intc0_phandle = 0;
+
+static uint32_t
+assign_phandle(void *fdt)
+{
+ static uint32_t next_phandle = 1;
+ uint32_t phandle;
+
+ phandle = next_phandle;
+ next_phandle++;
+ fdt_property_u32(fdt, "phandle", phandle);
+
+ return (phandle);
+}
+
+static void
+set_single_reg(void *fdt, uint64_t start, uint64_t len)
+{
+ void *reg;
+
+ fdt_property_placeholder(fdt, "reg", 2 * sizeof(uint64_t), ®);
+ SET_PROP_U64(reg, 0, start);
+ SET_PROP_U64(reg, 1, len);
+}
+
+static void
+add_cpu(void *fdt, int cpuid)
+{
+ char node_name[16];
+
+ snprintf(node_name, sizeof(node_name), "cpu@%d", cpuid);
+
+ fdt_begin_node(fdt, node_name);
+ fdt_property_string(fdt, "device_type", "cpu");
+ fdt_property_string(fdt, "compatible", "riscv");
+ fdt_property_u64(fdt, "reg", cpuid);
+ fdt_property_string(fdt, "riscv,isa", "rv64imafdch_zicntr_zihpm_sstc");
+ fdt_property_string(fdt, "mmu-type", "riscv,sv39");
+ fdt_property_string(fdt, "clock-frequency", "1000000000");
+
+ fdt_begin_node(fdt, "interrupt-controller");
+ intc0_phandle = assign_phandle(fdt);
+ fdt_property_u32(fdt, "#address-cells", 2);
+ fdt_property_u32(fdt, "#interrupt-cells", 1);
+ fdt_property(fdt, "interrupt-controller", NULL, 0);
+ fdt_property_string(fdt, "compatible", "riscv,cpu-intc");
+ fdt_end_node(fdt);
+
+ fdt_end_node(fdt);
+}
+
+static void
+add_cpus(void *fdt, int ncpu)
+{
+ int cpuid;
+
+ fdt_begin_node(fdt, "cpus");
+ /* XXX: Needed given the root #address-cells? */
+ fdt_property_u32(fdt, "#address-cells", 1);
+ fdt_property_u32(fdt, "#size-cells", 0);
+ fdt_property_u32(fdt, "timebase-frequency", 10000000);
+
+ for (cpuid = 0; cpuid < ncpu; cpuid++) {
+ add_cpu(fdt, cpuid);
+ }
+ fdt_end_node(fdt);
+}
+
+int
+fdt_init(struct vmctx *ctx, int ncpu, vm_paddr_t fdtaddr, vm_size_t fdtsize)
+{
+ void *fdt;
+ const char *bootargs;
+
+ fdt = paddr_guest2host(ctx, fdtaddr, fdtsize);
+ if (fdt == NULL)
+ return (EFAULT);
+
+ fdt_create(fdt, (int)fdtsize);
+
+ /* Add the memory reserve map (needed even if none is reserved) */
+ fdt_finish_reservemap(fdt);
+
+ /* Create the root node */
+ fdt_begin_node(fdt, "");
+
+ fdt_property_string(fdt, "compatible", "freebsd,bhyve");
+ fdt_property_u32(fdt, "#address-cells", 2);
+ fdt_property_u32(fdt, "#size-cells", 2);
+
+ fdt_begin_node(fdt, "chosen");
+ fdt_property_string(fdt, "stdout-path", "serial0:115200n8");
+ bootargs = get_config_value("fdt.bootargs");
+ if (bootargs != NULL)
+ fdt_property_string(fdt, "bootargs", bootargs);
+ fdt_end_node(fdt);
+
+ fdt_begin_node(fdt, "memory");
+ fdt_property_string(fdt, "device_type", "memory");
+ /* There is no lowmem on riscv. */
+ assert(vm_get_lowmem_size(ctx) == 0);
+ set_single_reg(fdt, vm_get_highmem_base(ctx), vm_get_highmem_size(ctx));
+ fdt_end_node(fdt);
+
+ add_cpus(fdt, ncpu);
+
+ /* Finalized by fdt_finalized(). */
+ fdtroot = fdt;
+
+ return (0);
+}
+
+void
+fdt_add_aplic(uint64_t mem_base, uint64_t mem_size)
+{
+ char node_name[32];
+ void *fdt, *prop;
+
+ fdt = fdtroot;
+
+ snprintf(node_name, sizeof(node_name), "interrupt-controller@%lx",
+ (unsigned long)mem_base);
+ fdt_begin_node(fdt, node_name);
+
+ aplic_phandle = assign_phandle(fdt);
+ fdt_property_string(fdt, "compatible", "riscv,aplic");
+ fdt_property(fdt, "interrupt-controller", NULL, 0);
+#if notyet
+ fdt_property(fdt, "msi-controller", NULL, 0);
+#endif
+ /* XXX: Needed given the root #address-cells? */
+ fdt_property_u32(fdt, "#address-cells", 2);
+ fdt_property_u32(fdt, "#interrupt-cells", 2);
+ fdt_property_placeholder(fdt, "reg", 2 * sizeof(uint64_t), &prop);
+ SET_PROP_U64(prop, 0, mem_base);
+ SET_PROP_U64(prop, 1, mem_size);
+
+ fdt_property_placeholder(fdt, "interrupts-extended",
+ 2 * sizeof(uint32_t), &prop);
+ SET_PROP_U32(prop, 0, intc0_phandle);
+ SET_PROP_U32(prop, 1, 9);
+ fdt_property_u32(fdt, "riscv,num-sources", 63);
+
+ fdt_end_node(fdt);
+
+ fdt_property_u32(fdt, "interrupt-parent", aplic_phandle);
+}
+
+void
+fdt_add_uart(uint64_t uart_base, uint64_t uart_size, int intr)
+{
+ void *fdt, *interrupts;
+ char node_name[32];
+
+ assert(aplic_phandle != 0);
+
+ fdt = fdtroot;
+
+ snprintf(node_name, sizeof(node_name), "serial@%lx", uart_base);
+ fdt_begin_node(fdt, node_name);
+ fdt_property_string(fdt, "compatible", "ns16550");
+ set_single_reg(fdt, uart_base, uart_size);
+ fdt_property_u32(fdt, "interrupt-parent", aplic_phandle);
+ fdt_property_placeholder(fdt, "interrupts", 2 * sizeof(uint32_t),
+ &interrupts);
+ SET_PROP_U32(interrupts, 0, intr);
+ SET_PROP_U32(interrupts, 1, IRQ_TYPE_LEVEL_HIGH);
+
+ fdt_end_node(fdt);
+
+ snprintf(node_name, sizeof(node_name), "/serial@%lx", uart_base);
+ fdt_begin_node(fdt, "aliases");
+ fdt_property_string(fdt, "serial0", node_name);
+ fdt_end_node(fdt);
+}
+
+void
+fdt_add_pcie(int intrs[static 4])
+{
+ void *fdt, *prop;
+ int slot, pin, intr, i;
+
+ assert(aplic_phandle != 0);
+
+ fdt = fdtroot;
+
+ fdt_begin_node(fdt, "pcie@1f0000000");
+ fdt_property_string(fdt, "compatible", "pci-host-ecam-generic");
+ fdt_property_u32(fdt, "#address-cells", 3);
+ fdt_property_u32(fdt, "#size-cells", 2);
+ fdt_property_string(fdt, "device_type", "pci");
+ fdt_property_u64(fdt, "bus-range", (0ul << 32) | 1);
+ set_single_reg(fdt, 0xe0000000, 0x10000000);
+ fdt_property_placeholder(fdt, "ranges",
+ 2 * 7 * sizeof(uint32_t), &prop);
+ SET_PROP_U32(prop, 0, 0x01000000);
+
+ SET_PROP_U32(prop, 1, 0);
+ SET_PROP_U32(prop, 2, 0xdf000000);
+
+ SET_PROP_U32(prop, 3, 0);
+ SET_PROP_U32(prop, 4, 0xdf000000);
+
+ SET_PROP_U32(prop, 5, 0);
+ SET_PROP_U32(prop, 6, 0x01000000);
+
+ SET_PROP_U32(prop, 7, 0x02000000);
+
+ SET_PROP_U32(prop, 8, 0);
+ SET_PROP_U32(prop, 9, 0xa0000000);
+
+ SET_PROP_U32(prop, 10, 0);
+ SET_PROP_U32(prop, 11, 0xa0000000);
+
+ SET_PROP_U32(prop, 12, 0);
+ SET_PROP_U32(prop, 13, 0x3f000000);
+
+#if notyet
+ fdt_property_placeholder(fdt, "msi-map", 4 * sizeof(uint32_t), &prop);
+ SET_PROP_U32(prop, 0, 0); /* RID base */
+ SET_PROP_U32(prop, 1, aplic_phandle); /* MSI parent */
+ SET_PROP_U32(prop, 2, 0); /* MSI base */
+ SET_PROP_U32(prop, 3, 0x10000); /* RID length */
+ fdt_property_u32(fdt, "msi-parent", aplic_phandle);
+#endif
+
+ fdt_property_u32(fdt, "#interrupt-cells", 1);
+ fdt_property_u32(fdt, "interrupt-parent", aplic_phandle);
+
+ /*
+ * Describe standard swizzled interrupts routing (pins rotated by one
+ * for each consecutive slot). Must match pci_irq_route().
+ */
+ fdt_property_placeholder(fdt, "interrupt-map-mask",
+ 4 * sizeof(uint32_t), &prop);
+ SET_PROP_U32(prop, 0, 3 << 11);
+ SET_PROP_U32(prop, 1, 0);
+ SET_PROP_U32(prop, 2, 0);
+ SET_PROP_U32(prop, 3, 7);
+ fdt_property_placeholder(fdt, "interrupt-map",
+ 16 * 9 * sizeof(uint32_t), &prop);
+ for (i = 0; i < 16; ++i) {
+ pin = i % 4;
+ slot = i / 4;
+ intr = intrs[(pin + slot) % 4];
+ SET_PROP_U32(prop, 10 * i + 0, slot << 11);
+ SET_PROP_U32(prop, 10 * i + 1, 0);
+ SET_PROP_U32(prop, 10 * i + 2, 0);
+ SET_PROP_U32(prop, 10 * i + 3, pin + 1);
+ SET_PROP_U32(prop, 10 * i + 4, aplic_phandle);
+ SET_PROP_U32(prop, 10 * i + 5, 0);
+ SET_PROP_U32(prop, 10 * i + 6, 0);
+ SET_PROP_U32(prop, 10 * i + 7, intr);
+ SET_PROP_U32(prop, 10 * i + 8, IRQ_TYPE_LEVEL_HIGH);
+ }
+
+ fdt_end_node(fdt);
+}
+
+void
+fdt_finalize(void)
+{
+ fdt_end_node(fdtroot);
+
+ fdt_finish(fdtroot);
+}
Index: usr.sbin/bhyve/riscv/pci_irq.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/pci_irq.c
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Jessica Clarke <jrtc27@FreeBSD.org>
+ *
+ * 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 <vmmapi.h>
+
+#include "pci_emul.h"
+#include "pci_irq.h"
+
+static int aplic_irqs[4];
+
+void
+pci_irq_init(int intrs[static 4])
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ aplic_irqs[i] = intrs[i];
+}
+
+void
+pci_irq_assert(struct pci_devinst *pi)
+{
+ vm_assert_irq(pi->pi_vmctx, pi->pi_lintr.irq.aplic_irq);
+}
+
+void
+pci_irq_deassert(struct pci_devinst *pi)
+{
+ vm_deassert_irq(pi->pi_vmctx, pi->pi_lintr.irq.aplic_irq);
+}
+
+void
+pci_irq_route(struct pci_devinst *pi, struct pci_irq *irq)
+{
+ /*
+ * Assign swizzled IRQ for this INTx if one is not yet assigned. Must
+ * match fdt_add_pcie().
+ */
+ if (irq->aplic_irq == 0)
+ irq->aplic_irq =
+ aplic_irqs[(pi->pi_slot + pi->pi_lintr.pin - 1) % 4];
+}
Index: usr.sbin/bhyve/riscv/pci_irq_machdep.h
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/pci_irq_machdep.h
@@ -0,0 +1,49 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Jessica Clarke <jrtc27@FreeBSD.org>
+ *
+ * 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 __PCI_IRQ_MD_H__
+#define __PCI_IRQ_MD_H__
+
+struct pci_irq {
+ int aplic_irq;
+};
+
+void pci_irq_init(int intrs[static 4]);
+
+static inline void
+pci_irq_init_irq(struct pci_irq *irq)
+{
+ irq->aplic_irq = 0;
+}
+
+static inline uint8_t
+pci_irq_intline(struct pci_irq *irq __unused)
+{
+ return (255);
+}
+
+#endif
Index: usr.sbin/bhyve/riscv/vmexit.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyve/riscv/vmexit.c
@@ -0,0 +1,188 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ * Copyright (c) 2024 Ruslan Bukin <br@bsdpad.com>
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * 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 NETAPP, INC ``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 NETAPP, INC 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/types.h>
+#include <sys/cpuset.h>
+
+#include <machine/riscvreg.h>
+#include <machine/cpu.h>
+#include <machine/sbi.h>
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+#include <machine/vmm_instruction_emul.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "config.h"
+#include "debug.h"
+#include "mem.h"
+#include "vmexit.h"
+
+static int
+vmexit_inst_emul(struct vmctx *ctx __unused, struct vcpu *vcpu,
+ struct vm_run *vmrun)
+{
+ struct vm_exit *vme;
+ struct vie *vie;
+ int err;
+
+ vme = vmrun->vm_exit;
+ vie = &vme->u.inst_emul.vie;
+
+ err = emulate_mem(vcpu, vme->u.inst_emul.gpa, vie,
+ &vme->u.inst_emul.paging);
+ if (err) {
+ if (err == ESRCH) {
+ EPRINTLN("Unhandled memory access to 0x%lx\n",
+ vme->u.inst_emul.gpa);
+ }
+ goto fail;
+ }
+
+ return (VMEXIT_CONTINUE);
+
+fail:
+ fprintf(stderr, "Failed to emulate instruction ");
+ FPRINTLN(stderr, "at 0x%lx", vme->pc);
+ return (VMEXIT_ABORT);
+}
+
+static int
+vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun)
+{
+ struct vm_exit *vme;
+ enum vm_suspend_how how;
+ int vcpuid = vcpu_id(vcpu);
+
+ vme = vmrun->vm_exit;
+ how = vme->u.suspended.how;
+
+ fbsdrun_deletecpu(vcpuid);
+
+ switch (how) {
+ case VM_SUSPEND_RESET:
+ exit(0);
+ case VM_SUSPEND_POWEROFF:
+ if (get_config_bool_default("destroy_on_poweroff", false))
+ vm_destroy(ctx);
+ exit(1);
+ case VM_SUSPEND_HALT:
+ exit(2);
+ default:
+ fprintf(stderr, "vmexit_suspend: invalid reason %d\n", how);
+ exit(100);
+ }
+
+ /* NOT REACHED. */
+
+ return (0);
+}
+
+static int
+vmexit_debug(struct vmctx *ctx __unused, struct vcpu *vcpu __unused,
+ struct vm_run *vmrun __unused)
+{
+
+ return (VMEXIT_CONTINUE);
+}
+
+static int
+vmexit_bogus(struct vmctx *ctx __unused, struct vcpu *vcpu __unused,
+ struct vm_run *vmrun __unused)
+{
+
+ return (VMEXIT_CONTINUE);
+}
+
+static void
+vmexit_ecall_srst(struct vmctx *ctx, struct vm_exit *vme)
+{
+ enum vm_suspend_how how;
+ int func_id;
+ int type;
+
+ func_id = vme->u.ecall.args[6];
+ type = vme->u.ecall.args[0];
+
+ switch (func_id) {
+ case SBI_SRST_SYSTEM_RESET:
+ switch (type) {
+ case SBI_SRST_TYPE_SHUTDOWN:
+ case SBI_SRST_TYPE_COLD_REBOOT:
+ case SBI_SRST_TYPE_WARM_REBOOT:
+ how = VM_SUSPEND_POWEROFF;
+ vm_suspend(ctx, how);
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static int
+vmexit_ecall(struct vmctx *ctx, struct vcpu *vcpu __unused,
+ struct vm_run *vmrun)
+{
+ int sbi_extension_id;
+ struct vm_exit *vme;
+
+ vme = vmrun->vm_exit;
+
+ sbi_extension_id = vme->u.ecall.args[7];
+ switch (sbi_extension_id) {
+ case SBI_EXT_ID_SRST:
+ vmexit_ecall_srst(ctx, vme);
+ break;
+ default:
+ break;
+ }
+
+ return (VMEXIT_CONTINUE);
+}
+
+const vmexit_handler_t vmexit_handlers[VM_EXITCODE_MAX] = {
+ [VM_EXITCODE_BOGUS] = vmexit_bogus,
+ [VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
+ [VM_EXITCODE_SUSPENDED] = vmexit_suspend,
+ [VM_EXITCODE_DEBUG] = vmexit_debug,
+ [VM_EXITCODE_ECALL] = vmexit_ecall,
+};
Index: usr.sbin/bhyvectl/riscv/Makefile.inc
===================================================================
--- /dev/null
+++ usr.sbin/bhyvectl/riscv/Makefile.inc
@@ -0,0 +1 @@
+SRCS+= bhyvectl_machdep.c
Index: usr.sbin/bhyvectl/riscv/bhyvectl_machdep.c
===================================================================
--- /dev/null
+++ usr.sbin/bhyvectl/riscv/bhyvectl_machdep.c
@@ -0,0 +1,82 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Mark Johnston <markj@FreeBSD.org>
+ *
+ * This software was developed by the University of Cambridge Computer
+ * Laboratory (Department of Computer Science and Technology) under Innovate
+ * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
+ * Prototype".
+ *
+ * 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 NETAPP, INC ``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 NETAPP, INC 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/types.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <vmmapi.h>
+
+#include "bhyvectl.h"
+
+void
+bhyvectl_dump_vm_run_exitcode(struct vm_exit *vmexit __unused,
+ int vcpu __unused)
+{
+}
+
+struct option *
+bhyvectl_opts(const struct option *options, size_t count)
+{
+ struct option *all_opts;
+
+ all_opts = calloc(count + 1, sizeof(struct option));
+ if (all_opts == NULL)
+ err(1, "calloc");
+ memcpy(all_opts, options, count * sizeof(struct option));
+ return (all_opts);
+}
+
+void
+bhyvectl_handle_opt(const struct option *opts __unused, int opt __unused)
+{
+}
+
+const char *
+bhyvectl_opt_desc(int opt __unused)
+{
+ /* No riscv-specific options yet. */
+ return ("???");
+}
+
+void
+bhyvectl_md_main(struct vmctx *ctx __unused, struct vcpu *vcpu __unused,
+ int vcpuid __unused, bool get_all __unused)
+{
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 23, 11:47 PM (17 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27891801
Default Alt Text
D45512.id139568.diff (38 KB)
Attached To
Mode
D45512: bhyve/riscv userspace part
Attached
Detach File
Event Timeline
Log In to Comment