From 655f3b4161bbc8874ffae4afa337317c9a1d26f1 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Mon, 12 Apr 2010 12:56:13 +0000 Subject: [PATCH] Seperate the generic (local) APIC stuff into it's own file and use it from the other places where previously the same functionality was duplicated. Also seperated the header which was originally arch_smp.h into apic.h and arch_smp.h again as some of it is MP and not actually APIC. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36182 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/arch/x86/{arch_apic.h => apic.h} | 96 ++----------- headers/private/kernel/arch/x86/arch_smp.h | 102 ++++++++++++++ src/system/kernel/arch/x86/Jamfile | 1 + src/system/kernel/arch/x86/apic.cpp | 133 ++++++++++++++++++ src/system/kernel/arch/x86/arch_int.cpp | 24 ++-- src/system/kernel/arch/x86/arch_smp.cpp | 91 ++---------- .../arch/x86/timers/{apic.h => apic_timer.h} | 2 +- .../kernel/arch/x86/timers/x86_apic.cpp | 102 +++++--------- 8 files changed, 301 insertions(+), 250 deletions(-) rename headers/private/kernel/arch/x86/{arch_apic.h => apic.h} (60%) create mode 100644 headers/private/kernel/arch/x86/arch_smp.h create mode 100644 src/system/kernel/arch/x86/apic.cpp rename src/system/kernel/arch/x86/timers/{apic.h => apic_timer.h} (80%) diff --git a/headers/private/kernel/arch/x86/arch_apic.h b/headers/private/kernel/arch/x86/apic.h similarity index 60% rename from headers/private/kernel/arch/x86/arch_apic.h rename to headers/private/kernel/arch/x86/apic.h index 5613e3ceb9..e1ff1fa685 100644 --- a/headers/private/kernel/arch/x86/arch_apic.h +++ b/headers/private/kernel/arch/x86/apic.h @@ -6,11 +6,11 @@ * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. */ -#ifndef _KERNEL_ARCH_x86_ARCH_APIC_H -#define _KERNEL_ARCH_x86_ARCH_APIC_H +#ifndef _KERNEL_ARCH_x86_APIC_H +#define _KERNEL_ARCH_x86_APIC_H -#define MP_FLOATING_SIGNATURE '_PM_' -#define MP_CONFIG_TABLE_SIGNATURE 'PCMP' +#include +#include #define APIC_ENABLE 0x100 #define APIC_FOCUS (~(1 << 9)) @@ -71,7 +71,7 @@ // timer defines #define APIC_LVT_TIMER_MASK 0xfffcef00 -// LINT0/1 defines +// LINT0/1 defines #define APIC_LVT_LINT_MASK 0xfffe0800 #define APIC_LVT_LINT_INPUT_POLARITY (1 << 13) @@ -113,83 +113,13 @@ #define IPI_STOP 0x44 */ -struct mp_config_table { - uint32 signature; /* "PCMP" */ - uint16 base_table_length; /* length of the base table entries and this structure */ - uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */ - uint8 checksum; /* checksum, all bytes add up to zero */ - char oem[8]; /* oem identification, not null-terminated */ - char product[12]; /* product name, not null-terminated */ - void *oem_table; /* addr of oem-defined table, zero if none */ - uint16 oem_length; /* length of oem table */ - uint16 num_base_entries; /* number of entries in base table */ - uint32 apic; /* address of apic */ - uint16 ext_length; /* length of extended section */ - uint8 ext_checksum; /* checksum of extended table entries */ - uint8 reserved; -}; +bool apic_available(); +uint32 apic_read(uint32 offset); +void apic_write(uint32 offset, uint32 data); +uint32 apic_local_id(); +void apic_end_of_interrupt(); -struct mp_floating_struct { - uint32 signature; /* "_MP_" */ - struct mp_config_table *config_table; /* address of mp configuration table */ - uint8 config_length; /* length of the table in 16-byte units */ - uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */ - uint8 checksum; /* checksum, all bytes add up to zero */ - uint8 mp_feature_1; /* mp system configuration type if no mpc */ - uint8 mp_feature_2; /* imcrp */ - uint8 mp_feature_3, mp_feature_4, mp_feature_5; /* reserved */ -}; +status_t apic_init(kernel_args *args); +status_t apic_per_cpu_init(kernel_args *args, int32 cpu); -/* base config entry types */ -enum { - MP_BASE_PROCESSOR = 0, - MP_BASE_BUS, - MP_BASE_IO_APIC, - MP_BASE_IO_INTR, - MP_BASE_LOCAL_INTR, -}; - -struct mp_base_processor { - uint8 type; - uint8 apic_id; - uint8 apic_version; - uint8 cpu_flags; - uint32 signature; /* stepping, model, family, each four bits */ - uint32 feature_flags; - uint32 res1, res2; -}; - -struct mp_base_ioapic { - uint8 type; - uint8 ioapic_id; - uint8 ioapic_version; - uint8 ioapic_flags; - uint32 *addr; -}; - -struct mp_base_bus { - uint8 type; - uint8 bus_id; - char name[6]; -}; - -struct mp_base_interrupt { - uint8 type; - uint8 interrupt_type; - uint16 polarity : 2; - uint16 trigger_mode : 2; - uint16 _reserved : 12; - uint8 source_bus_id; - uint8 source_bus_irq; - uint8 dest_apic_id; - uint8 dest_apic_int; -}; - -enum { - MP_INTR_TYPE_INT = 0, - MP_INTR_TYPE_NMI, - MP_INTR_TYPE_SMI, - MP_INTR_TYPE_ExtINT, -}; - -#endif /* _KERNEL_ARCH_x86_ARCH_APIC_H */ +#endif /* _KERNEL_ARCH_x86_APIC_H */ diff --git a/headers/private/kernel/arch/x86/arch_smp.h b/headers/private/kernel/arch/x86/arch_smp.h new file mode 100644 index 0000000000..5b2d654efc --- /dev/null +++ b/headers/private/kernel/arch/x86/arch_smp.h @@ -0,0 +1,102 @@ +/* + * Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved. + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ +#ifndef _KERNEL_ARCH_x86_ARCH_SMP_H +#define _KERNEL_ARCH_x86_ARCH_SMP_H + +#define MP_FLOATING_SIGNATURE '_PM_' +#define MP_CONFIG_TABLE_SIGNATURE 'PCMP' + +/* +#define IPI_CACHE_FLUSH 0x40 +#define IPI_INV_TLB 0x41 +#define IPI_INV_PTE 0x42 +#define IPI_INV_RESCHED 0x43 +#define IPI_STOP 0x44 +*/ + +struct mp_config_table { + uint32 signature; /* "PCMP" */ + uint16 base_table_length; /* length of the base table entries and this structure */ + uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */ + uint8 checksum; /* checksum, all bytes add up to zero */ + char oem[8]; /* oem identification, not null-terminated */ + char product[12]; /* product name, not null-terminated */ + void *oem_table; /* addr of oem-defined table, zero if none */ + uint16 oem_length; /* length of oem table */ + uint16 num_base_entries; /* number of entries in base table */ + uint32 apic; /* address of apic */ + uint16 ext_length; /* length of extended section */ + uint8 ext_checksum; /* checksum of extended table entries */ + uint8 reserved; +}; + +struct mp_floating_struct { + uint32 signature; /* "_MP_" */ + struct mp_config_table *config_table; /* address of mp configuration table */ + uint8 config_length; /* length of the table in 16-byte units */ + uint8 spec_revision; /* spec supported, 1 for 1.1 or 4 for 1.4 */ + uint8 checksum; /* checksum, all bytes add up to zero */ + uint8 mp_feature_1; /* mp system configuration type if no mpc */ + uint8 mp_feature_2; /* imcrp */ + uint8 mp_feature_3, mp_feature_4, mp_feature_5; /* reserved */ +}; + +/* base config entry types */ +enum { + MP_BASE_PROCESSOR = 0, + MP_BASE_BUS, + MP_BASE_IO_APIC, + MP_BASE_IO_INTR, + MP_BASE_LOCAL_INTR, +}; + +struct mp_base_processor { + uint8 type; + uint8 apic_id; + uint8 apic_version; + uint8 cpu_flags; + uint32 signature; /* stepping, model, family, each four bits */ + uint32 feature_flags; + uint32 res1, res2; +}; + +struct mp_base_ioapic { + uint8 type; + uint8 ioapic_id; + uint8 ioapic_version; + uint8 ioapic_flags; + uint32 *addr; +}; + +struct mp_base_bus { + uint8 type; + uint8 bus_id; + char name[6]; +}; + +struct mp_base_interrupt { + uint8 type; + uint8 interrupt_type; + uint16 polarity : 2; + uint16 trigger_mode : 2; + uint16 _reserved : 12; + uint8 source_bus_id; + uint8 source_bus_irq; + uint8 dest_apic_id; + uint8 dest_apic_int; +}; + +enum { + MP_INTR_TYPE_INT = 0, + MP_INTR_TYPE_NMI, + MP_INTR_TYPE_SMI, + MP_INTR_TYPE_ExtINT, +}; + +#endif /* _KERNEL_ARCH_x86_ARCH_SMP_H */ diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index e58d5f38c9..0825a68f80 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -29,6 +29,7 @@ KernelMergeObject kernel_arch_x86.o : arch_interrupts.S arch_system_info.cpp arch_user_debugger.cpp + apic.cpp apm.cpp bios.cpp cpuid.S diff --git a/src/system/kernel/arch/x86/apic.cpp b/src/system/kernel/arch/x86/apic.cpp new file mode 100644 index 0000000000..edd85a7549 --- /dev/null +++ b/src/system/kernel/arch/x86/apic.cpp @@ -0,0 +1,133 @@ +/* + * Copyright 2010, Michael Lotz, mmlr@mlotz.ch. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the NewOS License. + */ + +#include + +#include +#include + +#include "timers/apic_timer.h" + + +static void *sLocalAPIC = NULL; + + +bool +apic_available() +{ + return sLocalAPIC != NULL; +} + + +uint32 +apic_read(uint32 offset) +{ + return *(volatile uint32 *)((char *)sLocalAPIC + offset); +} + + +void +apic_write(uint32 offset, uint32 data) +{ + *(volatile uint32 *)((char *)sLocalAPIC + offset) = data; +} + + +uint32 +apic_local_id() +{ + return (apic_read(APIC_ID) & 0xffffffff) >> 24; +} + + +void +apic_end_of_interrupt() +{ + apic_write(APIC_EOI, 0); +} + + +status_t +apic_init(kernel_args *args) +{ + if (args->arch_args.apic == NULL) + return B_NO_INIT; + + sLocalAPIC = args->arch_args.apic; + dprintf("mapping local apic at %p\n", sLocalAPIC); + if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC, + B_EXACT_ADDRESS, B_PAGE_SIZE, + B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + args->arch_args.apic_phys, true) < 0) { + panic("mapping the local apic failed"); + return B_ERROR; + } + + return B_OK; +} + + +status_t +apic_per_cpu_init(kernel_args *args, int32 cpu) +{ + dprintf("setting up apic for CPU %ld: apic id %lu, version %lu\n", cpu, + apic_local_id(), apic_read(APIC_VERSION)); + + /* set spurious interrupt vector to 0xff */ + uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00; + config |= APIC_ENABLE | 0xff; + apic_write(APIC_SPURIOUS_INTR_VECTOR, config); + + // don't touch the LINT0/1 configuration in virtual wire mode + // ToDo: implement support for other modes... +#if 0 + if (cpu == 0) { + /* setup LINT0 as ExtINT */ + config = (apic_read(APIC_LINT0) & 0xffff00ff); + config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM; + apic_write(APIC_LINT0, config); + + /* setup LINT1 as NMI */ + config = (apic_read(APIC_LINT1) & 0xffff00ff); + config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP; + apic_write(APIC_LINT1, config); + } + if (cpu > 0) { + dprintf("LINT0: %p\n", (void *)apic_read(APIC_LINT0)); + dprintf("LINT1: %p\n", (void *)apic_read(APIC_LINT1)); + + /* disable LINT0/1 */ + config = apic_read(APIC_LINT0); + apic_write(APIC_LINT0, config | APIC_LVT_MASKED); + + config = apic_read(APIC_LINT1); + apic_write(APIC_LINT1, config | APIC_LVT_MASKED); + } else { + dprintf("0: LINT0: %p\n", (void *)apic_read(APIC_LINT0)); + dprintf("0: LINT1: %p\n", (void *)apic_read(APIC_LINT1)); + } +#endif + + apic_timer_per_cpu_init(args, cpu); + + /* setup error vector to 0xfe */ + config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe; + apic_write(APIC_LVT_ERROR, config); + + /* accept all interrupts */ + config = apic_read(APIC_TASK_PRIORITY) & 0xffffff00; + apic_write(APIC_TASK_PRIORITY, config); + + config = apic_read(APIC_SPURIOUS_INTR_VECTOR); + apic_end_of_interrupt(); + + return B_OK; +} diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 37bf03170b..3c203976aa 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include @@ -133,7 +133,6 @@ typedef struct ioapic_s { static ioapic *sIOAPIC = NULL; static uint32 sIOAPICMaxRedirectionEntry = 23; -static void *sLocalAPIC = NULL; static uint32 sIRQToIOAPICPin[256]; @@ -470,7 +469,7 @@ ioapic_is_spurious_interrupt(int32 num) static void ioapic_end_of_interrupt(int32 num) { - *(volatile uint32 *)((char *)sLocalAPIC + APIC_EOI) = 0; + apic_end_of_interrupt(); } @@ -551,22 +550,15 @@ ioapic_init(kernel_args *args) &ioapic_end_of_interrupt }; + // always init the local apic as it can be used for timers even if we + // don't end up using the io apic + apic_init(args); + if (args->arch_args.apic == NULL) { dprintf("no local apic available\n"); return; } - // always map the local apic as it can be used for timers even if we - // don't end up using the io apic - sLocalAPIC = args->arch_args.apic; - if (vm_map_physical_memory(B_SYSTEM_TEAM, "local apic", &sLocalAPIC, - B_EXACT_ADDRESS, B_PAGE_SIZE, - B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, - args->arch_args.apic_phys, true) < 0) { - panic("mapping the local apic failed"); - return; - } - if (args->arch_args.ioapic == NULL) { dprintf("no ioapic available, not using ioapics for interrupt routing\n"); return; @@ -666,7 +658,7 @@ ioapic_init(kernel_args *args) status = read_irq_routing_table(pciModule, acpiModule, &table); if (status != B_OK) return; - + // configure apic interrupts assume 1:1 mapping for (int i = 0; i < table.Count(); i++) { irq_routing_entry& entry = table.ElementAt(i); @@ -677,7 +669,7 @@ ioapic_init(kernel_args *args) config |= irqDescriptor.interrupt_mode; ioapic_configure_io_interrupt(irqDescriptor.irq, config); } - + // prefer the ioapic over the normal pic dprintf("using ioapic for interrupt routing\n"); sCurrentPIC = &ioapicController; diff --git a/src/system/kernel/arch/x86/arch_smp.cpp b/src/system/kernel/arch/x86/arch_smp.cpp index 1dfc8d6ab8..b119b16f57 100644 --- a/src/system/kernel/arch/x86/arch_smp.cpp +++ b/src/system/kernel/arch/x86/arch_smp.cpp @@ -17,17 +17,14 @@ #include #include -#include - +#include +#include #include -#include #include #include #include -#include "timers/apic.h" - //#define TRACE_ARCH_SMP #ifdef TRACE_ARCH_SMP @@ -36,7 +33,6 @@ # define TRACE(x) ; #endif -static void *sLocalAPIC = NULL; static uint32 sCPUAPICIds[B_MAX_CPU_COUNT]; static uint32 sCPUOSIds[B_MAX_CPU_COUNT]; static uint32 sAPICVersions[B_MAX_CPU_COUNT]; @@ -44,77 +40,6 @@ static uint32 sAPICVersions[B_MAX_CPU_COUNT]; extern bool gUsingIOAPIC; extern "C" void init_sse(void); -static uint32 -apic_read(uint32 offset) -{ - return *(volatile uint32 *)((char *)sLocalAPIC + offset); -} - - -static void -apic_write(uint32 offset, uint32 data) -{ - *(volatile uint32 *)((char *)sLocalAPIC + offset) = data; -} - - -static status_t -setup_apic(kernel_args *args, int32 cpu) -{ - TRACE(("setting up the APIC for CPU %ld...\n", cpu)); - TRACE((" apic id %ld, version %ld\n", apic_read(APIC_ID), apic_read(APIC_VERSION))); - - /* set spurious interrupt vector to 0xff */ - uint32 config = apic_read(APIC_SPURIOUS_INTR_VECTOR) & 0xffffff00; - config |= APIC_ENABLE | 0xff; - apic_write(APIC_SPURIOUS_INTR_VECTOR, config); - - // don't touch the LINT0/1 configuration in virtual wire mode - // ToDo: implement support for other modes... -#if 0 - if (cpu == 0) { - /* setup LINT0 as ExtINT */ - config = (apic_read(APIC_LINT0) & 0xffff00ff); - config |= APIC_LVT_DM_ExtINT | APIC_LVT_IIPP | APIC_LVT_TM; - apic_write(APIC_LINT0, config); - - /* setup LINT1 as NMI */ - config = (apic_read(APIC_LINT1) & 0xffff00ff); - config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP; - apic_write(APIC_LINT1, config); - } - if (cpu > 0) { - dprintf("LINT0: %p\n", (void *)apic_read(APIC_LINT0)); - dprintf("LINT1: %p\n", (void *)apic_read(APIC_LINT1)); - - /* disable LINT0/1 */ - config = apic_read(APIC_LINT0); - apic_write(APIC_LINT0, config | APIC_LVT_MASKED); - - config = apic_read(APIC_LINT1); - apic_write(APIC_LINT1, config | APIC_LVT_MASKED); - } else { - dprintf("0: LINT0: %p\n", (void *)apic_read(APIC_LINT0)); - dprintf("0: LINT1: %p\n", (void *)apic_read(APIC_LINT1)); - } -#endif - - apic_init_timer(args, cpu); - - /* setup error vector to 0xfe */ - config = (apic_read(APIC_LVT_ERROR) & 0xffffff00) | 0xfe; - apic_write(APIC_LVT_ERROR, config); - - /* accept all interrupts */ - config = apic_read(APIC_TASK_PRIORITY) & 0xffffff00; - apic_write(APIC_TASK_PRIORITY, config); - - config = apic_read(APIC_SPURIOUS_INTR_VECTOR); - apic_write(APIC_EOI, 0); - - return B_OK; -} - static int32 i386_ici_interrupt(void *data) @@ -126,7 +51,7 @@ i386_ici_interrupt(void *data) // if we are not using the IO APIC we need to acknowledge the // interrupt ourselfs if (!gUsingIOAPIC) - apic_write(APIC_EOI, 0); + apic_end_of_interrupt(); return smp_intercpu_int_handler(cpu); } @@ -154,7 +79,7 @@ i386_smp_error_interrupt(void *data) // if we are not using the IO APIC we need to acknowledge the // interrupt ourselfs if (!gUsingIOAPIC) - apic_write(APIC_EOI, 0); + apic_end_of_interrupt(); return B_HANDLED_INTERRUPT; } @@ -165,10 +90,10 @@ arch_smp_init(kernel_args *args) { TRACE(("arch_smp_init: entry\n")); - if (args->arch_args.apic == NULL) + if (!apic_available()) { + // if we don't have an apic we can't do smp return B_OK; - - sLocalAPIC = args->arch_args.apic; + } // setup some globals memcpy(sCPUAPICIds, args->arch_args.cpu_apic_id, sizeof(args->arch_args.cpu_apic_id)); @@ -194,7 +119,7 @@ arch_smp_per_cpu_init(kernel_args *args, int32 cpu) { // set up the local apic on the current cpu TRACE(("arch_smp_init_percpu: setting up the apic on cpu %ld\n", cpu)); - setup_apic(args, cpu); + apic_per_cpu_init(args, cpu); init_sse(); diff --git a/src/system/kernel/arch/x86/timers/apic.h b/src/system/kernel/arch/x86/timers/apic_timer.h similarity index 80% rename from src/system/kernel/arch/x86/timers/apic.h rename to src/system/kernel/arch/x86/timers/apic_timer.h index b44832b557..1cbd5ef3de 100644 --- a/src/system/kernel/arch/x86/timers/apic.h +++ b/src/system/kernel/arch/x86/timers/apic_timer.h @@ -7,6 +7,6 @@ #include -status_t apic_init_timer(struct kernel_args *args, int32 cpu); +status_t apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu); #endif /* _KERNEL_ARCH_x86_TIMERS_APIC_H */ diff --git a/src/system/kernel/arch/x86/timers/x86_apic.cpp b/src/system/kernel/arch/x86/timers/x86_apic.cpp index b735bcb695..4b65ec61b7 100644 --- a/src/system/kernel/arch/x86/timers/x86_apic.cpp +++ b/src/system/kernel/arch/x86/timers/x86_apic.cpp @@ -11,62 +11,47 @@ #include #include -#include +#include #include #include -#include "apic.h" +#include "apic_timer.h" /* Method Prototypes */ -static int apic_get_priority(); -static status_t apic_set_hardware_timer(bigtime_t relativeTimeout); -static status_t apic_clear_hardware_timer(); -static status_t apic_init(struct kernel_args *args); +static int apic_timer_get_priority(); +static status_t apic_timer_set_hardware_timer(bigtime_t relativeTimeout); +static status_t apic_timer_clear_hardware_timer(); +static status_t apic_timer_init(struct kernel_args *args); -static void *sApicPtr = NULL; static uint32 sApicTicsPerSec = 0; extern bool gUsingIOAPIC; struct timer_info gAPICTimer = { "APIC", - &apic_get_priority, - &apic_set_hardware_timer, - &apic_clear_hardware_timer, - &apic_init + &apic_timer_get_priority, + &apic_timer_set_hardware_timer, + &apic_timer_clear_hardware_timer, + &apic_timer_init }; static int -apic_get_priority() +apic_timer_get_priority() { return 3; } -static uint32 -_apic_read(uint32 offset) -{ - return *(volatile uint32 *)((char *)sApicPtr + offset); -} - - -static void -_apic_write(uint32 offset, uint32 data) -{ - *(volatile uint32 *)((char *)sApicPtr + offset) = data; -} - - static int32 apic_timer_interrupt(void *data) { // if we are not using the IO APIC we need to acknowledge the // interrupt ourselfs if (!gUsingIOAPIC) - _apic_write(APIC_EOI, 0); + apic_end_of_interrupt(); return timer_interrupt(); } @@ -75,11 +60,8 @@ apic_timer_interrupt(void *data) #define MIN_TIMEOUT 1 static status_t -apic_set_hardware_timer(bigtime_t relativeTimeout) +apic_timer_set_hardware_timer(bigtime_t relativeTimeout) { - if (sApicPtr == NULL) - return B_ERROR; - if (relativeTimeout < MIN_TIMEOUT) relativeTimeout = MIN_TIMEOUT; @@ -88,18 +70,18 @@ apic_set_hardware_timer(bigtime_t relativeTimeout) cpu_status state = disable_interrupts(); - uint32 config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer - _apic_write(APIC_LVT_TIMER, config); + uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer + apic_write(APIC_LVT_TIMER, config); - _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer + apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer - config = _apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer - _apic_write(APIC_LVT_TIMER, config); + config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer + apic_write(APIC_LVT_TIMER, config); //TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n", // config, relativeTimeout, sApicTicsPerSec, ticks)); - _apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up + apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up restore_interrupts(state); @@ -108,18 +90,15 @@ apic_set_hardware_timer(bigtime_t relativeTimeout) static status_t -apic_clear_hardware_timer() +apic_timer_clear_hardware_timer() { - if (sApicPtr == NULL) - return B_ERROR; - cpu_status state = disable_interrupts(); - uint32 config = _apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; + uint32 config = apic_read(APIC_LVT_TIMER) | APIC_LVT_MASKED; // mask the timer - _apic_write(APIC_LVT_TIMER, config); + apic_write(APIC_LVT_TIMER, config); - _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer + apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer restore_interrupts(state); return B_OK; @@ -127,42 +106,31 @@ apic_clear_hardware_timer() static status_t -apic_init(struct kernel_args *args) +apic_timer_init(struct kernel_args *args) { - /* If we're in this method, arch_smp called the special init function. - Therefore, if we got here with sApicPtr NULL, there is no APIC! */ - if (sApicPtr == NULL) + if (!apic_available()) return B_ERROR; + sApicTicsPerSec = args->arch_args.apic_time_cv_factor; + install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE, + &apic_timer_interrupt, NULL, B_NO_LOCK_VECTOR); + return B_OK; } status_t -apic_init_timer(struct kernel_args *args, int32 cpu) +apic_timer_per_cpu_init(struct kernel_args *args, int32 cpu) { - if (args->arch_args.apic == NULL) - return B_ERROR; - - /* This is in place of apic_preinit; if we're not already initialized, - register the interrupt handler and set the pointers */ - if (sApicPtr == NULL) { - sApicPtr = (void *)args->arch_args.apic; - sApicTicsPerSec = args->arch_args.apic_time_cv_factor; - install_io_interrupt_handler(0xfb - ARCH_INTERRUPT_BASE, - &apic_timer_interrupt, NULL, B_NO_LOCK_VECTOR); - } - /* setup timer */ - uint32 config = _apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK; + uint32 config = apic_read(APIC_LVT_TIMER) & APIC_LVT_TIMER_MASK; config |= 0xfb | APIC_LVT_MASKED; // vector 0xfb, timer masked - _apic_write(APIC_LVT_TIMER, config); + apic_write(APIC_LVT_TIMER, config); - _apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock + apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the clock - config = _apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0; + config = apic_read(APIC_TIMER_DIVIDE_CONFIG) & 0xfffffff0; config |= APIC_TIMER_DIVIDE_CONFIG_1; // clock division by 1 - _apic_write(APIC_TIMER_DIVIDE_CONFIG, config); - + apic_write(APIC_TIMER_DIVIDE_CONFIG, config); return B_OK; }