xref: /xv6-public/main.c (revision 96e4e2f4)
155e95b16Srtm #include "types.h"
2558ab49fSrsc #include "defs.h"
355e95b16Srtm #include "param.h"
49aa0337dSFrans Kaashoek #include "memlayout.h"
555e95b16Srtm #include "mmu.h"
655e95b16Srtm #include "proc.h"
755e95b16Srtm #include "x86.h"
855e95b16Srtm 
9a4b213cfSFrans Kaashoek static void startothers(void);
10832af025SFrans Kaashoek static void mpmain(void)  __attribute__((noreturn));
11bd71a450SFrans Kaashoek extern pde_t *kpgdir;
12c092540eSRobert Morris extern char end[]; // first address after kernel loaded from ELF file
139aa0337dSFrans Kaashoek 
148e1d1ec9Skaashoek // Bootstrap processor starts running C code here.
15faad047aSRobert Morris // Allocate a real stack and switch to it, first
16faad047aSRobert Morris // doing some setup required for memory allocator to work.
1719b42cc0Srsc int
main(void)1819b42cc0Srsc main(void)
1955e95b16Srtm {
20c092540eSRobert Morris   kinit1(end, P2V(4*1024*1024)); // phys page allocator
2166ba8079SFrans Kaashoek   kvmalloc();      // kernel page table
22c779cc2bSRobert Morris   mpinit();        // detect other processors
23c779cc2bSRobert Morris   lapicinit();     // interrupt controller
24c779cc2bSRobert Morris   seginit();       // segment descriptors
254f14d8d1SFrans Kaashoek   picinit();       // disable pic
26faad047aSRobert Morris   ioapicinit();    // another interrupt controller
27c779cc2bSRobert Morris   consoleinit();   // console hardware
28faad047aSRobert Morris   uartinit();      // serial port
2919333efbSrsc   pinit();         // process table
30b61c2547Srtm   tvinit();        // trap vectors
3119333efbSrsc   binit();         // buffer cache
32eaea18cbSrsc   fileinit();      // file table
3321575761Srsc   ideinit();       // disk
34c092540eSRobert Morris   startothers();   // start other processors
35c092540eSRobert Morris   kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
36c092540eSRobert Morris   userinit();      // first user process
37c779cc2bSRobert Morris   mpmain();        // finish this processor's setup
3855e95b16Srtm }
39df5cc916Srtm 
40c60a3551SFrans Kaashoek // Other CPUs jump here from entryother.S.
41c1b100e9Srsc static void
mpenter(void)42a4b213cfSFrans Kaashoek mpenter(void)
439aa0337dSFrans Kaashoek {
44bd71a450SFrans Kaashoek   switchkvm();
459aa0337dSFrans Kaashoek   seginit();
4670c55557SFrans Kaashoek   lapicinit();
479aa0337dSFrans Kaashoek   mpmain();
489aa0337dSFrans Kaashoek }
499aa0337dSFrans Kaashoek 
509aa0337dSFrans Kaashoek // Common CPU setup code.
519aa0337dSFrans Kaashoek static void
mpmain(void)52b74f4b57Srsc mpmain(void)
53b74f4b57Srsc {
54ed396c06SFrans Kaashoek   cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
551afc9d3fSRobert Morris   idtinit();       // load idt register
56abf847a0SFrans Kaashoek   xchg(&(mycpu()->started), 1); // tell startothers() we're up
571afc9d3fSRobert Morris   scheduler();     // start running processes
58b74f4b57Srsc }
59b74f4b57Srsc 
605e083578SRobert Morris pde_t entrypgdir[];  // For entry.S
61bd71a450SFrans Kaashoek 
62a4b213cfSFrans Kaashoek // Start the non-boot (AP) processors.
639e82bfb0Srsc static void
startothers(void)64a4b213cfSFrans Kaashoek startothers(void)
6599b11b6cSrsc {
66c60a3551SFrans Kaashoek   extern uchar _binary_entryother_start[], _binary_entryother_size[];
6799b11b6cSrsc   uchar *code;
6899b11b6cSrsc   struct cpu *c;
69ab08960fSrsc   char *stack;
7099b11b6cSrsc 
71a4b213cfSFrans Kaashoek   // Write entry code to unused memory at 0x7000.
72c60a3551SFrans Kaashoek   // The linker has placed the image of entryother.S in
73c60a3551SFrans Kaashoek   // _binary_entryother_start.
74a7c03bd9SRobert Morris   code = P2V(0x7000);
75c60a3551SFrans Kaashoek   memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
761afc9d3fSRobert Morris 
7799b11b6cSrsc   for(c = cpus; c < cpus+ncpu; c++){
78abf847a0SFrans Kaashoek     if(c == mycpu())  // We've started already.
7999b11b6cSrsc       continue;
8099b11b6cSrsc 
81e25b74caSFrans Kaashoek     // Tell entryother.S what stack to use, where to enter, and what
82e25b74caSFrans Kaashoek     // pgdir to use. We cannot use kpgdir yet, because the AP processor
83e25b74caSFrans Kaashoek     // is running in low  memory, so we use entrypgdir for the APs too.
84c092540eSRobert Morris     stack = kalloc();
85ab08960fSrsc     *(void**)(code-4) = stack + KSTACKSIZE;
86*96e4e2f4SFrans Kaashoek     *(void(**)(void))(code-8) = mpenter;
87a7c03bd9SRobert Morris     *(int**)(code-12) = (void *) V2P(entrypgdir);
88faad047aSRobert Morris 
89ae15515dSFrans Kaashoek     lapicstartap(c->apicid, V2P(code));
9099b11b6cSrsc 
91bd71a450SFrans Kaashoek     // wait for cpu to finish mpmain()
92a4b213cfSFrans Kaashoek     while(c->started == 0)
9399b11b6cSrsc       ;
9499b11b6cSrsc   }
9599b11b6cSrsc }
96cf4b1ad9SRuss Cox 
973431cd49SRobert Morris // The boot page table used in entry.S and entryother.S.
983431cd49SRobert Morris // Page directories (and page tables) must start on page boundaries,
993431cd49SRobert Morris // hence the __aligned__ attribute.
1003431cd49SRobert Morris // PTE_PS in a page directory entry enables 4Mbyte pages.
1013431cd49SRobert Morris 
10266ba8079SFrans Kaashoek __attribute__((__aligned__(PGSIZE)))
1035e083578SRobert Morris pde_t entrypgdir[NPDENTRIES] = {
10466ba8079SFrans Kaashoek   // Map VA's [0, 4MB) to PA's [0, 4MB)
1051e6f0146SAustin Clements   [0] = (0) | PTE_P | PTE_W | PTE_PS,
10666ba8079SFrans Kaashoek   // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
1071e6f0146SAustin Clements   [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS,
10866ba8079SFrans Kaashoek };
10966ba8079SFrans Kaashoek 
110cf4b1ad9SRuss Cox //PAGEBREAK!
111cf4b1ad9SRuss Cox // Blank page.
11274c77da6SFrans Kaashoek //PAGEBREAK!
1134638cabfSRobert Morris // Blank page.
1144638cabfSRobert Morris //PAGEBREAK!
1154638cabfSRobert Morris // Blank page.
1164638cabfSRobert Morris 
117