diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 2f9fda5c4..4e25ac827 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -285,6 +285,28 @@ void resume_vm(struct vm *vm) vm->state = VM_STARTED; } +/* Resume vm from S3 state + * + * To resume vm after guest enter S3 state: + * - reset BSP + * - BSP will be put to real mode with entry set as wakeup_vec + * - init_vmcs BSP. We could call init_vmcs here because we know current + * pcpu is mapped to BSP of vm. + */ +void resume_vm_from_s3(struct vm *vm, uint32_t wakeup_vec) +{ + struct vcpu *bsp = vcpu_from_vid(vm, 0); + + vm->state = VM_STARTED; + + reset_vcpu(bsp); + bsp->entry_addr = (void *)(uint64_t)wakeup_vec; + bsp->arch_vcpu.cpu_mode = CPU_MODE_REAL; + init_vmcs(bsp); + + schedule_vcpu(bsp); +} + /* Create vm/vcpu for vm0 */ int prepare_vm0(void) { diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index 0cf95a63b..a01b83ee0 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -72,6 +72,7 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, { uint32_t pcpu_id; uint64_t pmain_entry_saved; + uint32_t guest_wakeup_vec32; uint64_t *pmain_entry; if (vm->pm.sx_state_data == NULL) { @@ -83,6 +84,15 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, pcpu_id = get_cpu_id(); + /* Save the wakeup vec set by guest. Will return to guest + * with this wakeup vec as entry. + */ + guest_wakeup_vec32 = *vm->pm.sx_state_data->wake_vector_32; + + /* set ACRN wakeup vec instead */ + *vm->pm.sx_state_data->wake_vector_32 = + (uint32_t) trampoline_start16_paddr; + /* offline all APs */ stop_cpus(); @@ -128,5 +138,8 @@ int enter_s3(struct vm *vm, uint32_t pm1a_cnt_val, /* online all APs again */ start_cpus(); + /* jump back to vm */ + resume_vm_from_s3(vm, guest_wakeup_vec32); + return 0; } diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index b9471a863..9b649ff63 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -172,6 +172,7 @@ struct vm_description { int shutdown_vm(struct vm *vm); void pause_vm(struct vm *vm); void resume_vm(struct vm *vm); +void resume_vm_from_s3(struct vm *vm, uint32_t wakeup_vec); int start_vm(struct vm *vm); int create_vm(struct vm_description *vm_desc, struct vm **vm); int prepare_vm0(void);