forked from mit-pdos/xv6-public
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
131 lines (115 loc) · 3.25 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#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.