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
This commit is contained in:
Marcus Overhagen
2007-02-25 23:32:21 +00:00
parent 61381bf71d
commit a090257d09
3 changed files with 35 additions and 23 deletions
+1 -1
View File
@@ -10,6 +10,6 @@
int i386_smp_interrupt(int vector); int i386_smp_interrupt(int vector);
void arch_smp_ack_interrupt(void); void arch_smp_ack_interrupt(void);
status_t arch_smp_set_apic_timer(bigtime_t relativeTimeout); 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 */ #endif /* _KERNEL_ARCH_x86_SMP_PRIV_H */
+30 -18
View File
@@ -32,12 +32,19 @@
# define TRACE(x) ; # define TRACE(x) ;
#endif #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_apic_id[B_MAX_CPU_COUNT] = {0, 0};
static uint32 cpu_os_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 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; static uint32 apic_timer_tics_per_sec = 0;
@@ -54,7 +61,7 @@ static int32
i386_ici_interrupt(void *data) i386_ici_interrupt(void *data)
{ {
// genuine inter-cpu interrupt // 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(); arch_smp_ack_interrupt();
return smp_intercpu_int_handler(); return smp_intercpu_int_handler();
@@ -65,7 +72,7 @@ static int32
i386_spurious_interrupt(void *data) i386_spurious_interrupt(void *data)
{ {
// spurious interrupt // 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(); arch_smp_ack_interrupt();
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
@@ -76,7 +83,7 @@ static int32
i386_smp_error_interrupt(void *data) i386_smp_error_interrupt(void *data)
{ {
// smp error interrupt // 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(); arch_smp_ack_interrupt();
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
@@ -86,15 +93,14 @@ i386_smp_error_interrupt(void *data)
static uint32 static uint32
apic_read(uint32 offset) apic_read(uint32 offset)
{ {
return *(uint32 *)((uint32)apic + offset); return *(volatile uint32 *)((char *)apic + offset);
} }
static void static void
apic_write(uint32 offset, uint32 data) apic_write(uint32 offset, uint32 data)
{ {
uint32 *addr = (uint32 *)((uint32)apic + offset); *(volatile uint32 *)((char *)apic + offset) = data;
*addr = data;
} }
@@ -173,17 +179,17 @@ arch_smp_init(kernel_args *args)
if (args->num_cpus > 1) { if (args->num_cpus > 1) {
// setup some globals // setup some globals
apic = (uint32 *)args->arch_args.apic; apic = (void *)args->arch_args.apic;
ioapic = (uint32 *)args->arch_args.ioapic; 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_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_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)); 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; apic_timer_tics_per_sec = args->arch_args.apic_time_cv_factor;
// setup regions that represent the apic & ioapic // 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); 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); B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
// set up the local apic on the boot cpu // set up the local apic on the boot cpu
@@ -230,7 +236,10 @@ void
arch_smp_send_ici(int32 target_cpu) arch_smp_send_ici(int32 target_cpu)
{ {
uint32 config; 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; 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); 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_MODE_PHYSICAL
| APIC_INTR_COMMAND_1_DEST_FIELD); | APIC_INTR_COMMAND_1_DEST_FIELD);
timeout = 100000000;
// wait for message to be sent // 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); 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 config = apic_read(APIC_LVT_TIMER) & ~APIC_LVT_MASKED; // unmask the timer
apic_write(APIC_LVT_TIMER, config); 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)); config, relativeTimeout, apic_timer_tics_per_sec, ticks));
apic_write(APIC_INITIAL_TIMER_COUNT, ticks); // start it up 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) arch_smp_clear_apic_timer(void)
{ {
cpu_status state; cpu_status state;
uint32 config; uint32 config;
if (apic == NULL) if (apic == NULL)
return -1; return B_ERROR;
state = disable_interrupts(); state = disable_interrupts();
@@ -311,6 +323,6 @@ arch_smp_clear_apic_timer(void)
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); restore_interrupts(state);
return 0; return B_OK;
} }
+4 -4
View File
@@ -27,11 +27,11 @@
#define PIT_CLOCK_RATE 1193180 #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 static void
set_isa_hardware_timer(long long relative_timeout) set_isa_hardware_timer(bigtime_t relative_timeout)
{ {
uint16 next_event_clocks; uint16 next_event_clocks;
@@ -76,7 +76,7 @@ void
arch_timer_set_hardware_timer(bigtime_t timeout) arch_timer_set_hardware_timer(bigtime_t timeout)
{ {
// try the apic timer first // 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); set_isa_hardware_timer(timeout);
} }
@@ -84,7 +84,7 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
void void
arch_timer_clear_hardware_timer(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(); clear_isa_hardware_timer();
} }