summaryrefslogtreecommitdiff
path: root/main.c
blob: 6e1dabedce1489e9a99485a74fce8bb8c375ea82 (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
157
158
159
160
161
#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_userfs_start[], _binary_userfs_size[];
extern uchar _binary_init_start[], _binary_init_size[];

// 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;

  lcr4(0); // xxx copy of cpu #

  // 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.
  // xxx maybe replace w/ acquire remembering if FL_IF
  for(i=0; i<NCPU; i++){
    cpus[i].nlock++;
    cpus[i].guard1 = 0xdeadbeef;
    cpus[i].guard2 = 0xdeadbeef;
  }

  mp_init(); // collect info about this machine

  lapic_init(mp_bcpu());

  cprintf("\n\ncpu%d: booting xv6\n\n", cpu());

  pinit();
  binit();
  pic_init(); // initialize PIC
  ioapic_init();
  kinit(); // physical memory allocator
  tvinit(); // trap vectors
  idtinit(); // this CPU's idt register
  fd_init();
  iinit();

  // 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(KSTACKSIbZE);
  p->tf = (struct trapframe *) (p->kstack + KSTACKSIZE) - 1;
  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);
  // curproc[cpu()] = 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.
  cpus[cpu()].nlock--;
  sti();

  // p->cwd = iget(rootdev, 1);
  // iunlock(p->cwd);
  p = copyproc(&proc[0]);
  
  //load_icode(p, _binary_usertests_start, (uint) _binary_usertests_size);
  //load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);
  load_icode(p, _binary_init_start, (uint) _binary_init_size);
  p->state = RUNNABLE;

  scheduler();
}

// Additional processors start here.
void
mpmain(void)
{
  lcr4(1); // xxx copy of cpu #

  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.
  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;
  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;
    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);
  }
}