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; }