Applied NewOS change 1914: moved APIC setup into the kernel due to a

problem with the APIC clock speed test.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@6980 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2004-03-14 22:54:00 +00:00
parent 7ec81f4c11
commit 4a2e872cca
8 changed files with 129 additions and 93 deletions
+3 -2
View File
@@ -18,8 +18,9 @@ struct kernel_args;
extern "C" { extern "C" {
#endif #endif
int arch_smp_init(struct kernel_args *ka); status_t arch_smp_init(struct kernel_args *args);
void arch_smp_send_ici(int target_cpu); status_t arch_smp_per_cpu_init(struct kernel_args *args, int32 cpu);
void arch_smp_send_ici(int32 target_cpu);
void arch_smp_send_broadcast_ici(void); void arch_smp_send_broadcast_ici(void);
#ifdef __cplusplus #ifdef __cplusplus
+2 -2
View File
@@ -5,11 +5,11 @@
#ifndef _KERNEL_ARCH_x86_SMP_PRIV_H #ifndef _KERNEL_ARCH_x86_SMP_PRIV_H
#define _KERNEL_ARCH_x86_SMP_PRIV_H #define _KERNEL_ARCH_x86_SMP_PRIV_H
#include <ktypes.h> #include <SupportDefs.h>
int i386_smp_interrupt(int vector); int i386_smp_interrupt(int vector);
void arch_smp_ack_interrupt(void); void arch_smp_ack_interrupt(void);
int arch_smp_set_apic_timer(bigtime_t relative_timeout); status_t arch_smp_set_apic_timer(bigtime_t relativeTimeout);
int arch_smp_clear_apic_timer(void); int arch_smp_clear_apic_timer(void);
#endif /* _KERNEL_ARCH_x86_SMP_PRIV_H */ #endif /* _KERNEL_ARCH_x86_SMP_PRIV_H */
+2 -1
View File
@@ -26,7 +26,8 @@ enum {
SMP_MSG_FLAG_SYNC, SMP_MSG_FLAG_SYNC,
}; };
int smp_init(struct kernel_args *ka); status_t smp_init(struct kernel_args *args);
status_t smp_per_cpu_init(struct kernel_args *args, int32 cpu);
int smp_trap_non_boot_cpus(struct kernel_args *ka, int cpu); int smp_trap_non_boot_cpus(struct kernel_args *ka, int cpu);
void smp_wake_up_all_non_boot_cpus(void); void smp_wake_up_all_non_boot_cpus(void);
void smp_wait_for_ap_cpus(struct kernel_args *ka); void smp_wait_for_ap_cpus(struct kernel_args *ka);
-55
View File
@@ -259,56 +259,6 @@ smp_find_mp_config(kernel_args *ka)
} }
static int
smp_setup_apic(kernel_args *ka)
{
uint32 config;
TRACE(("setting up the apic..."));
/* set spurious interrupt vector to 0xff */
config = apic_read(APIC_SIVR) & 0xfffffc00;
config |= APIC_ENABLE | 0xff;
apic_write(APIC_SIVR, config);
#if 1
/* setup LINT0 as ExtINT */
config = (apic_read(APIC_LINT0) & 0xffff1c00);
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) & 0xffff1c00);
config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;
apic_write(APIC_LINT1, config);
#endif
/* setup timer */
config = apic_read(APIC_LVTT) & ~APIC_LVTT_MASK;
config |= 0xfb | APIC_LVTT_M; // vector 0xfb, timer masked
apic_write(APIC_LVTT, config);
apic_write(APIC_ICRT, 0); // zero out the clock
config = apic_read(APIC_TDCR) & ~0x0000000f;
config |= APIC_TDCR_1; // clock division by 1
apic_write(APIC_TDCR, config);
/* setup error vector to 0xfe */
config = (apic_read(APIC_LVT3) & 0xffffff00) | 0xfe;
apic_write(APIC_LVT3, config);
/* accept all interrupts */
config = apic_read(APIC_TPRI) & 0xffffff00;
apic_write(APIC_TPRI, config);
config = apic_read(APIC_SIVR);
apic_write(APIC_EOI, 0);
TRACE((" done\n"));
return 0;
}
/** Target function of the trampoline code. /** Target function of the trampoline code.
* The trampoline code should have the pgdir and a gdt set up for us, * The trampoline code should have the pgdir and a gdt set up for us,
* along with us being on the final stack for this processor. We need * along with us being on the final stack for this processor. We need
@@ -331,8 +281,6 @@ smp_cpu_ready(void)
asm("cld"); asm("cld");
asm("fninit"); asm("fninit");
smp_setup_apic(ka);
// Set up the final idt // Set up the final idt
idt_descr.a = IDT_LIMIT - 1; idt_descr.a = IDT_LIMIT - 1;
idt_descr.b = (uint32 *)ka->arch_args.vir_idt; idt_descr.b = (uint32 *)ka->arch_args.vir_idt;
@@ -537,9 +485,6 @@ smp_boot(kernel_args *ka, uint32 kernel_entry)
TRACE(("apic = %p\n", ka->arch_args.apic)); TRACE(("apic = %p\n", ka->arch_args.apic));
TRACE(("ioapic = %p\n", ka->arch_args.ioapic)); TRACE(("ioapic = %p\n", ka->arch_args.ioapic));
// set up the apic
smp_setup_apic(ka);
// calculate how fast the apic timer is // calculate how fast the apic timer is
calculate_apic_timer_conversion_factor(ka); calculate_apic_timer_conversion_factor(ka);
+94 -22
View File
@@ -3,12 +3,9 @@
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
*/ */
#include <boot/stage2.h> #include <OS.h>
#include <kernel.h> #include <boot/kernel_args.h>
#include <console.h>
#include <debug.h>
#include <vm.h> #include <vm.h>
#include <kernel.h>
#include <int.h> #include <int.h>
#include <smp.h> #include <smp.h>
#include <smp_priv.h> #include <smp_priv.h>
@@ -25,10 +22,18 @@
#include <stdio.h> #include <stdio.h>
//#define TRACE_ARCH_SMP
#ifdef TRACE_ARCH_SMP
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static uint32 *apic = NULL; static uint32 *apic = NULL;
static uint32 cpu_apic_id[SMP_MAX_CPUS] = {0, 0}; static uint32 cpu_apic_id[B_MAX_CPU_COUNT] = {0, 0};
static uint32 cpu_os_id[SMP_MAX_CPUS] = {0, 0}; static uint32 cpu_os_id[B_MAX_CPU_COUNT] = {0, 0};
static uint32 cpu_apic_version[SMP_MAX_CPUS] = {0, 0}; static uint32 cpu_apic_version[B_MAX_CPU_COUNT] = {0, 0};
static uint32 *ioapic = NULL; static uint32 *ioapic = NULL;
static uint32 apic_timer_tics_per_sec = 0; static uint32 apic_timer_tics_per_sec = 0;
@@ -68,7 +73,7 @@ static int32
i386_smp_error_interrupt(void *data) i386_smp_error_interrupt(void *data)
{ {
// smp error interrupt // smp error interrupt
// dprintf("smp error interrupt on cpu %d\n", arch_smp_get_current_cpu()); TRACE(("smp error interrupt on cpu %d\n", arch_smp_get_current_cpu()));
arch_smp_ack_interrupt(); arch_smp_ack_interrupt();
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
@@ -90,10 +95,10 @@ apic_write(uint32 offset, uint32 data)
} }
int status_t
arch_smp_init(kernel_args *ka) arch_smp_init(kernel_args *ka)
{ {
dprintf("arch_smp_init: entry\n"); TRACE(("arch_smp_init: entry\n"));
if (ka->num_cpus > 1) { if (ka->num_cpus > 1) {
// setup some globals // setup some globals
@@ -110,20 +115,84 @@ arch_smp_init(kernel_args *ka)
vm_create_anonymous_region(vm_get_kernel_aspace_id(), "ioapic", (void *)&ioapic, vm_create_anonymous_region(vm_get_kernel_aspace_id(), "ioapic", (void *)&ioapic,
REGION_ADDR_EXACT_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL); REGION_ADDR_EXACT_ADDRESS, PAGE_SIZE, REGION_WIRING_WIRED_ALREADY, LOCK_RW|LOCK_KERNEL);
// set up the local apic on the boot cpu
arch_smp_per_cpu_init(ka, 0);
install_interrupt_handler(0xfb, &i386_timer_interrupt, NULL); install_interrupt_handler(0xfb, &i386_timer_interrupt, NULL);
install_interrupt_handler(0xfd, &i386_ici_interrupt, NULL); install_interrupt_handler(0xfd, &i386_ici_interrupt, NULL);
install_interrupt_handler(0xfe, &i386_smp_error_interrupt, NULL); install_interrupt_handler(0xfe, &i386_smp_error_interrupt, NULL);
install_interrupt_handler(0xff, &i386_spurious_interrupt, NULL); install_interrupt_handler(0xff, &i386_spurious_interrupt, NULL);
} }
return B_OK;
}
static int
smp_setup_apic(kernel_args *ka)
{
uint32 config;
TRACE(("setting up the apic..."));
/* set spurious interrupt vector to 0xff */
config = apic_read(APIC_SIVR) & 0xfffffc00;
config |= APIC_ENABLE | 0xff;
apic_write(APIC_SIVR, config);
#if 0
/* setup LINT0 as ExtINT */
config = (apic_read(APIC_LINT0) & 0xffff1c00);
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) & 0xffff1c00);
config |= APIC_LVT_DM_NMI | APIC_LVT_IIPP;
apic_write(APIC_LINT1, config);
#endif
/* setup timer */
config = apic_read(APIC_LVTT) & ~APIC_LVTT_MASK;
config |= 0xfb | APIC_LVTT_M; // vector 0xfb, timer masked
apic_write(APIC_LVTT, config);
apic_write(APIC_ICRT, 0); // zero out the clock
config = apic_read(APIC_TDCR) & ~0x0000000f;
config |= APIC_TDCR_1; // clock division by 1
apic_write(APIC_TDCR, config);
/* setup error vector to 0xfe */
config = (apic_read(APIC_LVT3) & 0xffffff00) | 0xfe;
apic_write(APIC_LVT3, config);
/* accept all interrupts */
config = apic_read(APIC_TPRI) & 0xffffff00;
apic_write(APIC_TPRI, config);
config = apic_read(APIC_SIVR);
apic_write(APIC_EOI, 0);
TRACE((" done\n"));
return 0; return 0;
} }
status_t
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));
smp_setup_apic(args);
return B_OK;
}
void void
arch_smp_send_broadcast_ici(void) arch_smp_send_broadcast_ici(void)
{ {
uint32 config; uint32 config;
int state = disable_interrupts(); cpu_status state = disable_interrupts();
config = apic_read(APIC_ICR1) & APIC_ICR1_WRITE_MASK; config = apic_read(APIC_ICR1) & APIC_ICR1_WRITE_MASK;
apic_write(APIC_ICR1, config | 0xfd | APIC_ICR1_DELMODE_FIXED | APIC_ICR1_DESTMODE_PHYS | APIC_ICR1_DEST_ALL_BUT_SELF); apic_write(APIC_ICR1, config | 0xfd | APIC_ICR1_DELMODE_FIXED | APIC_ICR1_DESTMODE_PHYS | APIC_ICR1_DEST_ALL_BUT_SELF);
@@ -133,7 +202,7 @@ arch_smp_send_broadcast_ici(void)
void void
arch_smp_send_ici(int target_cpu) arch_smp_send_ici(int32 target_cpu)
{ {
uint32 config; uint32 config;
int state = disable_interrupts(); int state = disable_interrupts();
@@ -156,21 +225,21 @@ arch_smp_ack_interrupt(void)
#define MIN_TIMEOUT 1000 #define MIN_TIMEOUT 1000
int status_t
arch_smp_set_apic_timer(bigtime_t relative_timeout) arch_smp_set_apic_timer(bigtime_t relativeTimeout)
{ {
cpu_status state;
uint32 config; uint32 config;
uint32 ticks; uint32 ticks;
int state;
if (apic == NULL) if (apic == NULL)
return -1; return B_ERROR;
if (relative_timeout < MIN_TIMEOUT) if (relativeTimeout < MIN_TIMEOUT)
relative_timeout = MIN_TIMEOUT; relativeTimeout = MIN_TIMEOUT;
// calculation should be ok, since it's going to be 64-bit // calculation should be ok, since it's going to be 64-bit
ticks = ((relative_timeout * apic_timer_tics_per_sec) / 1000000); ticks = ((relativeTimeout * apic_timer_tics_per_sec) / 1000000);
state = disable_interrupts(); state = disable_interrupts();
@@ -182,19 +251,22 @@ arch_smp_set_apic_timer(bigtime_t relative_timeout)
config = apic_read(APIC_LVTT) & ~APIC_LVTT_M; // unmask the timer config = apic_read(APIC_LVTT) & ~APIC_LVTT_M; // unmask the timer
apic_write(APIC_LVTT, config); apic_write(APIC_LVTT, config);
TRACE(("arch_smp_set_apic_timer: config 0x%x, timeout %Ld, tics/sec %d, tics %d\n",
config, relative_timeout, apic_timer_tics_per_sec, ticks));
apic_write(APIC_ICRT, ticks); // start it up apic_write(APIC_ICRT, ticks); // start it up
restore_interrupts(state); restore_interrupts(state);
return 0; return B_OK;
} }
int int
arch_smp_clear_apic_timer(void) arch_smp_clear_apic_timer(void)
{ {
cpu_status state;
uint32 config; uint32 config;
int state;
if (apic == NULL) if (apic == NULL)
return -1; return -1;
+6 -1
View File
@@ -39,13 +39,16 @@ set_isa_hardware_timer(long long relative_timeout)
out8(0x30, 0x43); out8(0x30, 0x43);
out8(next_event_clocks & 0xff, 0x40); out8(next_event_clocks & 0xff, 0x40);
out8((next_event_clocks >> 8) & 0xff, 0x40); out8((next_event_clocks >> 8) & 0xff, 0x40);
arch_int_enable_io_interrupt(0);
} }
static void static void
clear_isa_hardware_timer(void) clear_isa_hardware_timer(void)
{ {
// XXX do something here // mask out the timer
arch_int_disable_io_interrupt(0);
} }
@@ -86,6 +89,8 @@ arch_init_timer(kernel_args *ka)
dprintf("arch_init_timer: entry\n"); dprintf("arch_init_timer: entry\n");
install_io_interrupt_handler(0, &isa_timer_interrupt, NULL, 0); install_io_interrupt_handler(0, &isa_timer_interrupt, NULL, 0);
clear_isa_hardware_timer();
// apic timer interrupt set up by smp code // apic timer interrupt set up by smp code
return 0; return 0;
+14 -9
View File
@@ -1,6 +1,9 @@
/* This is main - initializes processors and starts init */ /* This is main - initializes processors and starts init */
/* /*
** Copyright 2002-2004, The OpenBeOS Team. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
**
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. ** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License. ** Distributed under the terms of the NewOS License.
*/ */
@@ -34,8 +37,8 @@
#include <string.h> #include <string.h>
#define TRACE_BOOT 1 #define TRACE_BOOT
#if TRACE_BOOT #ifdef TRACE_BOOT
# define TRACE(x) dprintf x # define TRACE(x) dprintf x
#else #else
# define TRACE(x) ; # define TRACE(x) ;
@@ -91,9 +94,9 @@ _start(kernel_args *oldka, int cpu_num)
sem_init(&ka); sem_init(&ka);
dprintf("##################################################################\n"); TRACE(("##################################################################\n"));
dprintf("semaphores now available\n"); TRACE(("semaphores now available\n"));
dprintf("##################################################################\n"); TRACE(("##################################################################\n"));
// now we can create and use semaphores // now we can create and use semaphores
vm_init_postsem(&ka); vm_init_postsem(&ka);
@@ -118,16 +121,18 @@ _start(kernel_args *oldka, int cpu_num)
start_scheduler(); start_scheduler();
} else { } else {
// this is run per cpu for each AP processor after they've been set loose // this is run per cpu for each AP processor after they've been set loose
smp_per_cpu_init(&ka, cpu_num);
thread_init_percpu(cpu_num); thread_init_percpu(cpu_num);
} }
dprintf("##################################################################\n"); TRACE(("##################################################################\n"));
dprintf("interrupts now enabled\n"); TRACE(("interrupts now enabled\n"));
dprintf("##################################################################\n"); TRACE(("##################################################################\n"));
kernel_startup = false; kernel_startup = false;
enable_interrupts(); enable_interrupts();
TRACE(("main: done... begin idle loop on cpu %d\n", cpu_num)); TRACE(("main: done... begin idle loop on cpu %d\n", cpu_num));
for(;;) for (;;)
arch_cpu_idle(); arch_cpu_idle();
return 0; return 0;
+8 -1
View File
@@ -524,7 +524,7 @@ smp_wait_for_ap_cpus(kernel_args *ka)
} }
int status_t
smp_init(kernel_args *ka) smp_init(kernel_args *ka)
{ {
struct smp_msg *msg; struct smp_msg *msg;
@@ -554,6 +554,13 @@ smp_init(kernel_args *ka)
} }
status_t
smp_per_cpu_init(kernel_args *args, int32 cpu)
{
return arch_smp_per_cpu_init(args, cpu);
}
void void
smp_set_num_cpus(int num_cpus) smp_set_num_cpus(int num_cpus)
{ {