forked from mit-pdos/xv6-public
-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathmain.c
143 lines (117 loc) · 3.41 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
137
138
139
140
141
142
143
#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("\nxV6\n\n");
pic_init(); // initialize PIC
kinit(); // physical memory allocator
tvinit(); // trap vectors
idtinit(); // CPU's idt
// create fake process zero
p = &proc[0];
memset(p, 0, sizeof *p);
p->state = SLEEPING;
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;
p->pid = 0;
p->ppid = 0;
setupsegs(p);
mp_startthem();
// turn on timer and enable interrupts on the local APIC
lapic_timerinit();
lapic_enableintr();
// init disk device
ide_init();
// Enable interrupts on this processor.
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("an application processor\n");
idtinit(); // CPU's idt
if(cpu() == 0)
panic("mpmain on cpu 0");
lapic_init(cpu());
lapic_timerinit();
lapic_enableintr();
// 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);
}
}