summaryrefslogtreecommitdiff
path: root/main.c
blob: b558e41ad9499afc12d6e20d0b28c2ca8d75ed14 (plain)
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);

  // initialize I/O devices, let them enable interrupts
  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);
  }
}