SMP integration work. Separated initialization from booting the other CPUs;
this way, it won't mess with the MMU anymore after mmu_init_for_kernel() has been called. No other real changes; still disabled, still doesn't work (on my machine at least). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12284 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
|
* calculate_cpu_conversion_factor() was written by Travis Geiselbrecht and
|
||||||
@@ -21,14 +21,13 @@
|
|||||||
|
|
||||||
|
|
||||||
//#define TRACE_CPU
|
//#define TRACE_CPU
|
||||||
#ifdef TRACE_SMP
|
#ifdef TRACE_CPU
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
# define TRACE(x) ;
|
# define TRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern "C" void smp_boot(void);
|
|
||||||
extern "C" uint64 rdtsc();
|
extern "C" uint64 rdtsc();
|
||||||
|
|
||||||
uint32 gTimeConversionFactor;
|
uint32 gTimeConversionFactor;
|
||||||
@@ -232,13 +231,6 @@ spin(bigtime_t microseconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
cpu_boot_other_cpus()
|
|
||||||
{
|
|
||||||
smp_boot();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
cpu_init()
|
cpu_init()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2004, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef CPU_H
|
#ifndef CPU_H
|
||||||
#define CPU_H
|
#define CPU_H
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void cpu_init(void);
|
extern void cpu_init(void);
|
||||||
extern void cpu_boot_other_cpus(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef SMP_H
|
||||||
|
#define SMP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void smp_init(void);
|
||||||
|
extern void smp_boot_other_cpus(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SMP_H */
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004, Axel Dörfler, [email protected].
|
* Copyright 2004-2005, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
@@ -7,8 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// ToDo: this should be integrated better with the rest of the loader!
|
#include "smp.h"
|
||||||
|
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
@@ -22,16 +21,13 @@
|
|||||||
// ToDo: SMP is temporarily disabled!
|
// ToDo: SMP is temporarily disabled!
|
||||||
#define NO_SMP 1
|
#define NO_SMP 1
|
||||||
|
|
||||||
//#define TRACE_SMP
|
#define TRACE_SMP
|
||||||
#ifdef TRACE_SMP
|
#ifdef TRACE_SMP
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
# define TRACE(x) ;
|
# define TRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ADDR_MASK 0xfffff000
|
|
||||||
#define DEFAULT_PAGE_FLAGS (1 | 2) // present/rw
|
|
||||||
|
|
||||||
struct gdt_idt_descr {
|
struct gdt_idt_descr {
|
||||||
uint16 a;
|
uint16 a;
|
||||||
uint32 *b;
|
uint32 *b;
|
||||||
@@ -40,7 +36,6 @@ struct gdt_idt_descr {
|
|||||||
|
|
||||||
extern void execute_n_instructions(int count);
|
extern void execute_n_instructions(int count);
|
||||||
|
|
||||||
extern void smp_boot(void);
|
|
||||||
extern void smp_trampoline(void);
|
extern void smp_trampoline(void);
|
||||||
extern void smp_trampoline_end(void);
|
extern void smp_trampoline_end(void);
|
||||||
|
|
||||||
@@ -52,37 +47,6 @@ static struct mp_flt_struct *mp_flt_ptr = NULL;
|
|||||||
static int smp_get_current_cpu(void);
|
static int smp_get_current_cpu(void);
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
|
||||||
map_page(uint32 paddr, uint32 vaddr)
|
|
||||||
{
|
|
||||||
uint32 *pentry;
|
|
||||||
uint32 *pgdir = (uint32 *)(gKernelArgs.arch_args.page_hole + (4*1024*1024-B_PAGE_SIZE));
|
|
||||||
|
|
||||||
// check to see if a page table exists for this range
|
|
||||||
if (pgdir[vaddr / B_PAGE_SIZE / 1024] == 0) {
|
|
||||||
unsigned int pgtable;
|
|
||||||
// we need to allocate a pgtable
|
|
||||||
pgtable = gKernelArgs.physical_allocated_range[0].start + gKernelArgs.physical_allocated_range[0].size;
|
|
||||||
gKernelArgs.physical_allocated_range[0].size += B_PAGE_SIZE;
|
|
||||||
gKernelArgs.arch_args.pgtables[gKernelArgs.arch_args.num_pgtables++] = pgtable;
|
|
||||||
|
|
||||||
// put it in the pgdir
|
|
||||||
pgdir[vaddr / B_PAGE_SIZE / 1024] = (pgtable & ADDR_MASK) | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
// zero it out in it's new mapping
|
|
||||||
memset((uint32 *)((uint32 *)gKernelArgs.arch_args.page_hole + (vaddr / B_PAGE_SIZE / 1024) * B_PAGE_SIZE), 0, B_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
// now, fill in the pentry
|
|
||||||
pentry = (uint32 *)((uint32 *)gKernelArgs.arch_args.page_hole + vaddr / B_PAGE_SIZE);
|
|
||||||
|
|
||||||
*pentry = (paddr & ADDR_MASK) | DEFAULT_PAGE_FLAGS;
|
|
||||||
|
|
||||||
asm volatile("invlpg (%0)" : : "r" (vaddr));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32
|
static uint32
|
||||||
apic_read(uint32 offset)
|
apic_read(uint32 offset)
|
||||||
{
|
{
|
||||||
@@ -112,6 +76,16 @@ mp_phys_to_virt(void *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
smp_get_current_cpu(void)
|
||||||
|
{
|
||||||
|
if (gKernelArgs.arch_args.apic == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return gKernelArgs.arch_args.cpu_os_id[(apic_read(APIC_ID) & 0xffffffff) >> 24];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32 *
|
static uint32 *
|
||||||
smp_probe(uint32 base, uint32 limit)
|
smp_probe(uint32 base, uint32 limit)
|
||||||
{
|
{
|
||||||
@@ -138,7 +112,7 @@ smp_do_config(void)
|
|||||||
struct mp_ext_pe *pe;
|
struct mp_ext_pe *pe;
|
||||||
struct mp_ext_ioapic *io;
|
struct mp_ext_ioapic *io;
|
||||||
struct mp_ext_bus *bus;
|
struct mp_ext_bus *bus;
|
||||||
#if TRACE_SMP
|
#ifdef TRACE_SMP
|
||||||
const char *cpu_family[] = { "", "", "", "", "Intel 486",
|
const char *cpu_family[] = { "", "", "", "", "Intel 486",
|
||||||
"Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" };
|
"Intel Pentium", "Intel Pentium Pro", "Intel Pentium II" };
|
||||||
#endif
|
#endif
|
||||||
@@ -234,6 +208,11 @@ smp_find_mp_config(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#if NO_SMP
|
||||||
|
if (0)
|
||||||
|
return gKernelArgs.num_cpus = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
// XXX for now, assume the memory is identity mapped by the 1st stage
|
// XXX for now, assume the memory is identity mapped by the 1st stage
|
||||||
for (i = 0; smp_scan_spots[i].len > 0; i++) {
|
for (i = 0; smp_scan_spots[i].len > 0; i++) {
|
||||||
mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start,
|
mp_flt_ptr = (struct mp_flt_struct *)smp_probe(smp_scan_spots[i].start,
|
||||||
@@ -241,11 +220,8 @@ smp_find_mp_config(void)
|
|||||||
if (mp_flt_ptr != NULL)
|
if (mp_flt_ptr != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if NO_SMP
|
|
||||||
if (0) {
|
|
||||||
#else
|
|
||||||
if (mp_flt_ptr != NULL) {
|
if (mp_flt_ptr != NULL) {
|
||||||
#endif
|
|
||||||
mp_mem_phys = smp_scan_spots[i].start;
|
mp_mem_phys = smp_scan_spots[i].start;
|
||||||
mp_mem_virt = smp_scan_spots[i].start;
|
mp_mem_virt = smp_scan_spots[i].start;
|
||||||
|
|
||||||
@@ -274,10 +250,9 @@ smp_find_mp_config(void)
|
|||||||
smp_do_config();
|
smp_do_config();
|
||||||
}
|
}
|
||||||
return gKernelArgs.num_cpus;
|
return gKernelArgs.num_cpus;
|
||||||
} else {
|
|
||||||
gKernelArgs.num_cpus = 1;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return gKernelArgs.num_cpus = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -295,7 +270,7 @@ smp_cpu_ready(void)
|
|||||||
struct gdt_idt_descr idt_descr;
|
struct gdt_idt_descr idt_descr;
|
||||||
struct gdt_idt_descr gdt_descr;
|
struct gdt_idt_descr gdt_descr;
|
||||||
|
|
||||||
TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu));
|
//TRACE(("smp_cpu_ready: entry cpu %ld\n", curr_cpu));
|
||||||
|
|
||||||
// Important. Make sure supervisor threads can fault on read only pages...
|
// Important. Make sure supervisor threads can fault on read only pages...
|
||||||
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
asm("movl %%eax, %%cr0" : : "a" ((1 << 31) | (1 << 16) | (1 << 5) | 1));
|
||||||
@@ -328,13 +303,52 @@ smp_cpu_ready(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static void
|
||||||
smp_boot_all_cpus(void)
|
calculate_apic_timer_conversion_factor(void)
|
||||||
|
{
|
||||||
|
int64 t1, t2;
|
||||||
|
uint32 config;
|
||||||
|
uint32 count;
|
||||||
|
|
||||||
|
// setup the timer
|
||||||
|
config = apic_read(APIC_LVTT);
|
||||||
|
config = (config & ~APIC_LVTT_MASK) + APIC_LVTT_M; // timer masked, vector 0
|
||||||
|
apic_write(APIC_LVTT, config);
|
||||||
|
|
||||||
|
config = (apic_read(APIC_TDCR) & ~0x0000000f) + 0xb; // divide clock by one
|
||||||
|
apic_write(APIC_TDCR, config);
|
||||||
|
|
||||||
|
t1 = system_time();
|
||||||
|
apic_write(APIC_ICRT, 0xffffffff); // start the counter
|
||||||
|
|
||||||
|
execute_n_instructions(128*20000);
|
||||||
|
|
||||||
|
count = apic_read(APIC_CCRT);
|
||||||
|
t2 = system_time();
|
||||||
|
|
||||||
|
count = 0xffffffff - count;
|
||||||
|
|
||||||
|
gKernelArgs.arch_args.apic_time_cv_factor = (uint32)((1000000.0/(t2 - t1)) * count);
|
||||||
|
|
||||||
|
TRACE(("APIC ticks/sec = %ld\n", gKernelArgs.arch_args.apic_time_cv_factor));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
smp_boot_other_cpus(void)
|
||||||
{
|
{
|
||||||
uint32 trampoline_code;
|
uint32 trampoline_code;
|
||||||
uint32 trampoline_stack;
|
uint32 trampoline_stack;
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
|
if (gKernelArgs.num_cpus < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TRACE(("trampolining other cpus\n"));
|
||||||
|
|
||||||
// XXX assume low 1 meg is identity mapped by the 1st stage bootloader
|
// XXX assume low 1 meg is identity mapped by the 1st stage bootloader
|
||||||
// and nothing important is in 0x9e000 & 0x9f000
|
// and nothing important is in 0x9e000 & 0x9f000
|
||||||
|
|
||||||
@@ -342,8 +356,6 @@ smp_boot_all_cpus(void)
|
|||||||
// (these have to be < 1M physical)
|
// (these have to be < 1M physical)
|
||||||
trampoline_code = 0x9f000; // 640kB - 4096 == 0x9f000
|
trampoline_code = 0x9f000; // 640kB - 4096 == 0x9f000
|
||||||
trampoline_stack = 0x9e000; // 640kB - 8192 == 0x9e000
|
trampoline_stack = 0x9e000; // 640kB - 8192 == 0x9e000
|
||||||
map_page(0x9f000, 0x9f000);
|
|
||||||
map_page(0x9e000, 0x9e000);
|
|
||||||
|
|
||||||
// copy the trampoline code over
|
// copy the trampoline code over
|
||||||
memcpy((char *)trampoline_code, &smp_trampoline,
|
memcpy((char *)trampoline_code, &smp_trampoline,
|
||||||
@@ -358,10 +370,6 @@ smp_boot_all_cpus(void)
|
|||||||
uint32 num_startups;
|
uint32 num_startups;
|
||||||
uint32 j;
|
uint32 j;
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// set this stack up
|
// set this stack up
|
||||||
final_stack = (uint32 *)gKernelArgs.cpu_kstack[i].start;
|
final_stack = (uint32 *)gKernelArgs.cpu_kstack[i].start;
|
||||||
memset(final_stack, 0, KERNEL_STACK_SIZE);
|
memset(final_stack, 0, KERNEL_STACK_SIZE);
|
||||||
@@ -437,47 +445,16 @@ smp_boot_all_cpus(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
TRACE(("done trampolining\n"));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
calculate_apic_timer_conversion_factor(void)
|
|
||||||
{
|
|
||||||
int64 t1, t2;
|
|
||||||
uint32 config;
|
|
||||||
uint32 count;
|
|
||||||
|
|
||||||
// setup the timer
|
|
||||||
config = apic_read(APIC_LVTT);
|
|
||||||
config = (config & ~APIC_LVTT_MASK) + APIC_LVTT_M; // timer masked, vector 0
|
|
||||||
apic_write(APIC_LVTT, config);
|
|
||||||
|
|
||||||
config = (apic_read(APIC_TDCR) & ~0x0000000f) + 0xb; // divide clock by one
|
|
||||||
apic_write(APIC_TDCR, config);
|
|
||||||
|
|
||||||
t1 = system_time();
|
|
||||||
apic_write(APIC_ICRT, 0xffffffff); // start the counter
|
|
||||||
|
|
||||||
execute_n_instructions(128*20000);
|
|
||||||
|
|
||||||
count = apic_read(APIC_CCRT);
|
|
||||||
t2 = system_time();
|
|
||||||
|
|
||||||
count = 0xffffffff - count;
|
|
||||||
|
|
||||||
gKernelArgs.arch_args.apic_time_cv_factor = (uint32)((1000000.0/(t2 - t1)) * count);
|
|
||||||
|
|
||||||
TRACE(("APIC ticks/sec = %ld\n", gKernelArgs.arch_args.apic_time_cv_factor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
smp_boot(void)
|
smp_init(void)
|
||||||
{
|
{
|
||||||
// dprintf("smp_boot: entry\n");
|
|
||||||
|
|
||||||
if (smp_find_mp_config() > 1) {
|
if (smp_find_mp_config() > 1) {
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
TRACE(("smp_boot: had found > 1 cpus\n"));
|
TRACE(("smp_boot: had found > 1 cpus\n"));
|
||||||
TRACE(("post config:\n"));
|
TRACE(("post config:\n"));
|
||||||
TRACE(("num_cpus = %ld\n", gKernelArgs.num_cpus));
|
TRACE(("num_cpus = %ld\n", gKernelArgs.num_cpus));
|
||||||
@@ -485,13 +462,10 @@ smp_boot(void)
|
|||||||
TRACE(("ioapic_phys = %p\n", (void *)gKernelArgs.arch_args.ioapic_phys));
|
TRACE(("ioapic_phys = %p\n", (void *)gKernelArgs.arch_args.ioapic_phys));
|
||||||
|
|
||||||
// map in the apic & ioapic
|
// map in the apic & ioapic
|
||||||
map_page(gKernelArgs.arch_args.apic_phys, gKernelArgs.virtual_allocated_range[0].start + gKernelArgs.virtual_allocated_range[0].size);
|
gKernelArgs.arch_args.apic = (uint32 *)mmu_map_physical_memory(
|
||||||
gKernelArgs.arch_args.apic = (uint32 *)(gKernelArgs.virtual_allocated_range[0].start + gKernelArgs.virtual_allocated_range[0].size);
|
gKernelArgs.arch_args.apic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||||
gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE;
|
gKernelArgs.arch_args.ioapic = (uint32 *)mmu_map_physical_memory(
|
||||||
|
gKernelArgs.arch_args.ioapic_phys, B_PAGE_SIZE, kDefaultPageFlags);
|
||||||
map_page(gKernelArgs.arch_args.ioapic_phys, gKernelArgs.virtual_allocated_range[0].start + gKernelArgs.virtual_allocated_range[0].size);
|
|
||||||
gKernelArgs.arch_args.ioapic = (uint32 *)(gKernelArgs.virtual_allocated_range[0].start + gKernelArgs.virtual_allocated_range[0].size);
|
|
||||||
gKernelArgs.virtual_allocated_range[0].size += B_PAGE_SIZE;
|
|
||||||
|
|
||||||
TRACE(("apic = %p\n", gKernelArgs.arch_args.apic));
|
TRACE(("apic = %p\n", gKernelArgs.arch_args.apic));
|
||||||
TRACE(("ioapic = %p\n", gKernelArgs.arch_args.ioapic));
|
TRACE(("ioapic = %p\n", gKernelArgs.arch_args.ioapic));
|
||||||
@@ -499,20 +473,12 @@ smp_boot(void)
|
|||||||
// calculate how fast the apic timer is
|
// calculate how fast the apic timer is
|
||||||
calculate_apic_timer_conversion_factor();
|
calculate_apic_timer_conversion_factor();
|
||||||
|
|
||||||
TRACE(("trampolining other cpus\n"));
|
for (i = 1; i < gKernelArgs.num_cpus; i++) {
|
||||||
smp_boot_all_cpus();
|
// create a final stack the trampoline code will put the ap processor on
|
||||||
TRACE(("done trampolining\n"));
|
gKernelArgs.cpu_kstack[i].start = (addr_t)mmu_allocate(NULL, KERNEL_STACK_SIZE);
|
||||||
|
gKernelArgs.cpu_kstack[i].size = KERNEL_STACK_SIZE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(("smp_boot: exit\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
smp_get_current_cpu(void)
|
|
||||||
{
|
|
||||||
if (gKernelArgs.arch_args.apic == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return gKernelArgs.arch_args.cpu_os_id[(apic_read(APIC_ID) & 0xffffffff) >> 24];
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2003-2004, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2003-2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
** Distributed under the terms of the Haiku License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
|
#include "smp.h"
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#include "bios.h"
|
#include "bios.h"
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ platform_start_kernel(void)
|
|||||||
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;
|
||||||
|
|
||||||
mmu_init_for_kernel();
|
mmu_init_for_kernel();
|
||||||
cpu_boot_other_cpus();
|
smp_boot_other_cpus();
|
||||||
|
|
||||||
dprintf("kernel entry at %lx\n", gKernelArgs.kernel_image.elf_header.e_entry);
|
dprintf("kernel entry at %lx\n", gKernelArgs.kernel_image.elf_header.e_entry);
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ _start(void)
|
|||||||
if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
|
if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT)
|
||||||
serial_enable();
|
serial_enable();
|
||||||
|
|
||||||
|
smp_init();
|
||||||
main(&args);
|
main(&args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user