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
This commit is contained in:
Tomas Hruby 2010-09-15 14:10:00 +00:00
parent 62c666566e
commit a42ab504a0
3 changed files with 60 additions and 6 deletions

View File

@ -31,6 +31,7 @@ _PROTOTYPE(void trampoline, (void));
*/ */
extern volatile u32_t __ap_id; extern volatile u32_t __ap_id;
extern volatile struct segdesc_s __ap_gdt, __ap_idt; extern volatile struct segdesc_s __ap_gdt, __ap_idt;
extern void * __trampoline_end;
extern u32_t busclock[CONFIG_MAX_CPUS]; extern u32_t busclock[CONFIG_MAX_CPUS];
extern int panicking; extern int panicking;
@ -47,6 +48,49 @@ SPINLOCK_DEFINE(dispq_lock)
FORWARD _PROTOTYPE(void smp_init_vars, (void)); FORWARD _PROTOTYPE(void smp_init_vars, (void));
FORWARD _PROTOTYPE(void smp_reinit_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) PRIVATE void smp_start_aps(void)
{ {
/* /*
@ -54,7 +98,7 @@ PRIVATE void smp_start_aps(void)
*/ */
unsigned cpu; unsigned cpu;
u32_t biosresetvector; u32_t biosresetvector;
phys_bytes trampoline_base = vir2phys(trampoline); phys_bytes trampoline_base, __ap_id_phys;
/* TODO hack around the alignment problem */ /* TODO hack around the alignment problem */
@ -64,13 +108,20 @@ PRIVATE void smp_start_aps(void)
outb(RTC_INDEX, 0xF); outb(RTC_INDEX, 0xF);
outb(RTC_IO, 0xA); 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 */ /* prepare gdt and idt for the new cpus */
__ap_gdt = gdt[GDT_INDEX]; __ap_gdt = gdt[GDT_INDEX];
__ap_idt = gdt[IDT_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 /* okay, we're ready to go. boot all of the ap's now. we loop through
* using the processor's apic id values. * using the processor's apic id values.
*/ */
@ -86,6 +137,8 @@ PRIVATE void smp_start_aps(void)
} }
__ap_id = cpu; __ap_id = cpu;
phys_copy(vir2phys(__ap_id), __ap_id_phys, sizeof(__ap_id));
mfence();
if (apic_send_init_ipi(cpu, trampoline_base) || if (apic_send_init_ipi(cpu, trampoline_base) ||
apic_send_startup_ipi(cpu, trampoline_base)) { apic_send_startup_ipi(cpu, trampoline_base)) {
printf("WARNING cannot boot cpu %d\n", cpu); printf("WARNING cannot boot cpu %d\n", cpu);

View File

@ -29,3 +29,4 @@ LABEL(__ap_gdt)
.space 8 .space 8
LABEL(__ap_idt) LABEL(__ap_idt)
.space 8 .space 8
LABEL(__trampoline_end)

View File

@ -123,7 +123,7 @@ PUBLIC void cstart(
* get_value * * get_value *
*===========================================================================*/ *===========================================================================*/
PRIVATE char *get_value( PUBLIC char *get_value(
const char *params, /* boot monitor parameters */ const char *params, /* boot monitor parameters */
const char *name /* key to look up */ const char *name /* key to look up */
) )