[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:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 += \
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user