hv: vlapic: add apic register offset check API

Add apic rgister offset check before do vlapic read/write.

Tracked-On: #1842
Signed-off-by: Li, Fei1 <fei1.li@intel.com>
This commit is contained in:
Li, Fei1 2019-04-18 22:40:44 +08:00 committed by wenlingz
parent 70dd254456
commit 28d50f1b96
3 changed files with 65 additions and 31 deletions

View File

@ -2038,6 +2038,27 @@ vlapic_x2apic_pt_icr_access(struct acrn_vm *vm, uint64_t val)
return ret;
}
static bool apicv_basic_x2apic_read_msr_may_valid(uint32_t offset)
{
return (offset != APIC_OFFSET_DFR) && (offset != APIC_OFFSET_ICR_HI);
}
static bool apicv_advanced_x2apic_read_msr_may_valid(uint32_t offset)
{
return (offset == APIC_OFFSET_TIMER_CCR);
}
static bool apicv_basic_x2apic_write_msr_may_valid(uint32_t offset)
{
return (offset != APIC_OFFSET_DFR) && (offset != APIC_OFFSET_ICR_HI);
}
static bool apicv_advanced_x2apic_write_msr_may_valid(uint32_t offset)
{
return (offset != APIC_OFFSET_DFR) && (offset != APIC_OFFSET_ICR_HI) &&
(offset != APIC_OFFSET_EOI) && (offset != APIC_OFFSET_SELF_IPI);
}
int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
{
struct acrn_vlapic *vlapic;
@ -2062,8 +2083,8 @@ int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
break;
}
} else {
if (!is_x2apic_write_only_msr(msr)) {
offset = x2apic_msr_to_regoff(msr);
offset = x2apic_msr_to_regoff(msr);
if (apicv_ops->x2apic_read_msr_may_valid(offset)) {
error = vlapic_read(vlapic, offset, val);
}
}
@ -2094,8 +2115,8 @@ int32_t vlapic_x2apic_write(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val)
break;
}
} else {
if (!is_x2apic_read_only_msr(msr)) {
offset = x2apic_msr_to_regoff(msr);
offset = x2apic_msr_to_regoff(msr);
if (apicv_ops->x2apic_write_msr_may_valid(offset)) {
error = vlapic_write(vlapic, offset, val);
}
}
@ -2315,6 +2336,26 @@ bool vlapic_has_pending_delivery_intr(struct acrn_vcpu *vcpu)
return apicv_ops->has_pending_delivery_intr(vcpu);
}
static bool apicv_basic_apic_read_access_may_valid(__unused uint32_t offset)
{
return true;
}
static bool apicv_advanced_apic_read_access_may_valid(uint32_t offset)
{
return ((offset == APIC_OFFSET_CMCI_LVT) || (offset == APIC_OFFSET_TIMER_CCR));
}
static bool apicv_basic_apic_write_access_may_valid(uint32_t offset)
{
return (offset != APIC_OFFSET_SELF_IPI);
}
static bool apicv_advanced_apic_write_access_may_valid(uint32_t offset)
{
return (offset == APIC_OFFSET_CMCI_LVT);
}
int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
{
int32_t err = 0;
@ -2340,10 +2381,16 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
if (err >= 0) {
if (access_type == 1UL) {
if (emulate_instruction(vcpu) == 0) {
(void)vlapic_write(vlapic, offset, mmio->value);
if (apicv_ops->apic_write_access_may_valid(offset)) {
(void)vlapic_write(vlapic, offset, mmio->value);
}
}
} else if (access_type == 0UL) {
(void)vlapic_read(vlapic, offset, &mmio->value);
if (apicv_ops->apic_read_access_may_valid(offset)) {
(void)vlapic_read(vlapic, offset, &mmio->value);
} else {
mmio->value = 0ULL;
}
err = emulate_instruction(vcpu);
} else {
pr_err("Unhandled APIC access type: %lu\n", access_type);
@ -2502,12 +2549,20 @@ static const struct acrn_apicv_ops apicv_basic_ops = {
.accept_intr = apicv_basic_accept_intr,
.inject_intr = apicv_basic_inject_intr,
.has_pending_delivery_intr = apicv_basic_has_pending_delivery_intr,
.apic_read_access_may_valid = apicv_basic_apic_read_access_may_valid,
.apic_write_access_may_valid = apicv_basic_apic_write_access_may_valid,
.x2apic_read_msr_may_valid = apicv_basic_x2apic_read_msr_may_valid,
.x2apic_write_msr_may_valid = apicv_basic_x2apic_write_msr_may_valid,
};
static const struct acrn_apicv_ops apicv_advanced_ops = {
.accept_intr = apicv_advanced_accept_intr,
.inject_intr = apicv_advanced_inject_intr,
.has_pending_delivery_intr = apicv_advanced_has_pending_delivery_intr,
.apic_read_access_may_valid = apicv_advanced_apic_read_access_may_valid,
.apic_write_access_may_valid = apicv_advanced_apic_write_access_may_valid,
.x2apic_read_msr_may_valid = apicv_advanced_x2apic_read_msr_may_valid,
.x2apic_write_msr_may_valid = apicv_advanced_x2apic_write_msr_may_valid,
};
/*

View File

@ -86,6 +86,10 @@ struct acrn_apicv_ops {
void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level);
bool (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected);
bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu);
bool (*apic_read_access_may_valid)(uint32_t offset);
bool (*apic_write_access_may_valid)(uint32_t offset);
bool (*x2apic_read_msr_may_valid)(uint32_t offset);
bool (*x2apic_write_msr_may_valid)(uint32_t offset);
};
#endif /* VLAPIC_PRIV_H */

View File

@ -567,31 +567,6 @@ static inline bool is_x2apic_msr(uint32_t msr)
return ((msr >= 0x800U) && (msr < 0x900U));
}
static inline bool is_x2apic_read_only_msr(uint32_t msr)
{
bool ret = false;
if ((msr == MSR_IA32_EXT_XAPICID) ||
(msr == MSR_IA32_EXT_APIC_VERSION) ||
(msr == MSR_IA32_EXT_APIC_PPR) ||
(msr == MSR_IA32_EXT_APIC_LDR) ||
((msr >= MSR_IA32_EXT_APIC_ISR0) &&
(msr <= MSR_IA32_EXT_APIC_IRR7)) ||
(msr == MSR_IA32_EXT_APIC_CUR_COUNT)) {
ret = true;
}
return ret;
}
static inline bool is_x2apic_write_only_msr(uint32_t msr)
{
bool ret = false;
if ((msr == MSR_IA32_EXT_APIC_EOI) || (msr == MSR_IA32_EXT_APIC_SELF_IPI)) {
ret = true;
}
return ret;
}
struct acrn_vcpu;
void init_msr_emulation(struct acrn_vcpu *vcpu);