From a090257d0953e4a8b6d3e94a3df9ca3ae753b521 Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Sun, 25 Feb 2007 23:32:21 +0000 Subject: [PATCH] Add volatile keyword to apic memory access, cleanup, add timeout to arch_smp_send_ici. But this still doesn't help with bug #1018... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20231 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/arch/x86/smp_priv.h | 2 +- src/system/kernel/arch/x86/arch_smp.c | 48 ++++++++++++++-------- src/system/kernel/arch/x86/arch_timer.c | 8 ++-- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/headers/private/kernel/arch/x86/smp_priv.h b/headers/private/kernel/arch/x86/smp_priv.h index f7df7d4368..f5e6f4564e 100644 --- a/headers/private/kernel/arch/x86/smp_priv.h +++ b/headers/private/kernel/arch/x86/smp_priv.h @@ -10,6 +10,6 @@ int i386_smp_interrupt(int vector); void arch_smp_ack_interrupt(void); status_t arch_smp_set_apic_timer(bigtime_t relativeTimeout); -int arch_smp_clear_apic_timer(void); +status_t arch_smp_clear_apic_timer(void); #endif /* _KERNEL_ARCH_x86_SMP_PRIV_H */ diff --git a/src/system/kernel/arch/x86/arch_smp.c b/src/system/kernel/arch/x86/arch_smp.c index 68b52fab55..6d15001b99 100644 --- a/src/system/kernel/arch/x86/arch_smp.c +++ b/src/system/kernel/arch/x86/arch_smp.c @@ -32,12 +32,19 @@ # define TRACE(x) ; #endif +//#define TRACE_ARCH_SMP_TIMER +#ifdef TRACE_ARCH_SMP_TIMER +# define TRACE_TIMER(x) dprintf x +#else +# define TRACE_TIMER(x) ; +#endif -static uint32 *apic = NULL; + +static void *apic = NULL; static uint32 cpu_apic_id[B_MAX_CPU_COUNT] = {0, 0}; static uint32 cpu_os_id[B_MAX_CPU_COUNT] = {0, 0}; static uint32 cpu_apic_version[B_MAX_CPU_COUNT] = {0, 0}; -static uint32 *ioapic = NULL; +static void *ioapic = NULL; static uint32 apic_timer_tics_per_sec = 0; @@ -54,7 +61,7 @@ static int32 i386_ici_interrupt(void *data) { // genuine inter-cpu interrupt - TRACE(("inter-cpu interrupt on cpu %d\n", smp_get_current_cpu())); + TRACE(("inter-cpu interrupt on cpu %ld\n", smp_get_current_cpu())); arch_smp_ack_interrupt(); return smp_intercpu_int_handler(); @@ -65,7 +72,7 @@ static int32 i386_spurious_interrupt(void *data) { // spurious interrupt - TRACE(("spurious interrupt on cpu %d\n", smp_get_current_cpu())); + TRACE(("spurious interrupt on cpu %ld\n", smp_get_current_cpu())); arch_smp_ack_interrupt(); return B_HANDLED_INTERRUPT; @@ -76,7 +83,7 @@ static int32 i386_smp_error_interrupt(void *data) { // smp error interrupt - TRACE(("smp error interrupt on cpu %d\n", smp_get_current_cpu())); + TRACE(("smp error interrupt on cpu %ld\n", smp_get_current_cpu())); arch_smp_ack_interrupt(); return B_HANDLED_INTERRUPT; @@ -86,15 +93,14 @@ i386_smp_error_interrupt(void *data) static uint32 apic_read(uint32 offset) { - return *(uint32 *)((uint32)apic + offset); + return *(volatile uint32 *)((char *)apic + offset); } static void apic_write(uint32 offset, uint32 data) { - uint32 *addr = (uint32 *)((uint32)apic + offset); - *addr = data; + *(volatile uint32 *)((char *)apic + offset) = data; } @@ -173,17 +179,17 @@ arch_smp_init(kernel_args *args) if (args->num_cpus > 1) { // setup some globals - apic = (uint32 *)args->arch_args.apic; - ioapic = (uint32 *)args->arch_args.ioapic; + apic = (void *)args->arch_args.apic; + ioapic = (void *)args->arch_args.ioapic; memcpy(cpu_apic_id, args->arch_args.cpu_apic_id, sizeof(args->arch_args.cpu_apic_id)); memcpy(cpu_os_id, args->arch_args.cpu_os_id, sizeof(args->arch_args.cpu_os_id)); memcpy(cpu_apic_version, args->arch_args.cpu_apic_version, sizeof(args->arch_args.cpu_apic_version)); apic_timer_tics_per_sec = args->arch_args.apic_time_cv_factor; // setup regions that represent the apic & ioapic - create_area("local apic", (void *)&apic, B_EXACT_ADDRESS, B_PAGE_SIZE, + create_area("local apic", &apic, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - create_area("ioapic", (void *)&ioapic, B_EXACT_ADDRESS, B_PAGE_SIZE, + create_area("ioapic", &ioapic, B_EXACT_ADDRESS, B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); // set up the local apic on the boot cpu @@ -230,7 +236,10 @@ void arch_smp_send_ici(int32 target_cpu) { uint32 config; - int state = disable_interrupts(); + uint32 timeout; + cpu_status state; + + state = disable_interrupts(); config = apic_read(APIC_INTR_COMMAND_2) & APIC_INTR_COMMAND_2_MASK; apic_write(APIC_INTR_COMMAND_2, config | cpu_apic_id[target_cpu] << 24); @@ -241,9 +250,12 @@ arch_smp_send_ici(int32 target_cpu) | APIC_INTR_COMMAND_1_DEST_MODE_PHYSICAL | APIC_INTR_COMMAND_1_DEST_FIELD); + timeout = 100000000; // wait for message to be sent - while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0) + while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0 && --timeout != 0) ; + if (timeout == 0) + panic("arch_smp_send_ici: timeout, target_cpu %ld", target_cpu); restore_interrupts(state); } @@ -283,7 +295,7 @@ arch_smp_set_apic_timer(bigtime_t relativeTimeout) config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer apic_write(APIC_LVT_TIMER, config); - TRACE(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n", + TRACE_TIMER(("arch_smp_set_apic_timer: config 0x%lx, timeout %Ld, tics/sec %lu, tics %lu\n", config, relativeTimeout, apic_timer_tics_per_sec, ticks)); apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up @@ -294,14 +306,14 @@ arch_smp_set_apic_timer(bigtime_t relativeTimeout) } -int +status_t arch_smp_clear_apic_timer(void) { cpu_status state; uint32 config; if (apic == NULL) - return -1; + return B_ERROR; state = disable_interrupts(); @@ -311,6 +323,6 @@ arch_smp_clear_apic_timer(void) apic_write(APIC_INITIAL_TIMER_COUNT, 0); // zero out the timer restore_interrupts(state); - return 0; + return B_OK; } diff --git a/src/system/kernel/arch/x86/arch_timer.c b/src/system/kernel/arch/x86/arch_timer.c index 4ba13f4e9f..c1ef853ea4 100644 --- a/src/system/kernel/arch/x86/arch_timer.c +++ b/src/system/kernel/arch/x86/arch_timer.c @@ -27,11 +27,11 @@ #define PIT_CLOCK_RATE 1193180 -#define PIT_MAX_TIMER_INTERVAL ((long long)0xffff * 1000000 / PIT_CLOCK_RATE) +#define PIT_MAX_TIMER_INTERVAL (0xffff * 1000000ll / PIT_CLOCK_RATE) static void -set_isa_hardware_timer(long long relative_timeout) +set_isa_hardware_timer(bigtime_t relative_timeout) { uint16 next_event_clocks; @@ -76,7 +76,7 @@ void arch_timer_set_hardware_timer(bigtime_t timeout) { // try the apic timer first - if (arch_smp_set_apic_timer(timeout) < 0) + if (arch_smp_set_apic_timer(timeout) != B_OK) set_isa_hardware_timer(timeout); } @@ -84,7 +84,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout) void arch_timer_clear_hardware_timer(void) { - if (arch_smp_clear_apic_timer() < 0) + if (arch_smp_clear_apic_timer() != B_OK) clear_isa_hardware_timer(); }