mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-29 22:47:21 +00:00
hv: distinguish between LAPIC_PASSTHROUGH configured vs enabled
ACRN supports LAPIC emulation for guests using x86 APICv. When guest OS/BIOS switches from xAPIC to x2APIC mode of operation, ACRN also supports switching froom LAPIC emulation to LAPIC passthrough to guest. User/developer needs to configure GUEST_FLAG_LAPIC_PASSTHROUGH for guest_flags in the corresponding VM's config for ACRN to enable LAPIC passthrough. This patch does the following 1)Fixes a bug in the abovementioned feature. For a guest that is configured with GUEST_FLAG_LAPIC_PASSTHROUGH, during the time period guest is using xAPIC mode of LAPIC, virtual interrupts are not delivered. This can be manifested as guest hang when it does not receive virtual timer interrupts. 2)ACRN exposes physical topology via CPUID leaf 0xb to LAPIC PT VMs. This patch removes that condition and exposes virtual topology via CPUID leaf 0xb. Tracked-On: #3136 Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
cb6a3e8f08
commit
536c69b9ff
@ -639,7 +639,7 @@ int32_t ptirq_msix_remap(struct acrn_vm *vm, uint16_t virt_bdf, uint16_t phys_bd
|
||||
info->pmsi_data.full = 0U;
|
||||
} else {
|
||||
/* build physical config MSI, update to info->pmsi_xxx */
|
||||
if (is_lapic_pt(vm)) {
|
||||
if (is_lapic_pt_enabled(vm)) {
|
||||
/* for vm with lapic-pt, keep vector from guest */
|
||||
ptirq_build_physical_msi(vm, info, entry, (uint32_t)info->vmsi_data.bits.vector);
|
||||
} else {
|
||||
|
@ -595,7 +595,7 @@ void pause_vcpu(struct acrn_vcpu *vcpu, enum vcpu_state new_state)
|
||||
if (atomic_load32(&vcpu->running) == 1U) {
|
||||
remove_from_cpu_runqueue(&vcpu->sched_obj, vcpu->pcpu_id);
|
||||
|
||||
if (is_lapic_pt(vcpu->vm)) {
|
||||
if (is_lapic_pt_enabled(vcpu->vm)) {
|
||||
make_reschedule_request(vcpu->pcpu_id, DEL_MODE_INIT);
|
||||
} else {
|
||||
make_reschedule_request(vcpu->pcpu_id, DEL_MODE_IPI);
|
||||
|
@ -365,10 +365,7 @@ static void guest_cpuid_0bh(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
|
||||
uint32_t subleaf = *ecx;
|
||||
|
||||
/* Patching X2APIC */
|
||||
if (is_lapic_pt(vcpu->vm)) {
|
||||
/* for VM with LAPIC_PT, eg. PRE_LAUNCHED_VM or POST_LAUNCHED_VM with LAPIC_PT*/
|
||||
cpuid_subleaf(leaf, subleaf, eax, ebx, ecx, edx);
|
||||
} else if (is_sos_vm(vcpu->vm)) {
|
||||
if (is_sos_vm(vcpu->vm)) {
|
||||
cpuid_subleaf(leaf, subleaf, eax, ebx, ecx, edx);
|
||||
} else {
|
||||
*ecx = subleaf & 0xFFU;
|
||||
|
@ -1768,7 +1768,7 @@ int32_t vlapic_set_apicbase(struct acrn_vlapic *vlapic, uint64_t new)
|
||||
changed = vlapic->msr_apicbase ^ new;
|
||||
|
||||
if ((changed == APICBASE_X2APIC) && ((new & APICBASE_X2APIC) == APICBASE_X2APIC)) {
|
||||
vlapic->msr_apicbase = new;
|
||||
atomic_set64(&vlapic->msr_apicbase, changed);
|
||||
vlapic_build_x2apic_id(vlapic);
|
||||
switch_apicv_mode_x2apic(vlapic->vcpu);
|
||||
ret = 0;
|
||||
@ -2075,7 +2075,7 @@ int32_t vlapic_x2apic_read(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t *val)
|
||||
*/
|
||||
vlapic = vcpu_vlapic(vcpu);
|
||||
if (is_x2apic_enabled(vlapic)) {
|
||||
if (is_lapic_pt(vcpu->vm)) {
|
||||
if (is_lapic_pt_configured(vcpu->vm)) {
|
||||
switch (msr) {
|
||||
case MSR_IA32_EXT_APIC_LDR:
|
||||
case MSR_IA32_EXT_XAPICID:
|
||||
@ -2109,7 +2109,7 @@ int32_t vlapic_x2apic_write(struct acrn_vcpu *vcpu, uint32_t msr, uint64_t val)
|
||||
*/
|
||||
vlapic = vcpu_vlapic(vcpu);
|
||||
if (is_x2apic_enabled(vlapic)) {
|
||||
if (is_lapic_pt(vcpu->vm)) {
|
||||
if (is_lapic_pt_configured(vcpu->vm)) {
|
||||
switch (msr) {
|
||||
case MSR_IA32_EXT_APIC_ICR:
|
||||
error = vlapic_x2apic_pt_icr_access(vcpu->vm, val);
|
||||
@ -2575,3 +2575,14 @@ void vlapic_set_apicv_ops(void)
|
||||
apicv_ops = &apicv_basic_ops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
* @pre vm->vmid < CONFIG_MAX_VM_NUM
|
||||
*/
|
||||
bool is_lapic_pt_enabled(struct acrn_vm *vm)
|
||||
{
|
||||
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, 0U);
|
||||
|
||||
return ((is_x2apic_enabled(vcpu_vlapic(vcpu))) && (is_lapic_pt_configured(vm)));
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ bool is_prelaunched_vm(const struct acrn_vm *vm)
|
||||
/**
|
||||
* @pre vm != NULL && vm_config != NULL && vm->vmid < CONFIG_MAX_VM_NUM
|
||||
*/
|
||||
bool is_lapic_pt(const struct acrn_vm *vm)
|
||||
bool is_lapic_pt_configured(const struct acrn_vm *vm)
|
||||
{
|
||||
struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
|
||||
|
||||
@ -482,7 +482,7 @@ int32_t shutdown_vm(struct acrn_vm *vm)
|
||||
reset_vcpu(vcpu);
|
||||
offline_vcpu(vcpu);
|
||||
|
||||
if (is_lapic_pt(vm)) {
|
||||
if (is_lapic_pt_enabled(vm)) {
|
||||
bitmap_set_nolock(vcpu->pcpu_id, &mask);
|
||||
make_pcpu_offline(vcpu->pcpu_id);
|
||||
}
|
||||
@ -490,7 +490,7 @@ int32_t shutdown_vm(struct acrn_vm *vm)
|
||||
|
||||
wait_pcpus_offline(mask);
|
||||
|
||||
if (is_lapic_pt(vm) && !start_pcpus(mask)) {
|
||||
if (is_lapic_pt_enabled(vm) && !start_pcpus(mask)) {
|
||||
pr_fatal("Failed to start all cpus in mask(0x%llx)", mask);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
@ -575,7 +575,7 @@ void init_vmcs(struct acrn_vcpu *vcpu)
|
||||
void switch_apicv_mode_x2apic(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
uint32_t value32;
|
||||
if (is_lapic_pt(vcpu->vm)) {
|
||||
if (is_lapic_pt_configured(vcpu->vm)) {
|
||||
dev_dbg(ACRN_DBG_LAPICPT, "%s: switching to x2apic and passthru", __func__);
|
||||
/*
|
||||
* Disable external interrupt exiting and irq ack
|
||||
|
@ -27,7 +27,7 @@ void vcpu_thread(struct sched_object *obj)
|
||||
init_vmcs(vcpu);
|
||||
}
|
||||
|
||||
if (!is_lapic_pt(vcpu->vm)) {
|
||||
if (!is_lapic_pt_enabled(vcpu->vm)) {
|
||||
/* handle pending softirq when irq enable*/
|
||||
do_softirq();
|
||||
CPU_IRQ_DISABLE();
|
||||
@ -64,7 +64,7 @@ void vcpu_thread(struct sched_object *obj)
|
||||
|
||||
profiling_pre_vmexit_handler(vcpu);
|
||||
|
||||
if (!is_lapic_pt(vcpu->vm)) {
|
||||
if (!is_lapic_pt_enabled(vcpu->vm)) {
|
||||
CPU_IRQ_ENABLE();
|
||||
}
|
||||
/* Dispatch handler */
|
||||
|
@ -479,7 +479,7 @@ int32_t hcall_inject_msi(struct acrn_vm *vm, uint16_t vmid, uint64_t param)
|
||||
pr_err("%s: Unable copy param to vm\n", __func__);
|
||||
} else {
|
||||
/* For target cpu with lapic pt, send ipi instead of injection via vlapic */
|
||||
if (is_lapic_pt(target_vm)) {
|
||||
if (is_lapic_pt_enabled(target_vm)) {
|
||||
inject_msi_lapic_pt(target_vm, &msi);
|
||||
ret = 0;
|
||||
} else {
|
||||
|
@ -210,7 +210,7 @@ void vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
|
||||
uint32_t dest, bool phys, bool lowprio);
|
||||
void vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
|
||||
uint32_t dest, bool phys);
|
||||
|
||||
bool is_lapic_pt_enabled(struct acrn_vm *vm);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -216,7 +216,7 @@ extern vm_sw_loader_t vm_sw_loader;
|
||||
|
||||
void vrtc_init(struct acrn_vm *vm);
|
||||
|
||||
bool is_lapic_pt(const struct acrn_vm *vm);
|
||||
bool is_lapic_pt_configured(const struct acrn_vm *vm);
|
||||
bool is_rt_vm(const struct acrn_vm *vm);
|
||||
bool vm_hide_mtrr(const struct acrn_vm *vm);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user