Skip to content

Commit

Permalink
KVM: x86: Add support for vICR APIC-write VM-Exits in x2APIC mode
Browse files Browse the repository at this point in the history
Upcoming Intel CPUs will support virtual x2APIC MSR writes to the vICR,
i.e. will trap and generate an APIC-write VM-Exit instead of intercepting
the WRMSR.  Add support for handling "nodecode" x2APIC writes, which
were previously impossible.

Note, x2APIC MSR writes are 64 bits wide.

Signed-off-by: Zeng Guang <guang.zeng@intel.com>
Message-Id: <20220419153516.11739-1-guang.zeng@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
Zeng Guang authored and Paolo Bonzini committed Jun 8, 2022
1 parent 0b85baa commit 5413bcb
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions arch/x86/kvm/lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static bool lapic_timer_advance_dynamic __read_mostly;
#define LAPIC_TIMER_ADVANCE_NS_MAX 5000
/* step-by-step approximation to mitigate fluctuation */
#define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data);

static inline void __kvm_lapic_set_reg(char *regs, int reg_off, u32 val)
{
Expand Down Expand Up @@ -2231,10 +2232,27 @@ EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
/* emulate APIC access in a trap manner */
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
{
u32 val = kvm_lapic_get_reg(vcpu->arch.apic, offset);
struct kvm_lapic *apic = vcpu->arch.apic;
u64 val;

if (apic_x2apic_mode(apic)) {
/*
* When guest APIC is in x2APIC mode and IPI virtualization
* is enabled, accessing APIC_ICR may cause trap-like VM-exit
* on Intel hardware. Other offsets are not possible.
*/
if (WARN_ON_ONCE(offset != APIC_ICR))
return;

/* TODO: optimize to just emulate side effect w/o one more write */
kvm_lapic_reg_write(vcpu->arch.apic, offset, val);
kvm_lapic_msr_read(apic, offset, &val);
kvm_apic_send_ipi(apic, (u32)val, (u32)(val >> 32));
trace_kvm_apic_write(APIC_ICR, val);
} else {
val = kvm_lapic_get_reg(apic, offset);

/* TODO: optimize to just emulate side effect w/o one more write */
kvm_lapic_reg_write(apic, offset, (u32)val);
}
}
EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);

Expand Down

0 comments on commit 5413bcb

Please sign in to comment.