mirror of
https://github.com/torvalds/linux.git
synced 2026-06-03 12:03:54 +02:00
KVM: x86: Only allow "fast" IPIs in fastpath WRMSR(X2APIC_ICR) handler
Explicitly restrict fastpath ICR writes to IPIs that are "fast", i.e. can be delivered without having to walk all vCPUs, and that target at most 16 vCPUs. Artificially restricting ICR writes to physical mode guarantees at most one vCPU will receive in IPI (because x2APIC IDs are read-only), but that delivery might not be "fast". E.g. even if the vCPU exists, KVM might have to iterate over 4096 vCPUs to find the right one. Limiting delivery to fast IPIs aligns the WRMSR fastpath with kvm_arch_set_irq_inatomic() (which also runs with IRQs disabled), and will allow dropping the semi-arbitrary restrictions on delivery mode and type. Link: https://lore.kernel.org/r/20250805190526.1453366-4-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
15daa58e78
commit
7774143400
|
|
@ -2432,7 +2432,7 @@ EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
|
|||
|
||||
#define X2APIC_ICR_RESERVED_BITS (GENMASK_ULL(31, 20) | GENMASK_ULL(17, 16) | BIT(13))
|
||||
|
||||
int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
|
||||
static int __kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data, bool fast)
|
||||
{
|
||||
if (data & X2APIC_ICR_RESERVED_BITS)
|
||||
return 1;
|
||||
|
|
@ -2447,7 +2447,20 @@ int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
|
|||
*/
|
||||
data &= ~APIC_ICR_BUSY;
|
||||
|
||||
kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32));
|
||||
if (fast) {
|
||||
struct kvm_lapic_irq irq;
|
||||
int ignored;
|
||||
|
||||
kvm_icr_to_lapic_irq(apic, (u32)data, (u32)(data >> 32), &irq);
|
||||
|
||||
if (!kvm_irq_delivery_to_apic_fast(apic->vcpu->kvm, apic, &irq,
|
||||
&ignored, NULL))
|
||||
return -EWOULDBLOCK;
|
||||
|
||||
trace_kvm_apic_ipi((u32)data, irq.dest_id);
|
||||
} else {
|
||||
kvm_apic_send_ipi(apic, (u32)data, (u32)(data >> 32));
|
||||
}
|
||||
if (kvm_x86_ops.x2apic_icr_is_split) {
|
||||
kvm_lapic_set_reg(apic, APIC_ICR, data);
|
||||
kvm_lapic_set_reg(apic, APIC_ICR2, data >> 32);
|
||||
|
|
@ -2458,6 +2471,16 @@ int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data)
|
||||
{
|
||||
return __kvm_x2apic_icr_write(apic, data, false);
|
||||
}
|
||||
|
||||
int kvm_x2apic_icr_write_fast(struct kvm_lapic *apic, u64 data)
|
||||
{
|
||||
return __kvm_x2apic_icr_write(apic, data, true);
|
||||
}
|
||||
|
||||
static u64 kvm_x2apic_icr_read(struct kvm_lapic *apic)
|
||||
{
|
||||
if (kvm_x86_ops.x2apic_icr_is_split)
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
|
|||
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
|
||||
void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu);
|
||||
|
||||
int kvm_x2apic_icr_write(struct kvm_lapic *apic, u64 data);
|
||||
int kvm_x2apic_icr_write_fast(struct kvm_lapic *apic, u64 data);
|
||||
int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data);
|
||||
int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
|
||||
|
||||
|
|
|
|||
|
|
@ -2150,7 +2150,7 @@ static int handle_fastpath_set_x2apic_icr_irqoff(struct kvm_vcpu *vcpu, u64 data
|
|||
((data & APIC_DEST_MASK) == APIC_DEST_PHYSICAL) &&
|
||||
((data & APIC_MODE_MASK) == APIC_DM_FIXED) &&
|
||||
((u32)(data >> 32) != X2APIC_BROADCAST))
|
||||
return kvm_x2apic_icr_write(vcpu->arch.apic, data);
|
||||
return kvm_x2apic_icr_write_fast(vcpu->arch.apic, data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user