hv: add vm restart API

And export the API to DM. DM will do system reboot/S3 resume based
on this API.

Also add the pre-assumption description for some vm APIs.

Signed-off-by: Yin Fengwei <fengwei.yin@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Yin Fengwei 2018-05-11 19:19:27 +08:00 committed by lijinxia
parent a4eebb0ef8
commit f576f97ea8
6 changed files with 72 additions and 4 deletions

View File

@ -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)
{

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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
*

View File

@ -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