Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions arch/x86/ioapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}
74 changes: 38 additions & 36 deletions common/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand Down Expand Up @@ -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();
Expand Down
10 changes: 9 additions & 1 deletion common/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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();
Expand Down
11 changes: 10 additions & 1 deletion drivers/acpi/acpica/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#ifdef KTF_ACPICA
#include <acpi_ktf.h>
#include <cpu.h>
#include <ioapic.h>
#include <ktf.h>
#include <mm/slab.h>
#include <pagetable.h>
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}
Expand All @@ -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();
Expand Down
5 changes: 2 additions & 3 deletions include/acpi_ktf.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -293,7 +291,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);

Expand Down
1 change: 1 addition & 0 deletions include/arch/x86/apic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions include/arch/x86/ioapic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down