24#include "pedigree/kernel/BootstrapInfo.h"
25#include "pedigree/kernel/Log.h"
26#include "pedigree/kernel/machine/Device.h"
27#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
28#include "pedigree/kernel/processor/VirtualAddressSpace.h"
29#include "pedigree/kernel/utilities/RangeList.h"
30#include "pedigree/kernel/utilities/utility.h"
32#include "../../core/processor/x86_common/PhysicalMemoryManager.h"
38bool rangeContains(uint64_t rangeAddress, uint64_t rangeLength, uint64_t address, uint64_t length) {
39 const uint64_t rangeEnd = rangeAddress + rangeLength;
40 const uint64_t end = address + length;
41 return rangeEnd >= rangeAddress && end >= address && address >= rangeAddress && end <= rangeEnd;
44bool mappedRangeContains(
const MemoryRegion& region, uint64_t address, uint64_t length) {
49void Acpi::initialise() {
51 if (find() ==
false) {
52 WARNING(
"Acpi: not compliant to the ACPI Specification");
56 NOTICE(
"ACPI Specification");
57 NOTICE(
" RSDT pointer at " <<
Hex <<
reinterpret_cast<uintptr_t
>(m_pRsdtPointer));
60 if (m_pRsdtPointer->revision >= 2) {
61 if (m_pRsdtPointer->xsdtAddress != 0) {
62 NOTICE(
" XSDT at " <<
Hex << m_pRsdtPointer->xsdtAddress);
66 NOTICE(
" RSDT at " <<
Hex << m_pRsdtPointer->rsdtAddress);
73 bool foundAcpiRange =
false;
74 for (
size_t i = 0; i < AcpiRanges.
size(); ++i) {
76 if (AcpiRanges.
getRange(i, candidate) &&
77 rangeContains(candidate.address, candidate.length, m_pRsdtPointer->rsdtAddress,
78 sizeof(SystemDescriptionTableHeader))) {
79 AcpiRange = candidate;
80 foundAcpiRange =
true;
86 if (!foundAcpiRange && g_pBootstrapInfo) {
87 void* memoryMap = g_pBootstrapInfo->getMemoryMap();
89 const uint64_t address = g_pBootstrapInfo->getMemoryMapEntryAddress(memoryMap);
90 const uint64_t length = g_pBootstrapInfo->getMemoryMapEntryLength(memoryMap);
91 if (rangeContains(address, length, m_pRsdtPointer->rsdtAddress,
92 sizeof(SystemDescriptionTableHeader))) {
93 AcpiRange.address = address;
94 AcpiRange.length = length;
95 foundAcpiRange =
true;
96 NOTICE(
" ACPI tables are in firmware memory-map type "
97 <<
Hex << g_pBootstrapInfo->getMemoryMapEntryType(memoryMap));
100 memoryMap = g_pBootstrapInfo->nextMemoryMapEntry(memoryMap);
104 if (!foundAcpiRange) {
105 ERROR(
"Acpi: Could not locate the RSDT in the firmware memory map");
111 size_t sAddress = AcpiRange.length + (AcpiRange.address - address);
115 m_AcpiMemoryRegion, nPages,
119 ERROR(
"Acpi: Could not allocate the MemoryRegion");
124 m_pRsdt = m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(
125 m_pRsdtPointer->rsdtAddress);
126 if (m_pRsdt->signature != 0x54445352 || m_pRsdt->length <
sizeof(SystemDescriptionTableHeader) ||
127 !mappedRangeContains(m_AcpiMemoryRegion, m_pRsdtPointer->rsdtAddress, m_pRsdt->length) ||
128 checksum(m_pRsdt) !=
true) {
129 ERROR(
"Acpi: RSDT invalid");
135 size_t sEntries = (m_pRsdt->length -
sizeof(SystemDescriptionTableHeader)) / 4;
136 for (
size_t i = 0; i < sEntries; i++) {
137 uint32_t* pTable = adjust_pointer(
reinterpret_cast<uint32_t*
>(m_pRsdt),
138 sizeof(SystemDescriptionTableHeader) + 4 * i);
140 SystemDescriptionTableHeader* pSystemDescTable =
141 m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(*pTable);
143 if (!mappedRangeContains(m_AcpiMemoryRegion, *pTable,
sizeof(SystemDescriptionTableHeader))) {
144 ERROR(
" ACPI table header is outside the mapped firmware range");
148 if (pSystemDescTable->length <
sizeof(SystemDescriptionTableHeader) ||
149 !mappedRangeContains(m_AcpiMemoryRegion, *pTable, pSystemDescTable->length)) {
150 ERROR(
" ACPI table is outside the mapped firmware range");
155 StringCopyN(Signature,
reinterpret_cast<char*
>(&pSystemDescTable->signature), 4);
158 NOTICE(
" " << Signature <<
" at " <<
Hex << *pTable);
161 if (checksum(pSystemDescTable) !=
true) {
167 if (pSystemDescTable->signature == 0x50434146) {
168 if (pSystemDescTable->length <
sizeof(FixedACPIDescriptionTable)) {
169 ERROR(
"Acpi: truncated Fixed ACPI Description Table");
172 m_pFacp =
reinterpret_cast<FixedACPIDescriptionTable*
>(pSystemDescTable);
176 else if (pSystemDescTable->signature == 0x43495041)
177 m_pApic = pSystemDescTable;
179 else if (pSystemDescTable->signature == 0x52414d44) {
181 m_DmarPresent =
false;
182 ERROR(
"Acpi: duplicate DMAR table");
187 if (!AcpiDmar::parse(
reinterpret_cast<const uint8_t*
>(pSystemDescTable),
188 pSystemDescTable->length, info)) {
189 ERROR(
"Acpi: invalid DMAR table");
192 m_DmarPresent =
true;
193 NOTICE(
" ACPI DMAR: " <<
Dec << info.hardwareUnitCount <<
" DMA remapping units ("
194 << info.segmentZeroUnitCount <<
" on PCI segment 0), interrupt "
195 << (info.interruptRemapping ?
"remapping advertised"
196 :
"remapping absent"));
198 }
else if (pSystemDescTable->signature == 0x4746434d) {
199 constexpr size_t entriesOffset =
sizeof(SystemDescriptionTableHeader) + 8;
200 if (pSystemDescTable->length < entriesOffset ||
201 (pSystemDescTable->length - entriesOffset) %
sizeof(PciConfigurationRange)) {
202 ERROR(
"Acpi: invalid MCFG length");
206 (pSystemDescTable->length - entriesOffset) /
sizeof(PciConfigurationRange);
207 for (
size_t entryIndex = 0; entryIndex < count; ++entryIndex) {
209 adjust_pointer(
reinterpret_cast<const PciConfigurationRange*
>(pSystemDescTable),
210 entriesOffset + entryIndex *
sizeof(PciConfigurationRange));
211 if (entry->segment || entry->firstBus > entry->lastBus ||
212 (entry->base & ((1ULL << 20) - 1))) {
215 const uint64_t bytes = uint64_t(entry->lastBus + 1) << 20;
216 if (!entry->base || entry->base + bytes < entry->base) {
219 bool overlap =
false;
220 for (
const auto& range : m_PciConfigurationRanges) {
221 if (entry->firstBus <= range.lastBus && entry->lastBus >= range.firstBus) {
227 m_PciConfigurationRanges.pushBack(*entry);
228 NOTICE(
" ACPI MCFG segment 0 buses " <<
Dec << entry->firstBus <<
".." << entry->lastBus
229 <<
" at " <<
Hex << entry->base);
233 NOTICE(
" unknown table");
239 ERROR(
"Acpi: no Fixed ACPI Description Table (FACP)");
244 parseFixedACPIDescriptionTable();
245 initialisePowerManagement();
247 if (m_pFacp->dsdt && mappedRangeContains(m_AcpiMemoryRegion, m_pFacp->dsdt,
248 sizeof(SystemDescriptionTableHeader))) {
250 m_AcpiMemoryRegion.convertPhysicalPointer<SystemDescriptionTableHeader>(m_pFacp->dsdt);
251 if (dsdt->signature == 0x54445344 && dsdt->length >=
sizeof(SystemDescriptionTableHeader) &&
252 mappedRangeContains(m_AcpiMemoryRegion, m_pFacp->dsdt, dsdt->length) && checksum(dsdt)) {
253 m_PciInterruptRoutesPresent = AcpiPciRouting::parse(
254 reinterpret_cast<const uint8_t*
>(dsdt) +
sizeof(SystemDescriptionTableHeader),
255 dsdt->length -
sizeof(SystemDescriptionTableHeader), m_PciInterruptRoutes);
256 if (m_PciInterruptRoutesPresent) {
257 NOTICE(
" ACPI PCI IOAPIC routes available");
265 parseMultipleApicDescriptionTable();
274 m_AcpiMemoryRegion(
"ACPI"),
277 m_PciConfigurationRanges(),
279 m_DmarPresent(false),
284 m_bValidApicInfo(false),
286 m_LocalApicAddress(0),
288 m_bValidProcessorInfo(false),
292 for (
size_t irq = 0; irq < 16; ++irq) {
293 m_IsaGsis[irq] = irq;
297bool Acpi::getPmTimerPort(uint16_t& port, uint32_t& mask)
const {
298 if (!m_bValid || !m_pFacp || (m_pFacp->flags & (1U << 20)) || m_pFacp->pmTimerLength != 4) {
302 uint64_t address = m_pFacp->pmTimerBlock;
304 if (m_pFacp->header.length >= 220) {
305 const uint8_t* gas =
reinterpret_cast<const uint8_t*
>(m_pFacp) + 208;
306 uint64_t extendedAddress = 0;
307 MemoryCopy(&extendedAddress, gas + 4,
sizeof(extendedAddress));
308 if (extendedAddress) {
309 if (gas[0] != 1 || (gas[1] != 24 && gas[1] != 32) || gas[2] || (gas[3] != 0 && gas[3] != 3)) {
312 address = extendedAddress;
315 if (!address || address > 0xfffc) {
318 port =
static_cast<uint16_t
>(address);
319 mask = (m_pFacp->flags & (1U << 8)) ? 0xffffffffU : 0x00ffffffU;
323bool Acpi::pciConfigurationAddress(uint8_t bus, uint64_t& address)
const {
327 for (
const auto& range : m_PciConfigurationRanges) {
328 if (bus >= range.firstBus && bus <= range.lastBus) {
329 address = range.base + (uint64_t(bus) << 20);
336bool Acpi::pciBusRange(uint8_t& first, uint8_t& last)
const {
337 if (!m_bValid || !m_PciConfigurationRanges.size()) {
342 for (
const auto& range : m_PciConfigurationRanges) {
343 if (range.firstBus < first) {
344 first = range.firstBus;
346 if (range.lastBus > last) {
347 last = range.lastBus;
354 if (!m_bValid || !m_PciInterruptRoutesPresent || slot >= 32 || pin < 1 || pin > 4) {
357 route = m_PciInterruptRoutes[slot][pin - 1];
358 return route.gsi >= 16;
361void Acpi::setPciInterruptRouter(PciInterruptRouter router) {
362 __atomic_store_n(&m_PciInterruptRouter, router, __ATOMIC_RELEASE);
365bool Acpi::hasPciInterruptRouter()
const {
366 return __atomic_load_n(&m_PciInterruptRouter, __ATOMIC_ACQUIRE) !=
nullptr;
370 if (!device || pin < 1 || pin > 4) {
373 const auto router = __atomic_load_n(&m_PciInterruptRouter, __ATOMIC_ACQUIRE);
375 return router(device, pin, route);
393bool Acpi::isaIrqsForGsi(uint32_t gsi, uint16_t& irqs)
const {
396 if (!m_bValidApicInfo) {
400 if (!m_bValid || !m_IsaRoutingValid) {
403 for (uint32_t nmi : m_NmiGsis) {
408 for (
size_t irq = 0; irq < 16; ++irq) {
409 if (m_IsaGsis[irq] == gsi) {
410 irqs |= uint16_t(1U << irq);
416void Acpi::parseFixedACPIDescriptionTable() {
417 NOTICE(
"ACPI: Fixed Description Table (FACP)");
419 NOTICE(
" Firmware ACPI Control Structure at " <<
Hex << m_pFacp->firmwareControl);
420 NOTICE(
" Differentiated System Description Table at " <<
Hex << m_pFacp->dsdt);
421 NOTICE(
" Interrupt Model: " <<
Dec
422 << ((m_pFacp->interruptModel == 0) ?
"dual 8259 PICs"
423 :
"multiple local APICs"));
424 NOTICE(
" SCI Interrupt #" <<
Dec << m_pFacp->sciInterrupt);
425 NOTICE(
" SMI Command Port at " <<
Hex << m_pFacp->smiCommandPort);
426 NOTICE(
" enable " <<
Hex << m_pFacp->acpiEnableCommand);
427 NOTICE(
" disable " <<
Hex << m_pFacp->acpiDisableCommand);
428 if (m_pFacp->s4BiosCommand != 0) {
429 NOTICE(
" S4 BIOS " <<
Hex << m_pFacp->s4BiosCommand);
431 NOTICE(
" Power-Management");
432 NOTICE(
" Event 1A at " <<
Hex << m_pFacp->pm1aEventBlock <<
" - "
433 << (m_pFacp->pm1aEventBlock + m_pFacp->pm1EventLength));
434 if (m_pFacp->pm1bEventBlock != 0) {
435 NOTICE(
" Event 1B at " <<
Hex << m_pFacp->pm1bEventBlock <<
" - "
436 << (m_pFacp->pm1bEventBlock + m_pFacp->pm1EventLength));
438 NOTICE(
" Control 1A at " <<
Hex << m_pFacp->pm1aControlBlock <<
" - "
439 << (m_pFacp->pm1aControlBlock + m_pFacp->pm1ControlLength));
440 if (m_pFacp->pm1bControlBlock != 0) {
441 NOTICE(
" Control 1B at " <<
Hex << m_pFacp->pm1bControlBlock <<
" - "
442 << (m_pFacp->pm1bControlBlock + m_pFacp->pm1ControlLength));
444 if (m_pFacp->pm2ControlBlock != 0) {
445 NOTICE(
" Control 2 at " <<
Hex << m_pFacp->pm2ControlBlock <<
" - "
446 << (m_pFacp->pm2ControlBlock + m_pFacp->pm2ControlLength));
448 NOTICE(
" Timer at " <<
Hex << m_pFacp->pmTimerBlock <<
" - "
449 << (m_pFacp->pmTimerBlock + m_pFacp->pmTimerLength));
450 if (m_pFacp->gpe0Block != 0) {
451 NOTICE(
" General Purpose Event 0 at " <<
Hex << m_pFacp->gpe0Block <<
" - "
452 << (m_pFacp->gpe0Block + m_pFacp->gpe0BlockLength));
454 if (m_pFacp->gpe1Block != 0) {
455 NOTICE(
" General Purpose Event 1 at " <<
Hex << m_pFacp->gpe1Block <<
" - "
456 << (m_pFacp->gpe1Block + m_pFacp->gpe1BlockLength));
458 if (m_pFacp->gpe1Base != 0) {
459 NOTICE(
" General Purpose Event Base: " <<
Hex << m_pFacp->gpe1Base);
462 NOTICE(
" Flags " <<
Hex << m_pFacp->flags);
466void Acpi::parseMultipleApicDescriptionTable() {
467 NOTICE(
"ACPI: Multiple APIC Description Table (APIC)");
469 if (m_pApic->length <
sizeof(SystemDescriptionTableHeader) + 8) {
470 ERROR(
"ACPI: truncated Multiple APIC Description Table");
475 uint32_t* pLocalApicAddress =
476 reinterpret_cast<uint32_t*
>(adjust_pointer(m_pApic,
sizeof(SystemDescriptionTableHeader)));
477 uint32_t* pFlags = adjust_pointer(pLocalApicAddress, 4);
479 m_LocalApicAddress = *pLocalApicAddress;
480 m_bHasPICs = (((*pFlags) & 0x01) == 0x01);
482 uint8_t* pType =
reinterpret_cast<uint8_t*
>(adjust_pointer(pFlags, 4));
483 uint8_t*
const end =
reinterpret_cast<uint8_t*
>(adjust_pointer(m_pApic, m_pApic->length));
484 for (; end - pType >= 2;) {
485 const uint8_t entryLength = pType[1];
486 if (entryLength < 2 || entryLength > end - pType) {
487 ERROR(
"ACPI: invalid Multiple APIC Description Table entry");
491 if (*pType == 0 && entryLength >= 8) {
492 ProcessorLocalApic* pLocalApic =
493 reinterpret_cast<ProcessorLocalApic*
>(adjust_pointer(pType, 2));
494 bool bUsable = ((pLocalApic->flags & 0x01) == 0x01);
495 NOTICE(
" Processor #" <<
Dec << pLocalApic->processorId
496 << (bUsable ?
" usable" :
" unusable"));
503 m_Processors.pushBack(pProcessorInfo);
507 else if (*pType == 1 && entryLength >= 12) {
508 IoApic* pIoApic =
reinterpret_cast<IoApic*
>(adjust_pointer(pType, 2));
510 NOTICE(
" I/O APIC #" <<
Dec << pIoApic->apicId <<
" at " <<
Hex << pIoApic->address
511 <<
", global system interrupt base "
512 << pIoApic->globalSystemInterruptBase);
516 pIoApic->apicId, pIoApic->address, pIoApic->globalSystemInterruptBase);
517 m_IoApics.pushBack(pIoApicInfo);
520 else if (*pType == 2 && entryLength >= 10) {
521 InterruptSourceOverride* pInterruptSourceOverride =
522 reinterpret_cast<InterruptSourceOverride*
>(adjust_pointer(pType, 2));
524 ERROR(
" Interrupt override: " << ((pInterruptSourceOverride->bus == 0) ?
"ISA" :
"unknown")
525 <<
" bus, #" <<
Dec << pInterruptSourceOverride->source
526 <<
" -> #" << pInterruptSourceOverride->globalSystemInterrupt
527 <<
", flags " <<
Hex << pInterruptSourceOverride->flags);
529 const auto& source = *pInterruptSourceOverride;
530 if (source.bus || source.source >= 16 || (m_IsaOverrides & (1U << source.source)) ||
531 (source.flags & ~0xfU) || (source.flags & 3) == 2 || ((source.flags >> 2) & 3) == 2) {
532 m_IsaRoutingValid =
false;
534 m_IsaGsis[source.source] = source.globalSystemInterrupt;
535 m_IsaOverrides |= uint16_t(1U << source.source);
539 else if (*pType == 3) {
540 ERROR(
" NMI source");
541 if (entryLength < 8) {
542 m_IsaRoutingValid =
false;
544 m_NmiGsis.pushBack(uint32_t(pType[4]) | (uint32_t(pType[5]) << 8) |
545 (uint32_t(pType[6]) << 16) | (uint32_t(pType[7]) << 24));
549 else if (*pType == 4) {
550 ERROR(
" Local APIC NMI");
553 else if (*pType == 5) {
554 ERROR(
" Local APIC address override");
557 else if (*pType == 6) {
561 else if (*pType == 7) {
562 ERROR(
" Local SAPIC");
565 else if (*pType == 8) {
566 ERROR(
" Platform Interrupt Source");
568 NOTICE(
" unknown entry #" <<
Dec << *pType);
572 pType += entryLength;
575 m_bValidApicInfo =
true;
576 m_bValidProcessorInfo =
true;
581 if (g_pBootstrapInfo && g_pBootstrapInfo->getAcpiRsdp()) {
582 m_pRsdtPointer =
reinterpret_cast<RsdtPointer*
>(g_pBootstrapInfo->getAcpiRsdp());
583 if (m_pRsdtPointer->signature == 0x2052545020445352ULL && checksum(m_pRsdtPointer)) {
587 m_pRsdtPointer =
nullptr;
591bool Acpi::checksum(
const RsdtPointer* pRdstPointer) {
593 if (::checksum(
reinterpret_cast<const uint8_t*
>(pRdstPointer), 20) ==
false)
596 if (pRdstPointer->revision >= 2) {
598 if (::checksum(
reinterpret_cast<const uint8_t*
>(pRdstPointer), pRdstPointer->length) ==
false)
605bool Acpi::checksum(
const SystemDescriptionTableHeader* pHeader) {
606 return ::checksum(
reinterpret_cast<const uint8_t*
>(pHeader), pHeader->length);
uint32_t getPciDevicePosition()
uint8_t getPciClassCode()
uint8_t getPciSubclassCode()
Device * getParent() const
uint32_t getPciBusPosition()
Special memory entity in the kernel's virtual address space.
physical_uintptr_t physicalAddress() const
static const size_t continuous
static constexpr size_t getPageSize() PURE
static const size_t force
static const size_t nonRamMemory
bool getRange(size_t index, Range &range) const
static const size_t KernelMode
static const size_t Write
Implementation of the PhysicalMemoryManager for common x86.
static X86CommonPhysicalMemoryManager & instance()
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1) override