Skip to content

Commit da1f839

Browse files
committed
Lab 4
1 parent a9d7717 commit da1f839

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2696
-37
lines changed

GNUmakefile

+4
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ CFLAGS := $(CFLAGS) $(DEFS) $(LABDEFS) -O1 -fno-builtin -I$(TOP) -MD
8888
CFLAGS += -fno-omit-frame-pointer
8989
CFLAGS += -std=gnu99
9090
CFLAGS += -static
91+
CFLAGS += -fno-pie
9192
CFLAGS += -Wall -Wno-format -Wno-unused -Werror -gstabs -m32
9293
# -fno-tree-ch prevented gcc from sometimes reordering read_ebp() before
9394
# mon_backtrace()'s function prologue on gcc version: (Debian 4.7.2-5) 4.7.2
@@ -142,9 +143,12 @@ include lib/Makefrag
142143
include user/Makefrag
143144

144145

146+
CPUS ?= 1
147+
145148
QEMUOPTS = -drive file=$(OBJDIR)/kern/kernel.img,index=0,media=disk,format=raw -serial mon:stdio -gdb tcp::$(GDBPORT)
146149
QEMUOPTS += $(shell if $(QEMU) -nographic -help | grep -q '^-D '; then echo '-D qemu.log'; fi)
147150
IMAGES = $(OBJDIR)/kern/kernel.img
151+
QEMUOPTS += -smp $(CPUS)
148152
QEMUOPTS += $(QEMUEXTRA)
149153

150154
.gdbinit: .gdbinit.tmpl

boot/main.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ void
3939
bootmain(void)
4040
{
4141
struct Proghdr *ph, *eph;
42+
int i;
4243

4344
// read 1st page off disk
4445
readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);
@@ -50,10 +51,14 @@ bootmain(void)
5051
// load each program segment (ignores ph flags)
5152
ph = (struct Proghdr *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff);
5253
eph = ph + ELFHDR->e_phnum;
53-
for (; ph < eph; ph++)
54+
for (; ph < eph; ph++) {
5455
// p_pa is the load address of this segment (as well
5556
// as the physical address)
5657
readseg(ph->p_pa, ph->p_memsz, ph->p_offset);
58+
for (i = 0; i < ph->p_memsz - ph->p_filesz; i++) {
59+
*((char *) ph->p_pa + ph->p_filesz + i) = 0;
60+
}
61+
}
5762

5863
// call the entry point from the ELF header
5964
// note: does not return!

conf/lab.mk

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
LAB=3
2-
PACKAGEDATE=Tue Sep 25 12:21:10 EDT 2018
1+
LAB=4
2+
PACKAGEDATE=Mon Oct 8 21:31:51 PDT 2018

grade-lab4

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
#!/usr/bin/env python
2+
3+
import re
4+
from gradelib import *
5+
6+
r = Runner(save("jos.out"),
7+
stop_breakpoint("readline"))
8+
9+
def E(s, trim=False):
10+
"""Expand $En in s to the environment ID of the n'th user
11+
environment."""
12+
13+
tmpl = "%x" if trim else "%08x"
14+
return re.sub(r"\$E([0-9]+)",
15+
lambda m: tmpl % (0x1000 + int(m.group(1))-1), s)
16+
17+
@test(5)
18+
def test_dumbfork():
19+
r.user_test("dumbfork")
20+
r.match(E(".00000000. new env $E1"),
21+
E(".$E1. new env $E2"),
22+
"0: I am the parent.",
23+
"9: I am the parent.",
24+
"0: I am the child.",
25+
"9: I am the child.",
26+
"19: I am the child.",
27+
E(".$E1. exiting gracefully"),
28+
E(".$E1. free env $E1"),
29+
E(".$E2. exiting gracefully"),
30+
E(".$E2. free env $E2"))
31+
32+
end_part("A")
33+
34+
@test(5)
35+
def test_faultread():
36+
r.user_test("faultread")
37+
r.match(E(".$E1. user fault va 00000000 ip 008....."),
38+
"TRAP frame at 0xf....... from CPU .",
39+
" trap 0x0000000e Page Fault",
40+
" err 0x00000004.*",
41+
E(".$E1. free env $E1"),
42+
no=["I read ........ from location 0."])
43+
44+
@test(5)
45+
def test_faultwrite():
46+
r.user_test("faultwrite")
47+
r.match(E(".$E1. user fault va 00000000 ip 008....."),
48+
"TRAP frame at 0xf....... from CPU .",
49+
" trap 0x0000000e Page Fault",
50+
" err 0x00000006.*",
51+
E(".$E1. free env $E1"))
52+
53+
@test(5)
54+
def test_faultdie():
55+
r.user_test("faultdie")
56+
r.match("i faulted at va deadbeef, err 6",
57+
E(".$E1. exiting gracefully"),
58+
E(".$E1. free env $E1"))
59+
60+
@test(5)
61+
def test_faultregs():
62+
r.user_test("faultregs")
63+
r.match("Registers in UTrapframe OK",
64+
"Registers after page-fault OK",
65+
no=["Registers in UTrapframe MISMATCH",
66+
"Registers after page-fault MISMATCH"])
67+
68+
@test(5)
69+
def test_faultalloc():
70+
r.user_test("faultalloc")
71+
r.match("fault deadbeef",
72+
"this string was faulted in at deadbeef",
73+
"fault cafebffe",
74+
"fault cafec000",
75+
"this string was faulted in at cafebffe",
76+
E(".$E1. exiting gracefully"),
77+
E(".$E1. free env $E1"))
78+
79+
@test(5)
80+
def test_faultallocbad():
81+
r.user_test("faultallocbad")
82+
r.match(E(".$E1. user_mem_check assertion failure for va deadbeef"),
83+
E(".$E1. free env $E1"))
84+
85+
@test(5)
86+
def test_faultnostack():
87+
r.user_test("faultnostack")
88+
r.match(E(".$E1. user_mem_check assertion failure for va eebfff.."),
89+
E(".$E1. free env $E1"))
90+
91+
@test(5)
92+
def test_faultbadhandler():
93+
r.user_test("faultbadhandler")
94+
r.match(E(".$E1. user_mem_check assertion failure for va (deadb|eebfe)..."),
95+
E(".$E1. free env $E1"))
96+
97+
@test(5)
98+
def test_faultevilhandler():
99+
r.user_test("faultevilhandler")
100+
r.match(E(".$E1. user_mem_check assertion failure for va (f0100|eebfe)..."),
101+
E(".$E1. free env $E1"))
102+
103+
@test(5)
104+
def test_forktree():
105+
r.user_test("forktree")
106+
r.match("....: I am .0.",
107+
"....: I am .1.",
108+
"....: I am .000.",
109+
"....: I am .100.",
110+
"....: I am .110.",
111+
"....: I am .111.",
112+
"....: I am .011.",
113+
"....: I am .001.",
114+
E(".$E1. exiting gracefully"),
115+
E(".$E2. exiting gracefully"),
116+
".0000200.. exiting gracefully",
117+
".0000200.. free env 0000200.")
118+
119+
end_part("B")
120+
121+
@test(5)
122+
def test_spin():
123+
r.user_test("spin")
124+
r.match(E(".00000000. new env $E1"),
125+
"I am the parent. Forking the child...",
126+
E(".$E1. new env $E2"),
127+
"I am the parent. Running the child...",
128+
"I am the child. Spinning...",
129+
"I am the parent. Killing the child...",
130+
E(".$E1. destroying $E2"),
131+
E(".$E1. free env $E2"),
132+
E(".$E1. exiting gracefully"),
133+
E(".$E1. free env $E1"))
134+
135+
@test(5)
136+
def test_stresssched():
137+
r.user_test("stresssched", make_args=["CPUS=4"])
138+
r.match(".000010... stresssched on CPU 0",
139+
".000010... stresssched on CPU 1",
140+
".000010... stresssched on CPU 2",
141+
".000010... stresssched on CPU 3",
142+
no=[".*ran on two CPUs at once"])
143+
144+
@test(5)
145+
def test_sendpage():
146+
r.user_test("sendpage", make_args=["CPUS=2"])
147+
r.match(".00000000. new env 00001000",
148+
E(".00000000. new env $E1"),
149+
E(".$E1. new env $E2"),
150+
E("$E1 got message: hello child environment! how are you?", trim=True),
151+
E("child received correct message", trim=True),
152+
E("$E2 got message: hello parent environment! I'm good", trim=True),
153+
E("parent received correct message", trim=True),
154+
E(".$E1. exiting gracefully"),
155+
E(".$E1. free env $E1"),
156+
E(".$E2. exiting gracefully"),
157+
E(".$E2. free env $E2"))
158+
159+
@test(5)
160+
def test_pingpong():
161+
r.user_test("pingpong", make_args=["CPUS=4"])
162+
r.match(E(".00000000. new env $E1"),
163+
E(".$E1. new env $E2"),
164+
E("send 0 from $E1 to $E2", trim=True),
165+
E("$E2 got 0 from $E1", trim=True),
166+
E("$E1 got 1 from $E2", trim=True),
167+
E("$E2 got 8 from $E1", trim=True),
168+
E("$E1 got 9 from $E2", trim=True),
169+
E("$E2 got 10 from $E1", trim=True),
170+
E(".$E1. exiting gracefully"),
171+
E(".$E1. free env $E1"),
172+
E(".$E2. exiting gracefully"),
173+
E(".$E2. free env $E2"))
174+
175+
@test(5)
176+
def test_primes():
177+
r.user_test("primes", stop_on_line("CPU .: 1877"), stop_on_line(".*panic"),
178+
make_args=["CPUS=4"], timeout=60)
179+
r.match(E(".00000000. new env $E1"),
180+
E(".$E1. new env $E2"),
181+
E("CPU .: 2 .$E2. new env $E3"),
182+
E("CPU .: 3 .$E3. new env $E4"),
183+
E("CPU .: 5 .$E4. new env $E5"),
184+
E("CPU .: 7 .$E5. new env $E6"),
185+
E("CPU .: 11 .$E6. new env $E7"),
186+
E("CPU .: 1877 .$E289. new env $E290"))
187+
188+
end_part("C")
189+
190+
run_tests()

inc/env.h

+11
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,20 @@ struct Env {
5151
enum EnvType env_type; // Indicates special system environments
5252
unsigned env_status; // Status of the environment
5353
uint32_t env_runs; // Number of times environment has run
54+
int env_cpunum; // The CPU that the env is running on
5455

5556
// Address space
5657
pde_t *env_pgdir; // Kernel virtual address of page dir
58+
59+
// Exception handling
60+
void *env_pgfault_upcall; // Page fault upcall entry point
61+
62+
// Lab 4 IPC
63+
bool env_ipc_recving; // Env is blocked receiving
64+
void *env_ipc_dstva; // VA at which to map received page
65+
uint32_t env_ipc_value; // Data value sent to us
66+
envid_t env_ipc_from; // envid of the sender
67+
int env_ipc_perm; // Perm of page mapping received
5768
};
5869

5970
#endif // !JOS_INC_ENV_H

inc/error.h

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ enum {
1414
// the maximum allowed
1515
E_FAULT , // Memory fault
1616

17+
E_IPC_NOT_RECV , // Attempt to send to env that is not recving
18+
E_EOF , // Unexpected end of file
19+
1720
MAXERROR
1821
};
1922

inc/lib.h

+35
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <inc/env.h>
1717
#include <inc/memlayout.h>
1818
#include <inc/syscall.h>
19+
#include <inc/trap.h>
1920

2021
#define USED(x) (void)(x)
2122

@@ -31,6 +32,9 @@ extern const volatile struct PageInfo pages[];
3132
// exit.c
3233
void exit(void);
3334

35+
// pgfault.c
36+
void set_pgfault_handler(void (*handler)(struct UTrapframe *utf));
37+
3438
// readline.c
3539
char* readline(const char *buf);
3640

@@ -39,6 +43,37 @@ void sys_cputs(const char *string, size_t len);
3943
int sys_cgetc(void);
4044
envid_t sys_getenvid(void);
4145
int sys_env_destroy(envid_t);
46+
void sys_yield(void);
47+
static envid_t sys_exofork(void);
48+
int sys_env_set_status(envid_t env, int status);
49+
int sys_env_set_pgfault_upcall(envid_t env, void *upcall);
50+
int sys_page_alloc(envid_t env, void *pg, int perm);
51+
int sys_page_map(envid_t src_env, void *src_pg,
52+
envid_t dst_env, void *dst_pg, int perm);
53+
int sys_page_unmap(envid_t env, void *pg);
54+
int sys_ipc_try_send(envid_t to_env, uint32_t value, void *pg, int perm);
55+
int sys_ipc_recv(void *rcv_pg);
56+
57+
// This must be inlined. Exercise for reader: why?
58+
static inline envid_t __attribute__((always_inline))
59+
sys_exofork(void)
60+
{
61+
envid_t ret;
62+
asm volatile("int %2"
63+
: "=a" (ret)
64+
: "a" (SYS_exofork), "i" (T_SYSCALL));
65+
return ret;
66+
}
67+
68+
// ipc.c
69+
void ipc_send(envid_t to_env, uint32_t value, void *pg, int perm);
70+
int32_t ipc_recv(envid_t *from_env_store, void *pg, int *perm_store);
71+
envid_t ipc_find_env(enum EnvType type);
72+
73+
// fork.c
74+
#define PTE_SHARE 0x400
75+
envid_t fork(void);
76+
envid_t sfork(void); // Challenge!
4277

4378

4479

inc/memlayout.h

+3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@
138138
// The location of the user-level STABS data structure
139139
#define USTABDATA (PTSIZE / 2)
140140

141+
// Physical address of startup code for non-boot CPUs (APs)
142+
#define MPENTRY_PADDR 0x7000
143+
141144
#ifndef __ASSEMBLER__
142145

143146
typedef uint32_t pte_t;

inc/syscall.h

+9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ enum {
77
SYS_cgetc,
88
SYS_getenvid,
99
SYS_env_destroy,
10+
SYS_page_alloc,
11+
SYS_page_map,
12+
SYS_page_unmap,
13+
SYS_exofork,
14+
SYS_env_set_status,
15+
SYS_env_set_pgfault_upcall,
16+
SYS_yield,
17+
SYS_ipc_try_send,
18+
SYS_ipc_recv,
1019
NSYSCALLS
1120
};
1221

inc/trap.h

+11
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ struct Trapframe {
7474
uint16_t tf_padding4;
7575
} __attribute__((packed));
7676

77+
struct UTrapframe {
78+
/* information about the fault */
79+
uint32_t utf_fault_va; /* va for T_PGFLT, 0 otherwise */
80+
uint32_t utf_err;
81+
/* trap-time return state */
82+
struct PushRegs utf_regs;
83+
uintptr_t utf_eip;
84+
uint32_t utf_eflags;
85+
/* the trap-time stack to return to */
86+
uintptr_t utf_esp;
87+
} __attribute__((packed));
7788

7889
#endif /* !__ASSEMBLER__ */
7990

0 commit comments

Comments
 (0)