[arch][x86] start of an ioapic driver

Doesn't do much but provided the detection path for it and ability to
hold initialized state. The higher level platform code is going to need
to use it directly so will mostly just provide an api for access to it.

Moved ACPI sniffing back to just after the VM is initialized instead of
all the way into platform_init(). This should try to ensure that all
drivers that come up afterwards will have ioapics discovered in case
future development tries to enable and use them, kicking the machine out
of virtual-wire-mode.
This commit is contained in:
Travis Geiselbrecht
2025-09-24 00:55:17 -07:00
parent 72112c0676
commit 936ee8ac81
11 changed files with 177 additions and 23 deletions

View File

@@ -16,13 +16,20 @@
#include <platform/interrupts.h>
#include <arch/ops.h>
#include <arch/x86.h>
#include <arch/x86/lapic.h>
#include <arch/x86/apic.h>
#include <kernel/spinlock.h>
#include "platform_p.h"
#include <platform/pc.h>
#if WITH_LIB_ACPI_LITE
#include <lib/acpi_lite.h>
#endif
#define LOCAL_TRACE 0
// TODO: handle ioapics
static spin_lock_t lock;
#define INTC_TYPE_INTERNAL 0
@@ -209,3 +216,24 @@ status_t platform_compute_msi_values(unsigned int vector, unsigned int cpu, bool
return NO_ERROR;
}
// Try to detect the ioapic(s) from ACPI and initialize them
#if WITH_LIB_ACPI_LITE
static void io_apic_callback(const void *_entry, size_t entry_len, void *cookie) {
const struct acpi_madt_io_apic_entry *entry = _entry;
static int index = 0;
ioapic_init(index++, entry->io_apic_address, entry->io_apic_id, entry->global_system_interrupt_base);
}
#endif
void platform_init_interrupts_postvm(void) {
// Bring up the local apic on the first cpu
// Doesn't need ACPI to detect its presence
lapic_init_postvm();
#if WITH_LIB_ACPI_LITE
// Now that we've scanned ACPI, try to initialize the ioapic(s)
acpi_process_madt_entries_etc(ACPI_MADT_TYPE_IO_APIC, &io_apic_callback, NULL);
#endif
}

View File

@@ -10,15 +10,16 @@
#include <kernel/thread.h>
#include <kernel/vm.h>
#include <lib/acpi_lite.h>
#include <lk/err.h>
#include <lk/main.h>
#include <lk/trace.h>
#include <string.h>
#include <arch/x86/lapic.h>
#include <arch/x86/apic.h>
#if WITH_SMP
#include <lib/acpi_lite.h>
#define TRAMPOLINE_ADDRESS 0x4000
#define LOCAL_TRACE 1

View File

@@ -12,6 +12,7 @@
#include <lk/init.h>
#include <lk/trace.h>
#include <arch/x86/mmu.h>
#include <arch/x86/apic.h>
#include <platform.h>
#include <platform/pc.h>
#include <platform/console.h>
@@ -24,7 +25,6 @@
#include <assert.h>
#include <inttypes.h>
#include <kernel/vm.h>
#include <lib/acpi_lite.h>
#include "platform_p.h"
@@ -34,6 +34,11 @@
#if WITH_LIB_MINIP
#include <lib/minip.h>
#endif
#if WITH_LIB_ACPI_LITE
#include <lib/acpi_lite.h>
static bool found_acpi = false;
#endif
#define LOCAL_TRACE 0
@@ -215,21 +220,33 @@ void platform_early_init(void) {
dprintf(INFO, "PC: total memory detected %" PRIu64 " bytes\n", total_mem);
}
// Look for the ACPI tables just after the vm is initialized.
void platform_init_postvm(uint level) {
#if WITH_LIB_ACPI_LITE
// Look for the root ACPI table
status_t err = acpi_lite_init(0);
if (err != NO_ERROR) {
return;
}
found_acpi = true;
if (LOCAL_TRACE) {
acpi_lite_dump_tables(false);
}
acpi_lite_dump_madt_table();
#endif
platform_init_interrupts_postvm();
platform_init_timer();
}
LK_INIT_HOOK(platform_init_postvm, platform_init_postvm, LK_INIT_LEVEL_VM);
void platform_init(void) {
platform_init_debug();
platform_init_keyboard(&console_input_buf);
// Look for the root ACPI table
__UNUSED bool found_acpi = false;
if (acpi_lite_init(0) == NO_ERROR) {
if (LOCAL_TRACE) {
acpi_lite_dump_tables(false);
}
acpi_lite_dump_madt_table();
found_acpi = true;
}
// Look for secondary cpus
#if WITH_SMP
platform_start_secondary_cpus();

View File

@@ -15,6 +15,8 @@ extern cbuf_t console_input_buf;
void platform_init_debug_early(void);
void platform_init_debug(void);
void platform_init_interrupts(void);
void platform_init_interrupts_postvm(void);
void platform_init_timer(void);
// legacy programmable interrupt controller
void pic_init(void);

View File

@@ -6,13 +6,13 @@ MODULE := $(LOCAL_DIR)
# legacy implies older hardware, pre pentium, pre pci
CPU ?= modern
MODULE_DEPS += lib/acpi_lite
MODULE_DEPS += lib/bio
MODULE_DEPS += lib/cbuf
MODULE_DEPS += lib/fixed_point
ifneq ($(CPU),legacy)
MODULE_DEPS += dev/bus/pci/drivers
MODULE_DEPS += lib/acpi_lite
endif
MODULE_SRCS += \

View File

@@ -19,7 +19,7 @@
#include <platform/pc/timer.h>
#include <arch/x86.h>
#include <arch/x86/feature.h>
#include <arch/x86/lapic.h>
#include <arch/x86/apic.h>
#include <arch/x86/pv.h>
#include <inttypes.h>
#include <lib/fixed_point.h>
@@ -87,7 +87,7 @@ uint64_t time_to_tsc_ticks(lk_time_t time) {
return u64_mul_u32_fp32_64(time, timebase_to_tsc);
}
void pc_init_timer(unsigned int level) {
void platform_init_timer(void) {
// Initialize the PIT, it's always present in PC hardware
pit_init();
clock_source = CLOCK_SOURCE_PIT;
@@ -160,8 +160,6 @@ out:
dprintf(INFO, "PC: using %s clock source\n", clock_source_name());
}
LK_INIT_HOOK(pc_timer, pc_init_timer, LK_INIT_LEVEL_VM + 2);
status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
if (use_lapic_timer) {
PANIC_UNIMPLEMENTED;