1 #include <lwk/kernel.h>
3 #include <lwk/cpuinfo.h>
6 #include <lwk/bootmem.h>
9 #include <arch/atomic.h>
10 #include <arch/apicdef.h>
11 #include <arch/apic.h>
12 #include <arch/desc.h>
15 * MP boot trampoline 80x86 program as an array.
17 extern unsigned char trampoline_data[];
18 extern unsigned char trampoline_end[];
21 * These specify the initial stack pointer and instruction pointer for a
24 extern volatile unsigned long init_rsp;
25 extern void (*initial_code)(void);
31 cpu_set(this_cpu, cpu_online_map);
32 schedule(); /* runs idle_task, since that's the only task
33 * on the CPU's run queue at this point */
37 arch_boot_cpu(unsigned int cpu)
39 union task_union *new_task_union;
40 struct task_struct *new_task;
43 * Setup the 'trampoline' cpu boot code. The trampoline contains the
44 * first code executed by the CPU being booted. x86 CPUs boot in
45 * pre-historic 16-bit 'real mode'... the trampoline does the messy
46 * work to get us to 64-bit long mode and then calls the *initial_code
47 * kernel entry function.
49 memcpy(__va(SMP_TRAMPOLINE_BASE), trampoline_data,
50 trampoline_end - trampoline_data
54 * Allocate memory for the new CPU's GDT.
56 cpu_gdt_descr[cpu].address = (unsigned long) kmem_get_pages(0);
59 * Allocate memory for the new CPU's bootstrap task.
61 new_task_union = kmem_get_pages(TASK_ORDER);
62 new_task = &new_task_union->task_info;
65 * Initialize the bare minimum info needed to bootstrap the new CPU.
68 new_task->aspace = &bootstrap_aspace;
69 new_task->cpu_id = cpu;
70 strcpy(new_task->name, "bootstrap");
71 list_head_init(&new_task->sched_link);
74 * Set the initial kernel entry point and stack pointer for the new CPU.
76 initial_code = start_secondary;
77 init_rsp = (unsigned long)new_task_union
78 + sizeof(union task_union) - 1;
83 lapic_send_init_ipi(cpu);
84 lapic_send_startup_ipi(cpu, SMP_TRAMPOLINE_BASE);
85 lapic_send_startup_ipi(cpu, SMP_TRAMPOLINE_BASE);