From f81fb21a583f3a137fefeba2b07713fdb3f13725 Mon Sep 17 00:00:00 2001 From: Minggui Cao Date: Fri, 14 Dec 2018 16:33:14 +0800 Subject: [PATCH] HV: modularization to refine pm related code. 1. move out vm related code from arch/pm. 2. remove unnecssary global variables. 3. keep the global variables as static, not used by other modules directlly. Tracked-On: #1842 Signed-off-by: Minggui Cao Reviewed-by: Victor Sun Acked-by: Anthony Xu --- hypervisor/arch/x86/guest/pm.c | 36 ++++---- hypervisor/arch/x86/pm.c | 124 +++++++++++--------------- hypervisor/arch/x86/wakeup.S | 2 +- hypervisor/boot/acpi.c | 3 +- hypervisor/include/arch/x86/host_pm.h | 10 +-- 5 files changed, 79 insertions(+), 96 deletions(-) diff --git a/hypervisor/arch/x86/guest/pm.c b/hypervisor/arch/x86/guest/pm.c index a98f8f2e2..3b2b79cb2 100644 --- a/hypervisor/arch/x86/guest/pm.c +++ b/hypervisor/arch/x86/guest/pm.c @@ -106,7 +106,7 @@ void vm_setup_cpu_state(struct acrn_vm *vm) int32_t vm_load_pm_s_state(struct acrn_vm *vm) { #ifdef ACPI_INFO_VALIDATED - vm->pm.sx_state_data = (struct pm_s_state_data *)&host_pm_s_state; + vm->pm.sx_state_data = get_host_sstate_data(); pr_info("System S3/S5 is supported."); return 0; #else @@ -126,24 +126,28 @@ static inline uint8_t get_slp_typx(uint32_t pm1_cnt) return (uint8_t)((pm1_cnt & 0x1fffU) >> BIT_SLP_TYPx); } -static uint32_t pm1ab_io_read(__unused struct acrn_vm *vm, uint16_t addr, - size_t width) +static uint32_t pm1ab_io_read(__unused struct acrn_vm *vm, uint16_t addr, size_t width) { - uint32_t val = pio_read(addr, width); - - if (host_enter_s3_success == 0U) { - /* If host S3 enter failes, we should set BIT_WAK_STS - * bit for vm0 and let vm0 back from S3 failure path. - */ - if (addr == vm->pm.sx_state_data->pm1a_evt.address) { - val |= (1U << BIT_WAK_STS); - } - } - return val; + return pio_read(addr, width); } -static void pm1ab_io_write(__unused struct acrn_vm *vm, uint16_t addr, size_t width, - uint32_t v) +static inline void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val) +{ + uint32_t guest_wakeup_vec32; + + /* Save the wakeup vec set by guest OS. Will return to guest + * with this wakeup vec as entry. + */ + stac(); + guest_wakeup_vec32 = *(vm->pm.sx_state_data->wake_vector_32); + clac(); + + pause_vm(vm); /* pause vm0 before suspend system */ + host_enter_s3(vm->pm.sx_state_data, pm1a_cnt_val, pm1b_cnt_val); + resume_vm_from_s3(vm, guest_wakeup_vec32); /* jump back to vm */ +} + +static void pm1ab_io_write(struct acrn_vm *vm, uint16_t addr, size_t width, uint32_t v) { static uint32_t pm1a_cnt_ready = 0U; diff --git a/hypervisor/arch/x86/pm.c b/hypervisor/arch/x86/pm.c index cfc39c766..c62d1edbf 100644 --- a/hypervisor/arch/x86/pm.c +++ b/hypervisor/arch/x86/pm.c @@ -8,7 +8,7 @@ struct cpu_context cpu_ctx; /* The values in this structure should come from host ACPI table */ -struct pm_s_state_data host_pm_s_state = { +static struct pm_s_state_data host_pm_s_state = { .pm1a_evt = { .space_id = PM1A_EVT_SPACE_ID, .bit_width = PM1A_EVT_BIT_WIDTH, @@ -51,8 +51,16 @@ struct pm_s_state_data host_pm_s_state = { .wake_vector_64 = (uint64_t *)WAKE_VECTOR_64 }; -/* whether the host enter s3 success */ -uint8_t host_enter_s3_success = 1U; +void set_host_wake_vectors(void *vector_32, void *vector_64) +{ + host_pm_s_state.wake_vector_32 = (uint32_t *)vector_32; + host_pm_s_state.wake_vector_64 = (uint64_t *)vector_64; +} + +struct pm_s_state_data *get_host_sstate_data(void) +{ + return &host_pm_s_state; +} void restore_msrs(void) { @@ -87,29 +95,24 @@ static uint32_t acpi_gas_read(const struct acpi_generic_address *gas) return ret; } -void do_acpi_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, - uint32_t pm1b_cnt_val) +void do_acpi_s3(struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val) { uint32_t s1, s2; - struct pm_s_state_data *sx_data = vm->pm.sx_state_data; - acpi_gas_write(&(sx_data->pm1a_cnt), pm1a_cnt_val); + acpi_gas_write(&(sstate_data->pm1a_cnt), pm1a_cnt_val); - if (vm->pm.sx_state_data->pm1b_cnt.address != 0U) { - acpi_gas_write(&(sx_data->pm1b_cnt), pm1b_cnt_val); + if (sstate_data->pm1b_cnt.address != 0U) { + acpi_gas_write(&(sstate_data->pm1b_cnt), pm1b_cnt_val); } do { /* polling PM1 state register to detect wether * the Sx state enter is interrupted by wakeup event. */ - s1 = 0U; - s2 = 0U; + s1 = acpi_gas_read(&(sstate_data->pm1a_evt)); - s1 = acpi_gas_read(&(sx_data->pm1a_evt)); - - if (vm->pm.sx_state_data->pm1b_evt.address != 0U) { - s2 = acpi_gas_read(&(sx_data->pm1b_evt)); + if (sstate_data->pm1b_evt.address != 0U) { + s2 = acpi_gas_read(&(sstate_data->pm1b_evt)); s1 |= s2; } @@ -120,74 +123,53 @@ void do_acpi_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, } while ((s1 & (1U << BIT_WAK_STS)) == 0U); } -void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val) +void host_enter_s3(struct pm_s_state_data *sstate_data, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val) { uint64_t pmain_entry_saved; - uint32_t guest_wakeup_vec32; - /* We assume enter s3 success by default */ - host_enter_s3_success = 1U; - if (vm->pm.sx_state_data != NULL) { - pause_vm(vm); /* pause vm0 before suspend system */ + stac(); - stac(); - /* Save the wakeup vec set by guest. Will return to guest - * with this wakeup vec as entry. - */ - guest_wakeup_vec32 = *vm->pm.sx_state_data->wake_vector_32; + /* set ACRN wakeup vec instead */ + *(sstate_data->wake_vector_32) = (uint32_t)trampoline_start16_paddr; - /* set ACRN wakeup vec instead */ - *vm->pm.sx_state_data->wake_vector_32 = - (uint32_t) trampoline_start16_paddr; + clac(); + /* offline all APs */ + stop_cpus(); - clac(); - /* offline all APs */ - stop_cpus(); + stac(); + /* Save default main entry and we will restore it after + * back from S3. So the AP online could jmp to correct + * main entry. + */ + pmain_entry_saved = read_trampoline_sym(main_entry); - stac(); - /* Save default main entry and we will restore it after - * back from S3. So the AP online could jmp to correct - * main entry. - */ - pmain_entry_saved = read_trampoline_sym(main_entry); + /* Set the main entry for resume from S3 state */ + write_trampoline_sym(main_entry, (uint64_t)restore_s3_context); + clac(); - /* Set the main entry for resume from S3 state */ - write_trampoline_sym(main_entry, (uint64_t)restore_s3_context); - clac(); + CPU_IRQ_DISABLE(); + vmx_off(); - CPU_IRQ_DISABLE(); - vmx_off(); + suspend_console(); + suspend_ioapic(); + suspend_iommu(); + suspend_lapic(); - suspend_console(); - suspend_ioapic(); - suspend_iommu(); - suspend_lapic(); + asm_enter_s3(sstate_data, pm1a_cnt_val, pm1b_cnt_val); - asm_enter_s3(vm, pm1a_cnt_val, pm1b_cnt_val); + resume_lapic(); + resume_iommu(); + resume_ioapic(); + resume_console(); - resume_lapic(); - resume_iommu(); - resume_ioapic(); - resume_console(); + vmx_on(); + CPU_IRQ_ENABLE(); - vmx_on(); - CPU_IRQ_ENABLE(); + /* restore the default main entry */ + stac(); + write_trampoline_sym(main_entry, pmain_entry_saved); + clac(); - /* restore the default main entry */ - stac(); - write_trampoline_sym(main_entry, pmain_entry_saved); - clac(); - - /* online all APs again */ - start_cpus(); - - /* jump back to vm */ - resume_vm_from_s3(vm, guest_wakeup_vec32); - } else { - pr_err("No Sx state info avaiable. No Sx support"); - host_enter_s3_success = 0U; - } - - - return; + /* online all APs again */ + start_cpus(); } diff --git a/hypervisor/arch/x86/wakeup.S b/hypervisor/arch/x86/wakeup.S index 7451fe5c0..1a1c2eecf 100644 --- a/hypervisor/arch/x86/wakeup.S +++ b/hypervisor/arch/x86/wakeup.S @@ -92,7 +92,7 @@ asm_enter_s3: /*16U=0x10=CPU_CONTEXT_OFFSET_RDX*/ movq 0x10 + cpu_ctx(%rip), %rdx /* pm1b_cnt_val */ /*56U=0x38=CPU_CONTEXT_OFFSET_RDI*/ - movq 0x38 + cpu_ctx(%rip), %rdi /* *vm */ + movq 0x38 + cpu_ctx(%rip), %rdi /* pm sstate_data */ /*48U=0x30=CPU_CONTEXT_OFFSET_RSI*/ movq 0x30 + cpu_ctx(%rip), %rsi /* pm1a_cnt_val */ diff --git a/hypervisor/boot/acpi.c b/hypervisor/boot/acpi.c index aeaa5be75..afbff5c60 100644 --- a/hypervisor/boot/acpi.c +++ b/hypervisor/boot/acpi.c @@ -369,8 +369,7 @@ void acpi_fixup(void) void *facs_addr = get_facs_table(); if (facs_addr != NULL) { - host_pm_s_state.wake_vector_32 = (uint32_t *)(facs_addr + OFFSET_WAKE_VECTOR_32); - host_pm_s_state.wake_vector_64 = (uint64_t *)(facs_addr + OFFSET_WAKE_VECTOR_64); + set_host_wake_vectors(facs_addr + OFFSET_WAKE_VECTOR_32, facs_addr + OFFSET_WAKE_VECTOR_64); } } #endif diff --git a/hypervisor/include/arch/x86/host_pm.h b/hypervisor/include/arch/x86/host_pm.h index 057138719..b93b31b27 100644 --- a/hypervisor/include/arch/x86/host_pm.h +++ b/hypervisor/include/arch/x86/host_pm.h @@ -10,13 +10,11 @@ #define BIT_SLP_EN 13U #define BIT_WAK_STS 15U -extern struct pm_s_state_data host_pm_s_state; +void set_host_wake_vectors(void *vector_32, void *vector_64); +struct pm_s_state_data *get_host_sstate_data(void); -extern uint8_t host_enter_s3_success; - -void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val); -extern void asm_enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, - uint32_t pm1b_cnt_val); +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); #endif /* HOST_PM_H */