hv: riscv add vSBI IPI extension support

Implement the SBI IPI (Inter-Processor Interrupt) extension to enable
guest VMs to send software interrupts between virtual CPUs.

The implementation handles the SBI_IPI_SEND_IPI function call, which
allows a guest to target one or more vCPUs using either:
- A mask (bitmap of target harts relative to a base hart ID)
- Broadcast mode (when mask_base is UINT64_MAX)

The IPI is delivered by asserting the VS-level software interrupt
(VSSIP, bit 2) on each target vCPU. Proper validation is performed
to ensure hart IDs are within valid range and all masked harts exist.

Tracked-On: #8851
Signed-off-by: Haoyu Tang <haoyu.tang@intel.com>
Acked-by: Wang Yu1 <yu1.wang@intel.com>
This commit is contained in:
Haoyu Tang
2025-11-05 13:11:05 +08:00
committed by Sun, Victor
parent 369faf0d8b
commit b8db76fe55
3 changed files with 72 additions and 0 deletions

View File

@@ -79,6 +79,7 @@ VP_C_SRCS += arch/riscv/guest/vsbi/vsbi_srst.c
VP_C_SRCS += arch/riscv/guest/vsbi/vsbi_acrn.c
VP_C_SRCS += arch/riscv/guest/vsbi/vsbi_dbcn.c
VP_C_SRCS += arch/riscv/guest/vsbi/vsbi_timer.c
VP_C_SRCS += arch/riscv/guest/vsbi/vsbi_ipi.c
VM_CFG_C_SRCS += $(SCENARIO_CFG_DIR)/vm_configurations.c
VM_CFG_C_SRCS += $(BOARD_CFG_DIR)/pci_dev.c

View File

@@ -77,6 +77,7 @@ extern const struct acrn_vsbi_extension vsbi_ext_srst;
extern const struct acrn_vsbi_extension vsbi_ext_timer;
extern const struct acrn_vsbi_extension vsbi_ext_acrn;
extern const struct acrn_vsbi_extension vsbi_ext_dbcn;
extern const struct acrn_vsbi_extension vsbi_ext_ipi;
static const struct acrn_vsbi_extension *vsbi_extensions[MAX_NUM_SUPPORTED_VSBI_EXT] = {
&vsbi_ext_base,
&vsbi_ext_hsm,
@@ -84,6 +85,7 @@ static const struct acrn_vsbi_extension *vsbi_extensions[MAX_NUM_SUPPORTED_VSBI_
&vsbi_ext_acrn,
&vsbi_ext_dbcn,
&vsbi_ext_timer,
&vsbi_ext_ipi,
};
void init_vsbi(struct acrn_vm *vm)

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2025 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <types.h>
#include <vcpu.h>
#include <vm.h>
#include <per_cpu.h>
#include <asm/sbi.h>
#include <asm/trap.h>
#include <asm/guest/vsbi.h>
#include <asm/guest/virq.h>
#include <logmsg.h>
static int32_t vcpu_sbi_ipi_ecall_handler(struct acrn_vcpu *vcpu, __unused uint64_t ext_id,
uint64_t func_id, uint64_t *args, __unused struct vsbi_ret *out)
{
int32_t ret = SBI_SUCCESS;
uint16_t i;
struct acrn_vcpu *tmp_vcpu;
uint64_t mask = args[0];
uint64_t mask_base = args[1];
uint64_t bit_index = 0;
int early_exit = 0;
int is_broadcast = (mask_base == UINT64_MAX);
switch (func_id) {
case SBI_IPI_FID_SEND_IPI:
foreach_vcpu(i, vcpu->vm, tmp_vcpu) {
if (!is_broadcast) {
if (tmp_vcpu->vcpu_id < mask_base)
continue;
bit_index = tmp_vcpu->vcpu_id - mask_base;
if (bit_index >= 64UL) {
early_exit = 1;
break;
}
if (!(mask & (1UL << bit_index)))
continue;
}
/* asserts a VS-level software interrupt to target VCPU */
ret = vcpu_set_intr(tmp_vcpu, TRAP_CAUSE_IRQ_VS_SOFT);
if (ret < 0) {
pr_err("vsbi ipi: failed to send ipi to vcpu %hu", tmp_vcpu->vcpu_id);
early_exit = 1;
break;
}
}
if (!is_broadcast && early_exit)
ret = SBI_ERR_INVALID_PARAM;
break;
default:
ret = SBI_ERR_NOT_SUPPORTED;
break;
}
return ret;
}
const struct acrn_vsbi_extension vsbi_ext_ipi = {
.name = "ipi",
.eid_start = SBI_EID_IPI,
.eid_end = SBI_EID_IPI,
.handler = vcpu_sbi_ipi_ecall_handler,
};