mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-24 14:33:38 +00:00
HV: restore lapic state and apic id upon INIT
Per SDM 10.12.5.1 vol.3, local APIC should keep LAPIC state after receiving INIT. The local APIC ID register should also be preserved. Tracked-On: #4267 Signed-off-by: Victor Sun <victor.sun@intel.com> Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
ab13228591
commit
c6f7803f06
@ -194,7 +194,7 @@ void vcpu_reset_eoi_exit_bitmaps(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
|
||||
/* As a vcpu reset internal API, DO NOT touch any vcpu state transition in this function. */
|
||||
static void vcpu_reset_internal(struct acrn_vcpu *vcpu, __unused enum reset_mode mode)
|
||||
static void vcpu_reset_internal(struct acrn_vcpu *vcpu, enum reset_mode mode)
|
||||
{
|
||||
int32_t i;
|
||||
struct acrn_vlapic *vlapic;
|
||||
@ -217,7 +217,7 @@ static void vcpu_reset_internal(struct acrn_vcpu *vcpu, __unused enum reset_mode
|
||||
vcpu->thread_obj.notify_mode = SCHED_NOTIFY_IPI;
|
||||
|
||||
vlapic = vcpu_vlapic(vcpu);
|
||||
vlapic_reset(vlapic, apicv_ops);
|
||||
vlapic_reset(vlapic, apicv_ops, mode);
|
||||
|
||||
reset_vcpu_regs(vcpu);
|
||||
}
|
||||
|
@ -55,8 +55,8 @@ static inline uint32_t prio(uint32_t x)
|
||||
|
||||
#define VLAPIC_VERSION (16U)
|
||||
#define APICBASE_BSP 0x00000100UL
|
||||
#define APICBASE_X2APIC 0x00000400U
|
||||
#define APICBASE_XAPIC 0x00000800U
|
||||
#define APICBASE_X2APIC 0x00000400UL
|
||||
#define APICBASE_XAPIC 0x00000800UL
|
||||
#define APICBASE_LAPIC_MODE (APICBASE_XAPIC | APICBASE_X2APIC)
|
||||
#define APICBASE_ENABLED 0x00000800UL
|
||||
#define LOGICAL_ID_MASK 0xFU
|
||||
@ -1643,24 +1643,39 @@ static int32_t vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset, uint64_
|
||||
* @pre vlapic != NULL && ops != NULL
|
||||
*/
|
||||
void
|
||||
vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops)
|
||||
vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops, enum reset_mode mode)
|
||||
{
|
||||
struct lapic_regs *lapic;
|
||||
uint64_t preserved_lapic_mode = vlapic->msr_apicbase & APICBASE_LAPIC_MODE;
|
||||
uint32_t preserved_apic_id = vlapic->apic_page.id.v;
|
||||
|
||||
/*
|
||||
* Upon reset, vlapic is set to xAPIC mode.
|
||||
*/
|
||||
vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
|
||||
vlapic->msr_apicbase = DEFAULT_APIC_BASE;
|
||||
|
||||
if (vlapic->vcpu->vcpu_id == BOOT_CPU_ID) {
|
||||
vlapic->msr_apicbase |= APICBASE_BSP;
|
||||
}
|
||||
if (mode == INIT_RESET) {
|
||||
if ((preserved_lapic_mode & APICBASE_ENABLED) != 0U ) {
|
||||
/* Per SDM 10.12.5.1 vol.3, need to preserve lapic mode after INIT */
|
||||
vlapic->msr_apicbase |= preserved_lapic_mode;
|
||||
}
|
||||
} else {
|
||||
/* Upon reset, vlapic is set to xAPIC mode. */
|
||||
vlapic->msr_apicbase |= APICBASE_XAPIC;
|
||||
}
|
||||
|
||||
lapic = &(vlapic->apic_page);
|
||||
(void)memset((void *)lapic, 0U, sizeof(struct lapic_regs));
|
||||
(void)memset((void *)&(vlapic->pir_desc), 0U, sizeof(vlapic->pir_desc));
|
||||
|
||||
lapic->id.v = vlapic_build_id(vlapic);
|
||||
if (mode == INIT_RESET) {
|
||||
if ((preserved_lapic_mode & APICBASE_ENABLED) != 0U ) {
|
||||
/* the local APIC ID register should be preserved in XAPIC or X2APIC mode */
|
||||
lapic->id.v = preserved_apic_id;
|
||||
}
|
||||
} else {
|
||||
lapic->id.v = vlapic_build_id(vlapic);
|
||||
}
|
||||
lapic->version.v = VLAPIC_VERSION;
|
||||
lapic->version.v |= (VLAPIC_MAXLVT_INDEX << MAXLVTSHIFT);
|
||||
lapic->dfr.v = 0xffffffffU;
|
||||
@ -1779,7 +1794,8 @@ int32_t vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new)
|
||||
if ((new & APICBASE_LAPIC_MODE) ==
|
||||
(APICBASE_XAPIC | APICBASE_X2APIC)) {
|
||||
if (is_lapic_pt_configured(vcpu->vm)) {
|
||||
vlapic_reset(vlapic, &ptapic_ops);
|
||||
/* vlapic need to be reset to make sure it is in correct state */
|
||||
vlapic_reset(vlapic, &ptapic_ops, SOFTWARE_RESET);
|
||||
}
|
||||
vlapic->msr_apicbase = new;
|
||||
vlapic_build_x2apic_id(vlapic);
|
||||
|
@ -106,6 +106,7 @@ struct acrn_apicv_ops {
|
||||
bool (*x2apic_write_msr_may_valid)(uint32_t offset);
|
||||
};
|
||||
|
||||
enum reset_mode;
|
||||
extern const struct acrn_apicv_ops *apicv_ops;
|
||||
void vlapic_set_apicv_ops(void);
|
||||
|
||||
@ -194,7 +195,7 @@ void vlapic_free(struct acrn_vcpu *vcpu);
|
||||
* @pre vlapic->vcpu->vcpu_id < MAX_VCPUS_PER_VM
|
||||
*/
|
||||
void vlapic_init(struct acrn_vlapic *vlapic);
|
||||
void vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops);
|
||||
void vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops, enum reset_mode mode);
|
||||
void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs);
|
||||
uint64_t vlapic_apicv_get_apic_access_addr(void);
|
||||
uint64_t vlapic_apicv_get_apic_page_addr(struct acrn_vlapic *vlapic);
|
||||
|
Loading…
Reference in New Issue
Block a user