mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-03 02:26:24 +00:00
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:
parent
03262a96cf
commit
f81fb21a58
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user