From 7d0c0a3b099249d61c98b04ef5a2dbb5165da2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Tue, 11 Nov 2025 15:48:47 +0100 Subject: [PATCH 1/3] acpi: split ACPICA init in two MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - IOAPIC init requires ACPI tables - ACPI subsystem enable requires IOAPIC Hence, we first init ACPI tables, then IOAPIC, then enable ACPI subsystem. Signed-off-by: Sandro Rüegge --- common/acpi.c | 74 ++++++++++++++++++++++++---------------------- common/setup.c | 10 ++++++- include/acpi_ktf.h | 3 +- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/common/acpi.c b/common/acpi.c index 1cede225..bd21eebf 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -425,38 +425,6 @@ int init_acpi(void) { /* ACPI initialization and termination functions */ -static ACPI_STATUS InitializeFullAcpi(void) { - ACPI_STATUS status; - - /* Initialize the ACPICA subsystem */ - status = AcpiInitializeSubsystem(); - if (ACPI_FAILURE(status)) - return status; - - /* Initialize the ACPICA Table Manager and get all ACPI tables */ - status = AcpiInitializeTables(NULL, 16, true); - if (ACPI_FAILURE(status)) - return status; - - /* Create the ACPI namespace from ACPI tables */ - status = AcpiLoadTables(); - if (ACPI_FAILURE(status)) - return status; - - /* Note: Local handlers should be installed here */ - /* Initialize the ACPI hardware */ - status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); - if (ACPI_FAILURE(status)) - return status; - - /* Complete the ACPI namespace object initialization */ - status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); - if (ACPI_FAILURE(status)) - return status; - - return AE_OK; -} - static void madt_parser(ACPI_SUBTABLE_HEADER *entry, void *arg) { bus_t *isa_bus = add_system_bus(ACPI_MADT_INT_BUS_ISA, madt_int_bus_names[ACPI_MADT_INT_BUS_ISA], @@ -708,23 +676,57 @@ void acpi_walk_subtables(ACPI_SUBTABLE_HEADER *entry, uint32_t length, } } -ACPI_STATUS init_acpi(void) { +ACPI_STATUS init_acpi_tables(void) { ACPI_STATUS status; printk("Initializing ACPI support\n"); - status = InitializeFullAcpi(); - if (status != AE_OK) + /* Initialize the ACPICA subsystem */ + status = AcpiInitializeSubsystem(); + if (ACPI_FAILURE(status)) + return status; + + /* Initialize the ACPICA Table Manager and get all ACPI tables */ + status = AcpiInitializeTables(NULL, 16, true); + if (ACPI_FAILURE(status)) + return status; + + /* Create the ACPI namespace from ACPI tables */ + status = AcpiLoadTables(); + if (ACPI_FAILURE(status)) return status; status = init_fadt(); - if (status != AE_OK) + if (ACPI_FAILURE(status)) return status; status = init_madt(); return status; } +ACPI_STATUS init_acpi_subsystem(void) { + ACPI_STATUS status; + + printk("Initializing ACPI finalize\n"); + + /* Note: Local handlers should be installed here */ + /* Initialize the ACPI hardware */ + status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) + return status; + + /* Complete the ACPI namespace object initialization */ + status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) + return status; + + status = AcpiUpdateAllGpes(); + if (ACPI_FAILURE(status)) + return status; + + return AE_OK; +} + void acpi_power_off(void) { AcpiEnterSleepStatePrep(ACPI_STATE_S5); interrupts_disable(); diff --git a/common/setup.c b/common/setup.c index f6037198..cae1a7b9 100644 --- a/common/setup.c +++ b/common/setup.c @@ -245,7 +245,8 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, unsigned long #ifndef KTF_ACPICA if (init_acpi() < 0) { #else - if (ACPI_FAILURE(init_acpi())) { + ACPI_STATUS acpi_status = init_acpi_tables(); + if (ACPI_FAILURE(acpi_status)) { #endif /* Fallback to MP tables when no ACPI */ if (init_mptables() < 0) @@ -254,6 +255,13 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, unsigned long init_ioapic(); +#ifdef KTF_ACPICA + if (ACPI_SUCCESS(acpi_status)) { + if (ACPI_FAILURE(init_acpi_subsystem())) + panic("Failed to initialize ACPICA subsystem\n"); + } +#endif + /* Initialize timers and enable interrupts */ init_timers(bsp); interrupts_enable(); diff --git a/include/acpi_ktf.h b/include/acpi_ktf.h index 12988bd9..8caab91b 100644 --- a/include/acpi_ktf.h +++ b/include/acpi_ktf.h @@ -293,7 +293,8 @@ extern void *acpi_find_table(char *signature); extern void acpi_walk_subtables(ACPI_SUBTABLE_HEADER *entry, uint32_t length, acpi_subtable_parser_t parser, void *arg); -extern ACPI_STATUS init_acpi(void); +extern ACPI_STATUS init_acpi_tables(void); +extern ACPI_STATUS init_acpi_subsystem(void); extern void acpi_power_off(void); extern void acpi_reboot(void); From e907bdc0a0c23a6428bc36e9a0ab2d157cdefe45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Tue, 11 Nov 2025 15:50:17 +0100 Subject: [PATCH 2/3] ioapic: extend interface for flexibility and irq masking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - We need a configure_irq because SCI has special polarity and trigger mode - We need mask_irq to implement ACPICA handler removal Signed-off-by: Sandro Rüegge --- arch/x86/ioapic.c | 55 ++++++++++++++++++++++++++++----------- include/arch/x86/ioapic.h | 4 +++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/arch/x86/ioapic.c b/arch/x86/ioapic.c index 2cff3bbd..a2668aec 100644 --- a/arch/x86/ioapic.c +++ b/arch/x86/ioapic.c @@ -275,30 +275,42 @@ static ioapic_t *find_ioapic_for_irq(uint32_t irq_src) { return NULL; } -void configure_isa_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_mode, - uint8_t dst_ids) { - irq_override_t *irq_override = get_system_isa_bus_irq(IOAPIC_IRQ_TYPE_INT, irq_src); - ioapic_redirtbl_entry_t entry; - ioapic_polarity_t polarity = IOAPIC_POLARITY_AH; - ioapic_trigger_mode_t trigger_mode = IOAPIC_TRIGGER_MODE_EDGE; - ioapic_t *ioapic; - +/** + * Find the IOAPIC for an interrupt source while applying the override. + * If irq_dst is not NULL, it is updated with the irq_src or the override + * destination. + */ +static ioapic_t *find_ioapic_with_override(uint32_t irq_src, uint32_t *irq_dst, + irq_override_t *irq_override) { if (irq_override) { irq_src = irq_override->dst; + if (irq_override->dst_id != IOAPIC_DEST_ID_UNKNOWN) + return get_ioapic(irq_override->dst_id); + } + + if (irq_dst) + *irq_dst = irq_src; - if (irq_override->dst_id == IOAPIC_DEST_ID_UNKNOWN) - ioapic = find_ioapic_for_irq(irq_src); - else - ioapic = get_ioapic(irq_override->dst_id); + return find_ioapic_for_irq(irq_src); +} +void configure_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_mode, + uint8_t dst_ids, ioapic_polarity_t polarity, + ioapic_trigger_mode_t trigger_mode) { + irq_override_t *irq_override = get_system_isa_bus_irq(IOAPIC_IRQ_TYPE_INT, irq_src); + ioapic_t *ioapic = find_ioapic_with_override(irq_src, &irq_src, irq_override); + ioapic_redirtbl_entry_t entry; + + if (irq_override) { if (irq_override->polarity == IOAPIC_IRQ_OVR_POLARITY_AL) polarity = IOAPIC_POLARITY_AL; + else if (irq_override->polarity == IOAPIC_IRQ_OVR_POLARITY_AH) + polarity = IOAPIC_POLARITY_AH; if (irq_override->trigger_mode == IOAPIC_IRQ_OVR_TRIGGER_LT) trigger_mode = IOAPIC_TRIGGER_MODE_LEVEL; - } - else { - ioapic = find_ioapic_for_irq(irq_src); + else if (irq_override->trigger_mode == IOAPIC_IRQ_OVR_TRIGGER_ET) + trigger_mode = IOAPIC_TRIGGER_MODE_EDGE; } get_ioapic_redirtbl_entry(ioapic, irq_src, &entry); @@ -311,3 +323,16 @@ void configure_isa_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_ entry.int_mask = IOAPIC_INT_UNMASK; set_ioapic_redirtbl_entry(ioapic, irq_src, &entry); } + +void configure_isa_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_mode, + uint8_t dst_ids) { + configure_irq(irq_src, vector, dst_mode, dst_ids, IOAPIC_POLARITY_AH, + IOAPIC_TRIGGER_MODE_EDGE); +} + +void mask_irq(unsigned irq_src) { + irq_override_t *irq_override = get_system_isa_bus_irq(IOAPIC_IRQ_TYPE_INT, irq_src); + ioapic_t *ioapic = find_ioapic_with_override(irq_src, &irq_src, irq_override); + + set_ioapic_irq_mask(ioapic, irq_src, IOAPIC_INT_MASK); +} diff --git a/include/arch/x86/ioapic.h b/include/arch/x86/ioapic.h index 76870e92..ec4862bb 100644 --- a/include/arch/x86/ioapic.h +++ b/include/arch/x86/ioapic.h @@ -216,8 +216,12 @@ extern int get_ioapic_redirtbl_entry(ioapic_t *ioapic, unsigned n, extern int set_ioapic_redirtbl_entry(ioapic_t *ioapic, unsigned n, ioapic_redirtbl_entry_t *entry); extern void set_ioapic_irq_mask(ioapic_t *ioapic, unsigned irq, ioapic_int_mask_t mask); +extern void configure_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_mode, + uint8_t dst_ids, ioapic_polarity_t polarity, + ioapic_trigger_mode_t trigger_mode); extern void configure_isa_irq(unsigned irq_src, uint8_t vector, ioapic_dest_mode_t dst_mode, uint8_t dst_ids); +extern void mask_irq(unsigned irq_src); /* Static declarations */ From 389e86d99b00c6ff24aab286d14946099a3ebfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sandro=20R=C3=BCegge?= Date: Tue, 11 Nov 2025 15:56:50 +0100 Subject: [PATCH 3/3] acpi: properly configure/mask SCI interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We select an unused interrupt vector. Configure/mask the SCI interrupt in IOAPIC. We send the apic end of interrupt signal. Signed-off-by: Sandro Rüegge --- drivers/acpi/acpica/osl.c | 11 ++++++++++- include/acpi_ktf.h | 2 -- include/arch/x86/apic.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/acpica/osl.c b/drivers/acpi/acpica/osl.c index e1862cf7..41c71787 100644 --- a/drivers/acpi/acpica/osl.c +++ b/drivers/acpi/acpica/osl.c @@ -25,6 +25,7 @@ #ifdef KTF_ACPICA #include #include +#include #include #include #include @@ -574,6 +575,8 @@ void acpi_interrupt_handler(void) { acpi_irq_handled = true; else if (ret == ACPI_INTERRUPT_NOT_HANDLED) acpi_irq_handled = false; + + apic_EOI(); } ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLER Handler, @@ -591,10 +594,13 @@ ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 InterruptLevel, ACPI_OSD_HANDLE acpi_irq_handler = Handler; acpi_irq_context = Context; - set_intr_gate(&percpu->idt[acpi_irq_num], __KERN_CS, _ul(asm_interrupt_handler_acpi), + set_intr_gate(&percpu->idt[ACPI_SCI_IRQ], __KERN_CS, _ul(asm_interrupt_handler_acpi), GATE_DPL0, GATE_PRESENT, 1); barrier(); + configure_irq(acpi_irq_num, ACPI_SCI_IRQ, IOAPIC_DEST_MODE_PHYSICAL, cpu->id, + IOAPIC_POLARITY_AL, IOAPIC_TRIGGER_MODE_LEVEL); + acpi_irq_installed = true; return AE_OK; } @@ -613,6 +619,9 @@ ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 InterruptLevel, if (Handler != _ptr(get_intr_handler(&percpu->idt[acpi_irq_num]))) return AE_BAD_PARAMETER; + mask_irq(acpi_irq_num); + + barrier(); set_intr_gate(&percpu->idt[acpi_irq_num], __KERN_CS, _ul(NULL), GATE_DPL0, GATE_NOT_PRESENT, 0); barrier(); diff --git a/include/acpi_ktf.h b/include/acpi_ktf.h index 8caab91b..7788aac9 100644 --- a/include/acpi_ktf.h +++ b/include/acpi_ktf.h @@ -275,8 +275,6 @@ extern int init_acpi(void); #include "acpi.h" -#define ACPI_SCI_IRQ 0x9 - typedef void (*acpi_subtable_parser_t)(ACPI_SUBTABLE_HEADER *entry, void *arg); union inti_flags { diff --git a/include/arch/x86/apic.h b/include/arch/x86/apic.h index 717bbb40..e2666e26 100644 --- a/include/arch/x86/apic.h +++ b/include/arch/x86/apic.h @@ -33,6 +33,7 @@ #define APIC_IRQ_BASE PIC_IRQ_END_OFFSET #define APIC_TIMER_IRQ_OFFSET (APIC_IRQ_BASE + 0x00) #define APIC_TIMER_IRQ_VECTOR APIC_TIMER_IRQ_OFFSET +#define ACPI_SCI_IRQ (APIC_TIMER_IRQ_VECTOR + 0x01) #define MSR_X2APIC_REGS 0x800U