mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-23 05:57:33 +00:00
hv: fix SOS vapic_id assignment issue
Currently vlapic_build_id() uses vcpu_id to retrieve the lapic_id per_cpu variable: vlapic_id = per_cpu(lapic_id, vcpu->vcpu_id); SOS vcpu_id may not equal to pcpu_id, and in that case it runs into problems. For example, if any pre-launched VMs are launched on PCPUs whose IDs are smaller than any PCPU IDs that are used by SOS. This patch fixes the issue and simplify the code to create or get vapic_id by: - assign vapic_id in create_vlapic(), which now takes pcpu_id as input argument, and save it in the new field: vlapic->vapic_id, which will never be changed. - simplify vlapic_get_apicid() by returning te saved vapid_id directly. - remove vlapic_build_id(). - vlapic_init() is only called once, merge it into vlapic_create(). Tracked-On: #4268 Signed-off-by: Zide Chen <zide.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
00ad3863a1
commit
6040d8f6a2
@ -505,7 +505,7 @@ int32_t create_vcpu(uint16_t pcpu_id, struct acrn_vm *vm, struct acrn_vcpu **rtn
|
|||||||
vcpu->arch.pid.control.bits.ndst = per_cpu(lapic_id, pcpu_id);
|
vcpu->arch.pid.control.bits.ndst = per_cpu(lapic_id, pcpu_id);
|
||||||
|
|
||||||
/* Create per vcpu vlapic */
|
/* Create per vcpu vlapic */
|
||||||
vlapic_create(vcpu);
|
vlapic_create(vcpu, pcpu_id);
|
||||||
|
|
||||||
if (!vm_hide_mtrr(vm)) {
|
if (!vm_hide_mtrr(vm)) {
|
||||||
init_vmtrr(vcpu);
|
init_vmtrr(vcpu);
|
||||||
|
@ -135,8 +135,7 @@ static uint16_t vm_apicid2vcpu_id(struct acrn_vm *vm, uint32_t lapicid)
|
|||||||
uint16_t cpu_id = INVALID_CPU_ID;
|
uint16_t cpu_id = INVALID_CPU_ID;
|
||||||
|
|
||||||
foreach_vcpu(i, vm, vcpu) {
|
foreach_vcpu(i, vm, vcpu) {
|
||||||
const struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
|
if (vcpu_vlapic(vcpu)->vapic_id == lapicid) {
|
||||||
if (vlapic_get_apicid(vlapic) == lapicid) {
|
|
||||||
cpu_id = vcpu->vcpu_id;
|
cpu_id = vcpu->vcpu_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -150,57 +149,13 @@ static uint16_t vm_apicid2vcpu_id(struct acrn_vm *vm, uint32_t lapicid)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @pre vlapic != NULL
|
|
||||||
*/
|
|
||||||
uint32_t
|
|
||||||
vlapic_get_apicid(const struct acrn_vlapic *vlapic)
|
|
||||||
{
|
|
||||||
uint32_t apicid;
|
|
||||||
if (is_x2apic_enabled(vlapic)) {
|
|
||||||
apicid = vlapic->apic_page.id.v;
|
|
||||||
} else {
|
|
||||||
apicid = (vlapic->apic_page.id.v) >> APIC_ID_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apicid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
vlapic_build_id(const struct acrn_vlapic *vlapic)
|
|
||||||
{
|
|
||||||
const struct acrn_vcpu *vcpu = vlapic2vcpu(vlapic);
|
|
||||||
uint32_t vlapic_id, lapic_regs_id;
|
|
||||||
|
|
||||||
if (is_sos_vm(vcpu->vm)) {
|
|
||||||
/*
|
|
||||||
* For SOS_VM type, pLAPIC IDs need to be used because
|
|
||||||
* host ACPI tables are passthru to SOS.
|
|
||||||
* Get APIC ID sequence format from cpu_storage
|
|
||||||
*/
|
|
||||||
vlapic_id = per_cpu(lapic_id, vcpu->vcpu_id);
|
|
||||||
} else {
|
|
||||||
vlapic_id = (uint32_t)vcpu->vcpu_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_x2apic_enabled(vlapic)) {
|
|
||||||
lapic_regs_id = vlapic_id;
|
|
||||||
} else {
|
|
||||||
lapic_regs_id = vlapic_id << APIC_ID_SHIFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_dbg(DBG_LEVEL_VLAPIC, "vlapic APIC PAGE ID : 0x%08x", lapic_regs_id);
|
|
||||||
|
|
||||||
return lapic_regs_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void vlapic_build_x2apic_id(struct acrn_vlapic *vlapic)
|
static inline void vlapic_build_x2apic_id(struct acrn_vlapic *vlapic)
|
||||||
{
|
{
|
||||||
struct lapic_regs *lapic;
|
struct lapic_regs *lapic;
|
||||||
uint32_t logical_id, cluster_id;
|
uint32_t logical_id, cluster_id;
|
||||||
|
|
||||||
lapic = &(vlapic->apic_page);
|
lapic = &(vlapic->apic_page);
|
||||||
lapic->id.v = vlapic_build_id(vlapic);
|
lapic->id.v = vlapic->vapic_id;
|
||||||
logical_id = lapic->id.v & LOGICAL_ID_MASK;
|
logical_id = lapic->id.v & LOGICAL_ID_MASK;
|
||||||
cluster_id = (lapic->id.v & CLUSTER_ID_MASK) >> 4U;
|
cluster_id = (lapic->id.v & CLUSTER_ID_MASK) >> 4U;
|
||||||
lapic->ldr.v = (cluster_id << 16U) | (1U << logical_id);
|
lapic->ldr.v = (cluster_id << 16U) | (1U << logical_id);
|
||||||
@ -1667,7 +1622,10 @@ vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops, enum
|
|||||||
lapic->id.v = preserved_apic_id;
|
lapic->id.v = preserved_apic_id;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lapic->id.v = vlapic_build_id(vlapic);
|
lapic->id.v = vlapic->vapic_id;
|
||||||
|
if (!is_x2apic_enabled(vlapic)) {
|
||||||
|
lapic->id.v <<= APIC_ID_SHIFT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lapic->version.v = VLAPIC_VERSION;
|
lapic->version.v = VLAPIC_VERSION;
|
||||||
lapic->version.v |= (VLAPIC_MAXLVT_INDEX << MAXLVTSHIFT);
|
lapic->version.v |= (VLAPIC_MAXLVT_INDEX << MAXLVTSHIFT);
|
||||||
@ -1688,16 +1646,6 @@ vlapic_reset(struct acrn_vlapic *vlapic, const struct acrn_apicv_ops *ops, enum
|
|||||||
vlapic->ops = ops;
|
vlapic->ops = ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @pre vlapic2vcpu(vlapic)->vm != NULL
|
|
||||||
* @pre vlapic2vcpu(vlapic)->vcpu_id < MAX_VCPUS_PER_VM
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
vlapic_init(struct acrn_vlapic *vlapic)
|
|
||||||
{
|
|
||||||
vlapic_init_timer(vlapic);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs)
|
void vlapic_restore(struct acrn_vlapic *vlapic, const struct lapic_regs *regs)
|
||||||
{
|
{
|
||||||
struct lapic_regs *lapic;
|
struct lapic_regs *lapic;
|
||||||
@ -2174,8 +2122,13 @@ int32_t vlapic_x2apic_write(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vlapic_create(struct acrn_vcpu *vcpu)
|
/**
|
||||||
|
* @pre vcpu != NULL
|
||||||
|
*/
|
||||||
|
void vlapic_create(struct acrn_vcpu *vcpu, uint16_t pcpu_id)
|
||||||
{
|
{
|
||||||
|
struct acrn_vlapic *vlapic = vcpu_vlapic(vcpu);
|
||||||
|
|
||||||
if (is_vcpu_bsp(vcpu)) {
|
if (is_vcpu_bsp(vcpu)) {
|
||||||
uint64_t *pml4_page =
|
uint64_t *pml4_page =
|
||||||
(uint64_t *)vcpu->vm->arch_vm.nworld_eptp;
|
(uint64_t *)vcpu->vm->arch_vm.nworld_eptp;
|
||||||
@ -2191,7 +2144,20 @@ void vlapic_create(struct acrn_vcpu *vcpu)
|
|||||||
EPT_WR | EPT_RD | EPT_UNCACHED);
|
EPT_WR | EPT_RD | EPT_UNCACHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
vlapic_init(vcpu_vlapic(vcpu));
|
vlapic_init_timer(vlapic);
|
||||||
|
|
||||||
|
if (is_sos_vm(vcpu->vm)) {
|
||||||
|
/*
|
||||||
|
* For SOS_VM type, pLAPIC IDs need to be used because
|
||||||
|
* host ACPI tables are passthru to SOS.
|
||||||
|
* Get APIC ID sequence format from cpu_storage
|
||||||
|
*/
|
||||||
|
vlapic->vapic_id = per_cpu(lapic_id, pcpu_id);
|
||||||
|
} else {
|
||||||
|
vlapic->vapic_id = (uint32_t)vcpu->vcpu_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(DBG_LEVEL_VLAPIC, "vlapic APIC ID : 0x%04x", vlapic->vapic_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -61,6 +61,7 @@ struct acrn_vlapic {
|
|||||||
*/
|
*/
|
||||||
struct lapic_regs apic_page;
|
struct lapic_regs apic_page;
|
||||||
|
|
||||||
|
uint32_t vapic_id;
|
||||||
uint32_t esr_pending;
|
uint32_t esr_pending;
|
||||||
int32_t esr_firing;
|
int32_t esr_firing;
|
||||||
|
|
||||||
@ -163,17 +164,20 @@ int32_t vlapic_intr_msi(struct acrn_vm *vm, uint64_t addr, uint64_t msg);
|
|||||||
void vlapic_receive_intr(struct acrn_vm *vm, bool level, uint32_t dest,
|
void vlapic_receive_intr(struct acrn_vm *vm, bool level, uint32_t dest,
|
||||||
bool phys, uint32_t delmode, uint32_t vec, bool rh);
|
bool phys, uint32_t delmode, uint32_t vec, bool rh);
|
||||||
|
|
||||||
uint32_t vlapic_get_apicid(const struct acrn_vlapic *vlapic);
|
/**
|
||||||
void vlapic_create(struct acrn_vcpu *vcpu);
|
* @pre vlapic != NULL
|
||||||
|
*/
|
||||||
|
static inline uint32_t vlapic_get_apicid(const struct acrn_vlapic *vlapic)
|
||||||
|
{
|
||||||
|
return vlapic->vapic_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vlapic_create(struct acrn_vcpu *vcpu, uint16_t pcpu_id);
|
||||||
/*
|
/*
|
||||||
* @pre vcpu != NULL
|
* @pre vcpu != NULL
|
||||||
*/
|
*/
|
||||||
void vlapic_free(struct acrn_vcpu *vcpu);
|
void vlapic_free(struct acrn_vcpu *vcpu);
|
||||||
/**
|
|
||||||
* @pre vlapic->vm != NULL
|
|
||||||
* @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, enum reset_mode mode);
|
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);
|
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_access_addr(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user