diff options
-rw-r--r-- | arch/x86/machine/cpu.c | 30 | ||||
-rw-r--r-- | arch/x86/machine/cpu.h | 15 | ||||
-rw-r--r-- | arch/x86/machine/pmap.c | 23 | ||||
-rw-r--r-- | arch/x86/machine/pmap.h | 7 | ||||
-rw-r--r-- | kern/kernel.c | 7 | ||||
-rw-r--r-- | kern/kernel.h | 4 |
6 files changed, 42 insertions, 44 deletions
diff --git a/arch/x86/machine/cpu.c b/arch/x86/machine/cpu.c index 82af7c30..b0567943 100644 --- a/arch/x86/machine/cpu.c +++ b/arch/x86/machine/cpu.c @@ -70,7 +70,12 @@ struct cpu cpu_array[MAX_CPUS]; /* * Number of configured processors. + * + * The boot version is used until all processors are configured, since some + * modules depend on cpu_count() to adjust their behaviour when several + * processors are present. */ +static unsigned int cpu_boot_array_size; unsigned int cpu_array_size; /* @@ -298,6 +303,7 @@ cpu_setup(void) cpu_array[i].state = CPU_STATE_OFF; } + cpu_boot_array_size = 1; cpu_array_size = 1; cpu_init(&cpu_array[0]); } @@ -341,13 +347,13 @@ cpu_mp_register_lapic(unsigned int apic_id, int is_bsp) return; } - if (cpu_array_size == ARRAY_SIZE(cpu_array)) { + if (cpu_boot_array_size == ARRAY_SIZE(cpu_array)) { printk("cpu: ignoring processor beyond id %u\n", MAX_CPUS - 1); return; } - cpu_array[cpu_array_size].apic_id = apic_id; - cpu_array_size++; + cpu_array[cpu_boot_array_size].apic_id = apic_id; + cpu_boot_array_size++; } static void __init @@ -360,7 +366,7 @@ cpu_mp_start_aps(void) size_t map_size; unsigned int i; - if (cpu_array_size == 1) + if (cpu_boot_array_size == 1) return; assert(BOOT_MP_TRAMPOLINE_ADDR < BIOSMEM_BASE); @@ -396,7 +402,7 @@ cpu_mp_start_aps(void) * Preallocate stacks now, as the kernel mappings shouldn't change while * the APs are bootstrapping. */ - for (i = 1; i < cpu_array_size; i++) { + for (i = 1; i < cpu_boot_array_size; i++) { cpu = &cpu_array[i]; cpu->boot_stack = vm_kmem_alloc(BOOT_STACK_SIZE); @@ -405,7 +411,7 @@ cpu_mp_start_aps(void) } /* Perform the "Universal Start-up Algorithm" */ - for (i = 1; i < cpu_array_size; i++) { + for (i = 1; i < cpu_boot_array_size; i++) { cpu = &cpu_array[i]; boot_ap_id = i; @@ -424,6 +430,8 @@ cpu_mp_start_aps(void) while (cpu->state == CPU_STATE_OFF) cpu_pause(); } + + cpu_array_size = cpu_boot_array_size; } static void __init @@ -437,8 +445,6 @@ cpu_mp_setup(void) { acpimp_setup(); cpu_mp_start_aps(); - cpu_intr_enable(); - pmap_mp_setup(); cpu_mp_info(); } @@ -448,5 +454,11 @@ cpu_ap_setup(void) cpu_init(&cpu_array[boot_ap_id]); cpu_check(cpu_current()); lapic_ap_setup(); - cpu_intr_enable(); +} + +void __init +cpu_ap_sync(void) +{ + while (cpu_count() == 1) + cpu_pause(); } diff --git a/arch/x86/machine/cpu.h b/arch/x86/machine/cpu.h index 674892ad..66376e3a 100644 --- a/arch/x86/machine/cpu.h +++ b/arch/x86/machine/cpu.h @@ -436,18 +436,25 @@ void cpu_mp_register_lapic(unsigned int apic_id, int is_bsp); /* * Probe application processors and start them. - * - * This function enables interrupts. */ void cpu_mp_setup(void); /* * CPU initialization on APs. - * - * This function enables interrupts. */ void cpu_ap_setup(void); +/* + * Synchronize processors on kernel entry. + * + * Wait for all processors to reach a proper state when entering the kernel, + * so that memory allocations can proceed and thread scheduling started. + * + * Once this function returns, cpu_count can be used reliably to know if there + * are more than one processors, and how many. + */ +void cpu_ap_sync(void); + #endif /* __ASSEMBLER__ */ #endif /* _X86_CPU_H */ diff --git a/arch/x86/machine/pmap.c b/arch/x86/machine/pmap.c index cbd08b59..65f9708a 100644 --- a/arch/x86/machine/pmap.c +++ b/arch/x86/machine/pmap.c @@ -148,11 +148,6 @@ static unsigned long pmap_zero_va; static struct spinlock pmap_zero_va_lock; /* - * True if running on multiple processors (TLB flushes must be propagated). - */ -static volatile int pmap_mp_mode; - -/* * Shared variables used by the inter-processor update functions. */ static unsigned long pmap_update_start; @@ -364,6 +359,7 @@ pmap_bootstrap(void) cpu_tlb_flush(); + spinlock_init(&pmap_update_lock); pmap_kernel_limit = VM_MIN_KERNEL_ADDRESS; } @@ -372,9 +368,6 @@ pmap_ap_bootstrap(void) { if (cpu_has_global_pages()) cpu_enable_global_pages(); - - while (!pmap_mp_mode) - cpu_pause(); } unsigned long __init @@ -507,10 +500,7 @@ pmap_kupdate(unsigned long start, unsigned long end) { unsigned int nr_cpus; - if (pmap_mp_mode) - nr_cpus = cpu_count(); - else - nr_cpus = 1; + nr_cpus = cpu_count(); if (nr_cpus == 1) { pmap_kupdate_local(start, end); @@ -556,15 +546,6 @@ pmap_kextract(unsigned long va) } void -pmap_mp_setup(void) -{ - assert(cpu_intr_enabled()); - - spinlock_init(&pmap_update_lock); - pmap_mp_mode = 1; -} - -void pmap_update_intr(struct trap_frame *frame) { (void)frame; diff --git a/arch/x86/machine/pmap.h b/arch/x86/machine/pmap.h index 89b36b52..018bf900 100644 --- a/arch/x86/machine/pmap.h +++ b/arch/x86/machine/pmap.h @@ -176,13 +176,6 @@ void pmap_kupdate(unsigned long start, unsigned long end); phys_addr_t pmap_kextract(unsigned long va); /* - * Prepare the pmap module for a multiprocessor environment. - * - * Interrupts must be enabled when calling this function. - */ -void pmap_mp_setup(void); - -/* * Interrupt handler for inter-processor update requests. */ void pmap_update_intr(struct trap_frame *frame); diff --git a/kern/kernel.c b/kern/kernel.c index 760f68e8..07a0f660 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -30,7 +30,7 @@ kernel_main(void) task_setup(); thread_setup(); - /* Interrupts are enabled by this call */ + cpu_intr_enable(); cpu_mp_setup(); thread_run(); @@ -41,7 +41,10 @@ kernel_main(void) void __init kernel_ap_main(void) { - assert(cpu_intr_enabled()); + assert(!cpu_intr_enabled()); + + cpu_intr_enable(); + cpu_ap_sync(); thread_run(); diff --git a/kern/kernel.h b/kern/kernel.h index 22d5714b..f5821ca6 100644 --- a/kern/kernel.h +++ b/kern/kernel.h @@ -26,13 +26,15 @@ /* * Machine-independent entry point. + * + * Interrupts must be disabled when calling this function. */ void kernel_main(void); /* * Entry point for APs. * - * Interrupts must be enabled when calling this function. + * Interrupts must be disabled when calling this function. */ void kernel_ap_main(void); |