/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- main
- mpenter
- mpmain
- startothers
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 kinit1(end, P2V(4*1024*1024)); // phys page allocator
21 kvmalloc(); // kernel page table
22 mpinit(); // collect info about this machine
23 lapicinit();
24 seginit(); // set up segments
25 cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
26 picinit(); // interrupt controller
27 ioapicinit(); // another interrupt controller
28 consoleinit(); // I/O devices & their interrupts
29 uartinit(); // serial port
30 pinit(); // process table
31 tvinit(); // trap vectors
32 binit(); // buffer cache
33 fileinit(); // file table
34 ideinit(); // disk
35 if(!ismp)
36 timerinit(); // uniprocessor timer
37 startothers(); // start other processors
38 kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
39 userinit(); // first user process
40 // Finish setting up this processor in mpmain.
41 mpmain();
42 }
43
44 // Other CPUs jump here from entryother.S.
45 static void
46 mpenter(void)
47 {
48 switchkvm();
49 seginit();
50 lapicinit();
51 mpmain();
52 }
53
54 // Common CPU setup code.
55 static void
56 mpmain(void)
57 {
58 cprintf("cpu%d: starting\n", cpu->id);
59 idtinit(); // load idt register
60 xchg(&cpu->started, 1); // tell startothers() we're up
61 scheduler(); // start running processes
62 }
63
64 pde_t entrypgdir[]; // For entry.S
65
66 // Start the non-boot (AP) processors.
67 static void
68 startothers(void)
69 {
70 extern uchar _binary_entryother_start[], _binary_entryother_size[];
71 uchar *code;
72 struct cpu *c;
73 char *stack;
74
75 // Write entry code to unused memory at 0x7000.
76 // The linker has placed the image of entryother.S in
77 // _binary_entryother_start.
78 code = p2v(0x7000);
79 memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
80
81 for(c = cpus; c < cpus+ncpu; c++){
82 if(c == cpus+cpunum()) // We've started already.
83 continue;
84
85 // Tell entryother.S what stack to use, where to enter, and what
86 // pgdir to use. We cannot use kpgdir yet, because the AP processor
87 // is running in low memory, so we use entrypgdir for the APs too.
88 stack = kalloc();
89 *(void**)(code-4) = stack + KSTACKSIZE;
90 *(void**)(code-8) = mpenter;
91 *(int**)(code-12) = (void *) v2p(entrypgdir);
92
93 lapicstartap(c->id, v2p(code));
94
95 // wait for cpu to finish mpmain()
96 while(c->started == 0)
97 ;
98 }
99 }
100
101 // Boot page table used in entry.S and entryother.S.
102 // Page directories (and page tables), must start on a page boundary,
103 // hence the "__aligned__" attribute.
104 // Use PTE_PS in page directory entry to enable 4Mbyte pages.
105 __attribute__((__aligned__(PGSIZE)))
106 pde_t entrypgdir[NPDENTRIES] = {
107 // Map VA's [0, 4MB) to PA's [0, 4MB)
108 [0] = (0) | PTE_P | PTE_W | PTE_PS,
109 // Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
110 [KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS,
111 };
112
113 //PAGEBREAK!
114 // Blank page.
115 //PAGEBREAK!
116 // Blank page.
117 //PAGEBREAK!
118 // Blank page.