Maximilian Stein has submitted this change. (
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 the ACPI implementation to support the MADT. This table
contains information about the interrupt system (Local APIC, IO-APIC)
and partially replaces the Intel MP tables.
The change is particularly needed to support other OSes than Linux that
do not support Intel MP.
Change-Id: I132226f46f4d54e2e0b964e2986004e3e5f5f347
Signed-off-by: Maximilian Stein <m...@steiny.biz>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/41953
Reviewed-by: Gabe Black <gabe.bl...@gmail.com>
Maintainer: Gabe Black <gabe.bl...@gmail.com>
Tested-by: kokoro <noreply+kok...@google.com>
---
M src/arch/x86/bios/ACPI.py
M src/arch/x86/bios/acpi.cc
M src/arch/x86/bios/acpi.hh
3 files changed, 336 insertions(+), 0 deletions(-)
Approvals:
Gabe Black: Looks good to me, approved; Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/arch/x86/bios/ACPI.py b/src/arch/x86/bios/ACPI.py
index 19edac4..5dfcb4d 100644
--- a/src/arch/x86/bios/ACPI.py
+++ b/src/arch/x86/bios/ACPI.py
@@ -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'
diff --git a/src/arch/x86/bios/acpi.cc b/src/arch/x86/bios/acpi.cc
index 91c8e47..53b6e4d 100644
--- a/src/arch/x86/bios/acpi.cc
+++ b/src/arch/x86/bios/acpi.cc
@@ -195,6 +195,119 @@
entries = p.entries;
}
+
+//// MADT
+MADT::MADT::MADT(const Params& p) :
+ SysDescTable(p, "APIC", 4),
+ records(p.records)
+{}
+
+Addr
+MADT::MADT::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));
+
+ Mem* header = reinterpret_cast<Mem*>(mem.data());
+ header->localAPICAddress = params().local_apic_address;
+ header->flags = params().flags;
+
+ for (const auto& record : records) {
+ auto entry = record->prepare();
+ mem.insert(mem.end(), entry.begin(), entry.end());
+ }
+
+ DPRINTF(ACPI, "MADT: writing %d records (size: %d)\n",
+ records.size(), mem.size());
+
+ return SysDescTable::writeBuf(phys_proxy, alloc, mem);
+}
+
+void
+MADT::Record::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.size() >= sizeof(Mem));
+ DPRINTF(ACPI, "MADT: writing record type %d (size: %d)\n",
+ type, mem.size());
+
+ Mem* header = reinterpret_cast<Mem*>(mem.data());
+ header->type = type;
+ header->length = mem.size();
+}
+
+void
+MADT::LAPIC::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.empty());
+ mem.resize(sizeof(Mem));
+
+ Mem* data = reinterpret_cast<Mem*>(mem.data());
+ data->acpiProcessorId = params().acpi_processor_id;
+ data->apicId = params().apic_id;
+ data->flags = params().flags;
+
+ Record::prepareBuf(mem);
+}
+
+void
+MADT::IOAPIC::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.empty());
+ mem.resize(sizeof(Mem));
+
+ Mem* data = reinterpret_cast<Mem*>(mem.data());
+ data->ioApicId = params().id;
+ data->ioApicAddress = params().address;
+ data->intBase = params().int_base;
+
+ Record::prepareBuf(mem);
+}
+
+void
+MADT::IntSourceOverride::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.empty());
+ mem.resize(sizeof(Mem));
+
+ Mem* data = reinterpret_cast<Mem*>(mem.data());
+ data->busSource = params().bus_source;
+ data->irqSource = params().irq_source;
+ data->globalSystemInterrupt = params().sys_int;
+ data->flags = params().flags;
+
+ Record::prepareBuf(mem);
+}
+
+void
+MADT::NMI::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.empty());
+ mem.resize(sizeof(Mem));
+
+ Mem* data = reinterpret_cast<Mem*>(mem.data());
+ data->acpiProcessorId = params().acpi_processor_id;
+ // The "flags" field is not properly aligned.
+ memcpy(&data->flags, ¶ms().flags, sizeof(data->flags));
+ data->lintNo = params().lint_no;
+
+ Record::prepareBuf(mem);
+}
+
+void
+MADT::LAPICOverride::prepareBuf(std::vector<uint8_t>& mem) const
+{
+ assert(mem.empty());
+ mem.resize(sizeof(Mem));
+
+ Mem* data = reinterpret_cast<Mem*>(mem.data());
+ data->localAPICAddress = params().address;
+
+ Record::prepareBuf(mem);
+}
+
} // namespace ACPI
} // namespace X86ISA
diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh
index 64f75ea..1c9f8e0 100644
--- a/src/arch/x86/bios/acpi.hh
+++ b/src/arch/x86/bios/acpi.hh
@@ -46,6 +46,13 @@
#include "base/compiler.hh"
#include "base/types.hh"
#include "debug/ACPI.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"
@@ -193,6 +200,162 @@
XSDT(const Params &p);
};
+namespace MADT
+{
+class Record : public SimObject
+{
+ protected:
+ PARAMS(X86ACPIMadtRecord);
+
+ struct M5_ATTR_PACKED Mem
+ {
+ uint8_t type = 0;
+ uint8_t length = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ uint8_t type;
+
+ virtual void prepareBuf(std::vector<uint8_t>& mem) const = 0;
+
+ public:
+ Record(const Params& p, uint8_t _type) : SimObject(p), type(_type) {}
+
+ std::vector<uint8_t>
+ prepare() const
+ {
+ std::vector<uint8_t> mem;
+ prepareBuf(mem);
+ return mem;
+ }
+};
+
+class LAPIC : public Record
+{
+ protected:
+ PARAMS(X86ACPIMadtLAPIC);
+
+ struct M5_ATTR_PACKED Mem : public Record::Mem
+ {
+ uint8_t acpiProcessorId = 0;
+ uint8_t apicId = 0;
+ uint32_t flags = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ void prepareBuf(std::vector<uint8_t>& mem) const override;
+
+ public:
+ LAPIC(const Params& p) : Record(p, 0) {}
+};
+
+class IOAPIC : public Record
+{
+ protected:
+ PARAMS(X86ACPIMadtIOAPIC);
+
+ struct M5_ATTR_PACKED Mem : public Record::Mem
+ {
+ uint8_t ioApicId = 0;
+ uint8_t _reserved = 0;
+ uint32_t ioApicAddress = 0;
+ uint32_t intBase = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ void prepareBuf(std::vector<uint8_t>& mem) const override;
+
+ public:
+ IOAPIC(const Params& p) : Record(p, 1) {}
+};
+
+class IntSourceOverride : public Record
+{
+ protected:
+ PARAMS(X86ACPIMadtIntSourceOverride);
+
+ struct M5_ATTR_PACKED Mem : public Record::Mem
+ {
+ uint8_t busSource = 0;
+ uint8_t irqSource = 0;
+ uint32_t globalSystemInterrupt = 0;
+ uint16_t flags = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ void prepareBuf(std::vector<uint8_t>& mem) const override;
+
+ public:
+ IntSourceOverride(const Params& p) : Record(p, 2) {}
+};
+
+class NMI : public Record
+{
+ protected:
+ PARAMS(X86ACPIMadtNMI);
+
+ struct M5_ATTR_PACKED Mem : public Record::Mem
+ {
+ uint8_t acpiProcessorId = 0;
+ uint16_t flags = 0;
+ uint8_t lintNo = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ void prepareBuf(std::vector<uint8_t>& mem) const override;
+
+ public:
+ NMI(const Params& p) : Record(p, 3) {}
+};
+
+class LAPICOverride : public Record
+{
+ protected:
+ PARAMS(X86ACPIMadtLAPICOverride);
+
+ struct M5_ATTR_PACKED Mem : public Record::Mem
+ {
+ uint16_t _reserved = 0;
+ uint64_t localAPICAddress = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ void prepareBuf(std::vector<uint8_t>& mem) const override;
+
+ public:
+ LAPICOverride(const Params& p) : Record(p, 5) {}
+};
+
+class MADT : public SysDescTable
+{
+ protected:
+ PARAMS(X86ACPIMadt);
+
+ struct M5_ATTR_PACKED Mem : public SysDescTable::Mem
+ {
+ uint32_t localAPICAddress = 0;
+ uint32_t flags = 0;
+ };
+ static_assert(std::is_trivially_copyable<Mem>::value,
+ "Type not suitable for memcpy.");
+
+ std::vector<Record *> records;
+
+ Addr writeBuf(PortProxy& phys_proxy, Allocator& alloc,
+ std::vector<uint8_t>& mem) const override;
+
+ public:
+ MADT(const Params &p);
+};
+
+} // namespace MADT
+
} // namespace ACPI
} // namespace X86ISA
--
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: 15
Gerrit-Owner: Maximilian Stein <m...@steiny.biz>
Gerrit-Reviewer: Gabe Black <gabe.bl...@gmail.com>
Gerrit-Reviewer: Maximilian Stein <m...@steiny.biz>
Gerrit-Reviewer: kokoro <noreply+kok...@google.com>
Gerrit-CC: Jason Lowe-Power <power...@gmail.com>
Gerrit-MessageType: merged
_______________________________________________
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