Skip to content

Commit 0919e17

Browse files
committed
courselab: add mit 6_1810 2022 xv6 labs
1 parent 29f114d commit 0919e17

Some content is hidden

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

63 files changed

+2403
-0
lines changed

benchmarks/courselab_bench/data/courses.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727
"institution": "CMU",
2828
"year": 2024,
2929
"num_tasks": 1
30+
},
31+
{
32+
"course_id": "mit_6_1810_2022",
33+
"name": "MIT 6.1810: Operating System Engineering",
34+
"institution": "MIT",
35+
"year": 2022,
36+
"num_tasks": 10
3037
}
3138
]
3239
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM ubuntu:22.04
2+
3+
ENV DEBIAN_FRONTEND=noninteractive
4+
5+
RUN apt-get update && apt-get install -y --no-install-recommends \
6+
build-essential \
7+
gcc-riscv64-linux-gnu \
8+
qemu-system-misc \
9+
python3 \
10+
git \
11+
ca-certificates \
12+
ipxe-qemu \
13+
&& rm -rf /var/lib/apt/lists/*
14+
15+
WORKDIR /root/workspace
16+
17+
CMD ["/bin/bash"]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Docker image for the System Intelligence Benchmark's CourseLab tasks for MIT 6.1810 Operating System Engineering labs.
2+
3+
```bash
4+
docker build -t sysintelligence/xv6:latest .
5+
docker push sysintelligence/xv6:latest
6+
```
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
services:
2+
default:
3+
image: sysintelligence/xv6:latest
4+
init: true
5+
command: tail -f /dev/null
6+
working_dir: /root/workspace
7+
network_mode: bridge
8+
cpus: '8.0'
9+
mem_reservation: 8gb
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"instance_id": "mit_6_1810_2022__mmap",
3+
"course_id": "mit_6_1810_2022",
4+
"timeout_minutes": 60,
5+
"tags": ["operating-systems", "c", "memory-mapping", "virtual-memory", "xv6", "risc-v", "kernel"],
6+
"artifacts": [
7+
"Makefile",
8+
"kernel/defs.h",
9+
"kernel/param.h",
10+
"kernel/printf.c",
11+
"kernel/proc.c",
12+
"kernel/proc.h",
13+
"kernel/riscv.h",
14+
"kernel/syscall.c",
15+
"kernel/syscall.h",
16+
"kernel/sysproc.c",
17+
"kernel/trap.c",
18+
"user/user.h",
19+
"user/usys.pl",
20+
"time.txt"
21+
]
22+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
set -e
3+
4+
cd /root/workspace
5+
6+
# Verify protected files unchanged
7+
for file in grade-lab-mmap gradelib.py user/mmaptest.c; do
8+
checksum="/tmp/checksums/$(echo "$file" | tr '/' '_').sha256"
9+
if [ -f "$checksum" ]; then
10+
sha256sum -c "$checksum" > /dev/null 2>&1 || { echo "FAIL: $file modified"; exit 1; }
11+
fi
12+
done
13+
14+
# Run grading with retries (tests can be timing-sensitive)
15+
for attempt in 1 2 3; do
16+
if make LAB=mmap grade 2>&1 | tee /tmp/grade_output.txt | grep -q "Score:.*140/140"; then
17+
echo "PASS: All tests passed"
18+
exit 0
19+
fi
20+
[ $attempt -lt 3 ] && sleep 2
21+
done
22+
23+
echo "FAIL: Tests did not pass"
24+
cat /tmp/grade_output.txt
25+
exit 1
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
set -e
3+
4+
5+
cd /root
6+
7+
# Clone MIT xv6-labs-2022 skeleton (mmap branch)
8+
git clone git://g.csail.mit.edu/xv6-labs-2022 workspace
9+
cd workspace
10+
git checkout mmap
11+
# Pin to specific commit for reproducibility
12+
git checkout 9cc6b8345397c1f06cc93ed3fbaa20709cb1984e
13+
rm -rf .git
14+
15+
# Create checksums for protected files (grading scripts, tests)
16+
mkdir -p /tmp/checksums
17+
sha256sum grade-lab-mmap > /tmp/checksums/grade-lab-mmap.sha256
18+
sha256sum gradelib.py > /tmp/checksums/gradelib.py.sha256
19+
sha256sum user/mmaptest.c > /tmp/checksums/user_mmaptest.c.sha256
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
# Reference solution from: https://github.com/Cyrus-iwnl/xv6-labs-2022
3+
set -e
4+
5+
# Clone reference solution repository
6+
git clone https://github.com/Cyrus-iwnl/xv6-labs-2022.git /tmp/ref
7+
cd /tmp/ref
8+
git checkout origin/mmap
9+
10+
# Copy solution files
11+
cp Makefile /root/workspace/
12+
cp kernel/defs.h /root/workspace/kernel/
13+
cp kernel/param.h /root/workspace/kernel/
14+
cp kernel/printf.c /root/workspace/kernel/
15+
cp kernel/proc.c /root/workspace/kernel/
16+
cp kernel/proc.h /root/workspace/kernel/
17+
cp kernel/riscv.h /root/workspace/kernel/
18+
cp kernel/syscall.c /root/workspace/kernel/
19+
cp kernel/syscall.h /root/workspace/kernel/
20+
cp kernel/sysproc.c /root/workspace/kernel/
21+
cp kernel/trap.c /root/workspace/kernel/
22+
cp user/user.h /root/workspace/user/
23+
cp user/usys.pl /root/workspace/user/
24+
25+
cd /root/workspace
26+
27+
# Create time.txt (required by grading script - contains hours spent)
28+
echo "1" > time.txt
29+
30+
# Clean up
31+
rm -rf /tmp/ref
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Lab: mmap (hard)
2+
3+
The `mmap` and `munmap` system calls allow UNIX programs to exert detailed control over their address spaces. They can be used to share memory among processes, to map files into process address spaces, and as part of user-level page fault schemes such as garbage-collection algorithms. In this lab you'll add `mmap` and `munmap` to xv6, focusing on memory-mapped files.
4+
5+
The manual page (run `man 2 mmap`) shows this declaration for mmap:
6+
7+
```c
8+
void *mmap(void *addr, size_t length, int prot, int flags,
9+
int fd, off_t offset);
10+
```
11+
12+
`mmap` can be called in many ways, but this lab requires only a subset of its features relevant to memory-mapping a file. You can assume that `addr` will always be zero, meaning that the kernel should decide the virtual address at which to map the file. `mmap` returns that address, or 0xffffffffffffffff if it fails. `length` is the number of bytes to map; it might not be the same as the file's length. `prot` indicates whether the memory should be mapped readable, writeable, and/or executable; you can assume that `prot` is `PROT_READ` or `PROT_WRITE` or both. `flags` will be either `MAP_SHARED`, meaning that modifications to the mapped memory should be written back to the file, or `MAP_PRIVATE`, meaning that they should not. You don't have to implement any other bits in flags. `fd` is the open file descriptor of the file to map. You can assume offset is zero (it's the starting point in the file at which to map).
13+
14+
It's OK if processes that map the same `MAP_SHARED` file do **not** share physical pages.
15+
16+
`munmap(addr, length)` should remove mmap mappings in the indicated address range. If the process has modified the memory and has it mapped `MAP_SHARED`, the modifications should first be written to the file. An munmap call might cover only a portion of an mmap-ed region, but you can assume that it will either unmap at the start, or at the end, or the whole region (but not punch a hole in the middle of a region).
17+
18+
You should implement enough `mmap` and `munmap` functionality to make the mmaptest test program work. If mmaptest doesn't use a mmap feature, you don't need to implement that feature.
19+
20+
When you're done, you should see this output:
21+
22+
```
23+
$ mmaptest
24+
mmap_test starting
25+
test mmap f
26+
test mmap f: OK
27+
test mmap private
28+
test mmap private: OK
29+
test mmap read-only
30+
test mmap read-only: OK
31+
test mmap read/write
32+
test mmap read/write: OK
33+
test mmap dirty
34+
test mmap dirty: OK
35+
test not-mapped unmap
36+
test not-mapped unmap: OK
37+
test mmap two files
38+
test mmap two files: OK
39+
mmap_test: ALL OK
40+
fork_test starting
41+
fork_test OK
42+
mmaptest: all tests succeeded
43+
$ usertests -q
44+
usertests starting
45+
...
46+
ALL TESTS PASSED
47+
$
48+
```
49+
50+
Here are some hints:
51+
52+
- Start by adding `_mmaptest` to `UPROGS`, and `mmap` and `munmap` system calls, in order to get `user/mmaptest.c` to compile. For now, just return errors from mmap and munmap. We defined `PROT_READ` etc for you in `kernel/fcntl.h`. Run mmaptest, which will fail at the first mmap call.
53+
- Fill in the page table lazily, in response to page faults. That is, mmap should not allocate physical memory or read the file. Instead, do that in page fault handling code in (or called by) `usertrap`, as in the lazy page allocation lab. The reason to be lazy is to ensure that mmap of a large file is fast, and that mmap of a file larger than physical memory is possible.
54+
- Keep track of what mmap has mapped for each process. Define a structure corresponding to the VMA (virtual memory area), recording the address, length, permissions, file, etc. for a virtual memory range created by mmap. Since the xv6 kernel doesn't have a memory allocator in the kernel, it's OK to declare a fixed-size array of VMAs and allocate from that array as needed. A size of 16 should be sufficient.
55+
- Implement mmap: find an unused region in the process's address space in which to map the file, and add a VMA to the process's table of mapped regions. The VMA should contain a pointer to a `struct file` for the file being mapped; mmap should increase the file's reference count so that the structure doesn't disappear when the file is closed (hint: see `filedup`). Run mmaptest: the first mmap should succeed, but the first access to the mmap-ed memory will cause a page fault and kill mmaptest.
56+
- Add code to cause a page-fault in a mmap-ed region to allocate a page of physical memory, read 4096 bytes of the relevant file into that page, and map it into the user address space. Read the file with `readi`, which takes an offset argument at which to read in the file (but you will have to lock/unlock the inode passed to `readi`). Don't forget to set the permissions correctly on the page. Run mmaptest; it should get to the first munmap.
57+
- Implement munmap: find the VMA for the address range and unmap the specified pages (hint: use `uvmunmap`). If munmap removes all pages of a previous mmap, it should decrement the reference count of the corresponding `struct file`. If an unmapped page has been modified and the file is mapped `MAP_SHARED`, write the page back to the file. Look at `filewrite` for inspiration.
58+
- Ideally your implementation would only write back `MAP_SHARED` pages that the program actually modified. The dirty bit (D) in the RISC-V PTE indicates whether a page has been written. However, mmaptest does not check that non-dirty pages are not written back; thus you can get away with writing pages back without looking at D bits.
59+
- Modify `exit` to unmap the process's mapped regions as if munmap had been called. Run mmaptest; mmap_test should pass, but probably not fork_test.
60+
- Modify `fork` to ensure that the child has the same mapped regions as the parent. Don't forget to increment the reference count for a VMA's `struct file`. In the page fault handler of the child, it is OK to allocate a new physical page instead of sharing a page with the parent. The latter would be cooler, but it would require more implementation work. Run mmaptest; it should pass both mmap_test and fork_test.
61+
62+
Run `usertests -q` to make sure everything still works.
63+
64+
---
65+
66+
## Environment
67+
68+
The workspace is at `/root/workspace`. The environment includes:
69+
70+
- RISC-V cross-compiler (`riscv64-linux-gnu-gcc`)
71+
- QEMU system emulator (`qemu-system-riscv64`)
72+
- All necessary build tools
73+
74+
## Files to Modify
75+
76+
- `kernel/proc.h`
77+
- `kernel/proc.c`
78+
- `kernel/trap.c`
79+
- `kernel/sysfile.c`
80+
- `kernel/syscall.h`
81+
- `kernel/syscall.c`
82+
- `user/user.h`
83+
- `user/usys.pl`
84+
- `Makefile`
85+
- `time.txt` (create)
86+
- `answers-mmap.txt` (create)
87+
88+
## Important Notes
89+
90+
- Do NOT modify any grading scripts (`grade-lab-mmap`, `gradelib.py`) or test files (`user/mmaptest.c`)
91+
- Run `./grade-lab-mmap` to test your solutions
92+
- Run `make qemu` to build and test interactively in the xv6 shell
93+
- Run `usertests -q` to verify you haven't broken other kernel functionality
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
services:
2+
default:
3+
image: sysintelligence/xv6:latest
4+
init: true
5+
command: tail -f /dev/null
6+
working_dir: /root/workspace
7+
network_mode: bridge
8+
cpus: '8.0'
9+
mem_reservation: 8gb

0 commit comments

Comments
 (0)