mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-04 19:17:34 +00:00
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>
This commit is contained in:
parent
0c347e607a
commit
70dd254456
@ -1224,12 +1224,10 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode,
|
||||
return;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
||||
static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
||||
{
|
||||
uint16_t vcpu_id;
|
||||
bool phys;
|
||||
int32_t ret = 0;
|
||||
uint64_t dmask = 0UL;
|
||||
uint32_t icr_low, icr_high, dest;
|
||||
uint32_t vec, mode, shorthand;
|
||||
@ -1311,8 +1309,6 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret; /* handled completely in the kernel */
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t
|
||||
vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
|
||||
static int32_t vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
|
||||
{
|
||||
int32_t ret = 0;
|
||||
struct lapic_regs *lapic = &(vlapic->apic_page);
|
||||
uint32_t i;
|
||||
uint32_t offset = offset_arg;
|
||||
*data = 0ULL;
|
||||
|
||||
if (offset > sizeof(*lapic)) {
|
||||
*data = 0UL;
|
||||
ret = -EACCES;
|
||||
} else {
|
||||
|
||||
offset &= ~0x3UL;
|
||||
@ -1484,9 +1481,6 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
|
||||
case APIC_OFFSET_VER:
|
||||
*data = lapic->version.v;
|
||||
break;
|
||||
case APIC_OFFSET_APR:
|
||||
*data = lapic->apr.v;
|
||||
break;
|
||||
case APIC_OFFSET_PPR:
|
||||
*data = lapic->ppr.v;
|
||||
break;
|
||||
@ -1574,31 +1568,28 @@ vlapic_read(struct acrn_vlapic *vlapic, uint32_t offset_arg, uint64_t *data)
|
||||
case APIC_OFFSET_TIMER_DCR:
|
||||
*data = lapic->dcr_timer.v;
|
||||
break;
|
||||
case APIC_OFFSET_RRR:
|
||||
default:
|
||||
*data = 0UL;
|
||||
ret = -EACCES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_LAPIC, "vlapic read offset %#x, data %#llx", offset, *data);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
|
||||
static int32_t vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
|
||||
{
|
||||
struct lapic_regs *lapic = &(vlapic->apic_page);
|
||||
uint32_t *regptr;
|
||||
uint32_t data32 = (uint32_t)data;
|
||||
int32_t retval;
|
||||
int32_t ret = 0;
|
||||
|
||||
ASSERT(((offset & 0xfU) == 0U) && (offset < PAGE_SIZE),
|
||||
"%s: invalid offset %#x", __func__, offset);
|
||||
|
||||
dev_dbg(ACRN_DBG_LAPIC, "vlapic write offset %#x, data %#lx", offset, data);
|
||||
|
||||
retval = 0;
|
||||
if (offset <= sizeof(*lapic)) {
|
||||
switch (offset) {
|
||||
case APIC_OFFSET_ID:
|
||||
@ -1624,7 +1615,7 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
|
||||
lapic->icr_hi.v = (uint32_t)(data >> 32U);
|
||||
}
|
||||
lapic->icr_lo.v = data32;
|
||||
retval = vlapic_icrlo_write_handler(vlapic);
|
||||
vlapic_icrlo_write_handler(vlapic);
|
||||
break;
|
||||
case APIC_OFFSET_ICR_HI:
|
||||
lapic->icr_hi.v = data32;
|
||||
@ -1657,19 +1648,6 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
|
||||
vlapic_esr_write_handler(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_OFFSET_VER:
|
||||
case APIC_OFFSET_APR:
|
||||
case APIC_OFFSET_PPR:
|
||||
case APIC_OFFSET_RRR:
|
||||
break;
|
||||
/*The following cases fall to the default one:
|
||||
* APIC_OFFSET_ISR0 ... APIC_OFFSET_ISR7
|
||||
* APIC_OFFSET_TMR0 ... APIC_OFFSET_TMR7
|
||||
* APIC_OFFSET_IRR0 ... APIC_OFFSET_IRR7
|
||||
*/
|
||||
case APIC_OFFSET_TIMER_CCR:
|
||||
break;
|
||||
|
||||
case APIC_OFFSET_SELF_IPI:
|
||||
if (is_x2apic_enabled(vlapic)) {
|
||||
lapic->self_ipi.v = data32;
|
||||
@ -1679,13 +1657,15 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_t data)
|
||||
/* falls through */
|
||||
|
||||
default:
|
||||
retval = -EACCES;
|
||||
ret = -EACCES;
|
||||
/* Read only */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ret = -EACCES;
|
||||
}
|
||||
|
||||
return retval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2360,14 +2340,11 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
if (err >= 0) {
|
||||
if (access_type == 1UL) {
|
||||
if (emulate_instruction(vcpu) == 0) {
|
||||
err = vlapic_write(vlapic, offset, mmio->value);
|
||||
(void)vlapic_write(vlapic, offset, mmio->value);
|
||||
}
|
||||
} else if (access_type == 0UL) {
|
||||
err = vlapic_read(vlapic, offset, &mmio->value);
|
||||
if (err >= 0) {
|
||||
(void)vlapic_read(vlapic, offset, &mmio->value);
|
||||
err = emulate_instruction(vcpu);
|
||||
}
|
||||
|
||||
} else {
|
||||
pr_err("Unhandled APIC access type: %lu\n", access_type);
|
||||
err = -EINVAL;
|
||||
@ -2441,9 +2418,6 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
case APIC_OFFSET_ID:
|
||||
/* Force APIC ID as read only */
|
||||
break;
|
||||
case APIC_OFFSET_EOI:
|
||||
vlapic_process_eoi(vlapic);
|
||||
break;
|
||||
case APIC_OFFSET_LDR:
|
||||
vlapic_ldr_write_handler(vlapic);
|
||||
break;
|
||||
@ -2457,7 +2431,7 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
vlapic_esr_write_handler(vlapic);
|
||||
break;
|
||||
case APIC_OFFSET_ICR_LOW:
|
||||
err = vlapic_icrlo_write_handler(vlapic);
|
||||
vlapic_icrlo_write_handler(vlapic);
|
||||
break;
|
||||
case APIC_OFFSET_CMCI_LVT:
|
||||
case APIC_OFFSET_TIMER_LVT:
|
||||
|
@ -212,54 +212,6 @@ static const uint32_t unsupported_msrs[NUM_UNSUPPORTED_MSRS] = {
|
||||
/* MSR 0x400 ... 0x473, not in this array */
|
||||
};
|
||||
|
||||
#define NUM_X2APIC_MSRS 44U
|
||||
static const uint32_t x2apic_msrs[NUM_X2APIC_MSRS] = {
|
||||
MSR_IA32_EXT_XAPICID,
|
||||
MSR_IA32_EXT_APIC_VERSION,
|
||||
MSR_IA32_EXT_APIC_TPR,
|
||||
MSR_IA32_EXT_APIC_PPR,
|
||||
MSR_IA32_EXT_APIC_EOI,
|
||||
MSR_IA32_EXT_APIC_LDR,
|
||||
MSR_IA32_EXT_APIC_SIVR,
|
||||
MSR_IA32_EXT_APIC_ISR0,
|
||||
MSR_IA32_EXT_APIC_ISR1,
|
||||
MSR_IA32_EXT_APIC_ISR2,
|
||||
MSR_IA32_EXT_APIC_ISR3,
|
||||
MSR_IA32_EXT_APIC_ISR4,
|
||||
MSR_IA32_EXT_APIC_ISR5,
|
||||
MSR_IA32_EXT_APIC_ISR6,
|
||||
MSR_IA32_EXT_APIC_ISR7,
|
||||
MSR_IA32_EXT_APIC_TMR0,
|
||||
MSR_IA32_EXT_APIC_TMR1,
|
||||
MSR_IA32_EXT_APIC_TMR2,
|
||||
MSR_IA32_EXT_APIC_TMR3,
|
||||
MSR_IA32_EXT_APIC_TMR4,
|
||||
MSR_IA32_EXT_APIC_TMR5,
|
||||
MSR_IA32_EXT_APIC_TMR6,
|
||||
MSR_IA32_EXT_APIC_TMR7,
|
||||
MSR_IA32_EXT_APIC_IRR0,
|
||||
MSR_IA32_EXT_APIC_IRR1,
|
||||
MSR_IA32_EXT_APIC_IRR2,
|
||||
MSR_IA32_EXT_APIC_IRR3,
|
||||
MSR_IA32_EXT_APIC_IRR4,
|
||||
MSR_IA32_EXT_APIC_IRR5,
|
||||
MSR_IA32_EXT_APIC_IRR6,
|
||||
MSR_IA32_EXT_APIC_IRR7,
|
||||
MSR_IA32_EXT_APIC_ESR,
|
||||
MSR_IA32_EXT_APIC_LVT_CMCI,
|
||||
MSR_IA32_EXT_APIC_ICR,
|
||||
MSR_IA32_EXT_APIC_LVT_TIMER,
|
||||
MSR_IA32_EXT_APIC_LVT_THERMAL,
|
||||
MSR_IA32_EXT_APIC_LVT_PMI,
|
||||
MSR_IA32_EXT_APIC_LVT_LINT0,
|
||||
MSR_IA32_EXT_APIC_LVT_LINT1,
|
||||
MSR_IA32_EXT_APIC_LVT_ERROR,
|
||||
MSR_IA32_EXT_APIC_INIT_COUNT,
|
||||
MSR_IA32_EXT_APIC_CUR_COUNT,
|
||||
MSR_IA32_EXT_APIC_DIV_CONF,
|
||||
MSR_IA32_EXT_APIC_SELF_IPI,
|
||||
};
|
||||
|
||||
/* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */
|
||||
uint32_t vmsr_get_guest_msr_index(uint32_t msr)
|
||||
{
|
||||
@ -314,18 +266,14 @@ static void enable_msr_interception(uint8_t *bitmap, uint32_t msr_arg, uint32_t
|
||||
|
||||
/*
|
||||
* Enable read and write msr interception for x2APIC MSRs
|
||||
* MSRs that are not supported in the x2APIC range of MSRs,
|
||||
* i.e. anything other than the ones below and between
|
||||
* 0x802 and 0x83F, are not intercepted
|
||||
*/
|
||||
|
||||
static void intercept_x2apic_msrs(uint8_t *msr_bitmap_arg, uint32_t mode)
|
||||
{
|
||||
uint8_t *msr_bitmap = msr_bitmap_arg;
|
||||
uint32_t i;
|
||||
uint32_t msr;
|
||||
|
||||
for (i = 0U; i < NUM_X2APIC_MSRS; i++) {
|
||||
enable_msr_interception(msr_bitmap, x2apic_msrs[i], mode);
|
||||
for (msr = 0x800U; msr < 0x900U; msr++) {
|
||||
enable_msr_interception(msr_bitmap, msr, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,8 +594,8 @@ void update_msr_bitmap_x2apic_apicv(const struct acrn_vcpu *vcpu)
|
||||
* writes to them are virtualized with Register Virtualization
|
||||
* Refer to Section 29.1 in Intel SDM Vol. 3
|
||||
*/
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_EOI, INTERCEPT_READ);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_SELF_IPI, INTERCEPT_READ);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_EOI, INTERCEPT_DISABLE);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_SELF_IPI, INTERCEPT_DISABLE);
|
||||
}
|
||||
|
||||
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)
|
||||
*/
|
||||
void update_msr_bitmap_x2apic_passthru(const struct acrn_vcpu *vcpu)
|
||||
{
|
||||
uint32_t msr;
|
||||
uint8_t *msr_bitmap;
|
||||
uint8_t *msr_bitmap = vcpu->vm->arch_vm.msr_bitmap;
|
||||
|
||||
msr_bitmap = vcpu->vm->arch_vm.msr_bitmap;
|
||||
for (msr = MSR_IA32_EXT_XAPICID;
|
||||
msr <= MSR_IA32_EXT_APIC_SELF_IPI; msr++) {
|
||||
enable_msr_interception(msr_bitmap, msr, INTERCEPT_DISABLE);
|
||||
}
|
||||
intercept_x2apic_msrs(msr_bitmap, INTERCEPT_DISABLE);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_XAPICID, INTERCEPT_READ);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_LDR, INTERCEPT_READ);
|
||||
enable_msr_interception(msr_bitmap, MSR_IA32_EXT_APIC_ICR, INTERCEPT_WRITE);
|
||||
|
@ -561,14 +561,10 @@ static inline bool pat_mem_type_invalid(uint64_t x)
|
||||
|
||||
static inline bool is_x2apic_msr(uint32_t msr)
|
||||
{
|
||||
bool ret = false;
|
||||
/*
|
||||
* if msr is in the range of x2APIC MSRs
|
||||
*/
|
||||
if ((msr >= MSR_IA32_EXT_XAPICID) && (msr <= MSR_IA32_EXT_APIC_SELF_IPI)) {
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
return ((msr >= 0x800U) && (msr < 0x900U));
|
||||
}
|
||||
|
||||
static inline bool is_x2apic_read_only_msr(uint32_t msr)
|
||||
|
Loading…
Reference in New Issue
Block a user