Maximilian Stein has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/42824 )

Change subject: arch-x86: Implement ACPI root tables
......................................................................

arch-x86: Implement ACPI root tables

The RSDP points to the RSDT (32 bit) and/or the XSDT (64 bit), which are
both instances of the abstract System Description Table.
This commit implements the mechanism to write the three data structures
to memory based on the full system's configuration. The SysDescTable
class acts as base class for the RSDT and XSDT as well as any future
implementation of other System Description Tables.

Change-Id: I710279a72376c04f2a636ff2e96fa80228d03eaf
Signed-off-by: Maximilian Stein <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42824
Reviewed-by: Gabe Black <[email protected]>
Maintainer: Gabe Black <[email protected]>
Tested-by: kokoro <[email protected]>
---
M src/arch/x86/SConscript
M src/arch/x86/bios/ACPI.py
M src/arch/x86/bios/acpi.cc
M src/arch/x86/bios/acpi.hh
M src/arch/x86/fs_workload.cc
M src/arch/x86/fs_workload.hh
6 files changed, 248 insertions(+), 52 deletions(-)

Approvals:
  Gabe Black: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index d7da290..9b16fad 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -79,6 +79,7 @@
 DebugFlag('LocalApic', "Local APIC debugging")
 DebugFlag('Decoder', "Decoder debug output")
 DebugFlag('X86', "Generic X86 ISA debugging")
+DebugFlag('ACPI', "ACPI debugging")

 python_files = (
     '__init__.py',
diff --git a/src/arch/x86/bios/ACPI.py b/src/arch/x86/bios/ACPI.py
index 77de42f..19edac4 100644
--- a/src/arch/x86/bios/ACPI.py
+++ b/src/arch/x86/bios/ACPI.py
@@ -48,8 +48,8 @@
     oem_table_id = Param.String('', 'oem table ID')
     oem_revision = Param.UInt32(0, 'oem revision number for the table')

-    creator_id = Param.String('',
-            'string identifying the generator of the table')
+    creator_id = Param.UInt32(0,
+            'ID identifying the generator of the table')
     creator_revision = Param.UInt32(0,
             'revision number for the creator of the table')

@@ -78,6 +78,7 @@
     # here.
     revision = Param.UInt8(2, 'revision of ACPI being used, zero indexed')

-    rsdt = Param.X86ACPIRSDT(NULL, 'root system description table')
+    rsdt = Param.X86ACPIRSDT(X86ACPIRSDT(),
+            'root system description table')
     xsdt = Param.X86ACPIXSDT(X86ACPIXSDT(),
             'extended system description table')
diff --git a/src/arch/x86/bios/acpi.cc b/src/arch/x86/bios/acpi.cc
index 8cdcdac..91c8e47 100644
--- a/src/arch/x86/bios/acpi.cc
+++ b/src/arch/x86/bios/acpi.cc
@@ -37,16 +37,34 @@

 #include "arch/x86/bios/acpi.hh"

+#include <cassert>
+#include <cstring>
+
+#include "base/trace.hh"
 #include "mem/port.hh"
-#include "params/X86ACPIRSDP.hh"
-#include "params/X86ACPIRSDT.hh"
-#include "params/X86ACPISysDescTable.hh"
-#include "params/X86ACPIXSDT.hh"
+#include "mem/port_proxy.hh"
 #include "sim/byteswap.hh"
 #include "sim/sim_object.hh"

+namespace X86ISA
+{
+
+namespace ACPI
+{
+
+const char RSDP::signature[] = "RSD PTR ";
+
+static uint8_t
+apic_checksum(uint8_t* ptr, std::size_t size)
+{
+    uint8_t sum = 0;
+    for (unsigned i = 0; i < size; ++i)
+        sum += ptr[i];
+    return 0x100 - sum;
+}
+
 Addr
-X86ISA::ACPI::LinearAllocator::alloc(std::size_t size, unsigned align)
+LinearAllocator::alloc(std::size_t size, unsigned align)
 {
     if (align) {
         unsigned offset = next % align;
@@ -59,24 +77,124 @@
     return chunk;
 }

-const char X86ISA::ACPI::RSDP::signature[] = "RSD PTR ";
-
-X86ISA::ACPI::RSDP::RSDP(const Params &p) : SimObject(p), oemID(p.oem_id),
-    revision(p.revision), rsdt(p.rsdt), xsdt(p.xsdt)
+RSDP::RSDP(const Params &p) :
+    SimObject(p),
+    rsdt(p.rsdt),
+    xsdt(p.xsdt)
 {}

-X86ISA::ACPI::SysDescTable::SysDescTable(const Params &p,
-        const char * _signature, uint8_t _revision) : SimObject(p),
-    signature(_signature), revision(_revision),
-    oemID(p.oem_id), oemTableID(p.oem_table_id),
-    oemRevision(p.oem_revision),
-    creatorID(p.creator_id), creatorRevision(p.creator_revision)
+Addr
+RSDP::write(PortProxy& phys_proxy, Allocator& alloc) const
+{
+    std::vector<uint8_t> mem(sizeof(Mem));
+    Addr addr = alloc.alloc(mem.size(), 16);
+
+    Mem* data = (Mem*)mem.data();
+    static_assert(sizeof(signature) - 1 == sizeof(data->signature),
+            "signature length mismatch");
+    std::memcpy(data->signature, signature, sizeof(data->signature));
+ std::strncpy(data->oemID, params().oem_id.c_str(), sizeof(data->oemID));
+    data->revision = params().revision;
+    data->length = mem.size();
+
+    if (rsdt) {
+        data->rsdtAddress = rsdt->write(phys_proxy, alloc);
+        DPRINTF(ACPI, "Allocated RSDT @ %llx\n", data->rsdtAddress);
+    }
+    if (xsdt) {
+        data->xsdtAddress = xsdt->write(phys_proxy, alloc);
+        DPRINTF(ACPI, "Allocated XSDT @ %llx\n", data->xsdtAddress);
+    }
+
+    // checksum calculation
+    data->checksum = apic_checksum(mem.data(), sizeof(MemR0));
+    data->extendedChecksum = apic_checksum(mem.data(), mem.size());
+
+    // write the whole thing
+    phys_proxy.writeBlob(addr, mem.data(), mem.size());
+
+    return addr;
+}
+
+Addr
+SysDescTable::writeBuf(PortProxy& phys_proxy, Allocator& alloc,
+        std::vector<uint8_t> &mem) const
+{
+ // An empty SysDescTable doesn't make any sense, so assert that somebody
+    // else allocated a large enough blob.
+    assert(mem.size() >= sizeof(Mem));
+
+    // Allocate a place to write this blob.
+    Addr addr = alloc.alloc(mem.size());
+
+    DPRINTF(ACPI, "Writing system description table [%llx - %llx]\n", addr,
+            addr + mem.size());
+
+    // Fill in the header.
+    auto& p = params();
+    Mem* header = (Mem*)mem.data();
+    std::strncpy(header->signature, signature, sizeof(header->signature));
+    header->length = mem.size();
+    header->revision = revision;
+    std::strncpy(header->oemID, p.oem_id.c_str(), sizeof(header->oemID));
+    std::strncpy(header->oemTableID, p.oem_table_id.c_str(),
+            sizeof(header->oemTableID));
+    header->oemRevision = p.oem_revision;
+    header->creatorID = p.creator_id;
+    header->creatorRevision = p.creator_revision;
+
+    // Update checksum.
+    header->checksum = apic_checksum(mem.data(), mem.size());
+
+    // Write to memory.
+    phys_proxy.writeBlob(addr, mem.data(), mem.size());
+
+    return addr;
+}
+
+//// RSDT, XSDT
+template<class T>
+RXSDT<T>::RXSDT(const Params& p, const char *_signature, uint8_t _revision) :
+    SysDescTable(p, _signature, _revision)
 {}

-X86ISA::ACPI::RSDT::RSDT(const Params &p) :
-    SysDescTable(p, "RSDT", 1), entries(p.entries)
-{}
+template<class T>
+Addr
+RXSDT<T>::writeBuf(PortProxy& phys_proxy, Allocator& alloc,
+        std::vector<uint8_t>& mem) const
+{
+ // Since this table ends with a variably sized array, it can't be extended
+    // by another table type.
+    assert(mem.empty());
+    mem.resize(sizeof(Mem));

-X86ISA::ACPI::XSDT::XSDT(const Params &p) :
-    SysDescTable(p, "XSDT", 1), entries(p.entries)
-{}
+    auto base_size = mem.size();
+    mem.resize(base_size + sizeof(Ptr) * entries.size());
+
+    Ptr* ptr_array = reinterpret_cast<Ptr*>(mem.data() + base_size);
+ DPRINTF(ACPI, "RXSDT: Writing %d entries (ptr size: %d)\n", entries.size(),
+            sizeof(Ptr));
+    for (const auto *entry : entries) {
+        Addr entry_addr = entry->write(phys_proxy, alloc);
+        fatal_if((entry_addr & mask(sizeof(Ptr) * 8)) != entry_addr,
+                "RXSDT: Entry address doesn't fit in pointer type.");
+        DPRINTF(ACPI, "RXSDT: wrote entry @ %llx\n", entry_addr);
+        *ptr_array++ = entry_addr;
+    }
+
+    return SysDescTable::writeBuf(phys_proxy, alloc, mem);
+}
+
+RSDT::RSDT(const Params& p) : RXSDT(p, "RSDT", 1)
+{
+    entries = p.entries;
+}
+
+XSDT::XSDT(const Params& p) : RXSDT(p, "XSDT", 1)
+{
+    entries = p.entries;
+}
+
+} // namespace ACPI
+
+} // namespace X86ISA
diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh
index 6fe0f6e..64f75ea 100644
--- a/src/arch/x86/bios/acpi.hh
+++ b/src/arch/x86/bios/acpi.hh
@@ -39,18 +39,20 @@
 #define __ARCH_X86_BIOS_ACPI_HH__

 #include <string>
+#include <tuple>
+#include <type_traits>
 #include <vector>

+#include "base/compiler.hh"
 #include "base/types.hh"
+#include "debug/ACPI.hh"
+#include "params/X86ACPIRSDP.hh"
+#include "params/X86ACPIRSDT.hh"
+#include "params/X86ACPISysDescTable.hh"
+#include "params/X86ACPIXSDT.hh"
 #include "sim/sim_object.hh"

-class Port;
-
-struct X86ACPIRSDPParams;
-
-struct X86ACPISysDescTableParams;
-struct X86ACPIRSDTParams;
-struct X86ACPIXSDTParams;
+class PortProxy;

 namespace X86ISA
 {
@@ -60,7 +62,6 @@

 class RSDT;
 class XSDT;
-class SysDescTable;

 struct Allocator
 {
@@ -83,56 +84,110 @@
 class RSDP : public SimObject
 {
   protected:
-    typedef X86ACPIRSDPParams Params;
+    PARAMS(X86ACPIRSDP);

     static const char signature[];

-    std::string oemID;
-    uint8_t revision;
+    struct M5_ATTR_PACKED MemR0
+    {
+        // src: https://wiki.osdev.org/RSDP
+        char signature[8] = {};
+        uint8_t checksum = 0;
+        char oemID[6] = {};
+        uint8_t revision = 0;
+        uint32_t rsdtAddress = 0;
+    };
+    static_assert(std::is_trivially_copyable<MemR0>::value,
+            "Type not suitable for memcpy.");

-    RSDT * rsdt;
-    XSDT * xsdt;
+    struct M5_ATTR_PACKED Mem : public MemR0
+    {
+        // since version 2
+        uint32_t length = 0;
+        uint64_t xsdtAddress = 0;
+        uint8_t extendedChecksum = 0;
+        uint8_t _reserved[3] = {};
+    };
+    static_assert(std::is_trivially_copyable<Mem>::value,
+            "Type not suitable for memcpy,");
+
+    RSDT* rsdt;
+    XSDT* xsdt;

   public:
     RSDP(const Params &p);
+
+    Addr write(PortProxy& phys_proxy, Allocator& alloc) const;
 };

 class SysDescTable : public SimObject
 {
   protected:
-    typedef X86ACPISysDescTableParams Params;
+    PARAMS(X86ACPISysDescTable);

-    const char * signature;
+    struct M5_ATTR_PACKED Mem
+    {
+        // src: https://wiki.osdev.org/RSDT
+        char signature[4] = {};
+        uint32_t length = 0;
+        uint8_t revision = 0;
+        uint8_t checksum = 0;
+        char oemID[6] = {};
+        char oemTableID[8] = {};
+        uint32_t oemRevision = 0;
+        uint32_t creatorID = 0;
+        uint32_t creatorRevision = 0;
+    };
+    static_assert(std::is_trivially_copyable<Mem>::value,
+            "Type not suitable for memcpy.");
+
+    virtual Addr writeBuf(PortProxy& phys_proxy, Allocator& alloc,
+            std::vector<uint8_t>& mem) const = 0;
+
+    const char* signature;
     uint8_t revision;

-    std::string oemID;
-    std::string oemTableID;
-    uint32_t oemRevision;
-
-    std::string creatorID;
-    uint32_t creatorRevision;
+ SysDescTable(const Params& p, const char* _signature, uint8_t _revision) :
+        SimObject(p), signature(_signature), revision(_revision)
+    {}

   public:
- SysDescTable(const Params &p, const char * _signature, uint8_t _revision);
+    Addr
+    write(PortProxy& phys_proxy, Allocator& alloc) const
+    {
+        std::vector<uint8_t> mem;
+        return writeBuf(phys_proxy, alloc, mem);
+    }
 };

-class RSDT : public SysDescTable
+template<class T>
+class RXSDT : public SysDescTable
 {
   protected:
-    typedef X86ACPIRSDTParams Params;
+    using Ptr = T;

     std::vector<SysDescTable *> entries;

+    Addr writeBuf(PortProxy& phys_proxy, Allocator& alloc,
+            std::vector<uint8_t>& mem) const override;
+
+  protected:
+    RXSDT(const Params& p, const char* _signature, uint8_t _revision);
+};
+
+class RSDT : public RXSDT<uint32_t>
+{
+  protected:
+    PARAMS(X86ACPIRSDT);
+
   public:
     RSDT(const Params &p);
 };

-class XSDT : public SysDescTable
+class XSDT : public RXSDT<uint64_t>
 {
   protected:
-    typedef X86ACPIXSDTParams Params;
-
-    std::vector<SysDescTable *> entries;
+    PARAMS(X86ACPIXSDT);

   public:
     XSDT(const Params &p);
diff --git a/src/arch/x86/fs_workload.cc b/src/arch/x86/fs_workload.cc
index 381ab4f..f9818c5 100644
--- a/src/arch/x86/fs_workload.cc
+++ b/src/arch/x86/fs_workload.cc
@@ -38,11 +38,13 @@

 #include "arch/x86/fs_workload.hh"

+#include "arch/x86/bios/acpi.hh"
 #include "arch/x86/bios/intelmp.hh"
 #include "arch/x86/bios/smbios.hh"
 #include "arch/x86/faults.hh"
 #include "base/loader/object_file.hh"
 #include "cpu/thread_context.hh"
+#include "debug/ACPI.hh"
 #include "params/X86FsWorkload.hh"
 #include "sim/system.hh"

@@ -330,6 +332,10 @@
     // Write out the Intel MP Specification configuration table.
     writeOutMPTable(ebdaPos, fixed, table);
     ebdaPos += (fixed + table);
+
+    // Write out ACPI tables
+    writeOutACPITables(ebdaPos, table);
+    ebdaPos += table;
 }

 void
@@ -375,4 +381,17 @@
     assert(fpSize == 0x10);
 }

+void
+FsWorkload::writeOutACPITables(Addr fp, Addr &fpSize)
+{
+    fpSize = 0;
+    if (rsdp) {
+        ACPI::LinearAllocator alloc(fp, 0x000FFFFF);
+        rsdp->write(system->physProxy, alloc);
+        fpSize = alloc.alloc(0, 0) - fp;
+ DPRINTF(ACPI, "Wrote ACPI tables to memory at %llx with size %llx.\n",
+                fp, fpSize);
+    }
+}
+
 } // namespace X86ISA
diff --git a/src/arch/x86/fs_workload.hh b/src/arch/x86/fs_workload.hh
index f926dce..9e6fa80 100644
--- a/src/arch/x86/fs_workload.hh
+++ b/src/arch/x86/fs_workload.hh
@@ -89,6 +89,8 @@

     void writeOutMPTable(Addr fp,
             Addr &fpSize, Addr &tableSize, Addr table=0);
+
+    void writeOutACPITables(Addr begin, Addr &size);
 };

 } // namespace X86ISA

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/42824
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I710279a72376c04f2a636ff2e96fa80228d03eaf
Gerrit-Change-Number: 42824
Gerrit-PatchSet: 11
Gerrit-Owner: Maximilian Stein <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Maximilian Stein <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-CC: Jason Lowe-Power <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to