From: Sergiu Moga Date: Mon, 24 Apr 2023 13:25:05 +0000 (+0300) Subject: plat/common/acpi: Generalize `ACPI` initialization code X-Git-Tag: RELEASE-0.14.0~58 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b86ca45bb9503751cd8921117f52d14795f74c20;p=unikraft%2Funikraft.git plat/common/acpi: Generalize `ACPI` initialization code Write the code in such a manner that the same set of functions can accommodate any version of ACPI. Thus, remove `acpi10_*` functions and define an ACPI table generic fetching function `acpi_get_table`. Signed-off-by: Sergiu Moga Reviewed-by: Dragos Petre Reviewed-by: Marco Schlumpp Approved-by: Razvan Deaconescu Tested-by: Unikraft CI GitHub-Closes: #911 --- diff --git a/plat/common/include/x86/acpi/acpi.h b/plat/common/include/x86/acpi/acpi.h index 336b6091a..a23fdfbf1 100644 --- a/plat/common/include/x86/acpi/acpi.h +++ b/plat/common/include/x86/acpi/acpi.h @@ -54,18 +54,17 @@ struct acpi_rsdp { } __packed; /** - * Detect ACPI version and fetch ACPI tables. + * Get the Multiple APIC Descriptor Table (MADT). * - * @return 0 on success, -errno otherwise. + * @return ACPI table pointer on success, NULL otherwise. */ -int acpi_init(void); +struct acpi_madt *acpi_get_madt(void); /** - * Return the detected ACPI version. + * Detect ACPI version and fetch ACPI tables. * - * @return 0 if ACPI is not initialized or initialization failed, ACPI version - * otherwise. + * @return 0 on success, -errno otherwise. */ -int acpi_get_version(void); +int acpi_init(void); #endif /* __PLAT_CMN_X86_ACPI_H__ */ diff --git a/plat/common/x86/acpi.c b/plat/common/x86/acpi.c index 3b90f587d..a9648e5da 100644 --- a/plat/common/x86/acpi.c +++ b/plat/common/x86/acpi.c @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: BSD-3-Clause */ /* * Authors: Cristian Vijelie + * Sergiu Moga * - * Copyright (c) 2021, University POLITEHNICA of Bucharest. All rights reserved. + * Copyright (c) 2023, University POLITEHNICA of Bucharest. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,17 +35,39 @@ #include #include #include - #include #include +#include -#define RSDT_ENTRIES(rsdt) (((rsdt)->hdr.tab_len - sizeof((rsdt)->hdr)) / 4) #define RSDP10_LEN 20 +#define BIOS_ROM_START 0xE0000UL +#define BIOS_ROM_END 0xFFFFFUL +#define BIOS_ROM_STEP 16 -static __u8 acpi_version; -static struct acpi_rsdp *acpi_rsdp; -static struct acpi_rsdt *acpi_rsdt; static struct acpi_madt *acpi_madt; +static __u8 acpi_rsdt_entries; +static void *acpi_rsdt; +static __u8 acpi10; + +static struct { + struct acpi_sdt_hdr **sdt; + const char *sig; +} acpi_sdts[] = { + { + .sdt = (struct acpi_sdt_hdr **)&acpi_madt, + .sig = ACPI_MADT_SIG, + }, +}; + +static inline __paddr_t get_rsdt_entry(int idx) +{ + __u8 *entryp = (__u8 *)acpi_rsdt + sizeof(struct acpi_sdt_hdr); + + if (acpi10) + return ((__u32 *)entryp)[idx]; + + return ((__u64 *)entryp)[idx]; +} static __u8 get_acpi_checksum(void __maybe_unused *buf, __sz __maybe_unused len) { @@ -62,216 +85,136 @@ static __u8 get_acpi_checksum(void __maybe_unused *buf, __sz __maybe_unused len) #endif } -/** - * Find the Root System Descriptor Pointer (RSDP) in the physical memory area - * 0xe0000 -> 0xfffff and determine ACPI version. - * - * @return 0 on success, -ENOENT if the table is not found, or invalid, - * -ENOTSUP if the ACPI version is not supported. - */ - -static int detect_acpi_version(void) +static void acpi_init_tables(void) { - __u8 *start_addr = (__u8 *)0xe0000; /* BIOS read-only memory space */ - __u8 *end_addr = (__u8 *)0xfffff; - __u8 *ptr; - - UK_ASSERT(!acpi_rsdp); - UK_ASSERT(!acpi_version); - - for (ptr = start_addr; ptr < end_addr; ptr += 16) { - if (!memcmp(ptr, "RSD PTR ", 8)) { - acpi_rsdp = (struct acpi_rsdp *)ptr; - uk_pr_debug("ACPI RSDP present at %p\n", ptr); - break; - } - } - - if (!acpi_rsdp) { - uk_pr_debug("ACPI RSDP not found\n"); - return -ENOENT; - } + struct acpi_sdt_hdr *h; + const char *sig; + __sz i, j; - if (unlikely(!get_acpi_checksum(acpi_rsdp, RSDP10_LEN))) { - uk_pr_err("ACPI RSDP corrupted\n"); + UK_ASSERT(acpi_rsdt); - acpi_rsdp = NULL; - return -ENOENT; - } + for (i = 0; i < acpi_rsdt_entries; i++) + for (j = 0; j < ARRAY_SIZE(acpi_sdts); j++) { + if (*acpi_sdts[j].sdt) + continue; - uk_pr_info("ACPI version detected: "); - if (acpi_rsdp->revision == 0) { - uk_pr_info("1.0\n"); + h = (struct acpi_sdt_hdr *)get_rsdt_entry(i); + sig = acpi_sdts[j].sig; - acpi_version = 1; - } else { - uk_pr_info(">= 2\n"); + if (!memcmp(h->sig, sig, ACPI_SDT_SIG_LEN)) { + if (unlikely(get_acpi_checksum(h, + h->tab_len))) { + uk_pr_warn("ACPI %s corrupted\n", sig); - /* - * TODO: add support for ACPI version 2 and greater - */ - uk_pr_err("ACPI version not supported\n"); + continue; + } - return -ENOTSUP; - } + *acpi_sdts[j].sdt = h; - return 0; + continue; + } + } } /* - * Find the ACPI Root System Descriptor Table (RSDT) and check if it's valid. + * Print the detected ACPI tables to the debug output. */ - -static int acpi10_find_rsdt(void) +#ifdef UK_DEBUG +static void acpi_list_tables(void) { - UK_ASSERT(acpi_version == 1); - UK_ASSERT(acpi_rsdp); + int i; - acpi_rsdt = (struct acpi_rsdt *)((__uptr)acpi_rsdp->rsdt_paddr); - uk_pr_debug("ACPI RSDT present at %p\n", acpi_rsdt); + UK_ASSERT(acpi_rsdt); - if (unlikely(!get_acpi_checksum(&acpi_rsdt->hdr, - acpi_rsdt->hdr.tab_len))) { - uk_pr_err("ACPI RSDT corrupted\n"); + uk_pr_debug("%d ACPI tables found from %.4s\n", acpi_rsdt_entries, + acpi10 ? ACPI_RSDT_SIG : ACPI_XSDT_SIG); + for (i = 0; i < ARRAY_SIZE(acpi_sdts); i++) { + if (!acpi_sdts[i].sdt) + continue; - acpi_rsdt = NULL; - return -ENOENT; + uk_pr_debug("%p: %.4s\n", acpi_sdts[i].sdt, acpi_sdts[i].sig); } - - return 0; } +#endif /* UK_DEBUG */ -/* - * Find the Multiple APIC Descriptor Table (MADT) in the RSDT and check if - * it's valid. MADT can be found by searching for the string "APIC" in the - * first 4 bytes of each table entry. - */ - -static int acpi10_find_madt(void) +#if defined(__X86_64__) +static struct acpi_rsdp *acpi_get_bios_rom_rsdp(void) { - int entries, i; - struct acpi_sdt_hdr *h; + __paddr_t ptr; - UK_ASSERT(acpi_version == 1); - UK_ASSERT(acpi_rsdt); - UK_ASSERT(!acpi_madt); - - entries = RSDT_ENTRIES(acpi_rsdt); - - for (i = 0; i < entries; i++) { - h = (struct acpi_sdt_hdr *)((__uptr)acpi_rsdt->entry[i]); + for (ptr = BIOS_ROM_START; ptr < BIOS_ROM_END; ptr += BIOS_ROM_STEP) + if (!memcmp((void *)ptr, RSDP_SIG, sizeof(RSDP_SIG) - 1)) { + uk_pr_debug("ACPI RSDP present at %lx\n", ptr); - if (memcmp(h->sig, "APIC", 4) != 0) - continue; /* Not an APIC entry */ - - uk_pr_debug("ACPI MADT present at %p\n", h); - - if (unlikely(!get_acpi_checksum(h, h->tab_len))) { - uk_pr_err("ACPI MADT corrupted\n"); - return -ENOENT; + return (struct acpi_rsdp *)ptr; } - acpi_madt = (struct acpi_madt *)h; - return 0; - } + return NULL; +} +#endif - /* no MADT was found */ - return -ENOENT; +static struct acpi_rsdp *acpi_get_rsdp(void) +{ + return acpi_get_bios_rom_rsdp(); } /* - * Print the detected ACPI tables to the debug output. + * Detect ACPI version and discover ACPI tables. */ - -#ifdef UK_DEBUG -static void acpi10_list_tables(void) +int acpi_init(void) { - int entries, i; + struct acpi_rsdp *rsdp; struct acpi_sdt_hdr *h; - UK_ASSERT(acpi_version == 1); - UK_ASSERT(acpi_rsdt); - - entries = RSDT_ENTRIES(acpi_rsdt); + rsdp = acpi_get_rsdp(); + if (unlikely(!rsdp)) + return -ENOENT; - uk_pr_debug("%d ACPI tables found\n", entries); + if (unlikely(get_acpi_checksum(rsdp, RSDP10_LEN))) { + uk_pr_err("ACPI 1.0 RSDP corrupted\n"); - for (i = 0; i < entries; i++) { - h = (struct acpi_sdt_hdr *)((__uptr)acpi_rsdt->entry[i]); - uk_pr_debug("%p: %.4s\n", h, h->sig); + return -ENOENT; } -} -#endif /* UK_DEBUG */ - -/* - * Initialize ACPI 1.0 data structures. - */ - -static int acpi10_init(void) -{ - int ret; - - UK_ASSERT(acpi_version == 1); - if ((ret = acpi10_find_rsdt()) != 0) - return ret; + if (rsdp->revision == 0) { + h = (struct acpi_sdt_hdr *)((__uptr)rsdp->rsdt_paddr); + acpi_rsdt_entries = (h->tab_len - sizeof(*h)) / 4; + acpi10 = 1; + } else { + if (unlikely(get_acpi_checksum(rsdp, sizeof(*rsdp)))) { + uk_pr_err("ACPI 1.0 RSDP corrupted\n"); -#ifdef UK_DEBUG - acpi10_list_tables(); -#endif + return -ENOENT; + } - if ((ret = acpi10_find_madt()) != 0) - return ret; + h = (struct acpi_sdt_hdr *)rsdp->xsdt_paddr; + acpi_rsdt_entries = (h->tab_len - sizeof(*h)) / 8; + } - return 0; -} + UK_ASSERT(h); -/* - * Detect ACPI version and discover ACPI tables. - */ + if (unlikely(get_acpi_checksum(h, h->tab_len))) { + uk_pr_err("ACPI RSDT corrupted\n"); -int acpi_init(void) -{ - int ret; + return -ENOENT; + } - UK_ASSERT(!acpi_version); + acpi_rsdt = h; - if ((ret = detect_acpi_version()) != 0) - return ret; + acpi_init_tables(); - /* Try to initialize the respective ACPI support. If it fails, we reset - * acpi_version to indicate that ACPI support is not provided. - */ - if (acpi_version == 1) { - if ((ret = acpi10_init()) != 0) { - acpi_version = 0; - return ret; - } - } else { - UK_ASSERT(!acpi_version); - return -ENOTSUP; - } +#ifdef UK_DEBUG + acpi_list_tables(); +#endif return 0; } -/* - * Return detected ACPI version. - */ - -int acpi_get_version(void) -{ - return acpi_version; -} /* * Return the Multiple APIC Descriptor Table (MADT). */ - struct acpi_madt *acpi_get_madt(void) { - UK_ASSERT(acpi_version); - UK_ASSERT(acpi_madt); - return acpi_madt; } diff --git a/plat/common/x86/lcpu.c b/plat/common/x86/lcpu.c index f2f921b5e..80226f9ad 100644 --- a/plat/common/x86/lcpu.c +++ b/plat/common/x86/lcpu.c @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include