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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
#include "types.h"
#include "param.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
#include "x86.h"
#include "traps.h"
#include "syscall.h"
#include "elf.h"
#include "param.h"
#include "spinlock.h"
extern char edata[], end[];
extern uchar _binary_user1_start[], _binary_user1_size[];
extern uchar _binary_usertests_start[], _binary_usertests_size[];
extern uchar _binary_userfs_start[], _binary_userfs_size[];
extern int use_console_lock;
// CPU 0 starts running C code here.
// This is called main0 not main so that it can have
// a void return type. Gcc can't handle functions named
// main that don't return int. Really.
void
main0(void)
{
int i;
struct proc *p;
// clear BSS
memset(edata, 0, end - edata);
// Make sure interrupts stay disabled on all processors
// until each signals it is ready, by pretending to hold
// an extra lock.
for(i=0; i<NCPU; i++)
cpus[i].nlock++;
mp_init(); // collect info about this machine
use_console_lock = 1;
lapic_init(mp_bcpu());
cprintf("\n\ncpu%d: booting xv6\n\n", cpu());
pic_init(); // initialize PIC
ioapic_init();
kinit(); // physical memory allocator
tvinit(); // trap vectors
idtinit(); // this CPU's idt register
// create a fake process per CPU
// so each CPU always has a tss and a gdt
for(p = &proc[0]; p < &proc[NCPU]; p++){
p->state = IDLEPROC;
p->kstack = cpus[p-proc].mpstack;
p->pid = p - proc;
}
// fix process 0 so that copyproc() will work
p = &proc[0];
p->sz = 4 * PAGE;
p->mem = kalloc(p->sz);
memset(p->mem, 0, p->sz);
p->kstack = kalloc(KSTACKSIZE);
p->tf = (struct trapframe *) (p->kstack + KSTACKSIZE - sizeof(struct trapframe));
memset(p->tf, 0, sizeof(struct trapframe));
p->tf->es = p->tf->ds = p->tf->ss = (SEG_UDATA << 3) | 3;
p->tf->cs = (SEG_UCODE << 3) | 3;
p->tf->eflags = FL_IF;
setupsegs(p);
// init disk device
console_init();
ide_init();
mp_startthem();
// turn on timer and enable interrupts on the local APIC
lapic_timerinit();
lapic_enableintr();
// Enable interrupts on this processor.
cprintf("cpu%d: nlock %d before -- and sti\n",
cpu(), cpus[0].nlock);
cpus[cpu()].nlock--;
sti();
p = copyproc(&proc[0]);
//load_icode(p, _binary_usertests_start, (uint) _binary_usertests_size);
load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
p->state = RUNNABLE;
cprintf("loaded userfs\n");
scheduler();
}
// Additional processors start here.
void
mpmain(void)
{
cprintf("cpu%d: starting\n", cpu());
idtinit(); // CPU's idt
if(cpu() == 0)
panic("mpmain on cpu 0");
lapic_init(cpu());
lapic_timerinit();
lapic_enableintr();
setupsegs(&proc[cpu()]);
cpuid(0, 0, 0, 0, 0); // memory barrier
cpus[cpu()].booted = 1;
// Enable interrupts on this processor.
cprintf("cpu%d: initial nlock %d\n", cpu(), cpus[cpu()].nlock);
cpus[cpu()].nlock--;
sti();
scheduler();
}
void
load_icode(struct proc *p, uchar *binary, uint size)
{
int i;
struct elfhdr *elf;
struct proghdr *ph;
// Check magic number on binary
elf = (struct elfhdr*) binary;
cprintf("elf %x magic %x\n", elf, elf->magic);
if (elf->magic != ELF_MAGIC)
panic("load_icode: not an ELF binary");
p->tf->eip = elf->entry;
p->tf->esp = p->sz;
// Map and load segments as directed.
ph = (struct proghdr*) (binary + elf->phoff);
for (i = 0; i < elf->phnum; i++, ph++) {
if (ph->type != ELF_PROG_LOAD)
continue;
cprintf("va %x memsz %d\n", ph->va, ph->memsz);
if (ph->va + ph->memsz < ph->va)
panic("load_icode: overflow in elf header segment");
if (ph->va + ph->memsz >= p->sz)
panic("load_icode: icode wants to be above UTOP");
// Load/clear the segment
memmove(p->mem + ph->va, binary + ph->offset, ph->filesz);
memset(p->mem + ph->va + ph->filesz, 0, ph->memsz - ph->filesz);
}
}
|