Skip to content

Commit e5f733f

Browse files
peterfangwenlingz
authored andcommitted
hv: vm: properly reset pCPUs with LAPIC PT enabled during VM shutdown/reset
When a VM is configured with LAPIC PT mode and its vCPU is in x2APIC mode, the corresponding pCPU needs to be reset during VM shutdown/reset as its physical LAPIC was used by its guest This commit fixes an issue where this reset never happens. is_lapic_pt_enabled() needs to be called before reset_vcpu() to be able to correctly reflect a vCPU's APIC mode. A vCPU with LAPIC PT mode but in xAPIC mode does not require such reset, since its physical LAPIC was not touched by its guest directly. Tracked-On: #3708 Signed-off-by: Peter Fang <peter.fang@intel.com> Reviewed-by: Eddie Dong <eddie.dong@intel.com> Reviewed-by: Jack Ren <jack.ren@intel.com>
1 parent bad7532 commit e5f733f

File tree

1 file changed

+39
-11
lines changed
  • hypervisor/arch/x86/guest

1 file changed

+39
-11
lines changed

hypervisor/arch/x86/guest/vm.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,8 @@ int32_t create_vm(uint16_t vm_id, struct acrn_vm_config *vm_config, struct acrn_
545545
int32_t shutdown_vm(struct acrn_vm *vm)
546546
{
547547
uint16_t i;
548+
uint16_t this_pcpu_id = get_pcpu_id();
549+
bool offline_pcpu;
548550
uint64_t mask = 0UL;
549551
struct acrn_vcpu *vcpu = NULL;
550552
struct acrn_vm_config *vm_config = NULL;
@@ -557,18 +559,26 @@ int32_t shutdown_vm(struct acrn_vm *vm)
557559
vm->state = VM_POWERED_OFF;
558560

559561
foreach_vcpu(i, vm, vcpu) {
562+
offline_pcpu = is_lapic_pt_enabled(vcpu);
560563
reset_vcpu(vcpu);
561564
offline_vcpu(vcpu);
562565

563-
if (is_lapic_pt_enabled(vcpu)) {
564-
bitmap_set_nolock(vcpu->pcpu_id, &mask);
566+
if (offline_pcpu) {
567+
/*
568+
* If the current pcpu needs to offline itself,
569+
* it will be done after shutdown_vm() completes
570+
* in the idle thread.
571+
*/
572+
if (this_pcpu_id != vcpu->pcpu_id) {
573+
bitmap_set_nolock(vcpu->pcpu_id, &mask);
574+
}
565575
make_pcpu_offline(vcpu->pcpu_id);
566576
}
567577
}
568578

569579
wait_pcpus_offline(mask);
570580

571-
if (is_lapic_pt_configured(vm) && !start_pcpus(mask)) {
581+
if (mask != 0UL && !start_pcpus(mask)) {
572582
pr_fatal("Failed to start all cpus in mask(0x%llx)", mask);
573583
ret = -ETIMEDOUT;
574584
}
@@ -591,10 +601,8 @@ int32_t shutdown_vm(struct acrn_vm *vm)
591601

592602
/* Free EPT allocated resources assigned to VM */
593603
destroy_ept(vm);
594-
595-
ret = 0;
596604
} else {
597-
ret = -EINVAL;
605+
ret = -EINVAL;
598606
}
599607

600608
/* Return status to caller */
@@ -621,17 +629,39 @@ void start_vm(struct acrn_vm *vm)
621629
int32_t reset_vm(struct acrn_vm *vm)
622630
{
623631
uint16_t i;
632+
uint16_t this_pcpu_id = get_pcpu_id();
633+
bool offline_pcpu;
634+
uint64_t mask = 0UL;
624635
struct acrn_vcpu *vcpu = NULL;
625-
int32_t ret;
636+
int32_t ret = 0;
626637

627638
if (vm->state == VM_PAUSED) {
628639
foreach_vcpu(i, vm, vcpu) {
640+
offline_pcpu = is_lapic_pt_enabled(vcpu);
629641
reset_vcpu(vcpu);
642+
643+
if (offline_pcpu) {
644+
if (this_pcpu_id != vcpu->pcpu_id) {
645+
bitmap_set_nolock(vcpu->pcpu_id, &mask);
646+
make_pcpu_offline(vcpu->pcpu_id);
647+
} else {
648+
pr_warn("%s: cannot offline self(%u)",
649+
__func__, this_pcpu_id);
650+
ret = -EINVAL;
651+
}
652+
}
653+
}
654+
655+
wait_pcpus_offline(mask);
656+
657+
if (mask != 0UL && !start_pcpus(mask)) {
658+
pr_fatal("Failed to start all cpus in mask(0x%llx)", mask);
659+
ret = -ETIMEDOUT;
630660
}
661+
631662
/*
632663
* Set VM vLAPIC state to VM_VLAPIC_XAPIC
633664
*/
634-
635665
vm->arch_vm.vlapic_state = VM_VLAPIC_XAPIC;
636666

637667
if (is_sos_vm(vm)) {
@@ -643,10 +673,8 @@ int32_t reset_vm(struct acrn_vm *vm)
643673
destroy_secure_world(vm, false);
644674
vm->sworld_control.flag.active = 0UL;
645675
vm->state = VM_CREATED;
646-
647-
ret = 0;
648676
} else {
649-
ret = -1;
677+
ret = -EINVAL;
650678
}
651679

652680
return ret;

0 commit comments

Comments
 (0)