Skip to content

Commit 5413bcb

Browse files
arthurzeng19bonzini
authored andcommitted
KVM: x86: Add support for vICR APIC-write VM-Exits in x2APIC mode
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 <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 0b85baa commit 5413bcb

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

arch/x86/kvm/lapic.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static bool lapic_timer_advance_dynamic __read_mostly;
6767
#define LAPIC_TIMER_ADVANCE_NS_MAX 5000
6868
/* step-by-step approximation to mitigate fluctuation */
6969
#define LAPIC_TIMER_ADVANCE_ADJUST_STEP 8
70+
static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data);
7071

7172
static inline void __kvm_lapic_set_reg(char *regs, int reg_off, u32 val)
7273
{
@@ -2231,10 +2232,27 @@ EXPORT_SYMBOL_GPL(kvm_lapic_set_eoi);
22312232
/* emulate APIC access in a trap manner */
22322233
void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset)
22332234
{
2234-
u32 val = kvm_lapic_get_reg(vcpu->arch.apic, offset);
2235+
struct kvm_lapic *apic = vcpu->arch.apic;
2236+
u64 val;
2237+
2238+
if (apic_x2apic_mode(apic)) {
2239+
/*
2240+
* When guest APIC is in x2APIC mode and IPI virtualization
2241+
* is enabled, accessing APIC_ICR may cause trap-like VM-exit
2242+
* on Intel hardware. Other offsets are not possible.
2243+
*/
2244+
if (WARN_ON_ONCE(offset != APIC_ICR))
2245+
return;
22352246

2236-
/* TODO: optimize to just emulate side effect w/o one more write */
2237-
kvm_lapic_reg_write(vcpu->arch.apic, offset, val);
2247+
kvm_lapic_msr_read(apic, offset, &val);
2248+
kvm_apic_send_ipi(apic, (u32)val, (u32)(val >> 32));
2249+
trace_kvm_apic_write(APIC_ICR, val);
2250+
} else {
2251+
val = kvm_lapic_get_reg(apic, offset);
2252+
2253+
/* TODO: optimize to just emulate side effect w/o one more write */
2254+
kvm_lapic_reg_write(apic, offset, (u32)val);
2255+
}
22382256
}
22392257
EXPORT_SYMBOL_GPL(kvm_apic_write_nodecode);
22402258

0 commit comments

Comments
 (0)