#include "types.h" #include "defs.h" #include "param.h" #include "memlayout.h" #include "mmu.h" #include "proc.h" #include "x86.h" extern pde_t *kpgdir; extern char end[]; // first address after kernel loaded from ELF file static void main(void) __attribute__((noreturn)); static void startothers(void); // Bootstrap processor starts running C code here. // Allocate a real stack and switch to it, first // doing some setup required for memory allocator to work. int bpmain(uint64 mbmagic, uint64 mbaddr) { if(mbmagic != 0x2badb002) panic("multiboot header not found"); kinit1(end, P2V(4*1024*1024)); // phys page allocator kvmalloc(); // kernel page table mpinit(); // detect other processors lapicinit(); // interrupt controller seginit(); // segment descriptors picinit(); // disable pic ioapicinit(); // another interrupt controller consoleinit(); // console hardware uartinit(); // serial port pinit(); // process table tvinit(); // trap vectors binit(); // buffer cache fileinit(); // file table ideinit(); // disk startothers(); // start other processors kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers() userinit(); // first user process main(); return 0; } // Common CPU setup code. static void main(void) { cprintf("cpu%d: starting %d\n", cpuid(), cpuid()); idtinit(); // load idt register xchg(&(mycpu()->started), 1); // tell startothers() we're up scheduler(); // start running processes } // Other CPUs jump here from entryother.S. void apmain(void) { switchkvm(); seginit(); lapicinit(); main(); } void apstart(void); // Start the non-boot (AP) processors. static void startothers(void) { extern uchar _binary_entryother_start[], _binary_entryother_size[]; uchar *code; struct cpu *c; char *stack; // Write entry code to unused memory at 0x7000. // The linker has placed the image of entryother.S in // _binary_entryother_start. code = P2V(0x7000); memmove(code, _binary_entryother_start, (uint64)_binary_entryother_size); for(c = cpus; c < cpus+ncpu; c++){ if(c == mycpu()) // We've started already. continue; // Tell entryother.S what stack to use, where to enter, and what // pgdir to use. We cannot use kpgdir yet, because the AP processor // is running in low memory, so we use entrypgdir for the APs too. stack = kalloc(); *(uint32*)(code-4) = V2P(apstart); *(uint64*)(code-12) = (uint64) (stack+KSTACKSIZE); lapicstartap(c->apicid, V2P(code)); // wait for cpu to finish mpmain() while(c->started == 0) ; } }