-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.c
137 lines (123 loc) · 4.22 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
131
132
133
134
135
136
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
static void startothers(void);
static void mpmain(void) __attribute__((noreturn));
extern pde_t *kpgdir;
extern char end[]; // first address after kernel loaded from ELF file
// 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)
{
kinit1(end, P2V(4*1024*1024)); // phys page allocator
/*
* - main() immediately changes to a new page table by calling kvmalloc()
* - main() calls kvmalloc() to create and switch to a page table with
* the mappings above KERNBASE required for the kernel run
*/
kvmalloc(); // kernel page table
mpinit(); // detect other processors
lapicinit(); // interrupt controller
/*
设置当前CPU的GDT
*/
seginit(); // segment descriptors
picinit(); // disable pic
ioapicinit(); // another interrupt controller
consoleinit(); // console hardware
uartinit(); // serial port
/* 初始化全局进程锁 */
pinit(); // process table
/* 设置中断描述符表 */
tvinit(); // trap vectors
/* 初始化块设备缓冲区 */
binit(); // buffer cache
fileinit(); // file table
/*initialize the disk driver*/
ideinit(); // disk
startothers(); // start other processors
/*
* The allocator refers to physical pages by their virtual addresses
* as mapped in high memory, not by their physical addresses, this is why use P2V(PHYSTOP)
*/
kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
userinit(); // create the first user process
mpmain(); // finish this processor's setup
}
// Other CPUs jump here from entryother.S.
static void
mpenter(void)
{
switchkvm();
seginit();
lapicinit();
mpmain();
}
// Common CPU setup code.
static void
mpmain(void)
{
cprintf("cpu%d: starting %d\n", cpuid(), cpuid());
idtinit(); // load idt register
xchg(&(mycpu()->started), 1); // tell startothers() we're up
scheduler(); // start running processes
}
pde_t entrypgdir[]; // For entry.S
// Start the non-boot (AP) processors.
static void
startothers(void)
{
extern uchar _binary_entryother_start[], _binary_entryother_size[];
uchar *code;
struct cpu *c;
char *stack;
// Write entry code to unused memory at 0x7000.
// The linker has placed the image of entryother.S in
// _binary_entryother_start.
code = P2V(0x7000);
memmove(code, _binary_entryother_start, (uint)_binary_entryother_size);
for(c = cpus; c < cpus+ncpu; c++){
if(c == mycpu()) // We've started already.
continue;
// Tell entryother.S what stack to use, where to enter, and what
// pgdir to use. We cannot use kpgdir yet, because the AP processor
// is running in low memory, so we use entrypgdir for the APs too.
stack = kalloc();
*(void**)(code-4) = stack + KSTACKSIZE;
*(void(**)(void))(code-8) = mpenter;
*(int**)(code-12) = (void *) V2P(entrypgdir);
lapicstartap(c->apicid, V2P(code));
// wait for cpu to finish mpmain()
while(c->started == 0)
;
}
}
// The boot page table used in entry.S and entryother.S.
// Page directories (and page tables) must start on page boundaries,
// hence the __aligned__ attribute.
// PTE_PS in a page directory entry enables 4Mbyte pages.
/*
* The array initialization sets two of the 1024 PDEs, at indices 0 and 512, leaving the other PDEs zero.
* xv6 sets the PTE_PS bit in these two PDEs to mark them as "super pages".
*
* 初次使用entrypgdir, 由于设置了PTE_PS, 所以不会用到page table
*/
__attribute__((__aligned__(PGSIZE)))
pde_t entrypgdir[NPDENTRIES] = {
// Map VA's [0, 4MB) to PA's [0, 4MB)
[0] = (0) | PTE_P | PTE_W | PTE_PS, /*第0个entry, this mapping is required as long as entry is executing at low addresses, will be eventually be removed*/
// Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
[KERNBASE>>PDXSHIFT] = (0) | PTE_P | PTE_W | PTE_PS, /*第512个entry, this entry will be used by kernel after entry.S has finished*/
};
//PAGEBREAK!
// Blank page.
//PAGEBREAK!
// Blank page.
//PAGEBREAK!
// Blank page.