hv: shutdown guest VM upon triple fault exceptions
This patch implements triple fault vmexit handler and base on VM types: - post-launched VMs: shutdown_target_vm() injects S5 PIO write to request DM to shut down the target VM. - pre-launched VMs: shut down the guest. - SOS: similarly, but shut down all the non real-time post-launched VMs that depend to SOS before shutting down SOS. Tracked-On: #2700 Signed-off-by: Zide Chen <zide.chen@intel.com> Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
9aa3fe646b
commit
26f08680eb
|
@ -10,6 +10,55 @@
|
|||
#include <per_cpu.h>
|
||||
#include <vm_reset.h>
|
||||
|
||||
/**
|
||||
* @pre vm != NULL
|
||||
*/
|
||||
void triple_fault_shutdown_vm(struct acrn_vm *vm)
|
||||
{
|
||||
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BOOT_CPU_ID);
|
||||
|
||||
if (is_postlaunched_vm(vm)) {
|
||||
struct io_request *io_req = &vcpu->req;
|
||||
|
||||
/*
|
||||
* Hypervisor sets VM_POWERING_OFF to authenticate that the reboot request is
|
||||
* actually from the guest itself, not from external entities. (for example acrn-dm)
|
||||
*/
|
||||
if (is_rt_vm(vm)) {
|
||||
vm->state = VM_POWERING_OFF;
|
||||
}
|
||||
|
||||
/* Device model emulates PM1A for post-launched VMs */
|
||||
io_req->io_type = REQ_PORTIO;
|
||||
io_req->reqs.pio.direction = REQUEST_WRITE;
|
||||
io_req->reqs.pio.address = VIRTUAL_PM1A_CNT_ADDR;
|
||||
io_req->reqs.pio.size = 2ULL;
|
||||
io_req->reqs.pio.value = (VIRTUAL_PM1A_SLP_EN | (5U << 10U));
|
||||
|
||||
/* Inject pm1a S5 request to SOS to shut down the guest */
|
||||
(void)emulate_io(vcpu, io_req);
|
||||
} else {
|
||||
if (is_sos_vm(vm)) {
|
||||
uint16_t vm_id;
|
||||
|
||||
/* Shut down all non real time post-launched VMs */
|
||||
for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
|
||||
struct acrn_vm *pl_vm = get_vm_from_vmid(vm_id);
|
||||
|
||||
if (!is_poweroff_vm(pl_vm) && is_postlaunched_vm(pl_vm) && !is_rt_vm(pl_vm)) {
|
||||
(void)shutdown_vm(pl_vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Either SOS or pre-launched VMs */
|
||||
pause_vm(vm);
|
||||
|
||||
per_cpu(shutdown_vm_id, vcpu->pcpu_id) = vm->vm_id;
|
||||
make_shutdown_vm_request(vcpu->pcpu_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vcpu != NULL && vm != NULL
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <vcpu.h>
|
||||
#include <vm.h>
|
||||
#include <vmexit.h>
|
||||
#include <vm_reset.h>
|
||||
#include <vmx_io.h>
|
||||
#include <ept.h>
|
||||
#include <vtd.h>
|
||||
|
@ -24,6 +25,7 @@
|
|||
*/
|
||||
#define NR_VMX_EXIT_REASONS 65U
|
||||
|
||||
static int32_t triple_fault_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t unhandled_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t xsetbv_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
static int32_t wbinvd_vmexit_handler(struct acrn_vcpu *vcpu);
|
||||
|
@ -37,7 +39,7 @@ static const struct vm_exit_dispatch dispatch_table[NR_VMX_EXIT_REASONS] = {
|
|||
[VMX_EXIT_REASON_EXTERNAL_INTERRUPT] = {
|
||||
.handler = external_interrupt_vmexit_handler},
|
||||
[VMX_EXIT_REASON_TRIPLE_FAULT] = {
|
||||
.handler = unhandled_vmexit_handler},
|
||||
.handler = triple_fault_vmexit_handler},
|
||||
[VMX_EXIT_REASON_INIT_SIGNAL] = {
|
||||
.handler = init_signal_vmexit_handler},
|
||||
[VMX_EXIT_REASON_STARTUP_IPI] = {
|
||||
|
@ -249,6 +251,15 @@ static int32_t unhandled_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int32_t triple_fault_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
pr_fatal("VM%d: triple fault @ guest RIP 0x%016llx, exit qualification: 0x%016llx",
|
||||
vcpu->vm->vm_id, exec_vmread(VMX_GUEST_RIP), exec_vmread(VMX_EXIT_QUALIFICATION));
|
||||
triple_fault_shutdown_vm(vcpu->vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t cpuid_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
{
|
||||
uint64_t rax, rbx, rcx, rdx;
|
||||
|
|
|
@ -9,5 +9,6 @@
|
|||
|
||||
void register_reset_port_handler(struct acrn_vm *vm);
|
||||
void shutdown_vm_from_idle(uint16_t pcpu_id);
|
||||
void triple_fault_shutdown_vm(struct acrn_vm *vm);
|
||||
|
||||
#endif /* VM_RESET_H_ */
|
||||
|
|
Loading…
Reference in New Issue