diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index 64afcd971..16d9cc3d0 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -220,10 +220,16 @@ static bool rt_vm_pm1a_io_read(__unused struct acrn_vm *vm, __unused struct acrn return false; } -static bool rt_vm_pm1a_io_write(__unused struct acrn_vm *vm, __unused uint16_t addr, - __unused size_t width, __unused uint32_t v) +static bool rt_vm_pm1a_io_write(struct acrn_vm *vm, uint16_t addr, size_t width, uint32_t v) { - /* TODO: Check if the vm is trying to powering off itself */ + if ((addr != RT_VM_PM1A_CNT_ADDR) || (width != 2U)) { + pr_dbg("Invalid address (0x%x) or width (0x%x)", addr, width); + } else { + if (((v & RT_VM_PM1A_SLP_EN) && (((v & RT_VM_PM1A_SLP_TYP) >> 10U) == 5U)) != 0U) { + vm->state = VM_POWERING_OFF; + } + } + return false; } diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 2003d1ae5..e3f366260 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -88,6 +88,7 @@ enum vm_state { VM_STATE_INVALID = 0, VM_CREATED, /* VM created / awaiting start (boot) */ VM_STARTED, /* VM started (booted) */ + VM_POWERING_OFF, /* RTVM only, it is trying to poweroff by itself */ VM_PAUSED, /* VM paused */ }; diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index 90221706a..e0dced4e4 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -56,6 +56,8 @@ /* TODO: We may need to get this addr from guest ACPI instead of hardcode here */ #define RT_VM_PM1A_CNT_ADDR 0x404U +#define RT_VM_PM1A_SLP_TYP 0x1c00U +#define RT_VM_PM1A_SLP_EN 0x2000U /** * @brief Hypercall