diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index f93593cee..e4e615e16 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -289,6 +289,9 @@ int shutdown_vm(struct vm *vm) return status; } +/** + * * @pre vm != NULL + */ int start_vm(struct vm *vm) { struct vcpu *vcpu = NULL; @@ -303,9 +306,33 @@ int start_vm(struct vm *vm) return 0; } -/* - * DM only pause vm for shutdown/reboot. If we need to - * extend the pause vm for DM, this API should be extended. +/** + * * @pre vm != NULL + */ +int reset_vm(struct vm *vm) +{ + int i; + struct vcpu *vcpu = NULL; + + if (vm->state != VM_PAUSED) + return -1; + + foreach_vcpu(i, vm, vcpu) { + reset_vcpu(vcpu); + if (is_vcpu_bsp(vcpu)) + vm_sw_loader(vm, vcpu); + + vcpu->arch_vcpu.cpu_mode = CPU_MODE_REAL; + } + + vioapic_reset(vm->arch_vm.virt_ioapic); + + start_vm(vm); + return 0; +} + +/** + * * @pre vm != NULL */ void pause_vm(struct vm *vm) { @@ -323,6 +350,9 @@ void pause_vm(struct vm *vm) } } +/** + * * @pre vm != NULL + */ void resume_vm(struct vm *vm) { uint16_t i; @@ -335,13 +365,19 @@ void resume_vm(struct vm *vm) vm->state = VM_STARTED; } -/* Resume vm from S3 state +/** + * @brief 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. + * + * @vm[in] vm pointer to vm data structure + * @wakeup_vec[in] The resume address of vm + * + * @pre vm != NULL */ void resume_vm_from_s3(struct vm *vm, uint32_t wakeup_vec) { diff --git a/hypervisor/arch/x86/guest/vmcall.c b/hypervisor/arch/x86/guest/vmcall.c index 29594b7c2..0556e6ccd 100644 --- a/hypervisor/arch/x86/guest/vmcall.c +++ b/hypervisor/arch/x86/guest/vmcall.c @@ -65,6 +65,11 @@ int vmcall_vmexit_handler(struct vcpu *vcpu) ret = hcall_start_vm((uint16_t)param1); break; + case HC_RESET_VM: + /* param1: vmid */ + ret = hcall_reset_vm((uint16_t)param1); + break; + case HC_PAUSE_VM: /* param1: vmid */ ret = hcall_pause_vm((uint16_t)param1); diff --git a/hypervisor/common/hypercall.c b/hypervisor/common/hypercall.c index f5bac3b25..e4a57c0a1 100644 --- a/hypervisor/common/hypercall.c +++ b/hypervisor/common/hypercall.c @@ -266,6 +266,17 @@ int32_t hcall_create_vcpu(struct vm *vm, uint16_t vmid, uint64_t param) return ret; } +int32_t hcall_reset_vm(uint16_t vmid) +{ + struct vm *target_vm = get_vm_from_vmid(vmid); + + if ((target_vm == NULL) || is_vm0(target_vm)) + return -1; + + reset_vm(target_vm); + return 0; +} + int32_t hcall_assert_irqline(struct vm *vm, uint16_t vmid, uint64_t param) { int32_t ret = 0; diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index d3f0cab07..47992149c 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -173,6 +173,7 @@ 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 reset_vm(struct vm *vm); int create_vm(struct vm_description *vm_desc, struct vm **vm); int prepare_vm0(void); #ifdef CONFIG_VM0_DESC diff --git a/hypervisor/include/common/hypercall.h b/hypervisor/include/common/hypercall.h index 8a017ae87..210bbdd0f 100644 --- a/hypervisor/include/common/hypercall.h +++ b/hypervisor/include/common/hypercall.h @@ -76,6 +76,20 @@ int32_t hcall_create_vm(struct vm *vm, uint64_t param); */ int32_t hcall_destroy_vm(uint16_t vmid); +/** + * @brief reset virtual machine + * + * Reset a virtual machine, it will make target VM rerun from + * pre-defined entry. Comparing to start vm, this function reset + * each vcpu state and do some initialization for guest. + * The function will return -1 if the target VM does not exist. + * + * @param vmid ID of the VM + * + * @return 0 on success, non-zero on error. + */ +int32_t hcall_reset_vm(uint16_t vmid); + /** * @brief start virtual machine * diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index b442339d7..d4477d25a 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -35,6 +35,7 @@ #define HC_START_VM BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x02UL) #define HC_PAUSE_VM BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x03UL) #define HC_CREATE_VCPU BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x04UL) +#define HC_RESET_VM BASE_HC_ID(HC_ID, HC_ID_VM_BASE + 0x05UL) /* IRQ and Interrupts */ #define HC_ID_IRQ_BASE 0x20UL