Maximilian Stein has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/41953 )

Change subject: arch-x86: Add ACPI support for MADT
......................................................................

arch-x86: Add ACPI support for MADT

This extends ACPI to support the MADT. This table contains information
about the interrupt system (Local APIC, IO-APIC) and partly replaces the
Intel MP tables.
The change is particularly needed to support other OSes than Linux that
do not support Intel MP.

This patch contains the necessary python and c++ classes to create MADT
records, setup the MADT itself, and extends the RSDP, RSDT, and XSDT.

Change-Id: I132226f46f4d54e2e0b964e2986004e3e5f5f347
Signed-off-by: Maximilian Stein <m...@steiny.biz>
---
M configs/common/FSConfig.py
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
6 files changed, 619 insertions(+), 34 deletions(-)



diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py
index 6665225..98df117 100644
--- a/configs/common/FSConfig.py
+++ b/configs/common/FSConfig.py
@@ -501,6 +501,7 @@
     # Set up the Intel MP table
     base_entries = []
     ext_entries = []
+    madt_records = []
     for i in range(numCPUs):
         bp = X86IntelMPProcessor(
                 local_apic_id = i,
@@ -508,6 +509,11 @@
                 enable = True,
                 bootstrap = (i == 0))
         base_entries.append(bp)
+        lapic = X86ACPIMadtLAPIC(
+                acpi_processor_id=i,
+                apic_id=i,
+                flags=1)
+        madt_records.append(lapic)
     io_apic = X86IntelMPIOAPIC(
             id = numCPUs,
             version = 0x11,
@@ -515,6 +521,8 @@
             address = 0xfec00000)
     self.pc.south_bridge.io_apic.apic_id = io_apic.id
     base_entries.append(io_apic)
+    madt_records.append(X86ACPIMadtIOAPIC(id=io_apic.id,
+        address=io_apic.address, int_base=0))
     # In gem5 Pc::calcPciConfigAddr(), it required "assert(bus==0)",
     # but linux kernel cannot config PCI device if it was not connected to
     # PCI bus, so we fix PCI bus id to 0, and ISA bus id to 1.
@@ -534,6 +542,13 @@
             dest_io_apic_id = io_apic.id,
             dest_io_apic_intin = 16)
     base_entries.append(pci_dev4_inta)
+    pci_dev4_inta_madt = X86ACPIMadtIntSourceOverride(
+            bus_source = pci_dev4_inta.source_bus_id,
+            irq_source = pci_dev4_inta.source_bus_irq,
+            sys_int = pci_dev4_inta.dest_io_apic_intin,
+            flags = 0
+        )
+    madt_records.append(pci_dev4_inta_madt)
     def assignISAInt(irq, apicPin):
         assign_8259_to_apic = X86IntelMPIOIntAssignment(
                 interrupt_type = 'ExtInt',
@@ -553,6 +568,14 @@
                 dest_io_apic_id = io_apic.id,
                 dest_io_apic_intin = apicPin)
         base_entries.append(assign_to_apic)
+        # acpi
+        assign_to_apic_acpi = X86ACPIMadtIntSourceOverride(
+                bus_source = 1,
+                irq_source = irq,
+                sys_int = apicPin,
+                flags = 0
+            )
+        madt_records.append(assign_to_apic_acpi)
     assignISAInt(0, 2)
     assignISAInt(1, 1)
     for i in range(3, 15):
@@ -560,6 +583,13 @@
     workload.intel_mp_table.base_entries = base_entries
     workload.intel_mp_table.ext_entries = ext_entries

+    madt = X86ACPIMadt(local_apic_address=0,
+            records=madt_records, oem_id='madt')
+    workload.acpi_description_table_pointer.rsdt.entries.append(madt)
+    workload.acpi_description_table_pointer.xsdt.entries.append(madt)
+    workload.acpi_description_table_pointer.oem_id = 'gem5'
+    workload.acpi_description_table_pointer.rsdt.oem_id='gem5'
+    workload.acpi_description_table_pointer.xsdt.oem_id='gem5'
     return self

 def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False,
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index f790ec1..1fcf1dc 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -81,6 +81,7 @@
           "Page table walker state machine 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..5dfcb4d 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')

@@ -67,6 +67,66 @@

entries = VectorParam.X86ACPISysDescTable([], 'system description tables')

+
+class X86ACPIMadtRecord(SimObject):
+    type = 'X86ACPIMadtRecord'
+    cxx_class = 'X86ISA::ACPI::MADT::Record'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    abstract = True
+
+class X86ACPIMadt(X86ACPISysDescTable):
+    type = 'X86ACPIMadt'
+    cxx_class = 'X86ISA::ACPI::MADT::MADT'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+
+    local_apic_address = Param.UInt32(0, 'Address of the local apic')
+    flags = Param.UInt32(0, 'Flags')
+    records = VectorParam.X86ACPIMadtRecord([], 'Records in this MADT')
+
+class X86ACPIMadtLAPIC(X86ACPIMadtRecord):
+    type = 'X86ACPIMadtLAPIC'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    cxx_class = 'X86ISA::ACPI::MADT::LAPIC'
+
+    acpi_processor_id = Param.UInt8(0, 'ACPI Processor ID')
+    apic_id = Param.UInt8(0, 'APIC ID')
+    flags = Param.UInt32(0, 'Flags')
+
+class X86ACPIMadtIOAPIC(X86ACPIMadtRecord):
+    type = 'X86ACPIMadtIOAPIC'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    cxx_class = 'X86ISA::ACPI::MADT::IOAPIC'
+
+    id = Param.UInt8(0, 'I/O APIC ID')
+    address = Param.Addr(0, 'I/O APIC Address')
+    int_base = Param.UInt32(0, 'Global Interrupt Base')
+
+class X86ACPIMadtIntSourceOverride(X86ACPIMadtRecord):
+    type = 'X86ACPIMadtIntSourceOverride'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    cxx_class = 'X86ISA::ACPI::MADT::IntSourceOverride'
+
+    bus_source = Param.UInt8(0, 'Bus Source')
+    irq_source = Param.UInt8(0, 'IRQ Source')
+    sys_int = Param.UInt32(0, 'Global System Interrupt')
+    flags = Param.UInt16(0, 'Flags')
+
+class X86ACPIMadtNMI(X86ACPIMadtRecord):
+    type = 'X86ACPIMadtNMI'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    cxx_class = 'X86ISA::ACPI::MADT::NMI'
+
+    acpi_processor_id = Param.UInt8(0, 'ACPI Processor ID')
+    flags = Param.UInt16(0, 'Flags')
+    lint_no = Param.UInt8(0, 'LINT# (0 or 1)')
+
+class X86ACPIMadtLAPICOverride(X86ACPIMadtRecord):
+    type = 'X86ACPIMadtLAPICOverride'
+    cxx_header = 'arch/x86/bios/acpi.hh'
+    cxx_class = 'X86ISA::ACPI::MADT::LAPICOverride'
+
+    address = Param.Addr(0, '64-bit Physical Address of Local APIC')
+
 # Root System Description Pointer Structure
 class X86ACPIRSDP(SimObject):
     type = 'X86ACPIRSDP'
@@ -78,6 +138,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 20cf088..bb88246 100644
--- a/src/arch/x86/bios/acpi.cc
+++ b/src/arch/x86/bios/acpi.cc
@@ -37,7 +37,20 @@

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

+#include <cassert>
+#include <cstring>
+#include <type_traits>
+
+#include "base/trace.hh"
+#include "debug/ACPI.hh"
 #include "mem/port.hh"
+#include "params/X86ACPIMadt.hh"
+#include "params/X86ACPIMadtIOAPIC.hh"
+#include "params/X86ACPIMadtIntSourceOverride.hh"
+#include "params/X86ACPIMadtLAPIC.hh"
+#include "params/X86ACPIMadtLAPICOverride.hh"
+#include "params/X86ACPIMadtNMI.hh"
+#include "params/X86ACPIMadtRecord.hh"
 #include "params/X86ACPIRSDP.hh"
 #include "params/X86ACPIRSDT.hh"
 #include "params/X86ACPISysDescTable.hh"
@@ -45,24 +58,299 @@
 #include "sim/byteswap.hh"
 #include "sim/sim_object.hh"

-const char X86ISA::ACPI::RSDP::signature[] = "RSD PTR ";
+using namespace X86ISA::ACPI;

-X86ISA::ACPI::RSDP::RSDP(const Params &p) : SimObject(p), oemID(p.oem_id),
-    revision(p.revision), rsdt(p.rsdt), xsdt(p.xsdt)
+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;
+}
+
+RSDP::RSDP(const Params &p)
+    : SimObject(p)
+    , rsdt(p.rsdt)
+    , xsdt(p.xsdt)
+{
+    static_assert(sizeof(signature) - 1 == sizeof(d.Signature),
+            "signature length mismatch");
+    std::memcpy(d.Signature, signature, sizeof(d.Signature));
+    d.Checksum = 0;
+    std::strncpy(d.OEMID, p.oem_id.c_str(), sizeof(d.OEMID));
+    d.Revision = p.revision;
+    d.RsdtAddress = 0;
+    d.Length = sizeof(d);
+    d.XsdtAddress = 0;
+    d.ExtendedChecksum = 0;
+    d._reserved[0] = 0;
+    d._reserved[1] = 0;
+    d._reserved[2] = 0;
+}
+
+Addr
+RSDP::write(PortProxy* physProxy, Allocator* alloc) const
+{
+    std::vector<uint8_t> mem(sizeof(d));
+    Addr addr = alloc->alloc(sizeof(d), 16);
+
+    assert(mem.size() >= sizeof(d));
+    std::memcpy(mem.data(), &d, sizeof(d));
+    Mem* desc = (Mem*)mem.data();
+
+    desc->RsdtAddress = 0;
+    if (rsdt) {
+        desc->RsdtAddress = rsdt->write(physProxy, alloc);
+        DPRINTF(ACPI, "Allocated RSDT @ %llx\n", desc->RsdtAddress);
+    }
+    desc->XsdtAddress = 0;
+    if (xsdt) {
+        desc->XsdtAddress = xsdt->write(physProxy, alloc);
+        DPRINTF(ACPI, "Allocated XSDT @ %llx\n", desc->XsdtAddress);
+    }
+
+    // checksum calculation
+    assert(d.Length == sizeof(d));
+    desc->Checksum = apic_checksum(mem.data(), sizeof(MemR0));
+    desc->ExtendedChecksum = apic_checksum(mem.data(), d.Length);
+
+    // write the whole thing
+    physProxy->writeBlob(addr, mem.data(), mem.size());
+
+    return addr;
+}
+
+SysDescTable::SysDescTable(const Params &p, Mem* dp,
+        const char * _signature, uint8_t _revision)
+    : SimObject(p)
+    , dp(dp)
+{
+    std::strncpy(dp->Signature, _signature, sizeof(dp->Signature));
+    dp->Length = 0; // filled in write()
+    dp->Revision = _revision;
+    dp->Checksum = 0; // filled in write()
+    std::strncpy(dp->OEMID, p.oem_id.c_str(), sizeof(dp->OEMID));
+    std::strncpy(dp->OEMTableID, p.oem_table_id.c_str(),
+            sizeof(dp->OEMTableID));
+    dp->OEMRevision = p.oem_revision;
+    dp->CreatorID = p.creator_id;
+    dp->CreatorRevision = p.creator_revision;
+}
+
+Addr
+SysDescTable::_write(std::vector<uint8_t>* mem,
+        PortProxy* physProxy, Allocator* alloc) const
+{
+    mem->resize(sizeof(*dp));
+    std::memcpy(mem->data(), dp, mem->size());
+    return alloc->alloc(mem->size());
+}
+
+Addr
+SysDescTable::write(PortProxy* physProxy, Allocator* alloc) const
+{
+    std::vector<uint8_t> mem;
+    auto addr = this->_write(&mem, physProxy, alloc);
+
+    // checksum calculation
+    Mem* header = (Mem*)mem.data();
+    header->Length = mem.size();
+    header->Checksum = apic_checksum(mem.data(), mem.size());
+
+    // write to physical memory
+    physProxy->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, &d, _signature, _revision)
 {}

-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)
-{}
+template<class T>
+Addr
+RXSDT<T>::_write(std::vector<uint8_t>* mem,
+            PortProxy* physProxy, Allocator* alloc) const
+{
+    mem->resize(sizeof(d) + sizeof(Ptr) * entries.size());
+    assert(mem->size() >= sizeof(d));
+    std::memcpy(mem->data(), dp, sizeof(d));
+    auto addr = alloc->alloc(mem->size());
+    Mem* myMem = (Mem*)mem->data();
+    DPRINTF(ACPI, "RXSDT: writing %d entries @ %llx (ptr size: %d)\n",
+            entries.size(), addr, sizeof(Ptr));
+    for (unsigned i = 0; i < entries.size(); ++i) {
+        auto entry_addr = entries[i]->write(physProxy, alloc);
+        if (std::is_same<Ptr, uint32_t>::value)
+            assert((entry_addr & 0xFFFFFFFF) == entry_addr);
+        DPRINTF(ACPI, "RXSDT: wrote entry @ %llx\n", entry_addr);
+        myMem->ptr[i] = entry_addr;
+    }
+    return addr;
+}

-X86ISA::ACPI::RSDT::RSDT(const Params &p) :
-    SysDescTable(p, "RSDT", 1), entries(p.entries)
-{}
+template class RXSDT<uint32_t>;
+template class RXSDT<uint64_t>;

-X86ISA::ACPI::XSDT::XSDT(const Params &p) :
-    SysDescTable(p, "XSDT", 1), entries(p.entries)
-{}
+RSDT::RSDT(const Params& p)
+    : RXSDT(p, "RSDT", 1)
+{
+    entries = p.entries;
+}
+
+XSDT::XSDT(const Params& p)
+    : RXSDT(p, "XSDT", 1)
+{
+    entries = p.entries;
+}
+
+
+//// MADT
+MADT::MADT::MADT(const Params& p)
+    : SysDescTable(p, &d, "APIC", 0)
+    , records(p.records)
+{
+    d.LocalAPICAddress = p.local_apic_address;
+    d.Flags = p.flags;
+}
+
+Addr MADT::MADT::_write(std::vector<uint8_t>* mem,
+        PortProxy* physProxy, Allocator* alloc) const
+{
+    // size of header and records
+    std::size_t record_size = 0;
+    for (auto const& record : records)
+        record_size += record->size();
+    mem->resize(sizeof(d) + record_size);
+    auto p = mem->data();
+    auto addr = alloc->alloc(mem->size());
+
+    // header
+    assert(mem->size() >= sizeof(d));
+    std::memcpy(p, &d, sizeof(d));
+    p += sizeof(d);
+
+    // records
+    DPRINTF(ACPI, "MADT: writing %d records @ %llx (size: %d)\n",
+            records.size(), addr, mem->size());
+    for (auto const& record : records) {
+        assert(p < mem->data() + mem->size());
+        record->write(p);
+        p += record->size();
+    }
+
+    return addr;
+}
+
+MADT::Record::Record(const Params& p, Mem* dp, uint8_t Type, uint8_t Length)
+    : SimObject(p)
+    , dp(dp)
+{
+    dp->Type = Type;
+    dp->Length = Length;
+}
+
+void MADT::Record::write(uint8_t* mem) const
+{
+    DPRINTF(ACPI, "MADT: writing record type %d (size: %d)\n",
+            dp->Type, dp->Length);
+    std::memcpy(mem, dp, size());
+}
+
+MADT::LAPIC::LAPIC(const Params& p)
+    : Record(p, &d, 0, sizeof(d))
+{
+    d.ACPIProcessorId = p.acpi_processor_id;
+    d.ApicId = p.apic_id;
+    d.Flags = p.flags;
+}
+
+MADT::IOAPIC::IOAPIC(const Params& p)
+    : Record(p, &d, 1, sizeof(d))
+{
+    d.IoApicId = p.id;
+    d.IoApicAddress = p.address;
+    d._reserved = 0;
+    d.IntBase = p.int_base;
+}
+
+MADT::IntSourceOverride::IntSourceOverride(const Params& p)
+    : Record(p, &d, 2, sizeof(d))
+{
+    d.BusSource = p.bus_source;
+    d.IrqSource = p.irq_source;
+    d.GlobalSystemInterrupt = p.sys_int;
+    d.Flags = p.flags;
+}
+
+MADT::NMI::NMI(const Params& p)
+    : Record(p, &d, 4, sizeof(d))
+{
+    d.ACPIProcessorId = p.acpi_processor_id;
+    d.Flags = p.flags;
+    d.LintNo = p.lint_no;
+}
+
+MADT::LAPICOverride::LAPICOverride(const Params& p)
+    : Record(p, &d, 5, sizeof(d))
+{
+    d.LocalAPICAddress = p.address;
+}
+
+RSDP *
+X86ACPIRSDPParams::create() const
+{
+    return new RSDP(*this);
+}
+
+RSDT *
+X86ACPIRSDTParams::create() const
+{
+    return new RSDT(*this);
+}
+
+XSDT *
+X86ACPIXSDTParams::create() const
+{
+    return new XSDT(*this);
+}
+
+MADT::MADT *
+X86ACPIMadtParams::create() const
+{
+    return new MADT::MADT(*this);
+}
+
+MADT::LAPIC *
+X86ACPIMadtLAPICParams::create() const
+{
+    return new MADT::LAPIC(*this);
+}
+
+MADT::IOAPIC *
+X86ACPIMadtIOAPICParams::create() const
+{
+    return new MADT::IOAPIC(*this);
+}
+
+MADT::IntSourceOverride *
+X86ACPIMadtIntSourceOverrideParams::create() const
+{
+    return new MADT::IntSourceOverride(*this);
+}
+
+MADT::NMI *
+X86ACPIMadtNMIParams::create() const
+{
+    return new MADT::NMI(*this);
+}
+
+MADT::LAPICOverride *
+X86ACPIMadtLAPICOverrideParams::create() const
+{
+    return new MADT::LAPICOverride(*this);
+}
diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh
index bc6e2cd..2bc7b82 100644
--- a/src/arch/x86/bios/acpi.hh
+++ b/src/arch/x86/bios/acpi.hh
@@ -42,6 +42,8 @@
 #include <vector>

 #include "base/types.hh"
+#include "debug/ACPI.hh"
+#include "mem/port_proxy.hh"
 #include "sim/sim_object.hh"

 class Port;
@@ -51,6 +53,13 @@
 struct X86ACPISysDescTableParams;
 struct X86ACPIRSDTParams;
 struct X86ACPIXSDTParams;
+struct X86ACPIMadtParams;
+struct X86ACPIMadtRecordParams;
+struct X86ACPIMadtLAPICParams;
+struct X86ACPIMadtIOAPICParams;
+struct X86ACPIMadtIntSourceOverrideParams;
+struct X86ACPIMadtNMIParams;
+struct X86ACPIMadtLAPICOverrideParams;

 namespace X86ISA
 {
@@ -62,13 +71,58 @@
 class XSDT;
 class SysDescTable;

+struct Allocator
+{
+    virtual Addr alloc(std::size_t size, unsigned align = 1) = 0;
+};
+struct LinearAllocator : public Allocator
+{
+    LinearAllocator(Addr begin, Addr end = 0)
+        : next(begin)
+        , end(end)
+    {}
+
+    virtual Addr alloc(std::size_t size, unsigned align) override
+    {
+        if (align > 0)
+            next = ( (next + align - 1) / align ) * align;
+        Addr chunk = next;
+        next += size;
+        assert(0 == end || next <= end);
+        return chunk;
+    }
+
+  protected:
+    Addr next;
+    Addr const end;
+};
+
 class RSDP : public SimObject
 {
   protected:
     typedef X86ACPIRSDPParams Params;
-
     static const char signature[];

+    struct MemR0
+    {
+      // src: https://wiki.osdev.org/RSDP
+      char Signature[8];
+      uint8_t Checksum;
+      char OEMID[6];
+      uint8_t Revision;
+      uint32_t RsdtAddress;
+    } __attribute__((packed));
+    struct Mem : public MemR0
+    {
+      // since version 2
+      uint32_t Length;
+      uint64_t XsdtAddress;
+      uint8_t ExtendedChecksum;
+      uint8_t _reserved[3];
+    } __attribute__ ((packed));
+
+    Mem d;
+
     std::string oemID;
     uint8_t revision;

@@ -77,6 +131,8 @@

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

 class SysDescTable : public SimObject
@@ -84,42 +140,182 @@
   protected:
     typedef X86ACPISysDescTableParams Params;

-    const char * signature;
-    uint8_t revision;
+    struct Mem
+    {
+      // src: https://wiki.osdev.org/RSDT
+      char Signature[4];
+      uint32_t Length;
+      uint8_t Revision;
+      uint8_t Checksum;
+      char OEMID[6];
+      char OEMTableID[8];
+      uint32_t OEMRevision;
+      uint32_t CreatorID;
+      uint32_t CreatorRevision;
+    } __attribute__ ((packed));

-    std::string oemID;
-    std::string oemTableID;
-    uint32_t oemRevision;
+    Mem* dp;

-    std::string creatorID;
-    uint32_t creatorRevision;
+    virtual Addr _write(std::vector<uint8_t>* mem,
+            PortProxy* physProxy, Allocator* alloc) const;

   public:
- SysDescTable(const Params &p, const char * _signature, uint8_t _revision);
+    SysDescTable(const Params& p, Mem* dp, const char * _signature,
+            uint8_t _revision);
+
+    Addr write(PortProxy* physProxy, Allocator* alloc) const;
 };

-class RSDT : public SysDescTable
+template<class T>
+class RXSDT : public SysDescTable
+{
+  protected:
+    using Ptr = T;
+    struct Mem : public SysDescTable::Mem
+    {
+        Ptr ptr[0];
+    } __attribute__((packed)) d;
+
+    std::vector<SysDescTable *> entries;
+
+    virtual Addr _write(std::vector<uint8_t>* mem,
+            PortProxy* physProxy, Allocator* alloc) const override;
+
+    RXSDT(const Params& p, const char * _signature, uint8_t _revision);
+};
+
+class RSDT : public RXSDT<uint32_t>
 {
   protected:
     typedef X86ACPIRSDTParams Params;

-    std::vector<SysDescTable *> entries;
-
   public:
     RSDT(const Params &p);
 };

-class XSDT : public SysDescTable
+class XSDT : public RXSDT<uint64_t>
 {
   protected:
     typedef X86ACPIXSDTParams Params;

-    std::vector<SysDescTable *> entries;
-
   public:
     XSDT(const Params &p);
 };

+namespace MADT
+{
+class Record : public SimObject
+{
+  protected:
+    typedef X86ACPIMadtRecordParams Params;
+
+    struct Mem
+    {
+        uint8_t Type;
+        uint8_t Length;
+    } __attribute__((packed));
+
+    Mem* dp;
+  public:
+    Record(const Params &p, Mem* dp, uint8_t Type, uint8_t Length);
+
+    std::size_t size() const
+    { return dp->Length; }
+    void write(uint8_t* mem) const;
+};
+
+class LAPIC : public Record
+{
+  protected:
+    typedef X86ACPIMadtLAPICParams Params;
+    struct : public Record::Mem
+    {
+        uint8_t ACPIProcessorId;
+        uint8_t ApicId;
+        uint32_t Flags;
+    } __attribute__((packed)) d;
+  public:
+    LAPIC(const Params& p);
+};
+
+class IOAPIC : public Record
+{
+  protected:
+    typedef X86ACPIMadtIOAPICParams Params;
+    struct : public Record::Mem
+    {
+        uint8_t IoApicId;
+        uint8_t _reserved;
+        uint32_t IoApicAddress;
+        uint32_t IntBase;
+    } __attribute__((packed)) d;
+  public:
+    IOAPIC(const Params& p);
+};
+
+class IntSourceOverride : public Record
+{
+  protected:
+    typedef X86ACPIMadtIntSourceOverrideParams Params;
+    struct : public Record::Mem
+    {
+        uint8_t BusSource;
+        uint8_t IrqSource;
+        uint32_t GlobalSystemInterrupt;
+        uint16_t Flags;
+    } __attribute__((packed)) d;
+  public:
+    IntSourceOverride(const Params& p);
+};
+
+class NMI : public Record
+{
+  protected:
+    typedef X86ACPIMadtNMIParams Params;
+    struct : public Record::Mem
+    {
+        uint8_t ACPIProcessorId;
+        uint16_t Flags;
+        uint8_t LintNo;
+    } __attribute__((packed)) d;
+  public:
+    NMI(const Params& p);
+};
+
+class LAPICOverride : public Record
+{
+  protected:
+    typedef X86ACPIMadtLAPICOverrideParams Params;
+    struct : public Record::Mem
+    {
+        uint16_t _reserved;
+        uint64_t LocalAPICAddress;
+    } __attribute__((packed)) d;
+  public:
+    LAPICOverride(const Params& p);
+};
+
+class MADT : public SysDescTable
+{
+  protected:
+    typedef X86ACPIMadtParams Params;
+
+    struct : public SysDescTable::Mem
+    {
+        uint32_t LocalAPICAddress;
+        uint32_t Flags;
+    } __attribute__((packed)) d;
+
+    std::vector<Record *> records;
+
+    virtual Addr _write(std::vector<uint8_t>* mem,
+            PortProxy* physProxy, Allocator* alloc) const;
+  public:
+    MADT(const Params &p);
+};
+
+} // namespace MADT
+
 } // namespace ACPI

 } // namespace X86ISA
diff --git a/src/arch/x86/fs_workload.cc b/src/arch/x86/fs_workload.cc
index 7499e60..00e0709 100644
--- a/src/arch/x86/fs_workload.cc
+++ b/src/arch/x86/fs_workload.cc
@@ -38,12 +38,14 @@

 #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 "arch/x86/isa_traits.hh"
 #include "base/loader/object_file.hh"
 #include "cpu/thread_context.hh"
+#include "debug/ACPI.hh"
 #include "params/X86FsWorkload.hh"
 #include "sim/system.hh"

@@ -331,6 +333,13 @@
     // Write out the Intel MP Specification configuration table.
     writeOutMPTable(ebdaPos, fixed, table);
     ebdaPos += (fixed + table);
+
+    // Write out ACPI tables
+    if (rsdp) {
+        ACPI::LinearAllocator alloc(0x000E0000, 0x000E1000);
+        auto rsdpAddr = rsdp->write(&phys_proxy, &alloc);
+        DPRINTF(ACPI, "Wrote ACPI tables to memory at %llx.\n", rsdpAddr);
+    }
 }

 void

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/41953
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: I132226f46f4d54e2e0b964e2986004e3e5f5f347
Gerrit-Change-Number: 41953
Gerrit-PatchSet: 1
Gerrit-Owner: Maximilian Stein <m...@steiny.biz>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to