RISC-V: KVM: Fix the conversion between vsip and hvip

Per AIA spec 1.0 Section 6.3.2, the interrupt numbers 13-63
shares same bit position between related VS shadow CSRs and
hypervisor CSRs. So there's a shift only for SSI, STI and
SEI interrupt.

Currently the KVM always does a shift for all the interrupts
(include LCOFI with number 13) when doing the conversion
between vsip and hvip. Fix this by only doing shift the SSI,
STI and SEI. Add wrappers for doing the conversion between
vsip and hvip.

Fixes: 16b0bde9a3 ("RISC-V: KVM: Add perf sampling support for guests")
Signed-off-by: Yicong Yang <[email protected]>
Reviewed-by: Anup Patel <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Anup Patel <[email protected]>
This commit is contained in:
Yicong Yang authored and Anup Patel committed 2026-09-15 18:55:51 +05:30
1 parent aaad136d56
commit 52c6b7d20d
4 files changed
+36 -15

No files matched your search

+16 -4
View File
@@ -188,12 +188,24 @@
#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT
#endif
/* VSIP & HVIP relation */
/*
* VSIP & HVIP relation
*
* The bit positions are same between VSIP and HVIP for interrupt
* numbers 13-63, where there's a shift for the SSI, STI and SEI.
*/
#define VSIP_TO_HVIP_SHIFT (IRQ_VS_SOFT - IRQ_S_SOFT)
#define VSIP_VALID_MASK ((_AC(1, UL) << IRQ_S_SOFT) | \
#define VSIP_BIAS_MASK ((_AC(1, UL) << IRQ_S_SOFT) | \
(_AC(1, UL) << IRQ_S_TIMER) | \
(_AC(1, UL) << IRQ_S_EXT) | \
(_AC(1, UL) << IRQ_PMU_OVF))
(_AC(1, UL) << IRQ_S_EXT))
#define VSIP_NO_BIAS_MASK (_AC(1, UL) << IRQ_PMU_OVF)
#define VSIP_VALID_MASK (VSIP_BIAS_MASK | VSIP_NO_BIAS_MASK)
#define vsip_to_hvip(_vsip) ((((_vsip) & VSIP_BIAS_MASK) << \
VSIP_TO_HVIP_SHIFT) | \
((_vsip) & VSIP_NO_BIAS_MASK))
#define hvip_to_vsip(_hvip) ((((_hvip) >> VSIP_TO_HVIP_SHIFT) & \
VSIP_BIAS_MASK) | \
((_hvip) & VSIP_NO_BIAS_MASK))
/* AIA CSR bits */
#define TOPI_IID_SHIFT 16
+1 -2
View File
@@ -491,8 +491,7 @@ bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
bool ret;
raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
<< VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
ie = vsip_to_hvip(vcpu->arch.guest_csr.vsie) & (unsigned long)mask;
ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
(unsigned long)mask;
ret = vcpu->arch.irqs_pending[0] & ie;
+3 -5
View File
@@ -272,7 +272,7 @@ static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu,
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
kvm_riscv_vcpu_flush_interrupts(vcpu);
*out_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK;
*out_val = hvip_to_vsip(csr->hvip);
*out_val |= csr->hvip & ~IRQ_LOCAL_MASK;
} else
*out_val = ((unsigned long *)csr)[reg_num];
@@ -293,10 +293,8 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
reg_num = array_index_nospec(reg_num, regs_max);
if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
reg_val &= VSIP_VALID_MASK;
reg_val <<= VSIP_TO_HVIP_SHIFT;
}
if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
reg_val = vsip_to_hvip(reg_val);
((unsigned long *)csr)[reg_num] = reg_val;
+16 -4
View File
@@ -163,12 +163,24 @@
#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT
#endif
/* VSIP & HVIP relation */
/*
* VSIP & HVIP relation
*
* The bit positions are same between VSIP and HVIP for interrupt
* numbers 13-63, where there's a shift for the SSI, STI and SEI.
*/
#define VSIP_TO_HVIP_SHIFT (IRQ_VS_SOFT - IRQ_S_SOFT)
#define VSIP_VALID_MASK ((_AC(1, UL) << IRQ_S_SOFT) | \
#define VSIP_BIAS_MASK ((_AC(1, UL) << IRQ_S_SOFT) | \
(_AC(1, UL) << IRQ_S_TIMER) | \
(_AC(1, UL) << IRQ_S_EXT) | \
(_AC(1, UL) << IRQ_PMU_OVF))
(_AC(1, UL) << IRQ_S_EXT))
#define VSIP_NO_BIAS_MASK (_AC(1, UL) << IRQ_PMU_OVF)
#define VSIP_VALID_MASK (VSIP_BIAS_MASK | VSIP_NO_BIAS_MASK)
#define vsip_to_hvip(_vsip) ((((_vsip) & VSIP_BIAS_MASK) << \
VSIP_TO_HVIP_SHIFT) | \
((_vsip) & VSIP_NO_BIAS_MASK))
#define hvip_to_vsip(_hvip) ((((_hvip) >> VSIP_TO_HVIP_SHIFT) & \
VSIP_BIAS_MASK) | \
((_hvip) & VSIP_NO_BIAS_MASK))
/* AIA CSR bits */
#define TOPI_IID_SHIFT 16