Skip to content

Commit 382acfa

Browse files
KaigeFuacrnsi
authored andcommitted
HV: Using INIT to kick vCPUs off when RTVM poweroff by itself
When RTVM is trying to poweroff by itself, we use INIT to kick vCPUs off the non-root mode. For RTVM, only if vm state equal VM_POWERING_OFF, we take action to pause the vCPUs with INIT signal. Otherwise, we will reject the pause request. Tracked-On: #2865 Signed-off-by: Kaige Fu <kaige.fu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent 2771b46 commit 382acfa

File tree

3 files changed

+41
-5
lines changed

3 files changed

+41
-5
lines changed

hypervisor/arch/x86/guest/vcpu.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,13 @@ void pause_vcpu(struct acrn_vcpu *vcpu, enum vcpu_state new_state)
598598

599599
if (atomic_load32(&vcpu->running) == 1U) {
600600
remove_from_cpu_runqueue(&vcpu->sched_obj, vcpu->pcpu_id);
601-
make_reschedule_request(vcpu->pcpu_id, DEL_MODE_IPI);
601+
602+
if (is_lapic_pt(vcpu->vm)) {
603+
make_reschedule_request(vcpu->pcpu_id, DEL_MODE_INIT);
604+
} else {
605+
make_reschedule_request(vcpu->pcpu_id, DEL_MODE_IPI);
606+
}
607+
602608
release_schedule_lock(vcpu->pcpu_id);
603609

604610
if (vcpu->pcpu_id != pcpu_id) {

hypervisor/arch/x86/guest/vm.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,21 @@ void pause_vm(struct acrn_vm *vm)
547547
struct acrn_vcpu *vcpu = NULL;
548548

549549
if (vm->state != VM_PAUSED) {
550-
vm->state = VM_PAUSED;
550+
if (is_rt_vm(vm)) {
551+
/* Only when RTVM is powering off by itself, we can pause vcpu */
552+
if (vm->state == VM_POWERING_OFF) {
553+
foreach_vcpu(i, vm, vcpu) {
554+
pause_vcpu(vcpu, VCPU_ZOMBIE);
555+
}
551556

552-
foreach_vcpu(i, vm, vcpu) {
553-
pause_vcpu(vcpu, VCPU_ZOMBIE);
557+
vm->state = VM_PAUSED;
558+
}
559+
} else {
560+
foreach_vcpu(i, vm, vcpu) {
561+
pause_vcpu(vcpu, VCPU_ZOMBIE);
562+
}
563+
564+
vm->state = VM_PAUSED;
554565
}
555566
}
556567
}

hypervisor/arch/x86/guest/vmexit.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static int32_t unhandled_vmexit_handler(struct acrn_vcpu *vcpu);
2828
static int32_t xsetbv_vmexit_handler(struct acrn_vcpu *vcpu);
2929
static int32_t wbinvd_vmexit_handler(struct acrn_vcpu *vcpu);
3030
static int32_t undefined_vmexit_handler(struct acrn_vcpu *vcpu);
31+
static int32_t init_signal_vmexit_handler(__unused struct acrn_vcpu *vcpu);
3132

3233
/* VM Dispatch table for Exit condition handling */
3334
static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
@@ -38,7 +39,7 @@ static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
3839
[VMX_EXIT_REASON_TRIPLE_FAULT] = {
3940
.handler = unhandled_vmexit_handler},
4041
[VMX_EXIT_REASON_INIT_SIGNAL] = {
41-
.handler = unhandled_vmexit_handler},
42+
.handler = init_signal_vmexit_handler},
4243
[VMX_EXIT_REASON_STARTUP_IPI] = {
4344
.handler = unhandled_vmexit_handler},
4445
[VMX_EXIT_REASON_IO_SMI] = {
@@ -343,3 +344,21 @@ static int32_t undefined_vmexit_handler(struct acrn_vcpu *vcpu)
343344
vcpu_inject_ud(vcpu);
344345
return 0;
345346
}
347+
348+
/*
349+
* This handler is only triggered by INIT signal when poweroff from inside of RTVM
350+
*/
351+
static int32_t init_signal_vmexit_handler(__unused struct acrn_vcpu *vcpu)
352+
{
353+
/*
354+
* Intel SDM Volume 3, 25.2:
355+
* INIT signals. INIT signals cause VM exits. A logical processer performs none
356+
* of the operations normally associated with these events. Such exits do not modify
357+
* register state or clear pending events as they would outside of VMX operation (If
358+
* a logical processor is the wait-for-SIPI state, INIT signals are blocked. They do
359+
* not cause VM exits in this case).
360+
*
361+
* So, it is safe to ignore the signal and reture here.
362+
*/
363+
return 0;
364+
}

0 commit comments

Comments
 (0)