xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

main.c (3654B)


      1 #include "types.h"
      2 #include "defs.h"
      3 #include "param.h"
      4 #include "memlayout.h"
      5 #include "mmu.h"
      6 #include "proc.h"
      7 #include "x86.h"
      8 
      9 static void startothers(void);
     10 static void mpmain(void)  __attribute__((noreturn));
     11 extern pde_t *kpgdir;
     12 extern char end[]; // first address after kernel loaded from ELF file
     13 
     14 // Bootstrap processor starts running C code here.
     15 // Allocate a real stack and switch to it, first
     16 // doing some setup required for memory allocator to work.
     17 int
     18 main(void)
     19 {
     20   uartearlyinit();
     21   kinit1(end, P2V(4*1024*1024)); // phys page allocator
     22   kvmalloc();      // kernel page table
     23   if (acpiinit()) // try to use acpi for machine info
     24     mpinit();      // otherwise use bios MP tables
     25   lapicinit();
     26   seginit();       // set up segments
     27   cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
     28   picinit();       // interrupt controller
     29   ioapicinit();    // another interrupt controller
     30   consoleinit();   // I/O devices & their interrupts
     31   uartinit();      // serial port
     32   pinit();         // process table
     33   tvinit();        // trap vectors
     34   binit();         // buffer cache
     35   fileinit();      // file table
     36   iinit();         // inode cache
     37   ideinit();       // disk
     38   if(!ismp)
     39     timerinit();   // uniprocessor timer
     40   startothers();   // start other processors
     41   kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
     42   userinit();      // first user process
     43   // Finish setting up this processor in mpmain.
     44   mpmain();
     45 }
     46 
     47 // Other CPUs jump here from entryother.S.
     48 void
     49 mpenter(void)
     50 {
     51   switchkvm(); 
     52   seginit();
     53   lapicinit();
     54   mpmain();
     55 }
     56 
     57 // Common CPU setup code.
     58 static void
     59 mpmain(void)
     60 {
     61   cprintf("cpu%d: starting\n", cpu->id);
     62   idtinit();       // load idt register
     63   xchg(&cpu->started, 1); // tell startothers() we're up
     64   scheduler();     // start running processes
     65 }
     66 
     67 pde_t entrypgdir[];  // For entry.S
     68 void entry32mp(void);
     69 
     70 // Start the non-boot (AP) processors.
     71 static void
     72 startothers(void)
     73 {
     74   extern uchar _binary_out_entryother_start[], _binary_out_entryother_size[];
     75   uchar *code;
     76   struct cpu *c;
     77   char *stack;
     78 
     79   // Write entry code to unused memory at 0x7000.
     80   // The linker has placed the image of entryother.S in
     81   // _binary_entryother_start.
     82   code = p2v(0x7000);
     83   memmove(code, _binary_out_entryother_start, (uintp)_binary_out_entryother_size);
     84 
     85   for(c = cpus; c < cpus+ncpu; c++){
     86     if(c == cpus+cpunum())  // We've started already.
     87       continue;
     88 
     89     // Tell entryother.S what stack to use, where to enter, and what 
     90     // pgdir to use. We cannot use kpgdir yet, because the AP processor
     91     // is running in low  memory, so we use entrypgdir for the APs too.
     92     stack = kalloc();
     93 #if X64
     94     *(uint32*)(code-4) = 0x8000; // just enough stack to get us to entry64mp
     95     *(uint32*)(code-8) = v2p(entry32mp);
     96     *(uint64*)(code-16) = (uint64) (stack + KSTACKSIZE);
     97 #else
     98     *(void**)(code-4) = stack + KSTACKSIZE;
     99     *(void**)(code-8) = mpenter;
    100     *(int**)(code-12) = (void *) v2p(entrypgdir);
    101 #endif
    102 
    103     lapicstartap(c->apicid, v2p(code));
    104 
    105     // wait for cpu to finish mpmain()
    106     while(c->started == 0)
    107       ;
    108   }
    109 }
    110 
    111 #ifndef X64
    112 // Boot page table used in entry.S and entryother.S.
    113 // Page directories (and page tables), must start on a page boundary,
    114 // hence the "__aligned__" attribute.  
    115 // Use PTE_PS in page directory entry to enable 4Mbyte pages.
    116 __attribute__((__aligned__(PGSIZE)))
    117 pde_t entrypgdir[NPDENTRIES] = {
    118   // Map VA's [0, 4MB) to PA's [0, 4MB)
    119   [0] = (0) | PTE_P | PTE_W | PTE_PS,
    120   // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
    121   [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS,
    122 };
    123 #endif
    124 
    125 //PAGEBREAK!
    126 // Blank page.
    127