#include "types.h" #include "defs.h" #include "param.h" #include "memlayout.h" #include "mmu.h" #include "proc.h" #include "x86.h" static void bootothers(void); static void mpmain(void); void jmpkstack(void) __attribute__((noreturn)); void mainc(void); static volatile int newpgdir; // 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 main(void) { pginit(pgalloc); mpinit(); // collect info about this machine lapicinit(mpbcpu()); seginit(); // set up segments kinit(); // initialize memory allocator jmpkstack(); // call mainc() on a properly-allocated stack } void jmpkstack(void) { char *kstack, *top; kstack = kalloc(); if(kstack == 0) panic("jmpkstack kalloc"); top = kstack + PGSIZE; asm volatile("movl %0,%%esp; call mainc" : : "r" (top)); panic("jmpkstack"); } // Set up hardware and software. // Runs only on the boostrap processor. void mainc(void) { cprintf("\ncpu%d: starting xv6\n\n", cpu->id); picinit(); // interrupt controller ioapicinit(); // another interrupt controller consoleinit(); // I/O devices & their interrupts uartinit(); // serial port pinit(); // process table tvinit(); // trap vectors binit(); // buffer cache fileinit(); // file table iinit(); // inode cache ideinit(); // disk if(!ismp) timerinit(); // uniprocessor timer userinit(); // first user process bootothers(); // start other processors kvmalloc(); // new kernel page table wo. bottom mapped newpgdir = 1; // Finish setting up this processor in mpmain. mpmain(); } // Common CPU setup code. // Bootstrap CPU comes here from mainc(). // Other CPUs jump here from bootother.S. static void mpboot(void) { vmenable(); // turn on paging seginit(); lapicinit(cpunum()); mpmain(); } // Common CPU setup code. // Bootstrap CPU comes here from mainc(). // Other CPUs jump here from bootother.S. static void mpmain(void) { cprintf("cpu%d: starting\n", cpu->id); idtinit(); // load idt register xchg(&cpu->booted, 1); // tell bootothers() we're up while (!newpgdir) ; // wait until we have new page dir switchkvm(); // switch to new page dir scheduler(); // start running processes } // Start the non-boot processors. static void bootothers(void) { extern uchar _binary_bootother_start[], _binary_bootother_size[]; uchar *code; struct cpu *c; char *stack; // Write bootstrap code to unused memory at 0x7000. // The linker has placed the image of bootother.S in // _binary_bootother_start. code = p2v(0x7000); memmove(code, _binary_bootother_start, (uint)_binary_bootother_size); for(c = cpus; c < cpus+ncpu; c++){ if(c == cpus+cpunum()) // We've started already. continue; // Tell bootother.S what stack to use and the address of mpmain; // it expects to find these two addresses stored just before // its first instruction. stack = kalloc(); *(void**)(code-4) = stack + KSTACKSIZE; *(void**)(code-8) = mpboot; lapicstartap(c->id, v2p(code)); // Wait for cpu to finish mpmain() while(c->booted == 0) ; } } //PAGEBREAK! // Blank page.