From 35f9680d309ad6b1d818cdec41581ad274ca3fca Mon Sep 17 00:00:00 2001 From: Haicheng Li Date: Mon, 20 Oct 2025 10:36:12 +0000 Subject: [PATCH] hv: riscv: Add initial vsbi framework Adds initial vsbi framework. Tracked-On: #8841 Signed-off-by: Haicheng Li Signed-off-by: Yifan Liu Acked-by: Wang Yu1 --- hypervisor/arch/riscv/Makefile | 1 + hypervisor/arch/riscv/guest/vcpu.c | 1 + hypervisor/arch/riscv/guest/vcpu_exit.c | 4 + hypervisor/arch/riscv/guest/vm.c | 3 +- hypervisor/arch/riscv/guest/vsbi.c | 103 ++++++++++++++++++ hypervisor/arch/riscv/sbi.c | 2 +- hypervisor/include/arch/riscv/asm/guest/vm.h | 4 + .../include/arch/riscv/asm/guest/vsbi.h | 33 ++++++ hypervisor/include/arch/riscv/asm/sbi.h | 23 ++++ 9 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 hypervisor/arch/riscv/guest/vsbi.c create mode 100644 hypervisor/include/arch/riscv/asm/guest/vsbi.h diff --git a/hypervisor/arch/riscv/Makefile b/hypervisor/arch/riscv/Makefile index 2c4ff3d9e..54c81086a 100644 --- a/hypervisor/arch/riscv/Makefile +++ b/hypervisor/arch/riscv/Makefile @@ -70,6 +70,7 @@ VP_C_SRCS += arch/riscv/guest/guest_memory.c VP_C_SRCS += arch/riscv/guest/vcpu.c VP_C_SRCS += arch/riscv/guest/vm.c VP_C_SRCS += arch/riscv/guest/vcpu_exit.c +VP_C_SRCS += arch/riscv/guest/vsbi.c VM_CFG_C_SRCS += $(SCENARIO_CFG_DIR)/vm_configurations.c VM_CFG_C_SRCS += $(BOARD_CFG_DIR)/pci_dev.c diff --git a/hypervisor/arch/riscv/guest/vcpu.c b/hypervisor/arch/riscv/guest/vcpu.c index b67f00ad1..2acd21895 100644 --- a/hypervisor/arch/riscv/guest/vcpu.c +++ b/hypervisor/arch/riscv/guest/vcpu.c @@ -17,6 +17,7 @@ #include #include #include +#include void vcpu_set_epc(struct acrn_vcpu *vcpu, uint64_t val) { diff --git a/hypervisor/arch/riscv/guest/vcpu_exit.c b/hypervisor/arch/riscv/guest/vcpu_exit.c index b352e5d58..f03071546 100644 --- a/hypervisor/arch/riscv/guest/vcpu_exit.c +++ b/hypervisor/arch/riscv/guest/vcpu_exit.c @@ -16,6 +16,7 @@ #include #include +#include int32_t vcpu_virtual_inst_fault_handler(struct acrn_vcpu *vcpu) { /* TODO: to be implemented */ @@ -47,6 +48,9 @@ int32_t vcpu_exit_handler(struct acrn_vcpu *vcpu) } else { local_irq_enable(); switch (cause) { + case TRAP_CAUSE_EXC_VIRTUAL_SUPERVISOR_ECALL: + ret = vsbi_exit_handler(vcpu); + break; case TRAP_CAUSE_EXC_VIRTUAL_INST_FAULT: ret = vcpu_virtual_inst_fault_handler(vcpu); break; diff --git a/hypervisor/arch/riscv/guest/vm.c b/hypervisor/arch/riscv/guest/vm.c index 2dc304f0e..9e57646f9 100644 --- a/hypervisor/arch/riscv/guest/vm.c +++ b/hypervisor/arch/riscv/guest/vm.c @@ -49,7 +49,8 @@ struct acrn_vcpu *vcpu_from_vhartid(struct acrn_vm *vm, uint32_t vhartid) int32_t arch_init_vm(struct acrn_vm *vm, struct acrn_vm_config *vm_config) { - (void)vm; + init_vsbi(vm); + (void)vm_config; return 0; } diff --git a/hypervisor/arch/riscv/guest/vsbi.c b/hypervisor/arch/riscv/guest/vsbi.c new file mode 100644 index 000000000..e8bc919fa --- /dev/null +++ b/hypervisor/arch/riscv/guest/vsbi.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2018-2025 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Author: Haicheng Li + * Yifan Liu + * + * Re-written from OpenSBI sbi_ecall.c + * The original code is licensed under BSD-2-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +static const struct acrn_vsbi_extension *vcpu_find_extension(struct acrn_vcpu *vcpu, uint64_t eid) +{ + const struct acrn_vsbi_extension *e, *ret = NULL; + struct acrn_vm *vm = vcpu->vm; + int i; + + for (i = 0; i < vm->arch_vm.n_vsbi_exts; i++) { + e = vm->arch_vm.vsbi_exts[i]; + if ((eid >= e->eid_start) && (eid <= e->eid_end)) { + ret = e; + break; + } + } + + return ret; +} + +int32_t vsbi_exit_handler(struct acrn_vcpu *vcpu) +{ + struct cpu_regs *regs = &(vcpu->arch.regs); + uint64_t args[6]; + uint64_t eid = regs->a7, fid = regs->a6; + int32_t ret = SBI_ERR_NOT_SUPPORTED; + struct vsbi_ret out = { 0 }; + const struct acrn_vsbi_extension *e; + + args[0] = regs->a0; + args[1] = regs->a1; + args[2] = regs->a2; + args[3] = regs->a3; + args[4] = regs->a4; + args[5] = regs->a5; + + e = vcpu_find_extension(vcpu, eid); + if (e && e->handler) { + pr_dbg("vsbi: eid: 0x%x fid: 0x%x, args 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", + eid, fid, args[0], args[1], args[2], args[3], args[4], args[5]); + ret = e->handler(vcpu, eid, fid, args, &out); + } else { + pr_err("Unsupported ecall request: eid 0x%x fid 0x%x", eid, fid); + } + + if (!out.vcpu_retain_pc) { + regs->epc += 4; + } + + regs->a0 = ret; + regs->a1 = out.value; + + return 0; +} + +static const struct acrn_vsbi_extension *vsbi_extensions[MAX_NUM_SUPPORTED_VSBI_EXT] = { + NULL, +}; + +void init_vsbi(struct acrn_vm *vm) +{ + uint16_t i; + int32_t ret; + const struct acrn_vsbi_extension *e; + + for (i = 0; (i < MAX_NUM_SUPPORTED_VSBI_EXT) && (vsbi_extensions[i] != NULL); i++) { + e = vsbi_extensions[i]; + + /* Unconditionally register extension if no probe method is provided. + * if probe method is provided, register only when probe success. + */ + if (e->probe == NULL) { + vm->arch_vm.vsbi_exts[vm->arch_vm.n_vsbi_exts++] = e; + } else { + ret = e->probe(vm); + if (ret == 0) { + vm->arch_vm.vsbi_exts[vm->arch_vm.n_vsbi_exts++] = e; + } else if (ret != -ENOSYS) { + pr_err("Failed to register %s to VM%d, ret: %d", e->name, vm->vm_id, ret); + } else { + /* hide extension from this vm */ + } + } + } +} diff --git a/hypervisor/arch/riscv/sbi.c b/hypervisor/arch/riscv/sbi.c index f5a049330..fe808374f 100644 --- a/hypervisor/arch/riscv/sbi.c +++ b/hypervisor/arch/riscv/sbi.c @@ -33,7 +33,7 @@ * returning an error code. This is analogous to returning the C * structure. */ -static sbiret sbi_ecall(uint64_t arg0, uint64_t arg1, uint64_t arg2, +sbiret sbi_ecall(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t func, uint64_t ext) { diff --git a/hypervisor/include/arch/riscv/asm/guest/vm.h b/hypervisor/include/arch/riscv/asm/guest/vm.h index 8e78bf2fe..3de19a6b8 100644 --- a/hypervisor/include/arch/riscv/asm/guest/vm.h +++ b/hypervisor/include/arch/riscv/asm/guest/vm.h @@ -11,12 +11,16 @@ #include #include +#include + #define INVALID_PIO_IDX -1U #define UART_PIO_IDX0 INVALID_PIO_IDX /* FIXME: dummy. to be implemented later */ #define EMUL_PIO_IDX_MAX 1U struct vm_arch { + const struct acrn_vsbi_extension *vsbi_exts[MAX_NUM_SUPPORTED_VSBI_EXT]; + uint16_t n_vsbi_exts; }; struct acrn_vcpu; diff --git a/hypervisor/include/arch/riscv/asm/guest/vsbi.h b/hypervisor/include/arch/riscv/asm/guest/vsbi.h new file mode 100644 index 000000000..d578127c2 --- /dev/null +++ b/hypervisor/include/arch/riscv/asm/guest/vsbi.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018-2025 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RISCV_VSBI_H +#define RISCV_VSBI_H + +#include + +#define MAX_NUM_SUPPORTED_VSBI_EXT 8 + +#define MAX_VSBI_EXTENSION_NAME 16 + +struct vsbi_ret { + uint64_t value; + bool vcpu_retain_pc; +}; + +struct acrn_vsbi_extension { + const char *name; + uint64_t eid_start; + uint64_t eid_end; + int32_t (*handler)(struct acrn_vcpu *vcpu, uint64_t eid, + uint64_t fid, uint64_t *args, struct vsbi_ret *out); + int32_t (*probe)(struct acrn_vm *vm); +}; + +int32_t vsbi_exit_handler(struct acrn_vcpu *vcpu); +void init_vsbi(struct acrn_vm *vm); + +#endif /* RISCV_VSBI_H */ diff --git a/hypervisor/include/arch/riscv/asm/sbi.h b/hypervisor/include/arch/riscv/asm/sbi.h index 8e3d7569c..573d25a5f 100644 --- a/hypervisor/include/arch/riscv/asm/sbi.h +++ b/hypervisor/include/arch/riscv/asm/sbi.h @@ -60,6 +60,14 @@ enum sbi_eid { #define SBI_HSM_FID_HART_GET_STATUS 0x2 #define SBI_HSM_FID_HART_SUSPEND 0x3 +#define SBI_HSM_STATE_STARTED 0x0 +#define SBI_HSM_STATE_STOPPED 0x1 +#define SBI_HSM_STATE_START_PENDING 0x2 +#define SBI_HSM_STATE_STOP_PENDING 0x3 +#define SBI_HSM_STATE_SUSPENDED 0x4 +#define SBI_HSM_STATE_SUSPEND_PENDING 0x5 +#define SBI_HSM_STATE_RESUME_PENDING 0x6 + /* SBI function IDs for MPXY extension*/ #define SBI_MPXY_FID_GET_SHM_SIZE 0x0 #define SBI_MPXY_FID_SET_SHM 0x1 @@ -70,6 +78,17 @@ enum sbi_eid { #define SBI_MPXY_FID_SEND_MSG_WITHOUT_RESP 0x6 #define SBI_MPXY_FID_GET_NOTFICATION_EVENTS 0x7 +/* SBI function IDs for SRST extension */ +#define SBI_EXT_SRST_RESET 0x0 + +#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0 +#define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1 +#define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2 +#define SBI_SRST_RESET_TYPE_LAST SBI_SRST_RESET_TYPE_WARM_REBOOT + +#define SBI_SRST_RESET_REASON_NONE 0x0 +#define SBI_SRST_RESET_REASON_SYSFAIL 0x1 + /* SBI return error codes */ #define SBI_SUCCESS 0 #define SBI_ERR_FAILED -1 @@ -103,4 +122,8 @@ void send_dest_ipi_mask(uint64_t dest_mask, __unused uint32_t msg_type); int sbi_set_timer(uint64_t stime_value); +sbiret sbi_ecall(uint64_t arg0, uint64_t arg1, uint64_t arg2, + uint64_t arg3, uint64_t arg4, uint64_t arg5, + uint64_t func, uint64_t ext); + #endif /* RISCV_SBI_H */