* Delay initializing SMP stuff like APICs and kstacks of non-boot CPUs until after the boot menu
* When disabling SMP initialization of those parts is avoided so it works more cleanly * Moved smp_find_mp_config() into smp_init() and moved MPS specific parts into smp_do_mp_config() * Removed the global floating struct, if found it is now passed into smp_do_mp_config() like it is done for ACPI * Made the file a bit more C++, applied coding style to some variable names and unified/improved some of the debug output git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23216 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -60,8 +60,6 @@ extern "C" void smp_trampoline(void);
|
|||||||
extern "C" void smp_trampoline_end(void);
|
extern "C" void smp_trampoline_end(void);
|
||||||
|
|
||||||
|
|
||||||
static struct mp_floating_struct *sFloatingStruct = NULL;
|
|
||||||
|
|
||||||
static int smp_get_current_cpu(void);
|
static int smp_get_current_cpu(void);
|
||||||
|
|
||||||
|
|
||||||
@@ -90,19 +88,17 @@ smp_get_current_cpu(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32 *
|
static mp_floating_struct *
|
||||||
smp_mp_probe(uint32 base, uint32 limit)
|
smp_mp_probe(uint32 base, uint32 limit)
|
||||||
{
|
{
|
||||||
uint32 *ptr;
|
|
||||||
|
|
||||||
TRACE(("smp_mp_probe: entry base 0x%lx, limit 0x%lx\n", base, limit));
|
TRACE(("smp_mp_probe: entry base 0x%lx, limit 0x%lx\n", base, limit));
|
||||||
|
for (uint32 *pointer = (uint32 *)base; (uint32)pointer < limit; pointer++) {
|
||||||
for (ptr = (uint32 *) base; (uint32)ptr < limit; ptr++) {
|
if (*pointer == MP_FLOATING_SIGNATURE) {
|
||||||
if (*ptr == MP_FLOATING_SIGNATURE) {
|
TRACE(("smp_mp_probe: found floating pointer structure at %p\n", pointer));
|
||||||
TRACE(("smp_mp_probe: found floating pointer structure at %p\n", ptr));
|
return (mp_floating_struct *)pointer;
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,28 +118,43 @@ smp_acpi_probe(uint32 base, uint32 limit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static status_t
|
||||||
smp_do_mp_config()
|
smp_do_mp_config(mp_floating_struct *floatingStruct)
|
||||||
{
|
{
|
||||||
struct mp_config_table *config;
|
TRACE(("smp: intel mp version %s, %s",
|
||||||
char *ptr;
|
(floatingStruct->spec_revision == 1) ? "1.1" : "1.4",
|
||||||
int i;
|
(floatingStruct->mp_feature_2 & 0x80)
|
||||||
#ifdef TRACE_SMP
|
? "imcr and pic compatibility mode.\n"
|
||||||
const char *cpu_family[] = { "", "", "", "", "Intel 486",
|
: "virtual wire compatibility mode.\n"));
|
||||||
"Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" };
|
|
||||||
|
if (floatingStruct->config_table == NULL) {
|
||||||
|
#if 1
|
||||||
|
// XXX need to implement
|
||||||
|
TRACE(("smp: standard configuration %d unimplemented\n", floatingStruct->mp_feature_1));
|
||||||
|
gKernelArgs.num_cpus = 1;
|
||||||
|
return B_OK;
|
||||||
|
#else
|
||||||
|
/* this system conforms to one of the default configurations */
|
||||||
|
TRACE(("smp: standard configuration %d\n", floatingStruct->mp_feature_1));
|
||||||
|
gKernelArgs.num_cpus = 2;
|
||||||
|
gKernelArgs.cpu_apic_id[0] = 0;
|
||||||
|
gKernelArgs.cpu_apic_id[1] = 1;
|
||||||
|
apic_phys = (unsigned int *) 0xfee00000;
|
||||||
|
ioapic_phys = (unsigned int *) 0xfec00000;
|
||||||
|
dprintf("smp: WARNING: standard configuration code is untested");
|
||||||
|
return B_OK;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we are not running in standard configuration, so we have to look through
|
* we are not running in standard configuration, so we have to look through
|
||||||
* all of the mp configuration table crap to figure out how many processors
|
* all of the mp configuration table crap to figure out how many processors
|
||||||
* we have, where our apics are, etc.
|
* we have, where our apics are, etc.
|
||||||
*/
|
*/
|
||||||
|
mp_config_table *config = floatingStruct->config_table;
|
||||||
gKernelArgs.num_cpus = 0;
|
gKernelArgs.num_cpus = 0;
|
||||||
|
|
||||||
config = sFloatingStruct->config_table;
|
|
||||||
|
|
||||||
/* print out our new found configuration. */
|
/* print out our new found configuration. */
|
||||||
|
|
||||||
TRACE(("smp: oem id: %.8s product id: %.12s\n", config->oem,
|
TRACE(("smp: oem id: %.8s product id: %.12s\n", config->oem,
|
||||||
config->product));
|
config->product));
|
||||||
TRACE(("smp: base table has %d entries, extended section %d bytes\n",
|
TRACE(("smp: base table has %d entries, extended section %d bytes\n",
|
||||||
@@ -151,58 +162,62 @@ smp_do_mp_config()
|
|||||||
|
|
||||||
gKernelArgs.arch_args.apic_phys = (uint32)config->apic;
|
gKernelArgs.arch_args.apic_phys = (uint32)config->apic;
|
||||||
|
|
||||||
ptr = (char *)((uint32)config + sizeof(struct mp_config_table));
|
char *pointer = (char *)((uint32)config + sizeof(struct mp_config_table));
|
||||||
for (i = 0; i < config->num_base_entries; i++) {
|
for (int32 i = 0; i < config->num_base_entries; i++) {
|
||||||
switch (*ptr) {
|
switch (*pointer) {
|
||||||
case MP_BASE_PROCESSOR:
|
case MP_BASE_PROCESSOR:
|
||||||
{
|
{
|
||||||
if (gKernelArgs.num_cpus == MAX_BOOT_CPUS) {
|
if (gKernelArgs.num_cpus == MAX_BOOT_CPUS) {
|
||||||
TRACE(("smp: already reached maximum boot CPUs (%d)\n", MAX_BOOT_CPUS));
|
TRACE(("smp: already reached maximum boot CPUs (%d)\n", MAX_BOOT_CPUS));
|
||||||
ptr += sizeof(struct mp_base_processor);
|
pointer += sizeof(struct mp_base_processor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mp_base_processor *processor = (struct mp_base_processor *)ptr;
|
struct mp_base_processor *processor = (struct mp_base_processor *)pointer;
|
||||||
|
|
||||||
gKernelArgs.arch_args.cpu_apic_id[gKernelArgs.num_cpus] = processor->apic_id;
|
gKernelArgs.arch_args.cpu_apic_id[gKernelArgs.num_cpus] = processor->apic_id;
|
||||||
gKernelArgs.arch_args.cpu_os_id[processor->apic_id] = gKernelArgs.num_cpus;
|
gKernelArgs.arch_args.cpu_os_id[processor->apic_id] = gKernelArgs.num_cpus;
|
||||||
gKernelArgs.arch_args.cpu_apic_version[gKernelArgs.num_cpus] = processor->apic_version;
|
gKernelArgs.arch_args.cpu_apic_version[gKernelArgs.num_cpus] = processor->apic_version;
|
||||||
|
|
||||||
|
#ifdef TRACE_SMP
|
||||||
|
const char *cpuFamily[] = { "", "", "", "", "Intel 486",
|
||||||
|
"Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" };
|
||||||
|
#endif
|
||||||
TRACE(("smp: cpu#%ld: %s, apic id %d, version %d%s\n",
|
TRACE(("smp: cpu#%ld: %s, apic id %d, version %d%s\n",
|
||||||
gKernelArgs.num_cpus, cpu_family[(processor->signature & 0xf00) >> 8],
|
gKernelArgs.num_cpus, cpuFamily[(processor->signature & 0xf00) >> 8],
|
||||||
processor->apic_id, processor->apic_version, (processor->cpu_flags & 0x2) ?
|
processor->apic_id, processor->apic_version, (processor->cpu_flags & 0x2) ?
|
||||||
", BSP" : ""));
|
", BSP" : ""));
|
||||||
|
|
||||||
gKernelArgs.num_cpus++;
|
gKernelArgs.num_cpus++;
|
||||||
ptr += sizeof(struct mp_base_processor);
|
pointer += sizeof(struct mp_base_processor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MP_BASE_BUS:
|
case MP_BASE_BUS:
|
||||||
{
|
{
|
||||||
struct mp_base_bus *bus = (struct mp_base_bus *)ptr;
|
struct mp_base_bus *bus = (struct mp_base_bus *)pointer;
|
||||||
|
|
||||||
TRACE(("smp: bus %d: %c%c%c%c%c%c\n", bus->bus_id,
|
TRACE(("smp: bus %d: %c%c%c%c%c%c\n", bus->bus_id,
|
||||||
bus->name[0], bus->name[1], bus->name[2], bus->name[3],
|
bus->name[0], bus->name[1], bus->name[2], bus->name[3],
|
||||||
bus->name[4], bus->name[5]));
|
bus->name[4], bus->name[5]));
|
||||||
|
|
||||||
ptr += sizeof(struct mp_base_bus);
|
pointer += sizeof(struct mp_base_bus);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MP_BASE_IO_APIC:
|
case MP_BASE_IO_APIC:
|
||||||
{
|
{
|
||||||
struct mp_base_ioapic *io = (struct mp_base_ioapic *) ptr;
|
struct mp_base_ioapic *io = (struct mp_base_ioapic *)pointer;
|
||||||
gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr;
|
gKernelArgs.arch_args.ioapic_phys = (uint32)io->addr;
|
||||||
|
|
||||||
TRACE(("smp: found io apic with apic id %d, version %d\n",
|
TRACE(("smp: found io apic with apic id %d, version %d\n",
|
||||||
io->ioapic_id, io->ioapic_version));
|
io->ioapic_id, io->ioapic_version));
|
||||||
|
|
||||||
ptr += sizeof(struct mp_base_ioapic);
|
pointer += sizeof(struct mp_base_ioapic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MP_BASE_IO_INTR:
|
case MP_BASE_IO_INTR:
|
||||||
case MP_BASE_LOCAL_INTR:
|
case MP_BASE_LOCAL_INTR:
|
||||||
{
|
{
|
||||||
struct mp_base_interrupt *interrupt = (struct mp_base_interrupt *)ptr;
|
struct mp_base_interrupt *interrupt = (struct mp_base_interrupt *)pointer;
|
||||||
|
|
||||||
dprintf("smp: %s int: type %d, source bus %d, irq %3d, dest apic %d, int %3d, polarity %d, trigger mode %d\n",
|
dprintf("smp: %s int: type %d, source bus %d, irq %3d, dest apic %d, int %3d, polarity %d, trigger mode %d\n",
|
||||||
interrupt->type == MP_BASE_IO_INTR ? "I/O" : "local",
|
interrupt->type == MP_BASE_IO_INTR ? "I/O" : "local",
|
||||||
@@ -210,7 +225,7 @@ smp_do_mp_config()
|
|||||||
interrupt->source_bus_irq, interrupt->dest_apic_id,
|
interrupt->source_bus_irq, interrupt->dest_apic_id,
|
||||||
interrupt->dest_apic_int, interrupt->polarity,
|
interrupt->dest_apic_int, interrupt->polarity,
|
||||||
interrupt->trigger_mode);
|
interrupt->trigger_mode);
|
||||||
ptr += sizeof(struct mp_base_interrupt);
|
pointer += sizeof(struct mp_base_interrupt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,9 +236,7 @@ smp_do_mp_config()
|
|||||||
(void *)gKernelArgs.arch_args.ioapic_phys,
|
(void *)gKernelArgs.arch_args.ioapic_phys,
|
||||||
gKernelArgs.num_cpus);
|
gKernelArgs.num_cpus);
|
||||||
|
|
||||||
// this BIOS looks broken, because it didn't report any cpus (VMWare)
|
return gKernelArgs.num_cpus > 0 ? B_OK : B_ERROR;
|
||||||
if (gKernelArgs.num_cpus == 0)
|
|
||||||
gKernelArgs.num_cpus = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -313,69 +326,6 @@ smp_do_acpi_config(acpi_rsdp *rsdp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_find_mp_config(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#if NO_SMP
|
|
||||||
if (1)
|
|
||||||
return gKernelArgs.num_cpus = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// first try to find ACPI tables to get MP configuration as it handles
|
|
||||||
// physical as well as logical MP configurations as in multiple cpus,
|
|
||||||
// multiple cores or hyper threading.
|
|
||||||
for (i = 0; acpi_scan_spots[i].length > 0; i++) {
|
|
||||||
acpi_rsdp *rsdp = smp_acpi_probe(smp_scan_spots[i].start,
|
|
||||||
smp_scan_spots[i].stop);
|
|
||||||
if (rsdp != NULL && smp_do_acpi_config(rsdp) == B_OK)
|
|
||||||
return gKernelArgs.num_cpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; smp_scan_spots[i].length > 0; i++) {
|
|
||||||
sFloatingStruct = (struct mp_floating_struct *)smp_mp_probe(smp_scan_spots[i].start,
|
|
||||||
smp_scan_spots[i].stop);
|
|
||||||
if (sFloatingStruct != NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sFloatingStruct != NULL) {
|
|
||||||
TRACE(("smp_boot: intel mp version %s, %s",
|
|
||||||
(sFloatingStruct->spec_revision == 1) ? "1.1" : "1.4",
|
|
||||||
(sFloatingStruct->mp_feature_2 & 0x80)
|
|
||||||
? "imcr and pic compatibility mode.\n"
|
|
||||||
: "virtual wire compatibility mode.\n"));
|
|
||||||
|
|
||||||
if (sFloatingStruct->config_table == NULL) {
|
|
||||||
// XXX need to implement
|
|
||||||
#if 1
|
|
||||||
TRACE(("smp: standard configuration %d unimplemented\n", sFloatingStruct->mp_feature_1));
|
|
||||||
gKernelArgs.num_cpus = 1;
|
|
||||||
return 1;
|
|
||||||
#else
|
|
||||||
/* this system conforms to one of the default configurations */
|
|
||||||
// mp_num_def_config = sFloatingStruct->mp_feature_1;
|
|
||||||
TRACE(("smp: standard configuration %d\n", sFloatingStruct->mp_feature_1));
|
|
||||||
/* num_cpus = 2;
|
|
||||||
gKernelArgs.cpu_apic_id[0] = 0;
|
|
||||||
gKernelArgs.cpu_apic_id[1] = 1;
|
|
||||||
apic_phys = (unsigned int *) 0xfee00000;
|
|
||||||
ioapic_phys = (unsigned int *) 0xfec00000;
|
|
||||||
kprintf ("smp: WARNING: standard configuration code is untested");
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
smp_do_mp_config();
|
|
||||||
}
|
|
||||||
|
|
||||||
return gKernelArgs.num_cpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gKernelArgs.num_cpus = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** 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
|
||||||
@@ -459,21 +409,48 @@ calculate_apic_timer_conversion_factor(void)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
smp_boot_other_cpus(void)
|
smp_init_other_cpus(void)
|
||||||
{
|
{
|
||||||
uint32 trampolineCode;
|
|
||||||
uint32 trampolineStack;
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
void *handle = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
void *handle = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
||||||
if (handle != NULL) {
|
if (handle != NULL) {
|
||||||
if (get_driver_boolean_parameter(handle, B_SAFEMODE_DISABLE_SMP, false, false)) {
|
if (get_driver_boolean_parameter(handle, B_SAFEMODE_DISABLE_SMP, false, false)) {
|
||||||
// SMP has been disabled!
|
// SMP has been disabled!
|
||||||
|
TRACE(("smp disabled per safemode setting\n"));
|
||||||
gKernelArgs.num_cpus = 1;
|
gKernelArgs.num_cpus = 1;
|
||||||
}
|
}
|
||||||
unload_driver_settings(handle);
|
unload_driver_settings(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gKernelArgs.num_cpus < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TRACE(("smp: found %ld cpus\n", gKernelArgs.num_cpus));
|
||||||
|
TRACE(("smp: apic_phys = %p\n", (void *)gKernelArgs.arch_args.apic_phys));
|
||||||
|
TRACE(("smp: ioapic_phys = %p\n", (void *)gKernelArgs.arch_args.ioapic_phys));
|
||||||
|
|
||||||
|
// map in the apic & ioapic
|
||||||
|
gKernelArgs.arch_args.apic = (uint32 *)mmu_map_physical_memory(
|
||||||
|
gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||||
|
gKernelArgs.arch_args.ioapic = (uint32 *)mmu_map_physical_memory(
|
||||||
|
gKernelArgs.arch_args.ioapic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||||
|
|
||||||
|
TRACE(("smp: apic = %p\n", gKernelArgs.arch_args.apic));
|
||||||
|
TRACE(("smp: ioapic = %p\n", gKernelArgs.arch_args.ioapic));
|
||||||
|
|
||||||
|
// calculate how fast the apic timer is
|
||||||
|
calculate_apic_timer_conversion_factor();
|
||||||
|
|
||||||
|
for (uint32 i = 1; i < gKernelArgs.num_cpus; i++) {
|
||||||
|
// create a final stack the trampoline code will put the ap processor on
|
||||||
|
gKernelArgs.cpu_kstack[i].start = (addr_t)mmu_allocate(NULL, KERNEL_STACK_SIZE);
|
||||||
|
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
smp_boot_other_cpus(void)
|
||||||
|
{
|
||||||
if (gKernelArgs.num_cpus < 2)
|
if (gKernelArgs.num_cpus < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -486,11 +463,11 @@ smp_boot_other_cpus(void)
|
|||||||
// (these have to be < 1M physical, 0xa0000-0xfffff is reserved by the BIOS,
|
// (these have to be < 1M physical, 0xa0000-0xfffff is reserved by the BIOS,
|
||||||
// and when PXE services are used, the 0x8d000-0x9ffff is also reserved)
|
// and when PXE services are used, the 0x8d000-0x9ffff is also reserved)
|
||||||
#ifdef _PXE_ENV
|
#ifdef _PXE_ENV
|
||||||
trampolineCode = 0x8b000;
|
uint32 trampolineCode = 0x8b000;
|
||||||
trampolineStack = 0x8c000;
|
uint32 trampolineStack = 0x8c000;
|
||||||
#else
|
#else
|
||||||
trampolineCode = 0x9f000;
|
uint32 trampolineCode = 0x9f000;
|
||||||
trampolineStack = 0x9e000;
|
uint32 trampolineStack = 0x9e000;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// copy the trampoline code over
|
// copy the trampoline code over
|
||||||
@@ -498,7 +475,7 @@ smp_boot_other_cpus(void)
|
|||||||
(uint32)&smp_trampoline_end - (uint32)&smp_trampoline);
|
(uint32)&smp_trampoline_end - (uint32)&smp_trampoline);
|
||||||
|
|
||||||
// boot the cpus
|
// boot the cpus
|
||||||
for (i = 1; i < gKernelArgs.num_cpus; i++) {
|
for (uint32 i = 1; i < gKernelArgs.num_cpus; i++) {
|
||||||
uint32 *finalStack;
|
uint32 *finalStack;
|
||||||
uint32 *tempStack;
|
uint32 *tempStack;
|
||||||
uint32 config;
|
uint32 config;
|
||||||
@@ -611,31 +588,29 @@ smp_add_safemode_menus(Menu *menu)
|
|||||||
void
|
void
|
||||||
smp_init(void)
|
smp_init(void)
|
||||||
{
|
{
|
||||||
if (smp_find_mp_config() > 1) {
|
#if NO_SMP
|
||||||
uint32 i;
|
gKernelArgs.num_cpus = 1;
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
TRACE(("smp_boot: had found > 1 cpus\n"));
|
// first try to find ACPI tables to get MP configuration as it handles
|
||||||
TRACE(("post config:\n"));
|
// physical as well as logical MP configurations as in multiple cpus,
|
||||||
TRACE(("num_cpus = %ld\n", gKernelArgs.num_cpus));
|
// multiple cores or hyper threading.
|
||||||
TRACE(("apic_phys = %p\n", (void *)gKernelArgs.arch_args.apic_phys));
|
for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
|
||||||
TRACE(("ioapic_phys = %p\n", (void *)gKernelArgs.arch_args.ioapic_phys));
|
acpi_rsdp *rsdp = smp_acpi_probe(smp_scan_spots[i].start,
|
||||||
|
smp_scan_spots[i].stop);
|
||||||
// map in the apic & ioapic
|
if (rsdp != NULL && smp_do_acpi_config(rsdp) == B_OK)
|
||||||
gKernelArgs.arch_args.apic = (uint32 *)mmu_map_physical_memory(
|
return;
|
||||||
gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
|
||||||
gKernelArgs.arch_args.ioapic = (uint32 *)mmu_map_physical_memory(
|
|
||||||
gKernelArgs.arch_args.ioapic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
|
||||||
|
|
||||||
TRACE(("apic = %p\n", gKernelArgs.arch_args.apic));
|
|
||||||
TRACE(("ioapic = %p\n", gKernelArgs.arch_args.ioapic));
|
|
||||||
|
|
||||||
// calculate how fast the apic timer is
|
|
||||||
calculate_apic_timer_conversion_factor();
|
|
||||||
|
|
||||||
for (i = 1; i < gKernelArgs.num_cpus; i++) {
|
|
||||||
// create a final stack the trampoline code will put the ap processor on
|
|
||||||
gKernelArgs.cpu_kstack[i].start = (addr_t)mmu_allocate(NULL, KERNEL_STACK_SIZE);
|
|
||||||
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// then try to find MPS tables and do configuration based on them
|
||||||
|
for (int32 i = 0; smp_scan_spots[i].length > 0; i++) {
|
||||||
|
mp_floating_struct *floatingStruct = smp_mp_probe(
|
||||||
|
smp_scan_spots[i].start, smp_scan_spots[i].stop);
|
||||||
|
if (floatingStruct != NULL && smp_do_mp_config(floatingStruct) == B_OK)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// everything failed or we are not running an SMP system
|
||||||
|
gKernelArgs.num_cpus = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void smp_init(void);
|
extern void smp_init(void);
|
||||||
|
extern void smp_init_other_cpus(void);
|
||||||
extern void smp_boot_other_cpus(void);
|
extern void smp_boot_other_cpus(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ platform_start_kernel(void)
|
|||||||
// or I don't see something important...
|
// or I don't see something important...
|
||||||
addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
|
addr_t stackTop = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size;
|
||||||
|
|
||||||
|
smp_init_other_cpus();
|
||||||
serial_cleanup();
|
serial_cleanup();
|
||||||
mmu_init_for_kernel();
|
mmu_init_for_kernel();
|
||||||
smp_boot_other_cpus();
|
smp_boot_other_cpus();
|
||||||
|
|||||||
Reference in New Issue
Block a user