From: Tomas Hruby Date: Wed, 15 Sep 2010 14:10:00 +0000 (+0000) Subject: SMP - Kernel is loaded above 1M by default X-Git-Tag: v3.2.0~865 X-Git-Url: http://zhaoyanbai.com/repos/icons/debian/static/datamaps.china.min.js?a=commitdiff_plain;h=a42ab504a02c97153c442f12b8be2a1f8f459a75;p=minix.git SMP - Kernel is loaded above 1M by default - the 16-bit trampoline must be within the first megabyte of physical memory thus the smp trampoline is copied explicitly below 1M --- diff --git a/kernel/arch/i386/arch_smp.c b/kernel/arch/i386/arch_smp.c index 13daca166..5ef8d5d16 100644 --- a/kernel/arch/i386/arch_smp.c +++ b/kernel/arch/i386/arch_smp.c @@ -31,6 +31,7 @@ _PROTOTYPE(void trampoline, (void)); */ extern volatile u32_t __ap_id; extern volatile struct segdesc_s __ap_gdt, __ap_idt; +extern void * __trampoline_end; extern u32_t busclock[CONFIG_MAX_CPUS]; extern int panicking; @@ -47,6 +48,49 @@ SPINLOCK_DEFINE(dispq_lock) FORWARD _PROTOTYPE(void smp_init_vars, (void)); FORWARD _PROTOTYPE(void smp_reinit_vars, (void)); +/* + * copies the 16-bit AP trampoline code to the first 1M of memory + */ +PRIVATE phys_bytes copy_trampoline(void) +{ + char * s, *end; + phys_bytes tramp_base; + unsigned tramp_size; + + tramp_size = (unsigned) &__trampoline_end - (unsigned)&trampoline; + s = env_get("memory"); + if (!s) + return 0; + + while (*s != 0) { + phys_bytes base = 0xfffffff; + unsigned size; + /* Read fresh base and expect colon as next char. */ + base = strtoul(s, &end, 0x10); /* get number */ + if (end != s && *end == ':') + s = ++end; /* skip ':' */ + else + *s=0; + + /* Read fresh size and expect comma or assume end. */ + size = strtoul(s, &end, 0x10); /* get number */ + if (end != s && *end == ',') + s = ++end; /* skip ',' */ + + tramp_base = (base + 0xfff) & ~(0xfff); + /* the address must be less than 1M */ + if (tramp_base >= (1 << 20)) + continue; + if (size - (tramp_base - base) < tramp_size) + continue; + break; + } + + phys_copy(vir2phys(trampoline), tramp_base, tramp_size); + + return tramp_base; +} + PRIVATE void smp_start_aps(void) { /* @@ -54,7 +98,7 @@ PRIVATE void smp_start_aps(void) */ unsigned cpu; u32_t biosresetvector; - phys_bytes trampoline_base = vir2phys(trampoline); + phys_bytes trampoline_base, __ap_id_phys; /* TODO hack around the alignment problem */ @@ -64,13 +108,20 @@ PRIVATE void smp_start_aps(void) outb(RTC_INDEX, 0xF); outb(RTC_IO, 0xA); - /* setup the warm reset vector */ - phys_copy(vir2phys(&trampoline_base), 0x467, sizeof(u32_t)); - /* prepare gdt and idt for the new cpus */ __ap_gdt = gdt[GDT_INDEX]; __ap_idt = gdt[IDT_INDEX]; + if (!(trampoline_base = copy_trampoline())) { + printf("Copying trampoline code failed, cannot boot SMP\n"); + ncpus = 1; + } + __ap_id_phys = trampoline_base + + (phys_bytes) &__ap_id - (phys_bytes)&trampoline; + + /* setup the warm reset vector */ + phys_copy(vir2phys(&trampoline_base), 0x467, sizeof(u32_t)); + /* okay, we're ready to go. boot all of the ap's now. we loop through * using the processor's apic id values. */ @@ -86,6 +137,8 @@ PRIVATE void smp_start_aps(void) } __ap_id = cpu; + phys_copy(vir2phys(__ap_id), __ap_id_phys, sizeof(__ap_id)); + mfence(); if (apic_send_init_ipi(cpu, trampoline_base) || apic_send_startup_ipi(cpu, trampoline_base)) { printf("WARNING cannot boot cpu %d\n", cpu); @@ -222,7 +275,7 @@ PUBLIC void smp_init (void) /* set smp idt entries. */ apic_idt_init(0); /* Not a reset ! */ idt_reload(); - + BOOT_VERBOSE(printf("SMP initialized\n")); switch_k_stack((char *)get_k_stack_top(bsp_cpu_id) - diff --git a/kernel/arch/i386/trampoline.S b/kernel/arch/i386/trampoline.S index 1ec8919b6..90e9a415c 100644 --- a/kernel/arch/i386/trampoline.S +++ b/kernel/arch/i386/trampoline.S @@ -29,3 +29,4 @@ LABEL(__ap_gdt) .space 8 LABEL(__ap_idt) .space 8 +LABEL(__trampoline_end) diff --git a/kernel/start.c b/kernel/start.c index 1c178914b..7c6a5cf3c 100644 --- a/kernel/start.c +++ b/kernel/start.c @@ -123,7 +123,7 @@ PUBLIC void cstart( * get_value * *===========================================================================*/ -PRIVATE char *get_value( +PUBLIC char *get_value( const char *params, /* boot monitor parameters */ const char *name /* key to look up */ )