From 97b8dd5d0a0183a940de5613aa095c3977ccd4e2 Mon Sep 17 00:00:00 2001 From: tkchia Date: Wed, 13 Sep 2023 15:47:43 +0000 Subject: [PATCH] [metal] Rewrite ACPI code to avoid using kmalloc() --- libc/irq/acpi-madt.c | 23 ++++++++++++----------- libc/irq/acpi-xsdt.c | 37 ++++++++++++++++++++++++++++++++++--- libc/irq/acpi.internal.h | 1 + 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/libc/irq/acpi-madt.c b/libc/irq/acpi-madt.c index 2330b6956..623f2bcc5 100644 --- a/libc/irq/acpi-madt.c +++ b/libc/irq/acpi-madt.c @@ -25,7 +25,6 @@ │ OTHER DEALINGS IN THE SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" -#include "libc/intrin/kmalloc.h" #include "libc/inttypes.h" #include "libc/irq/acpi.internal.h" @@ -60,18 +59,20 @@ textstartup void _AcpiMadtInit(void) { p += h->Length; } ACPI_INFO("MADT: %zu I/O APIC(s)", num_io_apics); - _AcpiIoApics = kmalloc(num_io_apics * sizeof(const AcpiMadtIoApic *)); - icp = _AcpiIoApics; - p = madt->Subtable; - while (p != madt_end) { - h = (const AcpiSubtableHeader *)p; - switch (h->Type) { - case kAcpiMadtIoApic: - *icp++ = (const AcpiMadtIoApic *)p; + icp = _AcpiOsAllocate(num_io_apics * sizeof(const AcpiMadtIoApic *)); + if (icp) { + _AcpiIoApics = icp; + p = madt->Subtable; + while (p != madt_end) { + h = (const AcpiSubtableHeader *)p; + switch (h->Type) { + case kAcpiMadtIoApic: + *icp++ = (const AcpiMadtIoApic *)p; + } + p += h->Length; } - p += h->Length; + _AcpiNumIoApics = num_io_apics; } - _AcpiNumIoApics = num_io_apics; } } diff --git a/libc/irq/acpi-xsdt.c b/libc/irq/acpi-xsdt.c index c060b2ec5..835cb66f7 100644 --- a/libc/irq/acpi-xsdt.c +++ b/libc/irq/acpi-xsdt.c @@ -25,8 +25,9 @@ │ OTHER DEALINGS IN THE SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/dce.h" +#include "libc/intrin/atomic.h" #include "libc/intrin/bits.h" -#include "libc/intrin/kmalloc.h" +#include "libc/intrin/directmap.internal.h" #include "libc/intrin/kprintf.h" #include "libc/irq/acpi.internal.h" #include "libc/log/color.internal.h" @@ -34,6 +35,8 @@ #include "libc/nt/efi.h" #include "libc/runtime/pc.internal.h" #include "libc/str/str.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" #ifdef __x86_64__ @@ -55,6 +58,34 @@ textstartup void *_AcpiOsMapUncachedMemory(uintptr_t phy, size_t n) { return (void *)(BANE + phy); } +textstartup static void *_AcpiOsAllocatePages(size_t n) { + struct DirectMap dm = sys_mmap_metal(NULL, n, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + void *addr = dm.addr; + if (addr == (void *)-1) addr = NULL; + return addr; +} + +textstartup void *_AcpiOsAllocate(size_t n) { + static _Atomic(char *) slack = NULL; + char *addr = NULL; + size_t align = __BIGGEST_ALIGNMENT__, use; + if (n >= 4096) return _AcpiOsAllocatePages(n); + n = ROUNDUP(n, align); + for (;;) { + addr = atomic_exchange(&slack, NULL); + if (!addr) { + addr = _AcpiOsAllocatePages(4096); + if (!addr) return NULL; + } + use = (uintptr_t)addr % 4096 + n; + if (use <= 4096) { + if (use < 4096) atomic_store(&slack, addr + n); + return addr; + } + } +} + textstartup static uint8_t _AcpiTbChecksum(const uint8_t *p, size_t n) { uint8_t c = 0; while (n-- != 0) c += *p++; @@ -169,7 +200,7 @@ textstartup void _AcpiXsdtInit(void) { const AcpiTableRsdt *rsdt = _AcpiMapTable(rsdp->RsdtPhysicalAddress); nents = (rsdt->Header.Length - sizeof(rsdt->Header)) / sizeof(uint32_t); ACPI_INFO("RSDT @ %p, %#zx entries", rsdt, nents); - ents = kmalloc(nents * sizeof(AcpiTableHeader *)); + ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *)); if (ents) { for (i = 0; i < nents; ++i) { ents[i] = _AcpiMapTable(rsdt->TableOffsetEntry[i]); @@ -179,7 +210,7 @@ textstartup void _AcpiXsdtInit(void) { const AcpiTableXsdt *xsdt = _AcpiMapTable(rsdp->XsdtPhysicalAddress); nents = (xsdt->Header.Length - sizeof(xsdt->Header)) / sizeof(uint64_t); ACPI_INFO("XSDT @ %p, %#zx entries", xsdt, nents); - ents = kmalloc(nents * sizeof(AcpiTableHeader *)); + ents = _AcpiOsAllocate(nents * sizeof(AcpiTableHeader *)); if (ents) { for (i = 0; i < nents; ++i) { ents[i] = _AcpiMapTable(xsdt->TableOffsetEntry[i]); diff --git a/libc/irq/acpi.internal.h b/libc/irq/acpi.internal.h index 0caaf3d13..f8175953d 100644 --- a/libc/irq/acpi.internal.h +++ b/libc/irq/acpi.internal.h @@ -212,6 +212,7 @@ extern uint32_t _AcpiMadtFlags; extern const AcpiMadtIoApic **_AcpiIoApics; extern void *_AcpiOsMapUncachedMemory(uintptr_t, size_t); +extern void *_AcpiOsAllocate(size_t); extern void *_AcpiMapTable(uintptr_t); extern AcpiStatus _AcpiGetTableImpl(uint32_t, uint32_t, void **);