Skip to content

Commit 12c492e

Browse files
committed
acpi: add ACPICA-based MDAT table parsing
Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
1 parent ea4f092 commit 12c492e

File tree

3 files changed

+286
-60
lines changed

3 files changed

+286
-60
lines changed

common/acpi.c

Lines changed: 255 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,43 @@
2222
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2323
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
*/
25-
#ifndef KTF_ACPICA
2625
#include <acpi_ktf.h>
27-
#include <errno.h>
2826
#include <ioapic.h>
29-
#include <ktf.h>
30-
#include <lib.h>
31-
#include <mm/pmm.h>
32-
#include <page.h>
33-
#include <pagetable.h>
3427
#include <percpu.h>
3528
#include <setup.h>
3629
#include <string.h>
3730

38-
acpi_table_t *acpi_tables[128];
39-
unsigned max_acpi_tables;
31+
static const char *madt_int_bus_names[] = {
32+
[ACPI_MADT_INT_BUS_ISA] = "ISA",
33+
};
34+
35+
static const char *madt_int_polarity_names[] = {
36+
[ACPI_MADT_INT_POLARITY_BS] = "Bus Spec",
37+
[ACPI_MADT_INT_POLARITY_AH] = "Active High",
38+
[ACPI_MADT_INT_POLARITY_RSVD] = "Reserved",
39+
[ACPI_MADT_INT_POLARITY_AL] = "Active Low",
40+
};
41+
42+
static const char *madt_int_trigger_names[] = {
43+
[ACPI_MADT_INT_TRIGGER_BS] = "Bus Spec",
44+
[ACPI_MADT_INT_TRIGGER_ET] = "Edge",
45+
[ACPI_MADT_INT_TRIGGER_RSVD] = "Reserved",
46+
[ACPI_MADT_INT_TRIGGER_LT] = "Level",
47+
};
4048

4149
static unsigned nr_cpus;
4250

4351
unsigned acpi_get_nr_cpus(void) { return nr_cpus; }
4452

53+
#ifndef KTF_ACPICA
54+
#include <errno.h>
55+
#include <page.h>
56+
#include <pagetable.h>
57+
#include <string.h>
58+
59+
acpi_table_t *acpi_tables[128];
60+
unsigned max_acpi_tables;
61+
4562
/* Calculate number of entries in the ACPI table.
4663
* Formula: (table_length - header_length) / entry_size
4764
*/
@@ -202,24 +219,6 @@ static inline void acpi_dump_tables(void) {
202219
acpi_dump_table(acpi_tables[i], &acpi_tables[i]->header);
203220
}
204221

205-
static const char *madt_int_bus_names[] = {
206-
[ACPI_MADT_INT_BUS_ISA] = "ISA",
207-
};
208-
209-
static const char *madt_int_polarity_names[] = {
210-
[ACPI_MADT_INT_POLARITY_BS] = "Bus Spec",
211-
[ACPI_MADT_INT_POLARITY_AH] = "Active High",
212-
[ACPI_MADT_INT_POLARITY_RSVD] = "Reserved",
213-
[ACPI_MADT_INT_POLARITY_AL] = "Active Low",
214-
};
215-
216-
static const char *madt_int_trigger_names[] = {
217-
[ACPI_MADT_INT_TRIGGER_BS] = "Bus Spec",
218-
[ACPI_MADT_INT_TRIGGER_ET] = "Edge",
219-
[ACPI_MADT_INT_TRIGGER_RSVD] = "Reserved",
220-
[ACPI_MADT_INT_TRIGGER_LT] = "Level",
221-
};
222-
223222
static int process_fadt(void) {
224223
acpi_fadt_rev1_t *fadt = (acpi_fadt_rev1_t *) acpi_find_table(FADT_SIGNATURE);
225224

@@ -441,15 +440,8 @@ int init_acpi(unsigned bsp_cpu_id) {
441440
return process_madt_entries(bsp_cpu_id);
442441
}
443442
#else /* KTF_ACPICA */
444-
#include <acpi_ktf.h>
445-
#include <ioapic.h>
446-
#include <ktf.h>
447-
#include <percpu.h>
448-
449443
#include "acpi.h"
450444

451-
static unsigned nr_cpus;
452-
453445
/* ACPI initialization and termination functions */
454446

455447
static ACPI_STATUS InitializeFullAcpi(void) {
@@ -484,7 +476,231 @@ static ACPI_STATUS InitializeFullAcpi(void) {
484476
return AE_OK;
485477
}
486478

487-
unsigned acpi_get_nr_cpus(void) { return nr_cpus; }
479+
static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) {
480+
bus_t *isa_bus =
481+
add_system_bus(ACPI_MADT_INT_BUS_ISA, madt_int_bus_names[ACPI_MADT_INT_BUS_ISA],
482+
strlen(madt_int_bus_names[ACPI_MADT_INT_BUS_ISA]));
483+
484+
BUG_ON(!isa_bus);
485+
486+
switch (entry->Type) {
487+
case ACPI_MADT_TYPE_LOCAL_APIC: {
488+
ACPI_MADT_LOCAL_APIC *lapic = (ACPI_MADT_LOCAL_APIC *) entry;
489+
uint32_t bsp_cpu_id = (uint32_t) _ul(arg);
490+
percpu_t *percpu;
491+
bool enabled;
492+
493+
/* Some systems report all CPUs, marked as disabled */
494+
enabled = !!(lapic->LapicFlags & 0x1);
495+
if (!enabled)
496+
break;
497+
498+
percpu = get_percpu_page(lapic->ProcessorId);
499+
percpu->cpu_id = lapic->ProcessorId;
500+
percpu->apic_id = lapic->Id;
501+
percpu->bsp = !!(lapic->ProcessorId == bsp_cpu_id);
502+
percpu->enabled = enabled;
503+
504+
nr_cpus++;
505+
printk("ACPI: [MADT] APIC Processor ID: %u, APIC ID: %u, Flags: %08x\n",
506+
percpu->cpu_id, percpu->apic_id, lapic->LapicFlags);
507+
break;
508+
}
509+
case ACPI_MADT_TYPE_IO_APIC: {
510+
ACPI_MADT_IO_APIC *ioapic = (ACPI_MADT_IO_APIC *) entry;
511+
512+
add_ioapic(ioapic->Id, 0x00, true, ioapic->Address, ioapic->GlobalIrqBase);
513+
514+
printk("ACPI: [MADT] IOAPIC ID: %u, Base Address: 0x%08x, GSI Base: 0x%08x\n",
515+
ioapic->Id, ioapic->Address, ioapic->GlobalIrqBase);
516+
517+
break;
518+
}
519+
case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: {
520+
ACPI_MADT_INTERRUPT_OVERRIDE *irq_src = (ACPI_MADT_INTERRUPT_OVERRIDE *) entry;
521+
irq_override_t override;
522+
523+
memset(&override, 0, sizeof(override));
524+
override.type = ACPI_MADT_IRQ_TYPE_INT;
525+
override.src = irq_src->SourceIrq;
526+
override.dst = irq_src->GlobalIrq;
527+
/* Destination to be found. Each IOAPIC has GSI base and Max Redir Entry
528+
* register */
529+
override.dst_id = IOAPIC_DEST_ID_UNKNOWN;
530+
531+
inti_flags_t flags = (inti_flags_t) irq_src->IntiFlags;
532+
override.polarity = flags.polarity;
533+
override.trigger_mode = flags.trigger_mode;
534+
add_system_bus_irq_override(irq_src->Bus, &override);
535+
536+
printk("ACPI: [MADT] IRQ Src Override: Bus: %3s, IRQ: 0x%02x, GSI: 0x%08x, "
537+
"Polarity: %11s, Trigger: %9s\n",
538+
madt_int_bus_names[irq_src->Bus], irq_src->SourceIrq, irq_src->GlobalIrq,
539+
madt_int_polarity_names[flags.polarity],
540+
madt_int_trigger_names[flags.trigger_mode]);
541+
break;
542+
}
543+
case ACPI_MADT_TYPE_NMI_SOURCE: {
544+
ACPI_MADT_NMI_SOURCE *nmi_src = (ACPI_MADT_NMI_SOURCE *) entry;
545+
irq_override_t override;
546+
547+
memset(&override, 0, sizeof(override));
548+
override.type = ACPI_MADT_IRQ_TYPE_NMI;
549+
override.src = nmi_src->GlobalIrq;
550+
551+
inti_flags_t flags = (inti_flags_t) nmi_src->IntiFlags;
552+
override.polarity = flags.polarity;
553+
override.trigger_mode = flags.trigger_mode;
554+
add_system_bus_irq_override(ACPI_MADT_INT_BUS_ISA, &override);
555+
556+
printk("ACPI: [MADT] NMI Src: GSI: 0x%08x, Polarity: %11s, Trigger: %9s\n",
557+
nmi_src->GlobalIrq, madt_int_polarity_names[flags.polarity],
558+
madt_int_trigger_names[flags.trigger_mode]);
559+
break;
560+
}
561+
case ACPI_MADT_TYPE_LOCAL_APIC_NMI: {
562+
ACPI_MADT_LOCAL_APIC_NMI *lapic_nmi = (ACPI_MADT_LOCAL_APIC_NMI *) entry;
563+
irq_override_t override;
564+
565+
memset(&override, 0, sizeof(override));
566+
override.type = ACPI_MADT_IRQ_TYPE_NMI;
567+
override.dst_id = lapic_nmi->ProcessorId;
568+
override.dst = lapic_nmi->Lint;
569+
570+
inti_flags_t flags = (inti_flags_t) lapic_nmi->IntiFlags;
571+
override.polarity = flags.polarity;
572+
override.trigger_mode = flags.trigger_mode;
573+
add_system_bus_irq_override(ACPI_MADT_INT_BUS_ISA, &override);
574+
575+
printk("ACPI: [MADT] Local APIC NMI LINT#: CPU UID: %02x, Polarity: %11s, "
576+
"Trigger: %9s, LINT#: 0x%02x\n",
577+
lapic_nmi->ProcessorId, madt_int_polarity_names[flags.polarity],
578+
madt_int_trigger_names[flags.trigger_mode], lapic_nmi->Lint);
579+
break;
580+
}
581+
case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: {
582+
ACPI_MADT_LOCAL_APIC_OVERRIDE *lapic_addr =
583+
(ACPI_MADT_LOCAL_APIC_OVERRIDE *) entry;
584+
585+
/* FIXME: set for each Per-CPU apic_base */
586+
printk("ACPI: [MADT] Local APIC Address: 0x%016lx\n", lapic_addr->Address);
587+
break;
588+
}
589+
case ACPI_MADT_TYPE_IO_SAPIC: {
590+
ACPI_MADT_IO_SAPIC *iosapic = (ACPI_MADT_IO_SAPIC *) entry;
591+
592+
add_ioapic(iosapic->Id, 0x00, true, iosapic->Address, iosapic->GlobalIrqBase);
593+
594+
printk("ACPI: [MADT] IOSAPIC ID: %u, Base Address: %p, GSI Base: 0x%08x\n",
595+
iosapic->Id, _ptr(iosapic->Address), iosapic->GlobalIrqBase);
596+
break;
597+
}
598+
case ACPI_MADT_TYPE_LOCAL_SAPIC: {
599+
ACPI_MADT_LOCAL_SAPIC *slapic = (ACPI_MADT_LOCAL_SAPIC *) entry;
600+
percpu_t *percpu = get_percpu_page(slapic->ProcessorId);
601+
uint32_t bsp_cpu_id = (uint32_t) _ul(arg);
602+
603+
percpu->cpu_id = slapic->ProcessorId;
604+
percpu->sapic_id = slapic->Id;
605+
percpu->sapic_eid = slapic->Eid;
606+
607+
percpu->sapic_uid = slapic->Uid;
608+
percpu->sapic_uid_str[0] = slapic->UidString[0];
609+
610+
percpu->bsp = !!(slapic->ProcessorId == bsp_cpu_id);
611+
percpu->enabled = !!(slapic->LapicFlags & 0x1);
612+
613+
if (percpu->enabled) {
614+
nr_cpus++;
615+
printk("ACPI: [MADT] SAPIC Processor ID: %u, SAPIC ID: %u, SAPIC EID: %u, "
616+
"SAPIC UID: %u, SAPIC UID Str: %c Flags: %08x\n",
617+
percpu->cpu_id, slapic->Id, slapic->Eid, slapic->Uid,
618+
slapic->UidString[0], slapic->LapicFlags);
619+
}
620+
break;
621+
}
622+
case ACPI_MADT_TYPE_INTERRUPT_SOURCE: {
623+
/* TODO: to be implemented */
624+
break;
625+
}
626+
case ACPI_MADT_TYPE_LOCAL_X2APIC: {
627+
ACPI_MADT_LOCAL_X2APIC *x2lapic = (ACPI_MADT_LOCAL_X2APIC *) entry;
628+
percpu_t *percpu = get_percpu_page(x2lapic->Uid);
629+
uint32_t bsp_cpu_id = (uint32_t) _ul(arg);
630+
631+
percpu->cpu_id = x2lapic->Uid;
632+
percpu->apic_id = x2lapic->LocalApicId;
633+
percpu->bsp = !!(x2lapic->Uid == bsp_cpu_id);
634+
percpu->enabled = !!(x2lapic->LapicFlags & 0x1);
635+
636+
if (percpu->enabled) {
637+
nr_cpus++;
638+
printk("ACPI: [MADT] X2APIC Processor ID: %u, APIC ID: %u, Flags: %08x\n",
639+
percpu->cpu_id, percpu->apic_id, x2lapic->LapicFlags);
640+
}
641+
break;
642+
}
643+
case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: {
644+
ACPI_MADT_LOCAL_X2APIC_NMI *x2lapic_nmi = (ACPI_MADT_LOCAL_X2APIC_NMI *) entry;
645+
irq_override_t override;
646+
647+
memset(&override, 0, sizeof(override));
648+
override.type = ACPI_MADT_IRQ_TYPE_NMI;
649+
override.dst_id = x2lapic_nmi->Uid;
650+
override.dst = x2lapic_nmi->Lint;
651+
652+
inti_flags_t flags = (inti_flags_t) x2lapic_nmi->IntiFlags;
653+
override.polarity = flags.polarity;
654+
override.trigger_mode = flags.trigger_mode;
655+
add_system_bus_irq_override(ACPI_MADT_INT_BUS_ISA, &override);
656+
657+
printk("ACPI: [MADT] Local X2APIC NMI LINT#: CPU UID: %02x, Polarity: %11s, "
658+
"Trigger: %9s, LINT#: 0x%02x\n",
659+
x2lapic_nmi->Uid, madt_int_polarity_names[flags.polarity],
660+
madt_int_trigger_names[flags.trigger_mode], x2lapic_nmi->Lint);
661+
break;
662+
}
663+
case ACPI_MADT_TYPE_GENERIC_INTERRUPT: {
664+
/* TODO: to be implemented */
665+
break;
666+
}
667+
case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR: {
668+
/* TODO: to be implemented */
669+
break;
670+
}
671+
case ACPI_MADT_TYPE_GENERIC_MSI_FRAME: {
672+
/* TODO: to be implemented */
673+
break;
674+
}
675+
case ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR: {
676+
/* TODO: to be implemented */
677+
break;
678+
}
679+
case ACPI_MADT_TYPE_GENERIC_TRANSLATOR: {
680+
/* TODO: to be implemented */
681+
break;
682+
}
683+
case ACPI_MADT_TYPE_MULTIPROC_WAKEUP: {
684+
/* TODO: to be implemented */
685+
break;
686+
}
687+
default:
688+
panic("ACPI [MADT]: Unsupported subtable entry type: %x\n", entry->Type);
689+
break;
690+
}
691+
}
692+
693+
static ACPI_STATUS init_madt(unsigned bsp_cpu_id) {
694+
ACPI_TABLE_MADT *madt = acpi_find_table(ACPI_SIG_MADT);
695+
ACPI_SUBTABLE_HEADER *subtbl = (void *) madt + sizeof(*madt);
696+
uint32_t length = madt->Header.Length - sizeof(*madt);
697+
698+
if (!madt || !subtbl)
699+
return AE_ERROR;
700+
701+
acpi_walk_subtables(subtbl, length, madt_parser, (void *) _ul(bsp_cpu_id));
702+
return AE_OK;
703+
}
488704

489705
void *acpi_find_table(char *signature) {
490706
ACPI_TABLE_HEADER *hdr;
@@ -509,6 +725,10 @@ ACPI_STATUS init_acpi(unsigned bsp_cpu_id) {
509725
printk("Initializing ACPI support\n");
510726

511727
status = InitializeFullAcpi();
728+
if (status != AE_OK)
729+
return status;
730+
731+
status = init_madt(bsp_cpu_id);
512732
return status;
513733
}
514734

0 commit comments

Comments
 (0)