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:
parent
7ec81f4c11
commit
4a2e872cca
@ -18,8 +18,9 @@ struct kernel_args;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int arch_smp_init(struct kernel_args *ka);
|
||||
void arch_smp_send_ici(int target_cpu);
|
||||
status_t arch_smp_init(struct kernel_args *args);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -5,11 +5,11 @@
|
||||
#ifndef _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);
|
||||
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);
|
||||
|
||||
#endif /* _KERNEL_ARCH_x86_SMP_PRIV_H */
|
||||
|
@ -26,7 +26,8 @@ enum {
|
||||
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);
|
||||
void smp_wake_up_all_non_boot_cpus(void);
|
||||
void smp_wait_for_ap_cpus(struct kernel_args *ka);
|
||||
|
@ -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.
|
||||
* 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
|
||||
@ -331,8 +281,6 @@ smp_cpu_ready(void)
|
||||
asm("cld");
|
||||
asm("fninit");
|
||||
|
||||
smp_setup_apic(ka);
|
||||
|
||||
// Set up the final idt
|
||||
idt_descr.a = IDT_LIMIT - 1;
|
||||
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(("ioapic = %p\n", ka->arch_args.ioapic));
|
||||
|
||||
// set up the apic
|
||||
smp_setup_apic(ka);
|
||||
|
||||
// calculate how fast the apic timer is
|
||||
calculate_apic_timer_conversion_factor(ka);
|
||||
|
||||
|
@ -3,12 +3,9 @@
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <boot/stage2.h>
|
||||
#include <kernel.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <OS.h>
|
||||
#include <boot/kernel_args.h>
|
||||
#include <vm.h>
|
||||
#include <kernel.h>
|
||||
#include <int.h>
|
||||
#include <smp.h>
|
||||
#include <smp_priv.h>
|
||||
@ -25,10 +22,18 @@
|
||||
#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 cpu_apic_id[SMP_MAX_CPUS] = {0, 0};
|
||||
static uint32 cpu_os_id[SMP_MAX_CPUS] = {0, 0};
|
||||
static uint32 cpu_apic_version[SMP_MAX_CPUS] = {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_apic_version[B_MAX_CPU_COUNT] = {0, 0};
|
||||
static uint32 *ioapic = NULL;
|
||||
static uint32 apic_timer_tics_per_sec = 0;
|
||||
|
||||
@ -68,7 +73,7 @@ static int32
|
||||
i386_smp_error_interrupt(void *data)
|
||||
{
|
||||
// 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();
|
||||
|
||||
return B_HANDLED_INTERRUPT;
|
||||
@ -90,10 +95,10 @@ apic_write(uint32 offset, uint32 data)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
status_t
|
||||
arch_smp_init(kernel_args *ka)
|
||||
{
|
||||
dprintf("arch_smp_init: entry\n");
|
||||
TRACE(("arch_smp_init: entry\n"));
|
||||
|
||||
if (ka->num_cpus > 1) {
|
||||
// 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,
|
||||
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(0xfd, &i386_ici_interrupt, NULL);
|
||||
install_interrupt_handler(0xfe, &i386_smp_error_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;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
arch_smp_send_broadcast_ici(void)
|
||||
{
|
||||
uint32 config;
|
||||
int state = disable_interrupts();
|
||||
cpu_status state = disable_interrupts();
|
||||
|
||||
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);
|
||||
@ -133,7 +202,7 @@ arch_smp_send_broadcast_ici(void)
|
||||
|
||||
|
||||
void
|
||||
arch_smp_send_ici(int target_cpu)
|
||||
arch_smp_send_ici(int32 target_cpu)
|
||||
{
|
||||
uint32 config;
|
||||
int state = disable_interrupts();
|
||||
@ -156,21 +225,21 @@ arch_smp_ack_interrupt(void)
|
||||
|
||||
#define MIN_TIMEOUT 1000
|
||||
|
||||
int
|
||||
arch_smp_set_apic_timer(bigtime_t relative_timeout)
|
||||
status_t
|
||||
arch_smp_set_apic_timer(bigtime_t relativeTimeout)
|
||||
{
|
||||
cpu_status state;
|
||||
uint32 config;
|
||||
uint32 ticks;
|
||||
int state;
|
||||
|
||||
if (apic == NULL)
|
||||
return -1;
|
||||
return B_ERROR;
|
||||
|
||||
if (relative_timeout < MIN_TIMEOUT)
|
||||
relative_timeout = MIN_TIMEOUT;
|
||||
if (relativeTimeout < MIN_TIMEOUT)
|
||||
relativeTimeout = MIN_TIMEOUT;
|
||||
|
||||
// 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();
|
||||
|
||||
@ -182,19 +251,22 @@ arch_smp_set_apic_timer(bigtime_t relative_timeout)
|
||||
config = apic_read(APIC_LVTT) & ~APIC_LVTT_M; // unmask the timer
|
||||
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
|
||||
|
||||
restore_interrupts(state);
|
||||
|
||||
return 0;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
arch_smp_clear_apic_timer(void)
|
||||
{
|
||||
cpu_status state;
|
||||
uint32 config;
|
||||
int state;
|
||||
|
||||
if (apic == NULL)
|
||||
return -1;
|
||||
|
@ -39,13 +39,16 @@ set_isa_hardware_timer(long long relative_timeout)
|
||||
out8(0x30, 0x43);
|
||||
out8(next_event_clocks & 0xff, 0x40);
|
||||
out8((next_event_clocks >> 8) & 0xff, 0x40);
|
||||
|
||||
arch_int_enable_io_interrupt(0);
|
||||
}
|
||||
|
||||
|
||||
static 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");
|
||||
|
||||
install_io_interrupt_handler(0, &isa_timer_interrupt, NULL, 0);
|
||||
clear_isa_hardware_timer();
|
||||
|
||||
// apic timer interrupt set up by smp code
|
||||
|
||||
return 0;
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* 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.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
@ -34,8 +37,8 @@
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define TRACE_BOOT 1
|
||||
#if TRACE_BOOT
|
||||
#define TRACE_BOOT
|
||||
#ifdef TRACE_BOOT
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
@ -91,9 +94,9 @@ _start(kernel_args *oldka, int cpu_num)
|
||||
|
||||
sem_init(&ka);
|
||||
|
||||
dprintf("##################################################################\n");
|
||||
dprintf("semaphores now available\n");
|
||||
dprintf("##################################################################\n");
|
||||
TRACE(("##################################################################\n"));
|
||||
TRACE(("semaphores now available\n"));
|
||||
TRACE(("##################################################################\n"));
|
||||
|
||||
// now we can create and use semaphores
|
||||
vm_init_postsem(&ka);
|
||||
@ -118,16 +121,18 @@ _start(kernel_args *oldka, int cpu_num)
|
||||
start_scheduler();
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
dprintf("##################################################################\n");
|
||||
dprintf("interrupts now enabled\n");
|
||||
dprintf("##################################################################\n");
|
||||
TRACE(("##################################################################\n"));
|
||||
TRACE(("interrupts now enabled\n"));
|
||||
TRACE(("##################################################################\n"));
|
||||
|
||||
kernel_startup = false;
|
||||
enable_interrupts();
|
||||
|
||||
TRACE(("main: done... begin idle loop on cpu %d\n", cpu_num));
|
||||
for(;;)
|
||||
for (;;)
|
||||
arch_cpu_idle();
|
||||
|
||||
return 0;
|
||||
|
@ -524,7 +524,7 @@ smp_wait_for_ap_cpus(kernel_args *ka)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
status_t
|
||||
smp_init(kernel_args *ka)
|
||||
{
|
||||
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
|
||||
smp_set_num_cpus(int num_cpus)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user