mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2026-05-08 15:22:24 +00:00
hv: riscv: add virtual interrupt injection support
Add virtual interrupt injection infrastructure for RISC-V hypervisor. Implement vcpu_set_intr() and vcpu_clear_intr() to manage virtual interrupt pending state by updating irqs_pending bitmap. Add vcpu_inject_pending_intr() to inject pending interrupts into VS-mode by updating HVIP CSR with atomic operations. Tracked-On: #8844 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Wang Yu1 <yu1.wang@intel.com>
This commit is contained in:
committed by
acrnsi-robot
parent
b3fa6bbced
commit
75a932eeab
@@ -103,6 +103,8 @@ int32_t riscv_process_vcpu_requests(struct acrn_vcpu *vcpu)
|
||||
memset(&vcpu->arch.trap, 0, sizeof(struct riscv_vcpu_trap_info));
|
||||
vcpu->arch.trap.cause = EXCEPTION_INVALID;
|
||||
}
|
||||
|
||||
vcpu_inject_pending_intr(vcpu);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -177,6 +179,8 @@ void arch_reset_vcpu(struct acrn_vcpu *vcpu)
|
||||
memset(gctx, 0, sizeof(struct riscv_vcpu_guest_ctx));
|
||||
memset(trap, 0, sizeof(struct riscv_vcpu_trap_info));
|
||||
trap->cause = EXCEPTION_INVALID;
|
||||
vcpu->arch.irqs_pending = 0UL;
|
||||
vcpu->arch.irqs_pending_mask = 0UL;
|
||||
}
|
||||
|
||||
void arch_context_switch_out(struct thread_object *prev)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <types.h>
|
||||
#include <vcpu.h>
|
||||
#include <atomic.h>
|
||||
#include <logmsg.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
@@ -89,4 +90,66 @@ void vcpu_queue_exception(struct acrn_vcpu *vcpu,
|
||||
arch->trap = *trap;
|
||||
vcpu_make_request(vcpu, RISCV_VCPU_REQUEST_EXCEPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t vcpu_set_intr(struct acrn_vcpu *vcpu, uint32_t hwirq)
|
||||
{
|
||||
struct acrn_vcpu_arch *arch = &vcpu->arch;
|
||||
int32_t ret = -1;
|
||||
|
||||
/* HVIP is a WARL CSR */
|
||||
if (hwirq < BITS_PER_LONG) {
|
||||
bitmap_set(hwirq, &arch->irqs_pending);
|
||||
bitmap_set(hwirq, &arch->irqs_pending_mask);
|
||||
vcpu_make_request(vcpu, RISCV_VCPU_REQUEST_EVENT);
|
||||
signal_event(&vcpu->events[RISCV_VCPU_EVENT_VIRTUAL_INTERRUPT]);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t vcpu_clear_intr(struct acrn_vcpu *vcpu, uint32_t hwirq)
|
||||
{
|
||||
struct acrn_vcpu_arch *arch = &vcpu->arch;
|
||||
int32_t ret = -1;
|
||||
|
||||
/* HVIP is a WARL CSR */
|
||||
if (hwirq < BITS_PER_LONG) {
|
||||
bitmap_clear(hwirq, &arch->irqs_pending);
|
||||
bitmap_set(hwirq, &arch->irqs_pending_mask);
|
||||
vcpu_make_request(vcpu, RISCV_VCPU_REQUEST_EVENT);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool vcpu_inject_pending_intr(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
struct acrn_vcpu_arch *arch = &vcpu->arch;
|
||||
uint64_t hvip, mask, val;
|
||||
bool injected = false;
|
||||
|
||||
if (vcpu_take_request(vcpu, RISCV_VCPU_REQUEST_EVENT)) {
|
||||
/*
|
||||
* Only arch->irqs_pending_mask is cleared here;
|
||||
* arch->irqs_pending remains unchanged.
|
||||
* vcpu_set_intr/vcpu_clear_intr update individual bits of
|
||||
* arch->irqs_pending as needed.
|
||||
*
|
||||
* Note: arch->irqs_pending does not reflect the actual
|
||||
* VS-mode pending interrupt status, as it is not synchronized
|
||||
* with hardware. This approach is simple but requires caution.
|
||||
*/
|
||||
mask = atomic_readandclear64(&arch->irqs_pending_mask);
|
||||
val = arch->irqs_pending & mask;
|
||||
hvip = cpu_csr_read(CSR_HVIP);
|
||||
hvip &= ~mask;
|
||||
hvip |= val;
|
||||
cpu_csr_write(CSR_HVIP, hvip);
|
||||
injected = true;
|
||||
}
|
||||
|
||||
return injected;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#ifndef ASSEMBLER
|
||||
|
||||
#define RISCV_VCPU_REQUEST_EXCEPTION 0U
|
||||
#define RISCV_VCPU_REQUEST_EVENT 1U
|
||||
|
||||
#define RISCV_VCPU_EVENT_VIRTUAL_INTERRUPT 0U
|
||||
|
||||
struct riscv_vcpu_guest_ctx {
|
||||
uint64_t vsstatus;
|
||||
@@ -66,6 +69,8 @@ struct acrn_vcpu_arch {
|
||||
struct riscv_vcpu_host_ctx hctx;
|
||||
|
||||
struct riscv_vcpu_trap_info trap;
|
||||
uint64_t irqs_pending;
|
||||
uint64_t irqs_pending_mask;
|
||||
} __aligned(PAGE_SIZE);
|
||||
|
||||
struct acrn_vcpu;
|
||||
|
||||
@@ -9,5 +9,8 @@
|
||||
|
||||
void vcpu_set_trap(struct acrn_vcpu *vcpu, struct riscv_vcpu_trap_info *trap);
|
||||
void vcpu_queue_exception(struct acrn_vcpu *vcpu, struct riscv_vcpu_trap_info *trap);
|
||||
int32_t vcpu_set_intr(struct acrn_vcpu *vcpu, uint32_t hwirq);
|
||||
int32_t vcpu_clear_intr(struct acrn_vcpu *vcpu, uint32_t hwirq);
|
||||
bool vcpu_inject_pending_intr(struct acrn_vcpu *vcpu);
|
||||
|
||||
#endif /* ARCH_RISCV_GUEST_VIRQ_H */
|
||||
|
||||
Reference in New Issue
Block a user