Rework scanning MADT table entries
Get I/O APIC address from MADT entry. Add DEBUG flag for APIC. Show number of CPUs found.
This commit is contained in:
parent
c0a00b528e
commit
7264a31ff3
193
src/hulk/apic.d
193
src/hulk/apic.d
@ -13,6 +13,8 @@ import hulk.memory;
|
|||||||
|
|
||||||
struct Apic
|
struct Apic
|
||||||
{
|
{
|
||||||
|
private enum DEBUG = false;
|
||||||
|
private enum DEFAULT_IO_APIC_ADDRESS = 0xFEC0_0000u;
|
||||||
private enum uint PERIODIC_MODE = 0x2_0000u;
|
private enum uint PERIODIC_MODE = 0x2_0000u;
|
||||||
|
|
||||||
private enum ulong IRQ_PIT = 2u;
|
private enum ulong IRQ_PIT = 2u;
|
||||||
@ -28,16 +30,112 @@ struct Apic
|
|||||||
*/
|
*/
|
||||||
static struct Entry
|
static struct Entry
|
||||||
{
|
{
|
||||||
|
enum PROCESSOR_LOCAL_APIC = 0;
|
||||||
|
enum IO_APIC = 1;
|
||||||
|
enum IO_APIC_INTERRUPT_SOURCE_OVERRIDE = 2;
|
||||||
|
enum IO_APIC_NMI_SOURCE = 3;
|
||||||
|
enum LOCAL_APIC_NMI = 4;
|
||||||
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
|
enum LOCAL_APIC_ADDRESS_OVERRIDE = 5;
|
||||||
|
enum PROCESSOR_LOCAL_X2APIC = 9;
|
||||||
|
|
||||||
ubyte type;
|
ubyte type;
|
||||||
ubyte length;
|
ubyte length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor Local APIC.
|
||||||
|
*/
|
||||||
|
static struct Entry0
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ubyte acpi_processor_id;
|
||||||
|
ubyte apic_id;
|
||||||
|
uint flags;
|
||||||
|
}
|
||||||
|
static assert(Entry0.sizeof == 8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I/O APIC.
|
||||||
|
*/
|
||||||
|
static struct Entry1
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ubyte io_apic_id;
|
||||||
|
ubyte _reserved;
|
||||||
|
uint io_apic_address;
|
||||||
|
uint global_system_interrupt_base;
|
||||||
|
}
|
||||||
|
static assert(Entry1.sizeof == 12);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO/APIC Interrupt Source Override.
|
||||||
|
*/
|
||||||
|
static struct Entry2
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ubyte bus_source;
|
||||||
|
ubyte irq_source;
|
||||||
|
uint global_system_interrupt;
|
||||||
|
ushort flags;
|
||||||
|
ushort _reserved;
|
||||||
|
}
|
||||||
|
static assert(Entry2.sizeof == 12);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO/APIC Non-maskable interrupt source.
|
||||||
|
*/
|
||||||
|
static struct Entry3
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ubyte nmi_source;
|
||||||
|
ubyte _reserved;
|
||||||
|
ushort flags;
|
||||||
|
ubyte[4] global_system_interrupt;
|
||||||
|
}
|
||||||
|
static assert(Entry3.sizeof == 10);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local APIC Non-maskable interrupts.
|
||||||
|
*/
|
||||||
|
static struct Entry4
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ubyte acpi_processor_id;
|
||||||
|
ubyte[2] flags;
|
||||||
|
ubyte lint_nr;
|
||||||
|
}
|
||||||
|
static assert(Entry4.sizeof == 6);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local APIC Address Override.
|
||||||
|
*/
|
||||||
|
static struct Entry5
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ushort _reserved;
|
||||||
|
ubyte[8] local_apic_address;
|
||||||
|
}
|
||||||
|
static assert(Entry5.sizeof == 12);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor Local x2APIC.
|
||||||
|
*/
|
||||||
|
static struct Entry9
|
||||||
|
{
|
||||||
|
Entry header;
|
||||||
|
ushort _reserved;
|
||||||
|
uint local_x2apic_id;
|
||||||
|
uint flags;
|
||||||
|
uint acpi_id;
|
||||||
|
}
|
||||||
|
static assert(Entry9.sizeof == 16);
|
||||||
|
|
||||||
Acpi.Header header;
|
Acpi.Header header;
|
||||||
uint local_apic_address;
|
uint local_apic_address;
|
||||||
uint flags;
|
uint flags;
|
||||||
|
|
||||||
|
static assert(MADT.sizeof == 0x2C);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan the MADT table.
|
* Scan the MADT table.
|
||||||
*/
|
*/
|
||||||
@ -46,14 +144,99 @@ struct Apic
|
|||||||
apic_registers = cast(ApicRegisters *)local_apic_address;
|
apic_registers = cast(ApicRegisters *)local_apic_address;
|
||||||
const(void) * end = cast(const(void) *)(&this) + header.length;
|
const(void) * end = cast(const(void) *)(&this) + header.length;
|
||||||
const(Entry) * entry = cast(const(Entry) *)(cast(ulong)&this + MADT.sizeof);
|
const(Entry) * entry = cast(const(Entry) *)(cast(ulong)&this + MADT.sizeof);
|
||||||
|
bool first_io_apic = true;
|
||||||
|
size_t n_cpus = 0u;
|
||||||
while (entry < end)
|
while (entry < end)
|
||||||
{
|
{
|
||||||
entry = cast(const(Entry) *)(cast(size_t)entry + entry.length);
|
if (DEBUG)
|
||||||
if (entry.type == Entry.LOCAL_APIC_ADDRESS_OVERRIDE)
|
|
||||||
{
|
{
|
||||||
/* Found a 64-bit Local APIC Address Override entry. */
|
Klog.writefln("MADT entry type %u, length %u", entry.type, entry.length);
|
||||||
memcpy(cast(void *)&apic_registers, cast(const(void) *)entry + 4u, apic_registers.sizeof);
|
|
||||||
}
|
}
|
||||||
|
switch (entry.type)
|
||||||
|
{
|
||||||
|
case Entry.PROCESSOR_LOCAL_APIC:
|
||||||
|
Entry0 * e = cast(Entry0 *)entry;
|
||||||
|
n_cpus++;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
Klog.writefln(" ACPI processor ID: %u, APIC ID: %u, Flags: 0x%x",
|
||||||
|
e.acpi_processor_id, e.apic_id, e.flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.IO_APIC:
|
||||||
|
Entry1 * e = cast(Entry1 *)entry;
|
||||||
|
if (first_io_apic)
|
||||||
|
{
|
||||||
|
io_apic_registers = cast(IoApicRegisters *)e.io_apic_address;
|
||||||
|
first_io_apic = false;
|
||||||
|
}
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
Klog.writefln(" I/O APIC ID: %u, I/O APIC Address: 0x%x, GSIB: %u",
|
||||||
|
e.io_apic_id, e.io_apic_address, e.global_system_interrupt_base);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.IO_APIC_INTERRUPT_SOURCE_OVERRIDE:
|
||||||
|
Entry2 * e = cast(Entry2 *)entry;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
Klog.writefln(" Bus %u IRQ %u GSI %u Flags: 0x%x",
|
||||||
|
e.bus_source, e.irq_source, e.global_system_interrupt, e.flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.IO_APIC_NMI_SOURCE:
|
||||||
|
Entry3 * e = cast(Entry3 *)entry;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
uint global_system_interrupt;
|
||||||
|
memcpy(&global_system_interrupt, &e.global_system_interrupt, 4u);
|
||||||
|
Klog.writefln(" NMI Source: %u, Flags: 0x%x, GSI: %u",
|
||||||
|
e.nmi_source, e.flags, global_system_interrupt);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.LOCAL_APIC_NMI:
|
||||||
|
Entry4 * e = cast(Entry4 *)entry;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
ushort flags;
|
||||||
|
memcpy(&flags, &e.flags, 2u);
|
||||||
|
Klog.writefln(" ACPI Processor ID: %u, Flags: 0x%x, LINT#: %u",
|
||||||
|
e.acpi_processor_id, flags, e.lint_nr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.LOCAL_APIC_ADDRESS_OVERRIDE:
|
||||||
|
Entry5 * e = cast(Entry5 *)entry;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
memcpy(&apic_registers, &e.local_apic_address, 8u);
|
||||||
|
Klog.writefln(" Local APIC Address: 0x%x", apic_registers);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Entry.PROCESSOR_LOCAL_X2APIC:
|
||||||
|
Entry9 * e = cast(Entry9 *)entry;
|
||||||
|
if (DEBUG)
|
||||||
|
{
|
||||||
|
Klog.writefln(" x2APIC ID: %u, Flags: 0x%x, ACPI ID: %u",
|
||||||
|
e.local_x2apic_id, e.flags, e.acpi_id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to next entry. */
|
||||||
|
entry = cast(const(Entry) *)(cast(size_t)entry + entry.length);
|
||||||
|
}
|
||||||
|
if (n_cpus > 0u)
|
||||||
|
{
|
||||||
|
Klog.writefln("%u CPU(s) found", n_cpus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +305,7 @@ struct Apic
|
|||||||
public static void initialize()
|
public static void initialize()
|
||||||
{
|
{
|
||||||
Klog.writefln("\a3Initializing APIC");
|
Klog.writefln("\a3Initializing APIC");
|
||||||
io_apic_registers = cast(IoApicRegisters *)0xFEC0_0000u;
|
io_apic_registers = cast(IoApicRegisters *)DEFAULT_IO_APIC_ADDRESS;
|
||||||
MADT * madt = cast(MADT *)Acpi.get_table("APIC");
|
MADT * madt = cast(MADT *)Acpi.get_table("APIC");
|
||||||
madt.scan();
|
madt.scan();
|
||||||
Klog.writefln("APIC found at %p", apic_registers);
|
Klog.writefln("APIC found at %p", apic_registers);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user