Skip to content

Commit 70dd254

Browse files
lifeixwenlingz
authored andcommitted
hv: vmsr: refine x2apic MSR bitmap setting
In theory, we should trap out all the x2apic MSR access if APICv is not enabled. When "Use TPR shadow" and "Virtualize x2APIC mode" are enabled, we could disable TPR interception; when APICv is fully enabled, besides TPR, we could disable all MSR read, EOI and self-IPI interception; when we pass through lapic to guest, we could disable all the MSR access interception except XAPICID/LDR read and ICR write. Tracked-On: #1842 Signed-off-by: Li, Fei1 <fei1.li@intel.com>
1 parent 0c347e6 commit 70dd254

File tree

3 files changed

+26
-113
lines changed

3 files changed

+26
-113
lines changed

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 18 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,12 +1224,10 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode,
12241224
return;
12251225
}
12261226

1227-
static int32_t
1228-
vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
1227+
static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
12291228
{
12301229
uint16_t vcpu_id;
12311230
bool phys;
1232-
int32_t ret = 0;
12331231
uint64_t dmask = 0UL;
12341232
uint32_t icr_low, icr_high, dest;
12351233
uint32_t vec, mode, shorthand;
@@ -1311,8 +1309,6 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
13111309
}
13121310
}
13131311
}
1314-
1315-
return ret; /* handled completely in the kernel */
13161312
}
13171313

13181314
static inline uint32_t vlapic_find_highest_irr(const struct acrn_vlapic *vlapic)
@@ -1465,15 +1461,16 @@ vlapic_svr_write_handler(struct acrn_vlapic *vlapic)
14651461
}
14661462
}
14671463

1468-
static int32_t
1469-
vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
1464+
static int32_t vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
14701465
{
1466+
int32_t ret = 0;
14711467
struct lapic_regs *lapic = &(vlapic->apic_page);
14721468
uint32_t i;
14731469
uint32_t offset = offset_arg;
1470+
*data = 0ULL;
14741471

14751472
if (offset > sizeof(*lapic)) {
1476-
*data = 0UL;
1473+
ret = -EACCES;
14771474
} else {
14781475

14791476
offset &= ~0x3UL;
@@ -1484,9 +1481,6 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
14841481
case APIC_OFFSET_VER:
14851482
*data = lapic->version.v;
14861483
break;
1487-
case APIC_OFFSET_APR:
1488-
*data = lapic->apr.v;
1489-
break;
14901484
case APIC_OFFSET_PPR:
14911485
*data = lapic->ppr.v;
14921486
break;
@@ -1574,31 +1568,28 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
15741568
case APIC_OFFSET_TIMER_DCR:
15751569
*data = lapic->dcr_timer.v;
15761570
break;
1577-
case APIC_OFFSET_RRR:
15781571
default:
1579-
*data = 0UL;
1572+
ret = -EACCES;
15801573
break;
15811574
}
15821575
}
15831576

15841577
dev_dbg(ACRN_DBG_LAPIC, "vlapic read offset %#x, data %#llx", offset, *data);
1585-
return 0;
1578+
return ret;
15861579
}
15871580

1588-
static int32_t
1589-
vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
1581+
static int32_t vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
15901582
{
15911583
struct lapic_regs *lapic = &(vlapic->apic_page);
15921584
uint32_t *regptr;
15931585
uint32_t data32 = (uint32_t)data;
1594-
int32_t retval;
1586+
int32_t ret = 0;
15951587

15961588
ASSERT(((offset & 0xfU) == 0U) && (offset < PAGE_SIZE),
15971589
"%s: invalid offset %#x", __func__, offset);
15981590

15991591
dev_dbg(ACRN_DBG_LAPIC, "vlapic write offset %#x, data %#lx", offset, data);
16001592

1601-
retval = 0;
16021593
if (offset <= sizeof(*lapic)) {
16031594
switch (offset) {
16041595
case APIC_OFFSET_ID:
@@ -1624,7 +1615,7 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
16241615
lapic->icr_hi.v = (uint32_t)(data >> 32U);
16251616
}
16261617
lapic->icr_lo.v = data32;
1627-
retval = vlapic_icrlo_write_handler(vlapic);
1618+
vlapic_icrlo_write_handler(vlapic);
16281619
break;
16291620
case APIC_OFFSET_ICR_HI:
16301621
lapic->icr_hi.v = data32;
@@ -1657,19 +1648,6 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
16571648
vlapic_esr_write_handler(vlapic);
16581649
break;
16591650

1660-
case APIC_OFFSET_VER:
1661-
case APIC_OFFSET_APR:
1662-
case APIC_OFFSET_PPR:
1663-
case APIC_OFFSET_RRR:
1664-
break;
1665-
/*The following cases fall to the default one:
1666-
* APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7
1667-
* APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7
1668-
* APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7
1669-
*/
1670-
case APIC_OFFSET_TIMER_CCR:
1671-
break;
1672-
16731651
case APIC_OFFSET_SELF_IPI:
16741652
if (is_x2apic_enabled(vlapic)) {
16751653
lapic->self_ipi.v = data32;
@@ -1679,13 +1657,15 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
16791657
/* falls through */
16801658

16811659
default:
1682-
retval = -EACCES;
1660+
ret = -EACCES;
16831661
/* Read only */
16841662
break;
16851663
}
1664+
} else {
1665+
ret = -EACCES;
16861666
}
16871667

1688-
return retval;
1668+
return ret;
16891669
}
16901670

16911671
void
@@ -2360,14 +2340,11 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
23602340
if (err >= 0) {
23612341
if (access_type == 1UL) {
23622342
if (emulate_instruction(vcpu) == 0) {
2363-
err = vlapic_write(vlapic, offset, mmio->value);
2343+
(void)vlapic_write(vlapic, offset, mmio->value);
23642344
}
23652345
} else if (access_type == 0UL) {
2366-
err = vlapic_read(vlapic, offset, &mmio->value);
2367-
if (err >= 0) {
2368-
err = emulate_instruction(vcpu);
2369-
}
2370-
2346+
(void)vlapic_read(vlapic, offset, &mmio->value);
2347+
err = emulate_instruction(vcpu);
23712348
} else {
23722349
pr_err("Unhandled APIC access type: %lu\n", access_type);
23732350
err = -EINVAL;
@@ -2441,9 +2418,6 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
24412418
case APIC_OFFSET_ID:
24422419
/* Force APIC ID as read only */
24432420
break;
2444-
case APIC_OFFSET_EOI:
2445-
vlapic_process_eoi(vlapic);
2446-
break;
24472421
case APIC_OFFSET_LDR:
24482422
vlapic_ldr_write_handler(vlapic);
24492423
break;
@@ -2457,7 +2431,7 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
24572431
vlapic_esr_write_handler(vlapic);
24582432
break;
24592433
case APIC_OFFSET_ICR_LOW:
2460-
err = vlapic_icrlo_write_handler(vlapic);
2434+
vlapic_icrlo_write_handler(vlapic);
24612435
break;
24622436
case APIC_OFFSET_CMCI_LVT:
24632437
case APIC_OFFSET_TIMER_LVT:

hypervisor/arch/x86/guest/vmsr.c

Lines changed: 7 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -212,54 +212,6 @@ static const uint32_t unsupported_msrs[NUM_UNSUPPORTED_MSRS] = {
212212
/* MSR 0x400 ... 0x473, not in this array */
213213
};
214214

215-
#define NUM_X2APIC_MSRS 44U
216-
static const uint32_t x2apic_msrs[NUM_X2APIC_MSRS] = {
217-
MSR_IA32_EXT_XAPICID,
218-
MSR_IA32_EXT_APIC_VERSION,
219-
MSR_IA32_EXT_APIC_TPR,
220-
MSR_IA32_EXT_APIC_PPR,
221-
MSR_IA32_EXT_APIC_EOI,
222-
MSR_IA32_EXT_APIC_LDR,
223-
MSR_IA32_EXT_APIC_SIVR,
224-
MSR_IA32_EXT_APIC_ISR0,
225-
MSR_IA32_EXT_APIC_ISR1,
226-
MSR_IA32_EXT_APIC_ISR2,
227-
MSR_IA32_EXT_APIC_ISR3,
228-
MSR_IA32_EXT_APIC_ISR4,
229-
MSR_IA32_EXT_APIC_ISR5,
230-
MSR_IA32_EXT_APIC_ISR6,
231-
MSR_IA32_EXT_APIC_ISR7,
232-
MSR_IA32_EXT_APIC_TMR0,
233-
MSR_IA32_EXT_APIC_TMR1,
234-
MSR_IA32_EXT_APIC_TMR2,
235-
MSR_IA32_EXT_APIC_TMR3,
236-
MSR_IA32_EXT_APIC_TMR4,
237-
MSR_IA32_EXT_APIC_TMR5,
238-
MSR_IA32_EXT_APIC_TMR6,
239-
MSR_IA32_EXT_APIC_TMR7,
240-
MSR_IA32_EXT_APIC_IRR0,
241-
MSR_IA32_EXT_APIC_IRR1,
242-
MSR_IA32_EXT_APIC_IRR2,
243-
MSR_IA32_EXT_APIC_IRR3,
244-
MSR_IA32_EXT_APIC_IRR4,
245-
MSR_IA32_EXT_APIC_IRR5,
246-
MSR_IA32_EXT_APIC_IRR6,
247-
MSR_IA32_EXT_APIC_IRR7,
248-
MSR_IA32_EXT_APIC_ESR,
249-
MSR_IA32_EXT_APIC_LVT_CMCI,
250-
MSR_IA32_EXT_APIC_ICR,
251-
MSR_IA32_EXT_APIC_LVT_TIMER,
252-
MSR_IA32_EXT_APIC_LVT_THERMAL,
253-
MSR_IA32_EXT_APIC_LVT_PMI,
254-
MSR_IA32_EXT_APIC_LVT_LINT0,
255-
MSR_IA32_EXT_APIC_LVT_LINT1,
256-
MSR_IA32_EXT_APIC_LVT_ERROR,
257-
MSR_IA32_EXT_APIC_INIT_COUNT,
258-
MSR_IA32_EXT_APIC_CUR_COUNT,
259-
MSR_IA32_EXT_APIC_DIV_CONF,
260-
MSR_IA32_EXT_APIC_SELF_IPI,
261-
};
262-
263215
/* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */
264216
uint32_t vmsr_get_guest_msr_index(uint32_t msr)
265217
{
@@ -314,18 +266,14 @@ static void enable_msr_interception(uint8_t *bitmap, uint32_t msr_arg, uint32_t
314266

315267
/*
316268
* Enable read and write msr interception for x2APIC MSRs
317-
* MSRs that are not supported in the x2APIC range of MSRs,
318-
* i.e. anything other than the ones below and between
319-
* 0x802 and 0x83F, are not intercepted
320269
*/
321-
322270
static void intercept_x2apic_msrs(uint8_t *msr_bitmap_arg, uint32_t mode)
323271
{
324272
uint8_t *msr_bitmap = msr_bitmap_arg;
325-
uint32_t i;
273+
uint32_t msr;
326274

327-
for (i = 0U; i < NUM_X2APIC_MSRS; i++) {
328-
enable_msr_interception(msr_bitmap, x2apic_msrs[i], mode);
275+
for (msr = 0x800U; msr < 0x900U; msr++) {
276+
enable_msr_interception(msr_bitmap, msr, mode);
329277
}
330278
}
331279

@@ -646,8 +594,8 @@ void update_msr_bitmap_x2apic_apicv(const struct acrn_vcpu *vcpu)
646594
* writes to them are virtualized with Register Virtualization
647595
* Refer to Section 29.1 in Intel SDM Vol. 3
648596
*/
649-
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_EOI, INTERCEPT_READ);
650-
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_SELF_IPI, INTERCEPT_READ);
597+
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_EOI, INTERCEPT_DISABLE);
598+
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_SELF_IPI, INTERCEPT_DISABLE);
651599
}
652600

653601
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_TPR, INTERCEPT_DISABLE);
@@ -661,14 +609,9 @@ void update_msr_bitmap_x2apic_apicv(const struct acrn_vcpu *vcpu)
661609
*/
662610
void update_msr_bitmap_x2apic_passthru(const struct acrn_vcpu *vcpu)
663611
{
664-
uint32_t msr;
665-
uint8_t *msr_bitmap;
612+
uint8_t *msr_bitmap = vcpu->vm->arch_vm.msr_bitmap;
666613

667-
msr_bitmap = vcpu->vm->arch_vm.msr_bitmap;
668-
for (msr = MSR_IA32_EXT_XAPICID;
669-
msr <= MSR_IA32_EXT_APIC_SELF_IPI; msr++) {
670-
enable_msr_interception(msr_bitmap, msr, INTERCEPT_DISABLE);
671-
}
614+
intercept_x2apic_msrs(msr_bitmap, INTERCEPT_DISABLE);
672615
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_XAPICID, INTERCEPT_READ);
673616
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_LDR, INTERCEPT_READ);
674617
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_ICR, INTERCEPT_WRITE);

hypervisor/include/arch/x86/msr.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -561,14 +561,10 @@ static inline bool pat_mem_type_invalid(uint64_t x)
561561

562562
static inline bool is_x2apic_msr(uint32_t msr)
563563
{
564-
bool ret = false;
565564
/*
566565
* if msr is in the range of x2APIC MSRs
567566
*/
568-
if ((msr >= MSR_IA32_EXT_XAPICID) && (msr <= MSR_IA32_EXT_APIC_SELF_IPI)) {
569-
ret = true;
570-
}
571-
return ret;
567+
return ((msr >= 0x800U) && (msr < 0x900U));
572568
}
573569

574570
static inline bool is_x2apic_read_only_msr(uint32_t msr)

0 commit comments

Comments
 (0)