version 1.4.2.1, 2007/11/19 00:47:01 |
version 1.4.2.2, 2007/12/08 18:18:12 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/*- |
/*- |
* Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc. |
* Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* This code is derived from software contributed to The NetBSD Foundation |
* by RedBack Networks Inc. |
* by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran. |
* |
|
* Author: Bill Sommerfeld |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 85 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/device.h> |
#include <sys/device.h> |
#include <sys/malloc.h> |
#include <sys/malloc.h> |
|
#include <sys/cpu.h> |
|
#include <sys/atomic.h> |
|
|
#include <uvm/uvm_extern.h> |
#include <uvm/uvm_extern.h> |
|
|
#include <machine/cpu.h> |
|
#include <machine/cpufunc.h> |
#include <machine/cpufunc.h> |
#include <machine/cpuvar.h> |
#include <machine/cpuvar.h> |
#include <machine/pmap.h> |
#include <machine/pmap.h> |
Line 165 static void cpu_init_tss(struct i386tss |
|
Line 164 static void cpu_init_tss(struct i386tss |
|
#endif |
#endif |
|
|
uint32_t cpus_attached = 0; |
uint32_t cpus_attached = 0; |
|
uint32_t cpus_running = 0; |
|
|
extern char x86_64_doubleflt_stack[]; |
extern char x86_64_doubleflt_stack[]; |
|
|
Line 175 extern char x86_64_doubleflt_stack[]; |
|
Line 175 extern char x86_64_doubleflt_stack[]; |
|
*/ |
*/ |
struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary, }; |
struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary, }; |
|
|
uint32_t cpus_running = 0; |
|
|
|
void cpu_hatch(void *); |
void cpu_hatch(void *); |
static void cpu_boot_secondary(struct cpu_info *ci); |
static void cpu_boot_secondary(struct cpu_info *ci); |
static void cpu_start_secondary(struct cpu_info *ci); |
static void cpu_start_secondary(struct cpu_info *ci); |
Line 189 static void cpu_copy_trampoline(void); |
|
Line 187 static void cpu_copy_trampoline(void); |
|
* Called from lapic_boot_init() (from mpbios_scan()). |
* Called from lapic_boot_init() (from mpbios_scan()). |
*/ |
*/ |
void |
void |
cpu_init_first() |
cpu_init_first(void) |
{ |
{ |
int cpunum = lapic_cpu_number(); |
int cpunum = lapic_cpu_number(); |
|
|
Line 328 cpu_attach(struct device *parent, struct |
|
Line 326 cpu_attach(struct device *parent, struct |
|
switch (caa->cpu_role) { |
switch (caa->cpu_role) { |
case CPU_ROLE_SP: |
case CPU_ROLE_SP: |
aprint_normal(": (uniprocessor)\n"); |
aprint_normal(": (uniprocessor)\n"); |
ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY; |
atomic_or_32(&ci->ci_flags, |
|
CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY); |
cpu_intr_init(ci); |
cpu_intr_init(ci); |
identifycpu(ci); |
identifycpu(ci); |
cpu_init(ci); |
cpu_init(ci); |
Line 339 cpu_attach(struct device *parent, struct |
|
Line 338 cpu_attach(struct device *parent, struct |
|
|
|
case CPU_ROLE_BP: |
case CPU_ROLE_BP: |
aprint_normal(": (boot processor)\n"); |
aprint_normal(": (boot processor)\n"); |
ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY; |
atomic_or_32(&ci->ci_flags, |
|
CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY); |
cpu_intr_init(ci); |
cpu_intr_init(ci); |
identifycpu(ci); |
identifycpu(ci); |
cpu_init(ci); |
cpu_init(ci); |
Line 411 cpu_attach(struct device *parent, struct |
|
Line 411 cpu_attach(struct device *parent, struct |
|
*/ |
*/ |
|
|
void |
void |
cpu_init(ci) |
cpu_init(struct cpu_info *ci) |
struct cpu_info *ci; |
|
{ |
{ |
/* configure the CPU if needed */ |
/* configure the CPU if needed */ |
if (ci->cpu_setup != NULL) |
if (ci->cpu_setup != NULL) |
|
|
#endif /* i386 */ |
#endif /* i386 */ |
#endif /* MTRR */ |
#endif /* MTRR */ |
|
|
#ifdef MULTIPROCESSOR |
atomic_or_32(&ci->ci_flags, CPUF_RUNNING); |
ci->ci_flags |= CPUF_RUNNING; |
atomic_or_32(&cpus_running, ci->ci_cpumask); |
cpus_running |= ci->ci_cpumask; |
|
#else |
#ifndef MULTIPROCESSOR |
/* XXX */ |
/* XXX */ |
x86_patch(); |
x86_patch(); |
#endif |
#endif |
Line 564 cpu_start_secondary(ci) |
|
Line 563 cpu_start_secondary(ci) |
|
#endif |
#endif |
mp_pdirpa = kpm->pm_pdirpa; |
mp_pdirpa = kpm->pm_pdirpa; |
|
|
ci->ci_flags |= CPUF_AP; |
atomic_or_32(&ci->ci_flags, CPUF_AP); |
|
|
aprint_debug("%s: starting\n", ci->ci_dev->dv_xname); |
aprint_debug("%s: starting\n", ci->ci_dev->dv_xname); |
|
|
Line 575 cpu_start_secondary(ci) |
|
Line 574 cpu_start_secondary(ci) |
|
* wait for it to become ready |
* wait for it to become ready |
*/ |
*/ |
for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) { |
for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) { |
delay(10); |
i8254_delay(10); |
} |
} |
if (! (ci->ci_flags & CPUF_PRESENT)) { |
if ((ci->ci_flags & CPUF_PRESENT) == 0) { |
aprint_error("%s: failed to become ready\n", |
aprint_error("%s: failed to become ready\n", |
ci->ci_dev->dv_xname); |
ci->ci_dev->dv_xname); |
#if defined(MPDEBUG) && defined(DDB) |
#if defined(MPDEBUG) && defined(DDB) |
Line 595 cpu_boot_secondary(ci) |
|
Line 594 cpu_boot_secondary(ci) |
|
{ |
{ |
int i; |
int i; |
|
|
ci->ci_flags |= CPUF_GO; /* XXX atomic */ |
atomic_or_32(&ci->ci_flags, CPUF_GO); |
|
|
for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) { |
for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) { |
delay(10); |
i8254_delay(10); |
} |
} |
if (! (ci->ci_flags & CPUF_RUNNING)) { |
if ((ci->ci_flags & CPUF_RUNNING) == 0) { |
aprint_error("%s: failed to start\n", ci->ci_dev->dv_xname); |
aprint_error("%s: failed to start\n", ci->ci_dev->dv_xname); |
#if defined(MPDEBUG) && defined(DDB) |
#if defined(MPDEBUG) && defined(DDB) |
printf("dropping into debugger; continue from here to resume boot\n"); |
printf("dropping into debugger; continue from here to resume boot\n"); |
Line 629 cpu_hatch(void *v) |
|
Line 627 cpu_hatch(void *v) |
|
cpu_feature2 &= ci->ci_feature2_flags; |
cpu_feature2 &= ci->ci_feature2_flags; |
|
|
KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); |
KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0); |
ci->ci_flags |= CPUF_PRESENT; |
atomic_or_32(&ci->ci_flags, CPUF_PRESENT); |
while ((ci->ci_flags & CPUF_GO) == 0) { |
while ((ci->ci_flags & CPUF_GO) == 0) { |
/* Don't use delay, boot CPU may be patching the text. */ |
/* Don't use delay, boot CPU may be patching the text. */ |
for (i = 10000; i != 0; i--) |
for (i = 10000; i != 0; i--) |
Line 829 mp_cpu_start(struct cpu_info *ci) |
|
Line 827 mp_cpu_start(struct cpu_info *ci) |
|
if ((error = x86_ipi_init(ci->ci_apicid)) != 0) |
if ((error = x86_ipi_init(ci->ci_apicid)) != 0) |
return error; |
return error; |
|
|
delay(10000); |
i8254_delay(10000); |
|
|
if (cpu_feature & CPUID_APIC) { |
if (cpu_feature & CPUID_APIC) { |
|
|
Line 837 mp_cpu_start(struct cpu_info *ci) |
|
Line 835 mp_cpu_start(struct cpu_info *ci) |
|
ci->ci_apicid, |
ci->ci_apicid, |
LAPIC_DLMODE_STARTUP)) != 0) |
LAPIC_DLMODE_STARTUP)) != 0) |
return error; |
return error; |
delay(200); |
i8254_delay(200); |
|
|
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE, |
if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE, |
ci->ci_apicid, |
ci->ci_apicid, |
LAPIC_DLMODE_STARTUP)) != 0) |
LAPIC_DLMODE_STARTUP)) != 0) |
return error; |
return error; |
delay(200); |
i8254_delay(200); |
} |
} |
} |
} |
#endif |
#endif |