diff --git a/hypervisor/arch/riscv/Makefile b/hypervisor/arch/riscv/Makefile index 58f675d79..ada5a2ec7 100644 --- a/hypervisor/arch/riscv/Makefile +++ b/hypervisor/arch/riscv/Makefile @@ -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 diff --git a/hypervisor/arch/riscv/guest/vsbi.c b/hypervisor/arch/riscv/guest/vsbi.c index a1f73781a..0535ac53d 100644 --- a/hypervisor/arch/riscv/guest/vsbi.c +++ b/hypervisor/arch/riscv/guest/vsbi.c @@ -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) diff --git a/hypervisor/arch/riscv/guest/vsbi/vsbi_ipi.c b/hypervisor/arch/riscv/guest/vsbi/vsbi_ipi.c new file mode 100644 index 000000000..074b25888 --- /dev/null +++ b/hypervisor/arch/riscv/guest/vsbi/vsbi_ipi.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2025 Intel Corporation. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, +};