]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
plat/ukplatkvm: Provide ACPI structures and functionalities
authorcristian-vijelie <cristianvijelie@gmail.com>
Fri, 25 Jun 2021 16:08:22 +0000 (19:08 +0300)
committerUnikraft <monkey@unikraft.io>
Wed, 30 Jun 2021 14:07:10 +0000 (14:07 +0000)
Signed-off-by: cristian-vijelie <cristianvijelie@gmail.com>
Reviewed-by: Marc Rittinghaus <marc.rittinghaus@kit.edu>
Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Pull-Request: #183

plat/common/include/x86/acpi/acpi.h [new file with mode: 0644]
plat/common/include/x86/acpi/madt.h [new file with mode: 0644]
plat/common/include/x86/acpi/sdt.h [new file with mode: 0644]
plat/kvm/Makefile.uk
plat/kvm/x86/acpi.c [new file with mode: 0644]
plat/kvm/x86/pagetable.S
plat/kvm/x86/setup.c

diff --git a/plat/common/include/x86/acpi/acpi.h b/plat/common/include/x86/acpi/acpi.h
new file mode 100644 (file)
index 0000000..217f45e
--- /dev/null
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Vijelie <cristianvijelie@gmail.com>
+ *
+ * Copyright (c) 2021, 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PLAT_CMN_X86_ACPI_H__
+#define __PLAT_CMN_X86_ACPI_H__
+
+#include <x86/acpi/sdt.h>
+#include <x86/acpi/madt.h>
+
+struct RSDPDescriptor {
+       char Signature[8];
+       __u8 Checksum;
+       char OEMID[6];
+       __u8 Revision;
+       __u32 RsdtAddress;
+} __packed;
+
+struct RSDPDescriptor20 {
+       struct RSDPDescriptor v1;
+
+       __u32 Length;
+       __u64 XsdtAddress;
+       __u8 ExtendedChecksum;
+       __u8 Reserved[3];
+} __packed;
+
+/* Error codes returned by acpi_init */
+#define ACPI_INVALID_TABLE      -1
+#define ACPI_NOT_IMPLEMENTED    -2
+
+/**
+ * Detect ACPI version and discover ACPI tables.
+ *
+ * @return 0 on success, one of the ACPI_* error codes otherwise.
+ */
+int acpi_init(void);
+
+/**
+ * Return the detected ACPI version.
+ *
+ * @return 0 if ACPI is not initialized or initialization failed, ACPI version
+ *    otherwise.
+ */
+int acpi_get_version(void);
+
+#endif /* __PLAT_CMN_X86_ACPI_H__ */
diff --git a/plat/common/include/x86/acpi/madt.h b/plat/common/include/x86/acpi/madt.h
new file mode 100644 (file)
index 0000000..8513647
--- /dev/null
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Vijelie <cristianvijelie@gmail.com>
+ *
+ * Copyright (c) 2021, 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PLAT_CMN_X86_MADT_H__
+#define __PLAT_CMN_X86_MADT_H__
+
+#include <uk/arch/types.h>
+#include <x86/acpi/sdt.h>
+#include <uk/essentials.h>
+
+struct MADT {
+       struct ACPISDTHeader h;
+       __u32 LocalAPICAddress;
+       __u32 Flags;
+       __u8 Entries[];
+} __packed;
+
+struct MADTEntryHeader {
+       __u8 Type;
+       __u8 Length;
+} __packed;
+
+/*
+ * The following structures are declared according to the ACPI
+ * specification version 6.3.
+ *
+ * TODO: This header includes structures that are not related to x86. However,
+ * we move the header when integrating other architectures.
+ */
+
+/* Processor Local APIC Structure */
+struct MADTType0Entry {
+       struct MADTEntryHeader eh;
+       __u8 ACPIProcessorID;
+       __u8 APICID;
+       __u32 Flags;
+} __packed;
+
+/* I/O APIC Structure */
+struct MADTType1Entry {
+       struct MADTEntryHeader eh;
+       __u8 IOAPICID;
+       __u8 Reserved;
+       __u32 IOAPICAddress;
+       __u32 GlobalSystemInterruptBase;
+} __packed;
+
+/* Interrupt Source Override Structure */
+struct MADTType2Entry {
+       struct MADTEntryHeader eh;
+       __u8 BusSource;
+       __u8 IRQSource;
+       __u32 GlobalSystemInterrupt;
+       __u16 Flags;
+} __packed;
+
+/* Non-Maskable Interrupt (NMI) Source Structure */
+struct MADTType3Entry {
+       struct MADTEntryHeader eh;
+       __u16 Flags;
+       __u32 GlobalSystemInterrupt;
+} __packed;
+
+/* Local APIC NMI Structure */
+struct MADTType4Entry {
+       struct MADTEntryHeader eh;
+       __u8 ACPIProcessorID;
+       __u16 Flags;
+       __u8 LINT;
+} __packed;
+
+/* Local APIC Address Override Structure */
+struct MADTType5Entry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u64 LAPICOverride;
+} __packed;
+
+/* I/O SAPIC Structure */
+struct MADTType6Entry {
+       struct MADTEntryHeader eh;
+       __u8 IOAPICID;
+       __u8 Reserved;
+       __u32 GlobalSystemInterruptBase;
+       __u64 IOSAPICAddress;
+} __packed;
+
+/* Local SAPIC Structure */
+struct MADTType7Entry {
+       struct MADTEntryHeader eh;
+       __u8 ACPIProcessorID;
+       __u8 LocalSAPICID;
+       __u8 LocalSAPICEID;
+       __u8 Reserved[3];
+       __u32 Flags;
+       __u32 ACPIProcessorUIDValue;
+       __u32 ACPIProcessorUIDString[];
+} __packed;
+
+/* Platform Interrupt Source Structure */
+struct MADTType8Entry {
+       struct MADTEntryHeader eh;
+       __u16 Flags;
+       __u8 InterruptType;
+       __u8 ProcessorID;
+       __u8 ProcessorEID;
+       __u8 IOSAPICVector;
+       __u32 GlobalSystemInterrupt;
+       __u32 PlatformInterruptSourceFlags;
+} __packed;
+
+/* Processor Local x2APIC Structure */
+struct MADTType9Entry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u32 X2APICID;
+       __u32 Flags;
+       __u32 ACPIProcessorUID;
+} __packed;
+
+/* Local x2APIC NMI Structure */
+struct MADTTypeAEntry {
+       struct MADTEntryHeader eh;
+       __u16 Flags;
+       __u32 ACPIProcessorUID;
+       __u8 Localx2APICLINTNr;
+       __u8 Reserved[3];
+} __packed;
+
+/* GIC CPU Interface (GICC) Structure */
+struct MADTTypeBEntry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u32 CPUInterfaceNumber;
+       __u32 ACPIProcessorUID;
+       __u32 Flags;
+       __u32 ParkingProtocolVersion;
+       __u32 PerformanceInterruptGSIV;
+       __u64 ParkedAddress;
+       __u64 PhysicalBaseAddress;
+       __u64 GICV;
+       __u64 GICH;
+       __u32 VGICMaintenanceInterrupt;
+       __u64 GICRBaseAddress;
+       __u64 MPIDR;
+       __u8 ProcessorPowerEfficiencyClass;
+       __u8 Reserved2;
+       __u16 SPEOverflowInterrupt;
+} __packed;
+
+/* GIC Distributor (GICD) Structure */
+struct MADTTypeCEntry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u32 GICID;
+       __u64 PhysicalBaseAddress;
+       __u32 SystemVectorBase;
+       __u8 GICVersion;
+       __u8 Reserved2[3];
+} __packed;
+
+/* GIC MSI Frame Structure */
+struct MADTTypeDEntry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u32 GICMSIFrameID;
+       __u64 PhysicalBaseAddress;
+       __u32 Flags;
+       __u16 SPICount;
+       __u16 SPIBase;
+} __packed;
+
+/* GIC Redistributor (GICR) Structure */
+struct MADTTypeEEntry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u64 DiscoveryRangeBaseAddress;
+       __u64 DiscoveryRangeLength;
+} __packed;
+
+/* GIC Interrupt Translation Service (ITS) Structure */
+struct MADTTypeFEntry {
+       struct MADTEntryHeader eh;
+       __u16 Reserved;
+       __u32 GICITSID;
+       __u64 PhysicalBaseAddress;
+       __u32 Reserved2;
+} __packed;
+
+/* Multiprocessor Wakeup Structure */
+struct MADTType10Entry {
+       struct MADTEntryHeader eh;
+       __u16 MailBoxVersion;
+       __u32 Reserved;
+       __u64 MailBoxAddress;
+} __packed;
+
+/**
+ * Return the Multiple APIC Descriptor Table (MADT). ACPI needs to be
+ * initialized first.
+ *
+ * @return Pointer to MADT.
+ */
+struct MADT *acpi_get_madt(void);
+
+#endif /* __PLAT_CMN_X86_MADT_H__ */
diff --git a/plat/common/include/x86/acpi/sdt.h b/plat/common/include/x86/acpi/sdt.h
new file mode 100644 (file)
index 0000000..8b68b7b
--- /dev/null
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Vijelie <cristianvijelie@gmail.com>
+ *
+ * Copyright (c) 2021, 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PLAT_CMN_X86_SDT_H__
+#define __PLAT_CMN_X86_SDT_H__
+
+#include <uk/arch/types.h>
+#include <uk/essentials.h>
+
+struct ACPISDTHeader {
+       char Signature[4];
+       __u32 Length;
+       __u8 Revision;
+       __u8 Checksum;
+       char OEMID[6];
+       char OEMTableID[8];
+       __u32 OEMRevision;
+       __u32 CreatorID;
+       __u32 CreatorRevision;
+} __packed;
+
+struct RSDT {
+       struct ACPISDTHeader h;
+       __u32 Entry[];
+} __packed;
+
+struct XSDT {
+       struct ACPISDTHeader h;
+       __u64 Entry[];
+} __packed;
+
+#endif /* __PLAT_CMN_X86_SDT_H__ */
index 94321e0c639a0892be73030284aeed5648475a5d..82e4ba3590a4d561d1d8b1bc53f8aeef931c684b 100644 (file)
@@ -64,6 +64,9 @@ LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/intctrl.c
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/tscclock.c
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/time.c
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/memory.c|x86
+# ifeq ($(CONFIG_HAVE_SMP),y)
+LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/acpi.c
+# endif
 ifeq ($(findstring y,$(CONFIG_KVM_KERNEL_VGA_CONSOLE) $(CONFIG_KVM_DEBUG_VGA_CONSOLE)),y)
 LIBKVMPLAT_SRCS-$(CONFIG_ARCH_X86_64) += $(LIBKVMPLAT_BASE)/x86/vga_console.c
 endif
diff --git a/plat/kvm/x86/acpi.c b/plat/kvm/x86/acpi.c
new file mode 100644 (file)
index 0000000..2a466e9
--- /dev/null
@@ -0,0 +1,288 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Cristian Vijelie <cristianvijelie@gmail.com>
+ *
+ * Copyright (c) 2021, 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
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <uk/print.h>
+#include <string.h>
+#include <x86/acpi/acpi.h>
+#include <x86/acpi/madt.h>
+#include <uk/assert.h>
+
+#define RSDT_ENTRIES(rsdt) (((rsdt)->h.Length - sizeof((rsdt)->h)) / 4)
+
+static __u8 acpi_version;
+static struct RSDPDescriptor *acpi_rsdp;
+static struct RSDT *acpi_rsdt;
+static struct MADT *acpi_madt;
+
+/*
+ * Compute checksum for ACPI RSDP table.
+ */
+
+static inline int verify_rsdp_checksum(struct RSDPDescriptor *rsdp)
+{
+       __u8 checksum = 0;
+       __u8 *ptr = (__u8 *)rsdp;
+
+       while (ptr < (__u8 *)(rsdp + 1))
+               checksum += *ptr++;
+
+       return checksum == 0 ? 0 : -1;
+}
+
+/*
+ * Compute checksum for any ACPI table, except RSDP.
+ */
+
+static inline int verify_acpi_checksum(struct ACPISDTHeader *h)
+{
+       __u8 checksum = 0;
+       __u32 i;
+
+       for (i = 0; i < h->Length; i++)
+               checksum += ((__u8 *)h)[i];
+
+       return checksum == 0 ? 0 : -1;
+}
+
+/**
+ * Find the Root System Descriptor Pointer (RSDP) in the physical memory area
+ * 0xe0000 -> 0xfffff and determine ACPI version.
+ *
+ * @return ACPI_INVALID_TABLE if the table is not found, or invalid,
+ * ACPI_NOT_IMPLEMENTED if the ACPI version is >= 2, 0 otherwise.
+ */
+
+static int detect_acpi_version(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 RSDPDescriptor *)ptr;
+                       uk_pr_debug("ACPI RSDP present at %p\n", ptr);
+                       break;
+               }
+       }
+
+       if (!acpi_rsdp) {
+               uk_pr_debug("ACPI RSDP not found\n");
+               return ACPI_INVALID_TABLE;
+       }
+
+       if (verify_rsdp_checksum(acpi_rsdp) != 0) {
+               uk_pr_err("ACPI RSDP corrupted\n");
+
+               acpi_rsdp = NULL;
+               return ACPI_INVALID_TABLE;
+       }
+
+       uk_pr_info("ACPI version detected: ");
+       if (acpi_rsdp->Revision == 0) {
+               uk_pr_info("1.0\n");
+
+               acpi_version = 1;
+       } else {
+               uk_pr_info(">= 2\n");
+
+               /*
+                * TODO: add support for ACPI version 2 and greater
+                */
+               uk_pr_err("ACPI version not supported\n");
+
+               return ACPI_NOT_IMPLEMENTED;
+       }
+
+       return 0;
+}
+
+/*
+ * Find the ACPI Root System Descriptor Table (RSDT) and check if it's valid.
+ */
+
+static int acpi10_find_rsdt(void)
+{
+       UK_ASSERT(acpi_version == 1);
+       UK_ASSERT(acpi_rsdp);
+
+       acpi_rsdt = (struct RSDT *)((__uptr)acpi_rsdp->RsdtAddress);
+       uk_pr_debug("ACPI RSDT present at %p\n", acpi_rsdt);
+
+       if (verify_acpi_checksum(&acpi_rsdt->h) != 0) {
+               uk_pr_err("ACPI RSDT corrupted\n");
+
+               acpi_rsdt = NULL;
+               return ACPI_INVALID_TABLE;
+       }
+
+       return 0;
+}
+
+/*
+ * 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)
+{
+       int entries, i;
+       struct ACPISDTHeader *h;
+
+       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 ACPISDTHeader *)((__uptr)acpi_rsdt->Entry[i]);
+
+               if (memcmp(h->Signature, "APIC", 4) != 0)
+                       continue; /* Not an APIC entry */
+
+               uk_pr_debug("ACPI MADT present at %p\n", h);
+
+               if (verify_acpi_checksum(h) != 0) {
+                       uk_pr_err("ACPI MADT corrupted\n");
+                       return ACPI_INVALID_TABLE;
+               }
+
+               acpi_madt = (struct MADT *)h;
+               return 0;
+       }
+
+       /* no MADT was found */
+       return ACPI_INVALID_TABLE;
+}
+
+/*
+ * Print the detected ACPI tables to the debug output.
+ */
+
+#ifdef UK_DEBUG
+static void acpi10_list_tables(void)
+{
+       int entries, i;
+       struct ACPISDTHeader *h;
+
+       UK_ASSERT(acpi_version == 1);
+       UK_ASSERT(acpi_rsdt);
+
+       entries = RSDT_ENTRIES(acpi_rsdt);
+
+       uk_pr_debug("%d ACPI tables found\n", entries);
+
+       for (i = 0; i < entries; i++) {
+               h = (struct ACPISDTHeader *)((__uptr)acpi_rsdt->Entry[i]);
+               uk_pr_debug("%p: %.4s\n", h, h->Signature);
+       }
+}
+#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;
+
+#ifdef UK_DEBUG
+       acpi10_list_tables();
+#endif
+
+       if ((ret = acpi10_find_madt()) != 0)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * Detect ACPI version and discover ACPI tables.
+ */
+
+int acpi_init(void)
+{
+       int ret;
+
+       UK_ASSERT(!acpi_version);
+
+       if ((ret = detect_acpi_version()) != 0)
+               return ret;
+
+       /* 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 ACPI_NOT_IMPLEMENTED;
+       }
+
+       return 0;
+}
+
+/*
+ * Return detected ACPI version.
+ */
+
+int acpi_get_version(void)
+{
+       return acpi_version;
+}
+
+/*
+ * Return the Multiple APIC Descriptor Table (MADT).
+ */
+
+struct MADT *acpi_get_madt(void)
+{
+       UK_ASSERT(acpi_version);
+       UK_ASSERT(acpi_madt);
+
+       return acpi_madt;
+}
index 156ccf8a94fb35bc79590d7d7e2d2b61170914de..9b23c39ebb9177c775c4061acf3b5c631597cda4 100644 (file)
@@ -40,6 +40,7 @@ cpu_zeropt:
        /* the first 1M is inaccessible, except for:
           0x09000 - 0x09fff -> multiboot info @ 0x09500 (read-only)
           0xb8000 - 0xbffff -> VGA buffer (read+write)
+          0xe0000 - 0xfffff -> BIOS read-only memory
         */
        .fill 0x9, 0x8, 0x0
        .quad 0x0000000000009000 + PAGETABLE_RO
@@ -59,7 +60,39 @@ cpu_zeropt:
        .quad 0x00000000000bd000 + PAGETABLE_RW
        .quad 0x00000000000be000 + PAGETABLE_RW
        .quad 0x00000000000bf000 + PAGETABLE_RW
-       .fill 0x40, 0x8, 0x0
+       .fill 0x20, 0x8, 0x0
+       .quad 0x00000000000e0000 + PAGETABLE_RO
+       .quad 0x00000000000e1000 + PAGETABLE_RO
+       .quad 0x00000000000e2000 + PAGETABLE_RO
+       .quad 0x00000000000e3000 + PAGETABLE_RO
+       .quad 0x00000000000e4000 + PAGETABLE_RO
+       .quad 0x00000000000e5000 + PAGETABLE_RO
+       .quad 0x00000000000e6000 + PAGETABLE_RO
+       .quad 0x00000000000e7000 + PAGETABLE_RO
+       .quad 0x00000000000e8000 + PAGETABLE_RO
+       .quad 0x00000000000e9000 + PAGETABLE_RO
+       .quad 0x00000000000ea000 + PAGETABLE_RO
+       .quad 0x00000000000eb000 + PAGETABLE_RO
+       .quad 0x00000000000ec000 + PAGETABLE_RO
+       .quad 0x00000000000ed000 + PAGETABLE_RO
+       .quad 0x00000000000ee000 + PAGETABLE_RO
+       .quad 0x00000000000ef000 + PAGETABLE_RO
+       .quad 0x00000000000f0000 + PAGETABLE_RO
+       .quad 0x00000000000f1000 + PAGETABLE_RO
+       .quad 0x00000000000f2000 + PAGETABLE_RO
+       .quad 0x00000000000f3000 + PAGETABLE_RO
+       .quad 0x00000000000f4000 + PAGETABLE_RO
+       .quad 0x00000000000f5000 + PAGETABLE_RO
+       .quad 0x00000000000f6000 + PAGETABLE_RO
+       .quad 0x00000000000f7000 + PAGETABLE_RO
+       .quad 0x00000000000f8000 + PAGETABLE_RO
+       .quad 0x00000000000f9000 + PAGETABLE_RO
+       .quad 0x00000000000fa000 + PAGETABLE_RO
+       .quad 0x00000000000fb000 + PAGETABLE_RO
+       .quad 0x00000000000fc000 + PAGETABLE_RO
+       .quad 0x00000000000fd000 + PAGETABLE_RO
+       .quad 0x00000000000fe000 + PAGETABLE_RO
+       .quad 0x00000000000ff000 + PAGETABLE_RO
        .quad 0x00000000000100000 + PAGETABLE_RW
        .quad 0x00000000000101000 + PAGETABLE_RW
        .quad 0x00000000000102000 + PAGETABLE_RW
index fbc5c0d212287509cb2edcf8f722bdee8be8a861..a90bc78c5074d45b4ffea6dfc34c444c872a22b2 100644 (file)
@@ -40,6 +40,7 @@
 #include <uk/plat/console.h>
 #include <uk/assert.h>
 #include <uk/essentials.h>
+#include <x86/acpi/acpi.h>
 
 #define PLATFORM_MEM_START 0x100000
 #define PLATFORM_MAX_MEM_ADDR 0x40000000
@@ -287,6 +288,10 @@ void _libkvmplat_entry(void *arg)
        uk_pr_info("     stack top: %p\n",
                   (void *) _libkvmplat_cfg.bstack.start);
 
+#ifdef CONFIG_HAVE_SMP
+       acpi_init();
+#endif /* CONFIG_HAVE_SMP */
+
 #ifdef CONFIG_HAVE_SYSCALL
        _init_syscall();
 #endif /* CONFIG_HAVE_SYSCALL */