diff --git a/hypervisor/arch/x86/guest/vm_reset.c b/hypervisor/arch/x86/guest/vm_reset.c index 8f7e1f701..a15de301e 100644 --- a/hypervisor/arch/x86/guest/vm_reset.c +++ b/hypervisor/arch/x86/guest/vm_reset.c @@ -95,7 +95,7 @@ static bool handle_reset_reg_read(struct acrn_vcpu *vcpu, __unused uint16_t addr /** * @pre vm != NULL */ -static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset) +static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset, bool warm) { struct acrn_vm *vm = vcpu->vm; bool ret = true; @@ -105,7 +105,7 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset) poweroff_if_rt_vm(vm); if (get_highest_severity_vm(true) == vm) { - reset_host(); + reset_host(warm); } else if (is_postlaunched_vm(vm)) { /* re-inject to DM */ ret = false; @@ -142,7 +142,7 @@ static bool handle_common_reset_reg_write(struct acrn_vcpu *vcpu, bool reset) static bool handle_kb_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val) { /* ignore commands other than system reset */ - return handle_common_reset_reg_write(vcpu, ((bytes == 1U) && (val == 0xfeU))); + return handle_common_reset_reg_write(vcpu, ((bytes == 1U) && (val == 0xfeU)), false); } static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes) @@ -172,9 +172,9 @@ static bool handle_kb_read(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes) */ static bool handle_cf9_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, size_t bytes, uint32_t val) { - /* We don't differentiate among hard/soft/warm/cold reset */ return handle_common_reset_reg_write(vcpu, - ((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U))); + ((bytes == 1U) && ((val & 0x4U) == 0x4U) && ((val & 0xaU) != 0U)), + ((val & 0x8U) == 0U)); } /** @@ -189,7 +189,7 @@ static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t struct acpi_reset_reg *reset_reg = get_host_reset_reg_data(); if (val == reset_reg->val) { - ret = handle_common_reset_reg_write(vcpu, true); + ret = handle_common_reset_reg_write(vcpu, true, false); } else { /* * ACPI defines the reset value but doesn't specify the meaning of other values. diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index 33705f7c7..3fb634d15 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -244,10 +244,10 @@ void host_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_ resume_console(); } -void reset_host(void) +void reset_host(bool warm) { struct acrn_acpi_generic_address *gas = &(host_reset_reg.reg); - + uint8_t reboot_code = warm ? CF9_RESET_WARM : CF9_RESET_COLD; /* TODO: gracefully shut down all guests before doing host reset. */ @@ -256,11 +256,6 @@ void reset_host(void) * The platform we are running must support at least one of reset method: * - ACPI reset * - 0xcf9 reset - * - * UEFI more likely sets the reset value as 0x6 (not 0xe) for 0xcf9 port. - * This asserts PLTRST# to reset devices on the platform, but not the - * SLP_S3#/4#/5# signals, which power down the systems. This might not be - * enough for us. */ if ((gas->space_id == SPACE_SYSTEM_IO) && (gas->bit_width == 8U) && (gas->bit_offset == 0U) && @@ -270,7 +265,8 @@ void reset_host(void) /* making sure bit 2 (RST_CPU) is '0', when the reset command is issued. */ pio_write8(0x2U, 0xcf9U); udelay(50U); - pio_write8(0xeU, 0xcf9U); + pio_write8(reboot_code, 0xcf9U); + udelay(50U); } pr_fatal("%s(): can't reset host.", __func__); diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index fb850755e..cc3a7d5c6 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -1531,7 +1531,7 @@ static int32_t shell_cpuid(int32_t argc, char **argv) static int32_t shell_reboot(__unused int32_t argc, __unused char **argv) { - reset_host(); + reset_host(false); return 0; } diff --git a/hypervisor/include/arch/x86/asm/host_pm.h b/hypervisor/include/arch/x86/asm/host_pm.h index 6ee25e582..d70f504db 100644 --- a/hypervisor/include/arch/x86/asm/host_pm.h +++ b/hypervisor/include/arch/x86/asm/host_pm.h @@ -12,6 +12,9 @@ #define BIT_SLP_EN 13U #define BIT_WAK_STS 15U +#define CF9_RESET_WARM 0x6 +#define CF9_RESET_COLD 0xE + struct cpu_state_info { uint8_t px_cnt; /* count of all Px states */ const struct acrn_pstate_data *px_data; @@ -38,7 +41,7 @@ extern void asm_enter_s3(const struct pm_s_state_data *sstate_data, uint32_t pm1 extern void restore_s3_context(void); struct cpu_state_info *get_cpu_pm_state_info(void); struct acpi_reset_reg *get_host_reset_reg_data(void); -void reset_host(void); +void reset_host(bool warm); void init_frequency_policy(void); void apply_frequency_policy(void);