HV: enable acpi pm1a register info fixup

Previously ACPI PM1A register info was hardcoded to 0 in HV for generic boards,
but SOS still can know the real PM1A info so the system would hang if user
trigger S3 in SOS. Enabling PM1A register info fixup will let HV be able to
intercept the operation on PM1A and then make basic function of S3 work for
all boards;

Tracked-On: #2291

Signed-off-by: Victor Sun <victor.sun@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Victor Sun 2019-04-29 13:52:37 +08:00 committed by wenlingz
parent 81e13de407
commit e2d723d4fa
8 changed files with 77 additions and 46 deletions

View File

@ -12,8 +12,6 @@
#ifndef PLATFORM_ACPI_INFO_H
#define PLATFORM_ACPI_INFO_H
#define ACPI_INFO_VALIDATED
/* pm sstate data */
#define PM1A_EVT_ACCESS_SIZE 3U
#define PM1A_EVT_ADDRESS 0x400UL

View File

@ -100,15 +100,19 @@ 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 = get_host_sstate_data();
pr_info("System S3/S5 is supported.");
return 0;
#else
vm->pm.sx_state_data = NULL;
pr_err("System S3/S5 is NOT supported.");
return -1;
#endif
int32_t ret;
struct pm_s_state_data *sx_data = get_host_sstate_data();
if ((sx_data->pm1a_evt.address == 0UL) || (sx_data->pm1a_cnt.address == 0UL)
|| (sx_data->wake_vector_32 == NULL)) {
pr_err("System S3/S5 is NOT supported.");
ret = -1;
} else {
pr_info("System S3/S5 is supported.");
vm->pm.sx_state_data = sx_data;
ret = 0;
}
return ret;
}
static inline uint32_t s3_enabled(uint32_t pm1_cnt)

View File

@ -65,12 +65,6 @@ static struct pm_s_state_data host_pm_s_state = {
.wake_vector_64 = (uint64_t *)WAKE_VECTOR_64
};
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;

View File

@ -349,6 +349,8 @@ void *get_dmar_table(void)
/* FACP field offsets */
#define OFFSET_FACS_ADDR 36U
#define OFFSET_FACS_X_ADDR 132U
#define OFFSET_PM1A_EVT 148U
#define OFFSET_PM1A_CNT 172U
/* FACS field offsets */
#define OFFSET_FACS_SIGNATURE 0U
@ -368,35 +370,54 @@ static inline uint64_t get_acpi_dt_qword(const uint8_t *dt_addr, uint32_t dt_off
return *(uint64_t *)(dt_addr + dt_offset);
}
static void *get_facs_table(void)
struct packed_gas {
uint8_t space_id;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t access_size;
uint64_t address;
} __attribute__((packed));
/* get a GAS struct from given table and its offset.
* ACPI table stores packed gas, but it is not guaranteed that
* struct acpi_generic_address is packed, so do not use memcpy in function.
* @pre dt_addr != NULL && gas != NULL
*/
static inline void get_acpi_dt_gas(const uint8_t *dt_addr, uint32_t dt_offset, struct acpi_generic_address *gas)
{
uint8_t *facp_addr, *facs_addr, *facs_x_addr;
struct packed_gas *dt_gas = (struct packed_gas *)(dt_addr + dt_offset);
gas->space_id = dt_gas->space_id;
gas->bit_width = dt_gas->bit_width;
gas->bit_offset = dt_gas->bit_offset;
gas->access_size = dt_gas->access_size;
gas->address = dt_gas->address;
}
/* @pre facp_addr != NULL */
static void *get_facs_table(const uint8_t *facp_addr)
{
uint8_t *facs_addr, *facs_x_addr;
uint32_t signature, length;
facp_addr = (uint8_t *)get_acpi_tbl(ACPI_SIG_FADT);
facs_addr = (uint8_t *)(uint64_t)get_acpi_dt_dword(facp_addr, OFFSET_FACS_ADDR);
if (facp_addr == NULL) {
facs_addr = NULL;
} else {
facs_addr = (uint8_t *)(uint64_t)get_acpi_dt_dword(facp_addr, OFFSET_FACS_ADDR);
facs_x_addr = (uint8_t *)get_acpi_dt_qword(facp_addr, OFFSET_FACS_X_ADDR);
facs_x_addr = (uint8_t *)get_acpi_dt_qword(facp_addr, OFFSET_FACS_X_ADDR);
if (facs_x_addr != NULL) {
facs_addr = facs_x_addr;
}
if (facs_x_addr != NULL) {
facs_addr = facs_x_addr;
}
if (facs_addr != NULL) {
signature = get_acpi_dt_dword(facs_addr, OFFSET_FACS_SIGNATURE);
if (facs_addr != NULL) {
signature = get_acpi_dt_dword(facs_addr, OFFSET_FACS_SIGNATURE);
if (signature != ACPI_SIG_FACS) {
facs_addr = NULL;
} else {
length = get_acpi_dt_dword(facs_addr, OFFSET_FACS_LENGTH);
if (signature != ACPI_SIG_FACS) {
if (length < 64U) {
facs_addr = NULL;
} else {
length = get_acpi_dt_dword(facs_addr, OFFSET_FACS_LENGTH);
if (length < 64U) {
facs_addr = NULL;
}
}
}
}
@ -406,10 +427,25 @@ static void *get_facs_table(void)
/* put all ACPI fix up code here */
void acpi_fixup(void)
{
void *facs_addr = get_facs_table();
uint8_t *facp_addr, *facs_addr;
struct acpi_generic_address pm1a_cnt, pm1a_evt;
struct pm_s_state_data *sx_data = get_host_sstate_data();
if (facs_addr != NULL) {
set_host_wake_vectors(facs_addr + OFFSET_WAKE_VECTOR_32, facs_addr + OFFSET_WAKE_VECTOR_64);
facp_addr = (uint8_t *)get_acpi_tbl(ACPI_SIG_FADT);
if (facp_addr != NULL) {
get_acpi_dt_gas(facp_addr, OFFSET_PM1A_EVT, &pm1a_evt);
get_acpi_dt_gas(facp_addr, OFFSET_PM1A_CNT, &pm1a_cnt);
(void)memcpy_s((void *)&sx_data->pm1a_evt, sizeof(struct acpi_generic_address),
(const void *)&pm1a_evt, sizeof(struct acpi_generic_address));
(void)memcpy_s((void *)&sx_data->pm1a_cnt, sizeof(struct acpi_generic_address),
(const void *)&pm1a_cnt, sizeof(struct acpi_generic_address));
facs_addr = (uint8_t *)get_facs_table(facp_addr);
if (facs_addr != NULL) {
sx_data->wake_vector_32 = (uint32_t *)(facs_addr + OFFSET_WAKE_VECTOR_32);
sx_data->wake_vector_64 = (uint64_t *)(facs_addr + OFFSET_WAKE_VECTOR_64);
}
}
}
#endif

View File

@ -11,4 +11,8 @@ struct ioapic_info;
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM]);
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array);
#ifndef CONFIG_CONSTANT_ACPI
void acpi_fixup(void);
#endif
#endif /* !ACPI_H */

View File

@ -8,6 +8,7 @@
#include <vm.h>
#include <types.h>
#include <pgtable.h>
#include <acpi.h>
#include <firmware.h>
#include <firmware_sbl.h>
#include <firmware_uefi.h>

View File

@ -32,8 +32,4 @@ void *firmware_get_rsdp(void);
void firmware_init_irq(void);
int32_t firmware_init_vm_boot_info(struct acrn_vm *vm);
#ifndef CONFIG_CONSTANT_ACPI
void acpi_fixup(void);
#endif
#endif /* end of include guard: FIRMWARE_H */

View File

@ -17,9 +17,7 @@ struct cpu_state_info {
const struct cpu_cx_data *cx_data;
};
void set_host_wake_vectors(void *vector_32, void *vector_64);
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);