From bd09f471a69a3f15d9e003e7b194f270a69da2d5 Mon Sep 17 00:00:00 2001 From: Mingqiang Chi Date: Mon, 19 Aug 2019 13:05:54 +0800 Subject: [PATCH] hv:move some APIs related host reset to pm.c move some data structures and APIs related host reset from vm_reset.c to pm.c, these are not related with guest. Tracked-On: #1842 Signed-off-by: Mingqiang Chi Reviewed-by: Jason Chen CJ --- hypervisor/acpi_parser/acpi_ext.c | 1 - hypervisor/arch/x86/guest/vm_reset.c | 66 +++----------------- hypervisor/arch/x86/pm.c | 56 +++++++++++++++++ hypervisor/include/arch/x86/guest/vm_reset.h | 6 -- hypervisor/include/arch/x86/host_pm.h | 7 +++ 5 files changed, 70 insertions(+), 66 deletions(-) diff --git a/hypervisor/acpi_parser/acpi_ext.c b/hypervisor/acpi_parser/acpi_ext.c index 4cda879e4..764e93bf7 100644 --- a/hypervisor/acpi_parser/acpi_ext.c +++ b/hypervisor/acpi_parser/acpi_ext.c @@ -35,7 +35,6 @@ #include #include #include -#include /* Per ACPI spec: * There are two fundamental types of ACPI tables: diff --git a/hypervisor/arch/x86/guest/vm_reset.c b/hypervisor/arch/x86/guest/vm_reset.c index 50d7bdfcf..2c7bb1805 100644 --- a/hypervisor/arch/x86/guest/vm_reset.c +++ b/hypervisor/arch/x86/guest/vm_reset.c @@ -6,29 +6,13 @@ #include #include +#include #include #include #include #include #include -/* host reset register defined in ACPI */ -static struct acpi_reset_reg host_reset_reg = { - .reg = { - .space_id = RESET_REGISTER_SPACE_ID, - .bit_width = RESET_REGISTER_BIT_WIDTH, - .bit_offset = RESET_REGISTER_BIT_OFFSET, - .access_size = RESET_REGISTER_ACCESS_SIZE, - .address = RESET_REGISTER_ADDRESS, - }, - .val = RESET_REGISTER_VALUE -}; - -struct acpi_reset_reg *get_host_reset_reg_data(void) -{ - return &host_reset_reg; -} - /** * @pre vm != NULL */ @@ -70,45 +54,6 @@ void triple_fault_shutdown_vm(struct acrn_vcpu *vcpu) } } -static void reset_host(void) -{ - struct acpi_generic_address *gas = &(host_reset_reg.reg); - - - /* TODO: gracefully shut down all guests before doing host 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) && - (gas->address != 0U) && (gas->address != 0xcf9U)) { - pio_write8(host_reset_reg.val, (uint16_t)host_reset_reg.reg.address); - } - - /* - * Fall back - * making sure bit 2 (RST_CPU) is '0', when the reset command is issued. - */ - pio_write8(0x2U, 0xcf9U); - pio_write8(0xeU, 0xcf9U); - - /* - * Fall back - * keyboard controller might cause the INIT# being asserted, - * and not power cycle the system. - */ - pio_write8(0xfeU, 0x64U); - - pr_fatal("%s(): can't reset host.", __func__); - while (1) { - asm_pause(); - } -} - /** * @pre vcpu != NULL * @pre vcpu->vm != NULL @@ -197,7 +142,9 @@ static bool handle_cf9_write(struct acrn_vcpu *vcpu, __unused uint16_t addr, siz static bool handle_reset_reg_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t bytes, uint32_t val) { if (bytes == 1U) { - if (val == host_reset_reg.val) { + struct acpi_reset_reg *reset_reg = get_host_reset_reg_data(); + + if (val == reset_reg->val) { if (is_highest_severity_vm(vcpu->vm)) { reset_host(); } else { @@ -223,7 +170,8 @@ void register_reset_port_handler(struct acrn_vm *vm) { /* Don't support SOS and pre-launched VM re-launch for now. */ if (!is_postlaunched_vm(vm) || is_rt_vm(vm)) { - struct acpi_generic_address *gas = &(host_reset_reg.reg); + struct acpi_reset_reg *reset_reg = get_host_reset_reg_data(); + struct acpi_generic_address *gas = &(reset_reg->reg); struct vm_io_range io_range = { .len = 1U @@ -247,7 +195,7 @@ void register_reset_port_handler(struct acrn_vm *vm) (gas->bit_width == 8U) && (gas->bit_offset == 0U) && (gas->address != 0xcf9U) && (gas->address != 0x64U)) { - io_range.base = (uint16_t)host_reset_reg.reg.address; + io_range.base = (uint16_t)reset_reg->reg.address; register_pio_emulation_handler(vm, PIO_RESET_REG_IDX, &io_range, handle_reset_reg_read, handle_reset_reg_write); } diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index 5ed604412..f73203144 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -64,11 +64,28 @@ static struct pm_s_state_data host_pm_s_state = { .wake_vector_64 = (uint64_t *)WAKE_VECTOR_64 }; +/* host reset register defined in ACPI */ +static struct acpi_reset_reg host_reset_reg = { + .reg = { + .space_id = RESET_REGISTER_SPACE_ID, + .bit_width = RESET_REGISTER_BIT_WIDTH, + .bit_offset = RESET_REGISTER_BIT_OFFSET, + .access_size = RESET_REGISTER_ACCESS_SIZE, + .address = RESET_REGISTER_ADDRESS, + }, + .val = RESET_REGISTER_VALUE +}; + struct pm_s_state_data *get_host_sstate_data(void) { return &host_pm_s_state; } +struct acpi_reset_reg *get_host_reset_reg_data(void) +{ + return &host_reset_reg; +} + void restore_msrs(void) { #ifdef STACK_PROTECTOR @@ -182,3 +199,42 @@ void host_enter_s3(struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, u panic("Failed to start all APs!"); } } + +void reset_host(void) +{ + struct acpi_generic_address *gas = &(host_reset_reg.reg); + + + /* TODO: gracefully shut down all guests before doing host 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) && + (gas->address != 0U) && (gas->address != 0xcf9U)) { + pio_write8(host_reset_reg.val, (uint16_t)host_reset_reg.reg.address); + } + + /* + * Fall back + * making sure bit 2 (RST_CPU) is '0', when the reset command is issued. + */ + pio_write8(0x2U, 0xcf9U); + pio_write8(0xeU, 0xcf9U); + + /* + * Fall back + * keyboard controller might cause the INIT# being asserted, + * and not power cycle the system. + */ + pio_write8(0xfeU, 0x64U); + + pr_fatal("%s(): can't reset host.", __func__); + while (1) { + asm_pause(); + } +} diff --git a/hypervisor/include/arch/x86/guest/vm_reset.h b/hypervisor/include/arch/x86/guest/vm_reset.h index e0b05a772..5f3361784 100644 --- a/hypervisor/include/arch/x86/guest/vm_reset.h +++ b/hypervisor/include/arch/x86/guest/vm_reset.h @@ -9,14 +9,8 @@ #include -struct acpi_reset_reg { - struct acpi_generic_address reg; - uint8_t val; -}; - 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_vcpu *vcpu); -struct acpi_reset_reg *get_host_reset_reg_data(void); #endif /* VM_RESET_H_ */ diff --git a/hypervisor/include/arch/x86/host_pm.h b/hypervisor/include/arch/x86/host_pm.h index 32fbfac9a..f0e16bb20 100644 --- a/hypervisor/include/arch/x86/host_pm.h +++ b/hypervisor/include/arch/x86/host_pm.h @@ -24,10 +24,17 @@ struct cpu_state_table { struct cpu_state_info state_info; }; +struct acpi_reset_reg { + struct acpi_generic_address reg; + uint8_t val; +}; + struct pm_s_state_data *get_host_sstate_data(void); void host_enter_s3(struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val); extern void asm_enter_s3(struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val); 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); #endif /* HOST_PM_H */