diff --git a/sys/riscv/vmm/riscv.h b/sys/riscv/vmm/riscv.h
--- a/sys/riscv/vmm/riscv.h
+++ b/sys/riscv/vmm/riscv.h
@@ -150,9 +150,9 @@
struct hypctx *riscv_get_active_vcpu(void);
void vmm_switch(struct hypctx *);
void vmm_unpriv_trap(struct hyptrap *, uint64_t tmp);
-int vmm_sbi_ecall(struct vcpu *, bool *);
+bool vmm_sbi_ecall(struct vcpu *);
-void riscv_send_ipi(struct hypctx *hypctx, int hart_id);
+void riscv_send_ipi(struct hyp *hyp, cpuset_t *cpus);
int riscv_check_ipi(struct hypctx *hypctx, bool clear);
bool riscv_check_interrupts_pending(struct hypctx *hypctx);
diff --git a/sys/riscv/vmm/vmm_riscv.c b/sys/riscv/vmm/vmm_riscv.c
--- a/sys/riscv/vmm/vmm_riscv.c
+++ b/sys/riscv/vmm/vmm_riscv.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2024 Ruslan Bukin
+ * Copyright (c) 2024-2025 Ruslan Bukin
*
* This software was developed by the University of Cambridge Computer
* Laboratory (Department of Computer Science and Technology) under Innovate
@@ -450,7 +450,6 @@
uint64_t insn;
uint64_t gpa;
bool handled;
- bool retu;
int ret;
int i;
@@ -496,16 +495,12 @@
handled = false;
break;
case SCAUSE_VIRTUAL_SUPERVISOR_ECALL:
- retu = false;
- vmm_sbi_ecall(hypctx->vcpu, &retu);
- if (retu == false) {
- handled = true;
+ handled = vmm_sbi_ecall(hypctx->vcpu);
+ if (handled == true)
break;
- }
for (i = 0; i < nitems(vme->u.ecall.args); i++)
vme->u.ecall.args[i] = hypctx->guest_regs.hyp_a[i];
vme->exitcode = VM_EXITCODE_ECALL;
- handled = false;
break;
case SCAUSE_VIRTUAL_INSTRUCTION:
insn = vme->stval;
@@ -537,17 +532,23 @@
}
void
-riscv_send_ipi(struct hypctx *hypctx, int hart_id)
+riscv_send_ipi(struct hyp *hyp, cpuset_t *cpus)
{
- struct hyp *hyp;
+ struct hypctx *hypctx;
struct vm *vm;
+ uint16_t maxcpus;
+ int i;
- hyp = hypctx->hyp;
vm = hyp->vm;
- atomic_set_32(&hypctx->ipi_pending, 1);
-
- vcpu_notify_event(vm_vcpu(vm, hart_id));
+ maxcpus = vm_get_maxcpus(hyp->vm);
+ for (i = 0; i < maxcpus; i++) {
+ if (!CPU_ISSET(i, cpus))
+ continue;
+ hypctx = hyp->ctx[i];
+ atomic_set_32(&hypctx->ipi_pending, 1);
+ vcpu_notify_event(vm_vcpu(vm, i));
+ }
}
int
diff --git a/sys/riscv/vmm/vmm_sbi.c b/sys/riscv/vmm/vmm_sbi.c
--- a/sys/riscv/vmm/vmm_sbi.c
+++ b/sys/riscv/vmm/vmm_sbi.c
@@ -1,7 +1,7 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2024 Ruslan Bukin
+ * Copyright (c) 2024-2025 Ruslan Bukin
*
* This software was developed by the University of Cambridge Computer
* Laboratory (Department of Computer Science and Technology) under Innovate
@@ -32,29 +32,8 @@
#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
#include
#include "riscv.h"
@@ -64,13 +43,13 @@
vmm_sbi_handle_rfnc(struct vcpu *vcpu, struct hypctx *hypctx)
{
struct vmm_fence fence;
+ cpuset_t active_cpus;
uint64_t hart_mask;
uint64_t hart_mask_base;
uint64_t func_id;
struct hyp *hyp;
uint16_t maxcpus;
cpuset_t cpus;
- int vcpu_id;
int i;
func_id = hypctx->guest_regs.hyp_a[6];
@@ -94,31 +73,39 @@
fence.type = VMM_RISCV_FENCE_VMA_ASID;
break;
default:
- return (-1);
+ return (SBI_ERR_NOT_SUPPORTED);
}
/* Construct cpuset_t from the mask supplied. */
-
CPU_ZERO(&cpus);
hyp = hypctx->hyp;
+ active_cpus = vm_active_cpus(hyp->vm);
maxcpus = vm_get_maxcpus(hyp->vm);
for (i = 0; i < maxcpus; i++) {
vcpu = vm_vcpu(hyp->vm, i);
if (vcpu == NULL)
continue;
- vcpu_id = vcpu_vcpuid(vcpu);
if (hart_mask_base != -1UL) {
- if (vcpu_id < hart_mask_base)
+ if (i < hart_mask_base)
continue;
- if (!(hart_mask & (1UL << (vcpu_id - hart_mask_base))))
+ if (!(hart_mask & (1UL << (i - hart_mask_base))))
continue;
}
+ /*
+ * If either hart_mask_base or at least one hartid from
+ * hart_mask is not valid, then return error.
+ */
+ if (!CPU_ISSET(i, &active_cpus))
+ return (SBI_ERR_INVALID_PARAM);
CPU_SET(i, &cpus);
}
+ if (CPU_EMPTY(&cpus))
+ return (SBI_ERR_INVALID_PARAM);
+
vmm_fence_add(hyp->vm, &cpus, &fence);
- return (0);
+ return (SBI_SUCCESS);
}
static int
@@ -126,7 +113,6 @@
{
uint64_t func_id;
uint64_t next_val;
- int ret;
func_id = hypctx->guest_regs.hyp_a[6];
next_val = hypctx->guest_regs.hyp_a[0];
@@ -134,31 +120,25 @@
switch (func_id) {
case SBI_TIME_SET_TIMER:
vtimer_set_timer(hypctx, next_val);
- ret = 0;
break;
default:
- ret = -1;
- break;
+ return (SBI_ERR_NOT_SUPPORTED);
}
- hypctx->guest_regs.hyp_a[0] = ret;
-
- return (0);
+ return (SBI_SUCCESS);
}
static int
vmm_sbi_handle_ipi(struct vcpu *vcpu, struct hypctx *hypctx)
{
- struct hypctx *target_hypctx;
- struct vcpu *target_vcpu __unused;
cpuset_t active_cpus;
struct hyp *hyp;
uint64_t hart_mask;
uint64_t hart_mask_base;
uint64_t func_id;
+ cpuset_t cpus;
int hart_id;
int bit;
- int ret;
func_id = hypctx->guest_regs.hyp_a[6];
hart_mask = hypctx->guest_regs.hyp_a[0];
@@ -170,6 +150,7 @@
active_cpus = vm_active_cpus(hyp->vm);
+ CPU_ZERO(&cpus);
switch (func_id) {
case SBI_IPI_SEND_IPI:
while ((bit = ffs(hart_mask))) {
@@ -177,30 +158,28 @@
hart_mask &= ~(1u << hart_id);
if (hart_mask_base != -1)
hart_id += hart_mask_base;
- if (CPU_ISSET(hart_id, &active_cpus)) {
- /* TODO. */
- target_vcpu = vm_vcpu(hyp->vm, hart_id);
- target_hypctx = hypctx->hyp->ctx[hart_id];
- riscv_send_ipi(target_hypctx, hart_id);
- }
+ if (!CPU_ISSET(hart_id, &active_cpus))
+ return (SBI_ERR_INVALID_PARAM);
+ CPU_SET(hart_id, &cpus);
}
- ret = 0;
break;
default:
- printf("%s: unknown func %ld\n", __func__, func_id);
- ret = -1;
- break;
+ dprintf("%s: unknown func %ld\n", __func__, func_id);
+ return (SBI_ERR_NOT_SUPPORTED);
}
- hypctx->guest_regs.hyp_a[0] = ret;
+ if (CPU_EMPTY(&cpus))
+ return (SBI_ERR_INVALID_PARAM);
- return (0);
+ riscv_send_ipi(hyp, &cpus);
+
+ return (SBI_SUCCESS);
}
-int
-vmm_sbi_ecall(struct vcpu *vcpu, bool *retu)
+bool
+vmm_sbi_ecall(struct vcpu *vcpu)
{
- int sbi_extension_id __unused;
+ int sbi_extension_id;
struct hypctx *hypctx;
int error;
@@ -220,18 +199,20 @@
switch (sbi_extension_id) {
case SBI_EXT_ID_RFNC:
error = vmm_sbi_handle_rfnc(vcpu, hypctx);
- hypctx->guest_regs.hyp_a[0] = error;
break;
case SBI_EXT_ID_TIME:
- vmm_sbi_handle_time(vcpu, hypctx);
+ error = vmm_sbi_handle_time(vcpu, hypctx);
break;
case SBI_EXT_ID_IPI:
- vmm_sbi_handle_ipi(vcpu, hypctx);
+ error = vmm_sbi_handle_ipi(vcpu, hypctx);
break;
default:
- *retu = true;
- break;
+ /* Return to handle in userspace. */
+ return (false);
}
- return (0);
+ hypctx->guest_regs.hyp_a[0] = error;
+
+ /* Request is handled in kernel mode. */
+ return (true);
}