ACRN/HV: Assign the parsed RSDP to acpi_rsdp to avoid multiple RSDP parsing

Currently the get_rsdp() will be called several times and on some
platform it needs to scan the signature of "RSP ptr" in BIOS EBDA region
and 0xE0000-0xFFFFF region. It is slow.
So after the RSDP is parsed, it will be assigned to acpi_rsdp.

Tracked-On: #3184
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Zhao Yakui 2019-05-28 16:22:26 +08:00 committed by wenlingz
parent c5d4365770
commit 1c36508e83

View File

@ -143,22 +143,39 @@ found_rsdp(char *base, int32_t length)
return ret; return ret;
} }
/* RSDP parsed from BIOS region should exist.
* If it is NULL, the hypervisor can't be booted
*/
static struct acpi_table_rsdp *get_rsdp(void) static struct acpi_table_rsdp *get_rsdp(void)
{ {
struct acpi_table_rsdp *rsdp = NULL; struct acpi_table_rsdp *rsdp = NULL;
uint16_t *addr;
/* If acpi_rsdp is already parsed, it will be returned directly */
if (acpi_rsdp != NULL) {
rsdp = acpi_rsdp;
} else {
rsdp = (struct acpi_table_rsdp *)get_rsdp_ptr(); rsdp = (struct acpi_table_rsdp *)get_rsdp_ptr();
if (rsdp == NULL) { if (rsdp == NULL) {
uint16_t *addr;
/* EBDA is addressed by the 16 bit pointer at 0x40E */ /* EBDA is addressed by the 16 bit pointer at 0x40E */
addr = (uint16_t *)hpa2hva(0x40eUL); addr = (uint16_t *)hpa2hva(0x40eUL);
rsdp = found_rsdp((char *)hpa2hva((uint64_t)(*addr) << 4U), 0x400); rsdp = found_rsdp((char *)hpa2hva((uint64_t)(*addr) << 4U), 0x400);
}
if (rsdp == NULL) { if (rsdp == NULL) {
/* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */ /* Check the upper memory BIOS space, 0xe0000 - 0xfffff. */
rsdp = found_rsdp((char *)hpa2hva(0xe0000UL), 0x20000); rsdp = found_rsdp((char *)hpa2hva(0xe0000UL), 0x20000);
} }
if (rsdp == NULL)
panic("No RSDP is found");
/* After RSDP is parsed, it will be assigned to acpi_rsdp */
acpi_rsdp = rsdp;
} }
return rsdp; return rsdp;
} }
@ -185,7 +202,10 @@ void *get_acpi_tbl(const char *signature)
uint64_t addr = 0UL; uint64_t addr = 0UL;
uint32_t i, count; uint32_t i, count;
rsdp = acpi_rsdp; /* the returned RSDP should always exist. Otherwise the hypervisor
* can't be booted.
*/
rsdp = get_rsdp();
if ((rsdp->revision >= 2U) && (rsdp->xsdt_physical_address != 0UL)) { if ((rsdp->revision >= 2U) && (rsdp->xsdt_physical_address != 0UL)) {
/* /*
@ -294,9 +314,10 @@ ioapic_parse_madt(void *madt, struct ioapic_info *ioapic_id_array)
uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM]) uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM])
{ {
uint16_t ret = 0U; uint16_t ret = 0U;
struct acpi_table_rsdp *rsdp = NULL;
acpi_rsdp = get_rsdp(); rsdp = get_rsdp();
if (acpi_rsdp != NULL) { if (rsdp != NULL) {
struct acpi_table_madt *madt = (struct acpi_table_madt *)get_acpi_tbl(ACPI_SIG_MADT); struct acpi_table_madt *madt = (struct acpi_table_madt *)get_acpi_tbl(ACPI_SIG_MADT);
if (madt != NULL) { if (madt != NULL) {
ret = local_parse_madt(madt, lapic_id_array); ret = local_parse_madt(madt, lapic_id_array);
@ -308,13 +329,16 @@ uint16_t parse_madt(uint32_t lapic_id_array[CONFIG_MAX_PCPU_NUM])
uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array) uint16_t parse_madt_ioapic(struct ioapic_info *ioapic_id_array)
{ {
void *madt; uint16_t ret = 0U;
struct acpi_table_rsdp *rsdp = NULL;
acpi_rsdp = get_rsdp(); rsdp = get_rsdp();
ASSERT(acpi_rsdp != NULL, "fail to get rsdp"); if (rsdp != NULL) {
void *madt = get_acpi_tbl(ACPI_SIG_MADT);
madt = get_acpi_tbl(ACPI_SIG_MADT); if (madt != NULL) {
ASSERT(madt != NULL, "fail to get madt"); ret = ioapic_parse_madt(madt, ioapic_id_array);
}
return ioapic_parse_madt(madt, ioapic_id_array); }
return ret;
} }