dm: add S3 support for UOS
We do: - pause target vm - suspend all virtual devices - wait for resume notification - resume all virtual devices - reset target vm Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
8ee4c0b1dd
commit
a8a27d82d0
|
@ -256,6 +256,11 @@ pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||
error = vm_suspend(ctx, VM_SUSPEND_POWEROFF);
|
||||
assert(error == 0 || errno == EALREADY);
|
||||
}
|
||||
|
||||
if ((pm1_control & PM1_SLP_TYP) >> 10 == 3) {
|
||||
error = vm_suspend(ctx, VM_SUSPEND_SUSPEND);
|
||||
assert(error == 0 || errno == EALREADY);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "sw_load.h"
|
||||
#include "monitor.h"
|
||||
#include "ioc.h"
|
||||
#include "pm.h"
|
||||
|
||||
#define GUEST_NIO_PORT 0x488 /* guest upcalls via i/o port */
|
||||
|
||||
|
@ -447,6 +448,22 @@ handle_vmexit(struct vmctx *ctx, struct vhm_request *vhm_req, int vcpu)
|
|||
default:
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* If UOS is not in suspend or system reset mode, we don't
|
||||
* need to notify request done.
|
||||
*
|
||||
* But there is little difference between reset and suspend:
|
||||
* - We don't need to notify request done for reset because reset
|
||||
* doesn't care it.
|
||||
* - We don't need to notify request done for suspend because
|
||||
* guest will offline all APs, write PM register to trigger
|
||||
* PM. Then the PM register writting will trigger the latest
|
||||
* vmexit and it doesn't care request done either.
|
||||
*/
|
||||
if ((VM_SUSPEND_SYSTEM_RESET == vm_get_suspend_mode()) ||
|
||||
(VM_SUSPEND_SUSPEND == vm_get_suspend_mode()))
|
||||
return;
|
||||
|
||||
vm_notify_request_done(ctx, vcpu);
|
||||
}
|
||||
|
||||
|
@ -576,6 +593,39 @@ vm_system_reset(struct vmctx *ctx)
|
|||
vm_set_suspend_mode(VM_SUSPEND_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_suspend_resume(struct vmctx *ctx)
|
||||
{
|
||||
int vcpu_id = 0;
|
||||
|
||||
/*
|
||||
* If we get warm reboot request, we don't want to exit the
|
||||
* vcpu_loop/vm_loop/mevent_loop. So we do:
|
||||
* 1. pause VM
|
||||
* 2. notify request done to reset ioreq state in vhm
|
||||
* 3. stop vm watchdog
|
||||
* 4. wait for resume signal
|
||||
* 5. reset vm watchdog
|
||||
* 6. hypercall restart vm
|
||||
*/
|
||||
vm_pause(ctx);
|
||||
for (vcpu_id = 0; vcpu_id < 4; vcpu_id++) {
|
||||
struct vhm_request *vhm_req;
|
||||
|
||||
vhm_req = &vhm_req_buf[vcpu_id];
|
||||
if (vhm_req->valid &&
|
||||
(vhm_req->processed == REQ_STATE_PROCESSING) &&
|
||||
(vhm_req->client == ctx->ioreq_client))
|
||||
vm_notify_request_done(ctx, vcpu_id);
|
||||
}
|
||||
|
||||
vm_stop_watchdog(ctx);
|
||||
wait_for_resume(ctx);
|
||||
|
||||
vm_reset_watchdog(ctx);
|
||||
vm_reset(ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_loop(struct vmctx *ctx)
|
||||
{
|
||||
|
@ -606,6 +656,10 @@ vm_loop(struct vmctx *ctx)
|
|||
if (VM_SUSPEND_SYSTEM_RESET == vm_get_suspend_mode()) {
|
||||
vm_system_reset(ctx);
|
||||
}
|
||||
|
||||
if (VM_SUSPEND_SUSPEND == vm_get_suspend_mode()) {
|
||||
vm_suspend_resume(ctx);
|
||||
}
|
||||
}
|
||||
quit_vm_loop = 0;
|
||||
printf("VM loop exit\n");
|
||||
|
|
|
@ -316,6 +316,8 @@ mevent_dispatch(void)
|
|||
assert(pipev != NULL);
|
||||
|
||||
for (;;) {
|
||||
int suspend_mode;
|
||||
|
||||
/*
|
||||
* Block awaiting events
|
||||
*/
|
||||
|
@ -328,8 +330,11 @@ mevent_dispatch(void)
|
|||
*/
|
||||
mevent_handle(eventlist, ret);
|
||||
|
||||
if ((vm_get_suspend_mode() != VM_SUSPEND_NONE) &&
|
||||
(vm_get_suspend_mode() != VM_SUSPEND_SYSTEM_RESET))
|
||||
suspend_mode = vm_get_suspend_mode();
|
||||
|
||||
if ((suspend_mode != VM_SUSPEND_NONE) &&
|
||||
(suspend_mode != VM_SUSPEND_SYSTEM_RESET) &&
|
||||
(suspend_mode != VM_SUSPEND_SUSPEND))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -744,6 +744,11 @@ basl_fwrite_dsdt(FILE *fp, struct vmctx *ctx)
|
|||
dsdt_line("DefinitionBlock (\"dm_dsdt.aml\", \"DSDT\", 2,"
|
||||
"\"DM \", \"DMDSDT \", 0x00000001)");
|
||||
dsdt_line("{");
|
||||
dsdt_line(" Name (_S3, Package ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" 0x03,");
|
||||
dsdt_line(" Zero,");
|
||||
dsdt_line(" })");
|
||||
dsdt_line(" Name (_S5, Package ()");
|
||||
dsdt_line(" {");
|
||||
dsdt_line(" 0x05,");
|
||||
|
|
Loading…
Reference in New Issue