Move MADT table processing from ACPI to APIC

This commit is contained in:
Josh Holtrop 2023-10-25 21:11:21 -04:00
parent 2b87792c67
commit e32282f6f0
4 changed files with 74 additions and 53 deletions

View File

@ -15,14 +15,13 @@ struct Acpi
*/ */
private static __gshared List!Header tables; private static __gshared List!Header tables;
enum uint APIC_SIGNATURE = signature("APIC");
enum uint MCFG_SIGNATURE = signature("MCFG"); enum uint MCFG_SIGNATURE = signature("MCFG");
enum uint XSDT_SIGNATURE = signature("XSDT"); enum uint XSDT_SIGNATURE = signature("XSDT");
/** /**
* ACPI table header structure. * ACPI table header structure.
*/ */
static struct Header public static struct Header
{ {
uint signature; uint signature;
uint length; uint length;
@ -46,37 +45,6 @@ struct Acpi
} }
static assert(XSDT.tables.offsetof == 36); static assert(XSDT.tables.offsetof == 36);
static struct MADT
{
static struct Entry
{
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
ubyte type;
ubyte length;
}
Header header;
uint local_apic_address;
uint flags;
void initialize()
{
apic_address = local_apic_address;
const(void) * end = cast(const(void) *)(&this) + header.length;
const(Entry) * entry = cast(const(Entry) *)(cast(ulong)&this + MADT.sizeof);
while (entry < end)
{
entry = cast(const(Entry) *)(cast(size_t)entry + entry.length);
if (entry.type == Entry.LOCAL_APIC_ADDRESS_OVERRIDE)
{
/* Found a 64-bit Local APIC Address Override entry. */
memcpy(cast(void *)&apic_address, cast(const(void) *)entry + 4u, apic_address.sizeof);
}
}
}
}
static struct MCFG static struct MCFG
{ {
/* PCI Segment Group Memory Area Descriptor. */ /* PCI Segment Group Memory Area Descriptor. */
@ -106,10 +74,6 @@ struct Acpi
} }
} }
public __gshared ulong apic_address;
public __gshared MADT * madt;
public __gshared MCFG * mcfg; public __gshared MCFG * mcfg;
public static void initialize(ulong acpi_xsdt_phys) public static void initialize(ulong acpi_xsdt_phys)
@ -148,20 +112,11 @@ struct Acpi
(signature >> 16u) & 0xFFu, (signature >> 16u) & 0xFFu,
(signature >> 24u) & 0xFFu, (signature >> 24u) & 0xFFu,
address); address);
if (signature == APIC_SIGNATURE) if (signature == MCFG_SIGNATURE)
{
madt = cast(MADT *)address;
madt.initialize();
}
else if (signature == MCFG_SIGNATURE)
{ {
mcfg = cast(MCFG *)address; mcfg = cast(MCFG *)address;
} }
} }
if (madt == null)
{
Klog.fatal_error("MADT table not found");
}
if (mcfg == null) if (mcfg == null)
{ {
Klog.fatal_error("MCFG table not found"); Klog.fatal_error("MCFG table not found");
@ -174,14 +129,14 @@ struct Acpi
* @param name * @param name
* Table name. * Table name.
*/ */
public Header * get_table(string name) public static Header * get_table(string name)
{ {
uint signature = signature(name); uint signature = signature(name);
foreach (table; tables) foreach (table; tables)
{ {
if (table.signature == signature) if (table.signature == signature)
{ {
return &table; return table;
} }
} }
Klog.fatal_error("Could not find requested ACPI table"); Klog.fatal_error("Could not find requested ACPI table");

View File

@ -9,6 +9,7 @@ import hulk.idt;
import hulk.rtc; import hulk.rtc;
import hulk.pit; import hulk.pit;
import hulk.klog; import hulk.klog;
import hulk.memory;
struct Apic struct Apic
{ {
@ -17,6 +18,49 @@ struct Apic
private enum ulong IRQ_PIT = 2u; private enum ulong IRQ_PIT = 2u;
private enum ulong IRQ_RTC = 8u; private enum ulong IRQ_RTC = 8u;
/**
* MADT ACPI table structure.
*/
static struct MADT
{
/**
* MADT table entry header.
*/
static struct Entry
{
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
ubyte type;
ubyte length;
}
Acpi.Header header;
uint local_apic_address;
uint flags;
/**
* Scan the MADT table.
*/
public void scan()
{
apic_registers = cast(ApicRegisters *)local_apic_address;
const(void) * end = cast(const(void) *)(&this) + header.length;
const(Entry) * entry = cast(const(Entry) *)(cast(ulong)&this + MADT.sizeof);
while (entry < end)
{
entry = cast(const(Entry) *)(cast(size_t)entry + entry.length);
if (entry.type == Entry.LOCAL_APIC_ADDRESS_OVERRIDE)
{
/* Found a 64-bit Local APIC Address Override entry. */
memcpy(cast(void *)&apic_registers, cast(const(void) *)entry + 4u, apic_registers.sizeof);
}
}
}
}
/**
* APIC register structure.
*/
static struct ApicRegister static struct ApicRegister
{ {
public uint value; public uint value;
@ -25,6 +69,9 @@ struct Apic
private ubyte[12] _padding; private ubyte[12] _padding;
} }
/**
* APIC registers.
*/
static struct ApicRegisters static struct ApicRegisters
{ {
ApicRegister[2] _reserved0; ApicRegister[2] _reserved0;
@ -57,6 +104,9 @@ struct Apic
ApicRegister divide_configuration; ApicRegister divide_configuration;
} }
/**
* I/O APIC registers.
*/
static struct IoApicRegisters static struct IoApicRegisters
{ {
ApicRegister address; ApicRegister address;
@ -66,10 +116,17 @@ struct Apic
private static __gshared ApicRegisters * apic_registers; private static __gshared ApicRegisters * apic_registers;
private static __gshared IoApicRegisters * io_apic_registers; private static __gshared IoApicRegisters * io_apic_registers;
/**
* Initialize APIC.
*/
public static void initialize() public static void initialize()
{ {
apic_registers = cast(ApicRegisters *)Acpi.apic_address; Klog.writefln("\a3Initializing APIC");
io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u; io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u;
MADT * madt = cast(MADT *)Acpi.get_table("APIC");
madt.scan();
Klog.writefln("APIC found at %p", apic_registers);
Klog.writefln("I/O APIC found at %p", io_apic_registers);
Hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers, Hurl.map(cast(ulong)apic_registers, cast(ulong)apic_registers,
PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE); PT_WRITABLE | PT_WRITE_THROUGH | PT_DISABLE_CACHE | PT_NO_EXECUTE);
Hurl.map(cast(ulong)io_apic_registers, cast(ulong)io_apic_registers, Hurl.map(cast(ulong)io_apic_registers, cast(ulong)io_apic_registers,
@ -86,6 +143,9 @@ struct Apic
configure_io_apic_irq(IRQ_RTC, Idt.INT_APIC_BASE + IRQ_RTC); configure_io_apic_irq(IRQ_RTC, Idt.INT_APIC_BASE + IRQ_RTC);
} }
/**
* Configure routing for an I/O APIC IRQ.
*/
private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id) private static void configure_io_apic_irq(size_t io_apic_irq, size_t interrupt_id)
{ {
ulong entry = interrupt_id; ulong entry = interrupt_id;
@ -95,11 +155,17 @@ struct Apic
io_apic_registers.data.value = entry >> 32u; io_apic_registers.data.value = entry >> 32u;
} }
/**
* Signal APIC end of interrupt.
*/
public static void eoi() public static void eoi()
{ {
apic_registers.eoi.value = 0u; apic_registers.eoi.value = 0u;
} }
/**
* APIC interrupt handler.
*/
public static void isr(ulong vector) public static void isr(ulong vector)
{ {
switch (vector) switch (vector)

View File

@ -34,12 +34,12 @@ struct List(T)
/** /**
* Allow foreach iteration across a List. * Allow foreach iteration across a List.
*/ */
public int opApply(scope int delegate(ref T) dg) public int opApply(scope int delegate(T *) dg)
{ {
List!T * entry = &this; List!T * entry = &this;
while (entry.next != null) while (entry.next != null)
{ {
int result = dg(*entry.item); int result = dg(entry.item);
if (result != 0) if (result != 0)
{ {
return result; return result;

View File

@ -17,7 +17,7 @@ struct Usb
{ {
if (pci_device.type == Pci.XHCI_CONTROLLER) if (pci_device.type == Pci.XHCI_CONTROLLER)
{ {
XHCI.build(&pci_device); XHCI.build(pci_device);
} }
} }
} }