mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
[kernel] Make sure to virtualize ACPI table pointers
Probably due to old UEFI page tables going away, some systems failed to load ACPI tables at their physical location. Make sure to translate them to kernel offset-mapped addresses.
This commit is contained in:
@@ -23,7 +23,7 @@ struct acpi_table_header
|
|||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
#define TABLE_HEADER(signature) \
|
#define TABLE_HEADER(signature) \
|
||||||
static const uint32_t type_id = kutil::byteswap(signature); \
|
static constexpr uint32_t type_id = kutil::byteswap(signature); \
|
||||||
acpi_table_header header;
|
acpi_table_header header;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ struct acpi2_rsdp
|
|||||||
uint32_t rsdt_address;
|
uint32_t rsdt_address;
|
||||||
|
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint64_t xsdt_address;
|
acpi_table_header *xsdt_address;
|
||||||
uint8_t checksum20;
|
uint8_t checksum20;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
@@ -73,13 +73,20 @@ device_manager::device_manager() :
|
|||||||
m_irqs[2] = ignore_endpoint;
|
m_irqs[2] = ignore_endpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> static const T *
|
||||||
|
check_get_table(const acpi_table_header *header)
|
||||||
|
{
|
||||||
|
kassert(header && header->validate(T::type_id), "Invalid ACPI table.");
|
||||||
|
return reinterpret_cast<const T *>(header);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::parse_acpi(const void *root_table)
|
device_manager::parse_acpi(const void *root_table)
|
||||||
{
|
{
|
||||||
kassert(root_table != 0, "ACPI root table pointer is null.");
|
kassert(root_table != 0, "ACPI root table pointer is null.");
|
||||||
|
|
||||||
const acpi1_rsdp *acpi1 =
|
const acpi1_rsdp *acpi1 = memory::to_virtual(
|
||||||
reinterpret_cast<const acpi1_rsdp *>(root_table);
|
reinterpret_cast<const acpi1_rsdp *>(root_table));
|
||||||
|
|
||||||
for (int i = 0; i < sizeof(acpi1->signature); ++i)
|
for (int i = 0; i < sizeof(acpi1->signature); ++i)
|
||||||
kassert(acpi1->signature[i] == expected_signature[i],
|
kassert(acpi1->signature[i] == expected_signature[i],
|
||||||
@@ -96,7 +103,7 @@ device_manager::parse_acpi(const void *root_table)
|
|||||||
sum = kutil::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
|
sum = kutil::checksum(acpi2, sizeof(acpi2_rsdp), sizeof(acpi1_rsdp));
|
||||||
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
kassert(sum == 0, "ACPI 2.0 RSDP checksum mismatch.");
|
||||||
|
|
||||||
load_xsdt(reinterpret_cast<const acpi_xsdt *>(acpi2->xsdt_address));
|
load_xsdt(memory::to_virtual(acpi2->xsdt_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
ioapic *
|
ioapic *
|
||||||
@@ -112,9 +119,9 @@ put_sig(char *into, uint32_t type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::load_xsdt(const acpi_xsdt *xsdt)
|
device_manager::load_xsdt(const acpi_table_header *header)
|
||||||
{
|
{
|
||||||
kassert(xsdt && acpi_validate(xsdt), "Invalid ACPI XSDT.");
|
const auto *xsdt = check_get_table<acpi_xsdt>(header);
|
||||||
|
|
||||||
char sig[5] = {0,0,0,0,0};
|
char sig[5] = {0,0,0,0,0};
|
||||||
log::info(logs::device, "ACPI 2.0+ tables loading");
|
log::info(logs::device, "ACPI 2.0+ tables loading");
|
||||||
@@ -124,7 +131,8 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt)
|
|||||||
|
|
||||||
size_t num_tables = acpi_table_entries(xsdt, sizeof(void*));
|
size_t num_tables = acpi_table_entries(xsdt, sizeof(void*));
|
||||||
for (size_t i = 0; i < num_tables; ++i) {
|
for (size_t i = 0; i < num_tables; ++i) {
|
||||||
const acpi_table_header *header = xsdt->headers[i];
|
const acpi_table_header *header =
|
||||||
|
memory::to_virtual(xsdt->headers[i]);
|
||||||
|
|
||||||
put_sig(sig, header->type);
|
put_sig(sig, header->type);
|
||||||
log::debug(logs::device, " Found table %s", sig);
|
log::debug(logs::device, " Found table %s", sig);
|
||||||
@@ -133,15 +141,15 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt)
|
|||||||
|
|
||||||
switch (header->type) {
|
switch (header->type) {
|
||||||
case acpi_apic::type_id:
|
case acpi_apic::type_id:
|
||||||
load_apic(reinterpret_cast<const acpi_apic *>(header));
|
load_apic(header);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case acpi_mcfg::type_id:
|
case acpi_mcfg::type_id:
|
||||||
load_mcfg(reinterpret_cast<const acpi_mcfg *>(header));
|
load_mcfg(header);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case acpi_hpet::type_id:
|
case acpi_hpet::type_id:
|
||||||
load_hpet(reinterpret_cast<const acpi_hpet *>(header));
|
load_hpet(header);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -151,8 +159,10 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::load_apic(const acpi_apic *apic)
|
device_manager::load_apic(const acpi_table_header *header)
|
||||||
{
|
{
|
||||||
|
const auto *apic = check_get_table<acpi_apic>(header);
|
||||||
|
|
||||||
uintptr_t local = apic->local_address;
|
uintptr_t local = apic->local_address;
|
||||||
m_lapic = new lapic(local, isr::isrSpurious);
|
m_lapic = new lapic(local, isr::isrSpurious);
|
||||||
|
|
||||||
@@ -249,8 +259,10 @@ device_manager::load_apic(const acpi_apic *apic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::load_mcfg(const acpi_mcfg *mcfg)
|
device_manager::load_mcfg(const acpi_table_header *header)
|
||||||
{
|
{
|
||||||
|
const auto *mcfg = check_get_table<acpi_mcfg>(header);
|
||||||
|
|
||||||
size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry));
|
size_t count = acpi_table_entries(mcfg, sizeof(acpi_mcfg_entry));
|
||||||
m_pci.set_size(count);
|
m_pci.set_size(count);
|
||||||
m_devices.set_capacity(16);
|
m_devices.set_capacity(16);
|
||||||
@@ -271,8 +283,10 @@ device_manager::load_mcfg(const acpi_mcfg *mcfg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
device_manager::load_hpet(const acpi_hpet *hpet)
|
device_manager::load_hpet(const acpi_table_header *header)
|
||||||
{
|
{
|
||||||
|
const auto *hpet = check_get_table<acpi_hpet>(header);
|
||||||
|
|
||||||
log::debug(logs::device, " Found HPET device #%3d: base %016lx pmin %d attr %02x",
|
log::debug(logs::device, " Found HPET device #%3d: base %016lx pmin %d attr %02x",
|
||||||
hpet->index, hpet->base_address.address, hpet->periodic_min, hpet->attributes);
|
hpet->index, hpet->base_address.address, hpet->periodic_min, hpet->attributes);
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
#include "hpet.h"
|
#include "hpet.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
struct acpi_xsdt;
|
struct acpi_table_header;
|
||||||
struct acpi_apic;
|
|
||||||
struct acpi_mcfg;
|
|
||||||
struct acpi_hpet;
|
|
||||||
class block_device;
|
class block_device;
|
||||||
class endpoint;
|
class endpoint;
|
||||||
|
|
||||||
@@ -100,19 +97,19 @@ public:
|
|||||||
private:
|
private:
|
||||||
/// Parse the ACPI XSDT and load relevant sub-tables.
|
/// Parse the ACPI XSDT and load relevant sub-tables.
|
||||||
/// \arg xsdt Pointer to the XSDT from the firmware
|
/// \arg xsdt Pointer to the XSDT from the firmware
|
||||||
void load_xsdt(const acpi_xsdt *xsdt);
|
void load_xsdt(const acpi_table_header *xsdt);
|
||||||
|
|
||||||
/// Parse the ACPI MADT and initialize APICs from it.
|
/// Parse the ACPI MADT and initialize APICs from it.
|
||||||
/// \arg apic Pointer to the MADT from the XSDT
|
/// \arg apic Pointer to the MADT from the XSDT
|
||||||
void load_apic(const acpi_apic *apic);
|
void load_apic(const acpi_table_header *apic);
|
||||||
|
|
||||||
/// Parse the ACPI MCFG and initialize PCIe from it.
|
/// Parse the ACPI MCFG and initialize PCIe from it.
|
||||||
/// \arg mcfg Pointer to the MCFG from the XSDT
|
/// \arg mcfg Pointer to the MCFG from the XSDT
|
||||||
void load_mcfg(const acpi_mcfg *mcfg);
|
void load_mcfg(const acpi_table_header *mcfg);
|
||||||
|
|
||||||
/// Parse the ACPI HPET and initialize an HPET from it.
|
/// Parse the ACPI HPET and initialize an HPET from it.
|
||||||
/// \arg hpet Pointer to the HPET from the XSDT
|
/// \arg hpet Pointer to the HPET from the XSDT
|
||||||
void load_hpet(const acpi_hpet *hpet);
|
void load_hpet(const acpi_table_header *hpet);
|
||||||
|
|
||||||
/// Probe the PCIe busses and add found devices to our
|
/// Probe the PCIe busses and add found devices to our
|
||||||
/// device list. The device list is destroyed and rebuilt.
|
/// device list. The device list is destroyed and rebuilt.
|
||||||
|
|||||||
Reference in New Issue
Block a user