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:
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user