Skip to content

Commit ddad47b

Browse files
committed
Merge tag 'kvm-x86-apic-6.3' of https://github.com/kvm-x86/linux into HEAD
KVM x86 APIC changes for 6.3: - Remove a superfluous variables from apic_get_tmcct() - Fix various edge cases in x2APIC MSR emulation - Mark APIC timer as expired if its in one-shot mode and the count underflows while the vCPU task was being migrated - Reset xAPIC when userspace forces "impossible" x2APIC => xAPIC transition
2 parents 4090871 + eb98192 commit ddad47b

4 files changed

Lines changed: 125 additions & 49 deletions

File tree

arch/x86/kvm/lapic.c

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,6 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
14871487
{
14881488
ktime_t remaining, now;
14891489
s64 ns;
1490-
u32 tmcct;
14911490

14921491
ASSERT(apic != NULL);
14931492

@@ -1502,10 +1501,7 @@ static u32 apic_get_tmcct(struct kvm_lapic *apic)
15021501
remaining = 0;
15031502

15041503
ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
1505-
tmcct = div64_u64(ns,
1506-
(APIC_BUS_CYCLE_NS * apic->divide_count));
1507-
1508-
return tmcct;
1504+
return div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->divide_count));
15091505
}
15101506

15111507
static void __report_tpr_access(struct kvm_lapic *apic, bool write)
@@ -1565,19 +1561,15 @@ static inline struct kvm_lapic *to_lapic(struct kvm_io_device *dev)
15651561
#define APIC_REGS_MASK(first, count) \
15661562
(APIC_REG_MASK(first) * ((1ull << (count)) - 1))
15671563

1568-
static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
1569-
void *data)
1564+
u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic)
15701565
{
1571-
unsigned char alignment = offset & 0xf;
1572-
u32 result;
1573-
/* this bitmask has a bit cleared for each reserved register */
1566+
/* Leave bits '0' for reserved and write-only registers. */
15741567
u64 valid_reg_mask =
15751568
APIC_REG_MASK(APIC_ID) |
15761569
APIC_REG_MASK(APIC_LVR) |
15771570
APIC_REG_MASK(APIC_TASKPRI) |
15781571
APIC_REG_MASK(APIC_PROCPRI) |
15791572
APIC_REG_MASK(APIC_LDR) |
1580-
APIC_REG_MASK(APIC_DFR) |
15811573
APIC_REG_MASK(APIC_SPIV) |
15821574
APIC_REGS_MASK(APIC_ISR, APIC_ISR_NR) |
15831575
APIC_REGS_MASK(APIC_TMR, APIC_ISR_NR) |
@@ -1597,21 +1589,33 @@ static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
15971589
if (kvm_lapic_lvt_supported(apic, LVT_CMCI))
15981590
valid_reg_mask |= APIC_REG_MASK(APIC_LVTCMCI);
15991591

1600-
/*
1601-
* ARBPRI and ICR2 are not valid in x2APIC mode. WARN if KVM reads ICR
1602-
* in x2APIC mode as it's an 8-byte register in x2APIC and needs to be
1603-
* manually handled by the caller.
1604-
*/
1592+
/* ARBPRI, DFR, and ICR2 are not valid in x2APIC mode. */
16051593
if (!apic_x2apic_mode(apic))
16061594
valid_reg_mask |= APIC_REG_MASK(APIC_ARBPRI) |
1595+
APIC_REG_MASK(APIC_DFR) |
16071596
APIC_REG_MASK(APIC_ICR2);
1608-
else
1609-
WARN_ON_ONCE(offset == APIC_ICR);
1597+
1598+
return valid_reg_mask;
1599+
}
1600+
EXPORT_SYMBOL_GPL(kvm_lapic_readable_reg_mask);
1601+
1602+
static int kvm_lapic_reg_read(struct kvm_lapic *apic, u32 offset, int len,
1603+
void *data)
1604+
{
1605+
unsigned char alignment = offset & 0xf;
1606+
u32 result;
1607+
1608+
/*
1609+
* WARN if KVM reads ICR in x2APIC mode, as it's an 8-byte register in
1610+
* x2APIC and needs to be manually handled by the caller.
1611+
*/
1612+
WARN_ON_ONCE(apic_x2apic_mode(apic) && offset == APIC_ICR);
16101613

16111614
if (alignment + len > 4)
16121615
return 1;
16131616

1614-
if (offset > 0x3f0 || !(valid_reg_mask & APIC_REG_MASK(offset)))
1617+
if (offset > 0x3f0 ||
1618+
!(kvm_lapic_readable_reg_mask(apic) & APIC_REG_MASK(offset)))
16151619
return 1;
16161620

16171621
result = __apic_read(apic, offset & ~0xf);
@@ -1964,8 +1968,12 @@ static bool set_target_expiration(struct kvm_lapic *apic, u32 count_reg)
19641968
if (unlikely(count_reg != APIC_TMICT)) {
19651969
deadline = tmict_to_ns(apic,
19661970
kvm_lapic_get_reg(apic, count_reg));
1967-
if (unlikely(deadline <= 0))
1968-
deadline = apic->lapic_timer.period;
1971+
if (unlikely(deadline <= 0)) {
1972+
if (apic_lvtt_period(apic))
1973+
deadline = apic->lapic_timer.period;
1974+
else
1975+
deadline = 0;
1976+
}
19691977
else if (unlikely(deadline > apic->lapic_timer.period)) {
19701978
pr_info_ratelimited(
19711979
"vcpu %i: requested lapic timer restore with "
@@ -2328,10 +2336,14 @@ static int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
23282336
break;
23292337

23302338
case APIC_SELF_IPI:
2331-
if (apic_x2apic_mode(apic))
2332-
kvm_apic_send_ipi(apic, APIC_DEST_SELF | (val & APIC_VECTOR_MASK), 0);
2333-
else
2339+
/*
2340+
* Self-IPI exists only when x2APIC is enabled. Bits 7:0 hold
2341+
* the vector, everything else is reserved.
2342+
*/
2343+
if (!apic_x2apic_mode(apic) || (val & ~APIC_VECTOR_MASK))
23342344
ret = 1;
2345+
else
2346+
kvm_apic_send_ipi(apic, APIC_DEST_SELF | val, 0);
23352347
break;
23362348
default:
23372349
ret = 1;
@@ -2498,8 +2510,12 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
24982510
}
24992511
}
25002512

2501-
if (((old_value ^ value) & X2APIC_ENABLE) && (value & X2APIC_ENABLE))
2502-
kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
2513+
if ((old_value ^ value) & X2APIC_ENABLE) {
2514+
if (value & X2APIC_ENABLE)
2515+
kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
2516+
else if (value & MSR_IA32_APICBASE_ENABLE)
2517+
kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
2518+
}
25032519

25042520
if ((old_value ^ value) & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) {
25052521
kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
@@ -3114,13 +3130,17 @@ static int kvm_lapic_msr_read(struct kvm_lapic *apic, u32 reg, u64 *data)
31143130
static int kvm_lapic_msr_write(struct kvm_lapic *apic, u32 reg, u64 data)
31153131
{
31163132
/*
3117-
* ICR is a 64-bit register in x2APIC mode (and Hyper'v PV vAPIC) and
3133+
* ICR is a 64-bit register in x2APIC mode (and Hyper-V PV vAPIC) and
31183134
* can be written as such, all other registers remain accessible only
31193135
* through 32-bit reads/writes.
31203136
*/
31213137
if (reg == APIC_ICR)
31223138
return kvm_x2apic_icr_write(apic, data);
31233139

3140+
/* Bits 63:32 are reserved in all other registers. */
3141+
if (data >> 32)
3142+
return 1;
3143+
31243144
return kvm_lapic_reg_write(apic, reg, (u32)data);
31253145
}
31263146

@@ -3143,9 +3163,6 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data)
31433163
if (!lapic_in_kernel(vcpu) || !apic_x2apic_mode(apic))
31443164
return 1;
31453165

3146-
if (reg == APIC_DFR)
3147-
return 1;
3148-
31493166
return kvm_lapic_msr_read(apic, reg, data);
31503167
}
31513168

arch/x86/kvm/lapic.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data);
146146
int kvm_lapic_set_pv_eoi(struct kvm_vcpu *vcpu, u64 data, unsigned long len);
147147
void kvm_lapic_exit(void);
148148

149+
u64 kvm_lapic_readable_reg_mask(struct kvm_lapic *apic);
150+
149151
#define VEC_POS(v) ((v) & (32 - 1))
150152
#define REG_POS(v) (((v) >> 5) << 4)
151153

arch/x86/kvm/vmx/vmx.c

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4018,29 +4018,20 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type)
40184018
vmx_set_msr_bitmap_write(msr_bitmap, msr);
40194019
}
40204020

4021-
static void vmx_reset_x2apic_msrs(struct kvm_vcpu *vcpu, u8 mode)
4022-
{
4023-
unsigned long *msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
4024-
unsigned long read_intercept;
4025-
int msr;
4026-
4027-
read_intercept = (mode & MSR_BITMAP_MODE_X2APIC_APICV) ? 0 : ~0;
4028-
4029-
for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) {
4030-
unsigned int read_idx = msr / BITS_PER_LONG;
4031-
unsigned int write_idx = read_idx + (0x800 / sizeof(long));
4032-
4033-
msr_bitmap[read_idx] = read_intercept;
4034-
msr_bitmap[write_idx] = ~0ul;
4035-
}
4036-
}
4037-
40384021
static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu)
40394022
{
4023+
/*
4024+
* x2APIC indices for 64-bit accesses into the RDMSR and WRMSR halves
4025+
* of the MSR bitmap. KVM emulates APIC registers up through 0x3f0,
4026+
* i.e. MSR 0x83f, and so only needs to dynamically manipulate 64 bits.
4027+
*/
4028+
const int read_idx = APIC_BASE_MSR / BITS_PER_LONG_LONG;
4029+
const int write_idx = read_idx + (0x800 / sizeof(u64));
40404030
struct vcpu_vmx *vmx = to_vmx(vcpu);
4031+
u64 *msr_bitmap = (u64 *)vmx->vmcs01.msr_bitmap;
40414032
u8 mode;
40424033

4043-
if (!cpu_has_vmx_msr_bitmap())
4034+
if (!cpu_has_vmx_msr_bitmap() || WARN_ON_ONCE(!lapic_in_kernel(vcpu)))
40444035
return;
40454036

40464037
if (cpu_has_secondary_exec_ctrls() &&
@@ -4058,7 +4049,18 @@ static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu)
40584049

40594050
vmx->x2apic_msr_bitmap_mode = mode;
40604051

4061-
vmx_reset_x2apic_msrs(vcpu, mode);
4052+
/*
4053+
* Reset the bitmap for MSRs 0x800 - 0x83f. Leave AMD's uber-extended
4054+
* registers (0x840 and above) intercepted, KVM doesn't support them.
4055+
* Intercept all writes by default and poke holes as needed. Pass
4056+
* through reads for all valid registers by default in x2APIC+APICv
4057+
* mode, only the current timer count needs on-demand emulation by KVM.
4058+
*/
4059+
if (mode & MSR_BITMAP_MODE_X2APIC_APICV)
4060+
msr_bitmap[read_idx] = ~kvm_lapic_readable_reg_mask(vcpu->arch.apic);
4061+
else
4062+
msr_bitmap[read_idx] = ~0ull;
4063+
msr_bitmap[write_idx] = ~0ull;
40624064

40634065
/*
40644066
* TPR reads and writes can be virtualized even if virtual interrupt

tools/testing/selftests/kvm/x86_64/xapic_state_test.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,59 @@ static void test_icr(struct xapic_vcpu *x)
132132
__test_icr(x, -1ull & ~APIC_DM_FIXED_MASK);
133133
}
134134

135+
static void __test_apic_id(struct kvm_vcpu *vcpu, uint64_t apic_base)
136+
{
137+
uint32_t apic_id, expected;
138+
struct kvm_lapic_state xapic;
139+
140+
vcpu_set_msr(vcpu, MSR_IA32_APICBASE, apic_base);
141+
142+
vcpu_ioctl(vcpu, KVM_GET_LAPIC, &xapic);
143+
144+
expected = apic_base & X2APIC_ENABLE ? vcpu->id : vcpu->id << 24;
145+
apic_id = *((u32 *)&xapic.regs[APIC_ID]);
146+
147+
TEST_ASSERT(apic_id == expected,
148+
"APIC_ID not set back to %s format; wanted = %x, got = %x",
149+
(apic_base & X2APIC_ENABLE) ? "x2APIC" : "xAPIC",
150+
expected, apic_id);
151+
}
152+
153+
/*
154+
* Verify that KVM switches the APIC_ID between xAPIC and x2APIC when userspace
155+
* stuffs MSR_IA32_APICBASE. Setting the APIC_ID when x2APIC is enabled and
156+
* when the APIC transitions for DISABLED to ENABLED is architectural behavior
157+
* (on Intel), whereas the x2APIC => xAPIC transition behavior is KVM ABI since
158+
* attempted to transition from x2APIC to xAPIC without disabling the APIC is
159+
* architecturally disallowed.
160+
*/
161+
static void test_apic_id(void)
162+
{
163+
const uint32_t NR_VCPUS = 3;
164+
struct kvm_vcpu *vcpus[NR_VCPUS];
165+
uint64_t apic_base;
166+
struct kvm_vm *vm;
167+
int i;
168+
169+
vm = vm_create_with_vcpus(NR_VCPUS, NULL, vcpus);
170+
vm_enable_cap(vm, KVM_CAP_X2APIC_API, KVM_X2APIC_API_USE_32BIT_IDS);
171+
172+
for (i = 0; i < NR_VCPUS; i++) {
173+
apic_base = vcpu_get_msr(vcpus[i], MSR_IA32_APICBASE);
174+
175+
TEST_ASSERT(apic_base & MSR_IA32_APICBASE_ENABLE,
176+
"APIC not in ENABLED state at vCPU RESET");
177+
TEST_ASSERT(!(apic_base & X2APIC_ENABLE),
178+
"APIC not in xAPIC mode at vCPU RESET");
179+
180+
__test_apic_id(vcpus[i], apic_base);
181+
__test_apic_id(vcpus[i], apic_base | X2APIC_ENABLE);
182+
__test_apic_id(vcpus[i], apic_base);
183+
}
184+
185+
kvm_vm_free(vm);
186+
}
187+
135188
int main(int argc, char *argv[])
136189
{
137190
struct xapic_vcpu x = {
@@ -157,4 +210,6 @@ int main(int argc, char *argv[])
157210
virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
158211
test_icr(&x);
159212
kvm_vm_free(vm);
213+
214+
test_apic_id();
160215
}

0 commit comments

Comments
 (0)