[RFC PATCH 41/55] KVM: x86: hyperv: Refuse a synthetic IPI to a higher VTL
From: David Woodhouse
Date: Sat Oct 17 2026 - 08:44:54 EST
From: David Woodhouse <dwmw@xxxxxxxxxxxx>
HvCallSendSyntheticClusterIpi(Ex) honours the target VTL in its input
but does not check it against the caller's VTL. A guest running in a
lower VTL can therefore assert any fixed interrupt in a higher VTL on
any VP, which crosses the boundary that VTLs exist to enforce.
Refuse a target VTL above the caller's with HV_STATUS_ACCESS_DENIED.
A VTL may still interrupt its own level and lower ones. The old
upper-bound check on the target plane goes away: a target at or below
the caller's level is below KVM_MAX_PLANES by construction.
Matches the equivalent fix in the reference VSM implementation. The
production Nitro Hypervisor permits the injection; the conformance
suite probes for either behaviour.
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
Assisted-by: LLM
---
arch/x86/kvm/hyperv.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 0bc9435ea3b9..e3ac840c8e5e 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -2710,13 +2710,21 @@ static int kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc)
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
return HV_STATUS_INVALID_HYPERCALL_INPUT;
- /* TLFS: in_vtl bit 4 selects an explicit target VTL. */
- if (in_vtl & 0x10)
+ /*
+ * TLFS: in_vtl bit 4 selects an explicit target VTL. A VTL may
+ * interrupt its own level and lower ones, never a higher one
+ * (TLFS 15.9, "VTL Interrupt Management": each VTL sends and
+ * receives interrupts without interference from a less secure
+ * VTL). The reference host omits this check; the suite's
+ * SendIpi test probes for both behaviours.
+ */
+ if (in_vtl & 0x10) {
target_plane = in_vtl & 0xf;
- else
+ if (target_plane > vcpu->plane_level)
+ return HV_STATUS_ACCESS_DENIED;
+ } else {
target_plane = vcpu->plane_level;
- if (target_plane >= KVM_MAX_PLANES)
- return HV_STATUS_INVALID_HYPERCALL_INPUT;
+ }
if (all_cpus)
kvm_hv_send_ipi_to_many(kvm, vector, NULL, 0, target_plane);
--
2.50.1