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 <minggui.cao@intel.com>
Reviewed-by: Victor Sun <victor.sun@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Minggui Cao 2018-12-14 16:33:14 +08:00 committed by wenlingz
parent 03262a96cf
commit f81fb21a58
5 changed files with 79 additions and 96 deletions

View File

@ -106,7 +106,7 @@ void vm_setup_cpu_state(struct acrn_vm *vm)
int32_t vm_load_pm_s_state(struct acrn_vm *vm) int32_t vm_load_pm_s_state(struct acrn_vm *vm)
{ {
#ifdef ACPI_INFO_VALIDATED #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."); pr_info("System S3/S5 is supported.");
return 0; return 0;
#else #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); return (uint8_t)((pm1_cnt & 0x1fffU) >> BIT_SLP_TYPx);
} }
static uint32_t pm1ab_io_read(__unused struct acrn_vm *vm, uint16_t addr, static uint32_t pm1ab_io_read(__unused struct acrn_vm *vm, uint16_t addr, size_t width)
size_t width)
{ {
uint32_t val = pio_read(addr, width); return 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;
} }
static void pm1ab_io_write(__unused struct acrn_vm *vm, uint16_t addr, size_t width, static inline void enter_s3(struct acrn_vm *vm, uint32_t pm1a_cnt_val, uint32_t pm1b_cnt_val)
uint32_t v) {
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; static uint32_t pm1a_cnt_ready = 0U;

View File

@ -8,7 +8,7 @@
struct cpu_context cpu_ctx; struct cpu_context cpu_ctx;
/* The values in this structure should come from host ACPI table */ /* 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 = { .pm1a_evt = {
.space_id = PM1A_EVT_SPACE_ID, .space_id = PM1A_EVT_SPACE_ID,
.bit_width = PM1A_EVT_BIT_WIDTH, .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 .wake_vector_64 = (uint64_t *)WAKE_VECTOR_64
}; };
/* whether the host enter s3 success */ void set_host_wake_vectors(void *vector_32, void *vector_64)
uint8_t host_enter_s3_success = 1U; {
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) void restore_msrs(void)
{ {
@ -87,29 +95,24 @@ static uint32_t acpi_gas_read(const struct acpi_generic_address *gas)
return ret; return ret;
} }
void do_acpi_s3(struct acrn_vm *vm, uint32_t pm1a_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 pm1b_cnt_val)
{ {
uint32_t s1, s2; 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) { if (sstate_data->pm1b_cnt.address != 0U) {
acpi_gas_write(&(sx_data->pm1b_cnt), pm1b_cnt_val); acpi_gas_write(&(sstate_data->pm1b_cnt), pm1b_cnt_val);
} }
do { do {
/* polling PM1 state register to detect wether /* polling PM1 state register to detect wether
* the Sx state enter is interrupted by wakeup event. * the Sx state enter is interrupted by wakeup event.
*/ */
s1 = 0U; s1 = acpi_gas_read(&(sstate_data->pm1a_evt));
s2 = 0U;
s1 = acpi_gas_read(&(sx_data->pm1a_evt)); if (sstate_data->pm1b_evt.address != 0U) {
s2 = acpi_gas_read(&(sstate_data->pm1b_evt));
if (vm->pm.sx_state_data->pm1b_evt.address != 0U) {
s2 = acpi_gas_read(&(sx_data->pm1b_evt));
s1 |= s2; 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); } 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; uint64_t pmain_entry_saved;
uint32_t guest_wakeup_vec32;
/* We assume enter s3 success by default */ stac();
host_enter_s3_success = 1U;
if (vm->pm.sx_state_data != NULL) {
pause_vm(vm); /* pause vm0 before suspend system */
stac(); /* set ACRN wakeup vec instead */
/* Save the wakeup vec set by guest. Will return to guest *(sstate_data->wake_vector_32) = (uint32_t)trampoline_start16_paddr;
* with this wakeup vec as entry.
*/
guest_wakeup_vec32 = *vm->pm.sx_state_data->wake_vector_32;
/* set ACRN wakeup vec instead */ clac();
*vm->pm.sx_state_data->wake_vector_32 = /* offline all APs */
(uint32_t) trampoline_start16_paddr; stop_cpus();
clac(); stac();
/* offline all APs */ /* Save default main entry and we will restore it after
stop_cpus(); * back from S3. So the AP online could jmp to correct
* main entry.
*/
pmain_entry_saved = read_trampoline_sym(main_entry);
stac(); /* Set the main entry for resume from S3 state */
/* Save default main entry and we will restore it after write_trampoline_sym(main_entry, (uint64_t)restore_s3_context);
* back from S3. So the AP online could jmp to correct clac();
* main entry.
*/
pmain_entry_saved = read_trampoline_sym(main_entry);
/* Set the main entry for resume from S3 state */ CPU_IRQ_DISABLE();
write_trampoline_sym(main_entry, (uint64_t)restore_s3_context); vmx_off();
clac();
CPU_IRQ_DISABLE(); suspend_console();
vmx_off(); suspend_ioapic();
suspend_iommu();
suspend_lapic();
suspend_console(); asm_enter_s3(sstate_data, pm1a_cnt_val, pm1b_cnt_val);
suspend_ioapic();
suspend_iommu();
suspend_lapic();
asm_enter_s3(vm, pm1a_cnt_val, pm1b_cnt_val); resume_lapic();
resume_iommu();
resume_ioapic();
resume_console();
resume_lapic(); vmx_on();
resume_iommu(); CPU_IRQ_ENABLE();
resume_ioapic();
resume_console();
vmx_on(); /* restore the default main entry */
CPU_IRQ_ENABLE(); stac();
write_trampoline_sym(main_entry, pmain_entry_saved);
clac();
/* restore the default main entry */ /* online all APs again */
stac(); start_cpus();
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;
} }

View File

@ -92,7 +92,7 @@ asm_enter_s3:
/*16U=0x10=CPU_CONTEXT_OFFSET_RDX*/ /*16U=0x10=CPU_CONTEXT_OFFSET_RDX*/
movq 0x10 + cpu_ctx(%rip), %rdx /* pm1b_cnt_val */ movq 0x10 + cpu_ctx(%rip), %rdx /* pm1b_cnt_val */
/*56U=0x38=CPU_CONTEXT_OFFSET_RDI*/ /*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*/ /*48U=0x30=CPU_CONTEXT_OFFSET_RSI*/
movq 0x30 + cpu_ctx(%rip), %rsi /* pm1a_cnt_val */ movq 0x30 + cpu_ctx(%rip), %rsi /* pm1a_cnt_val */

View File

@ -369,8 +369,7 @@ void acpi_fixup(void)
void *facs_addr = get_facs_table(); void *facs_addr = get_facs_table();
if (facs_addr != NULL) { if (facs_addr != NULL) {
host_pm_s_state.wake_vector_32 = (uint32_t *)(facs_addr + OFFSET_WAKE_VECTOR_32); set_host_wake_vectors(facs_addr + OFFSET_WAKE_VECTOR_32, facs_addr + OFFSET_WAKE_VECTOR_64);
host_pm_s_state.wake_vector_64 = (uint64_t *)(facs_addr + OFFSET_WAKE_VECTOR_64);
} }
} }
#endif #endif

View File

@ -10,13 +10,11 @@
#define BIT_SLP_EN 13U #define BIT_SLP_EN 13U
#define BIT_WAK_STS 15U #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 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);
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);
extern void restore_s3_context(void); extern void restore_s3_context(void);
#endif /* HOST_PM_H */ #endif /* HOST_PM_H */