mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-10 12:32:45 +00:00
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:
parent
70dd254456
commit
28d50f1b96
@ -2038,6 +2038,27 @@ vlapic_x2apic_pt_icr_access(struct acrn_vm *vm, uint64_t val)
|
|||||||
return ret;
|
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)
|
int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
|
||||||
{
|
{
|
||||||
struct acrn_vlapic *vlapic;
|
struct acrn_vlapic *vlapic;
|
||||||
@ -2062,8 +2083,8 @@ int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
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);
|
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 apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
int32_t err = 0;
|
int32_t err = 0;
|
||||||
@ -2340,10 +2381,16 @@ int32_t apic_access_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||||||
if (err >= 0) {
|
if (err >= 0) {
|
||||||
if (access_type == 1UL) {
|
if (access_type == 1UL) {
|
||||||
if (emulate_instruction(vcpu) == 0) {
|
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) {
|
} 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);
|
err = emulate_instruction(vcpu);
|
||||||
} else {
|
} else {
|
||||||
pr_err("Unhandled APIC access type: %lu\n", access_type);
|
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,
|
.accept_intr = apicv_basic_accept_intr,
|
||||||
.inject_intr = apicv_basic_inject_intr,
|
.inject_intr = apicv_basic_inject_intr,
|
||||||
.has_pending_delivery_intr = apicv_basic_has_pending_delivery_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 = {
|
static const struct acrn_apicv_ops apicv_advanced_ops = {
|
||||||
.accept_intr = apicv_advanced_accept_intr,
|
.accept_intr = apicv_advanced_accept_intr,
|
||||||
.inject_intr = apicv_advanced_inject_intr,
|
.inject_intr = apicv_advanced_inject_intr,
|
||||||
.has_pending_delivery_intr = apicv_advanced_has_pending_delivery_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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -86,6 +86,10 @@ struct acrn_apicv_ops {
|
|||||||
void (*accept_intr)(struct acrn_vlapic *vlapic, uint32_t vector, bool level);
|
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 (*inject_intr)(struct acrn_vlapic *vlapic, bool guest_irq_enabled, bool injected);
|
||||||
bool (*has_pending_delivery_intr)(struct acrn_vcpu *vcpu);
|
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 */
|
#endif /* VLAPIC_PRIV_H */
|
||||||
|
@ -567,31 +567,6 @@ static inline bool is_x2apic_msr(uint32_t msr)
|
|||||||
return ((msr >= 0x800U) && (msr < 0x900U));
|
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;
|
struct acrn_vcpu;
|
||||||
|
|
||||||
void init_msr_emulation(struct acrn_vcpu *vcpu);
|
void init_msr_emulation(struct acrn_vcpu *vcpu);
|
||||||
|
Loading…
Reference in New Issue
Block a user