A small Unix-like kernel built from scratch for x86_64, implementing core OS subsystems from bootloader through to a working shell with file I/O, multiprocessing, pipes, and demand paging.
| Lab | Feature | Status |
|---|---|---|
| 1 | File descriptors — open, read, write, close, dup, fstat, readdir |
Done |
| 2 | Multiprocessing — fork, wait, exit with process trees |
Done |
| 3 | Pipes — pipe, buffered IPC between processes |
Done |
| 4 | Demand paging — sbrk, heap growth, stack growth, malloc/free |
Done |
| 5 | Copy-on-write fork | In progress |
arch/x86_64/ # Machine-dependent: bootloader, GDT/IDT/paging,
# context switch (swtch.S), APIC/PIC drivers
kernel/ # Portable kernel: proc, thread, sched, syscall,
# VM (mm/), VFS + sfs filesystem (fs/), pipes, drivers
include/kernel/ # Kernel-internal headers
include/lib/ # Shared headers (syscall numbers, userspace stubs)
lib/ # Minimal libc shared by kernel and userspace
user/ # Userspace programs + lab test suites (lab1–lab5)
tools/ # mkfs: host tool that builds fs.img
CacheSizeTest/ # Cache hierarchy benchmarking tool
TLBSizeTest/ # TLB size benchmarking tool
Key design points:
- Many subsystems have two halves — policy in
kernel/, mechanism inarch/x86_64/kernel/. When modifying thread/VM/trap behavior, check both sides. - Syscall dispatch lives in
kernel/syscall.c, indexed by numbers ininclude/lib/syscall-num.h. User pointers are validated viavalidate_ptr/validate_strbefore the kernel touches them. - The VFS layer (
kernel/fs/fs.c) usesfile_operationsvtables so pipes, console, and thesfsfilesystem all plug in uniformly throughstruct file.
arch/x86_64/boot/bootasm.S + bootmain.c (real-mode → long mode, loads kernel)
└─ arch/x86_64/kernel/kstart.S / entry.S
└─ kernel/main.c:main() (VM, threading, syscalls, console)
└─ kernel_init() (block device, filesystem, SMP)
└─ proc_spawn(init) → user/init.c → sh prompt
Building requires Linux tooling (gcc, binutils, qemu-system-x86_64, python3). On Windows use Docker or WSL — PowerShell alone cannot build this project.
docker build -t osv .
docker run --rm -it osv # builds with `make` by defaultmake # build kernel ELF + disk images (build/osv.img, build/fs.img)
make qemu # boot in QEMU, serial console in terminal
make qemu-graphic # boot with QEMU graphical window
make qemu-low-mem # boot with 4 MB RAM (tests paging edge cases)
make qemu-gdb # boot paused, then `make gdb` in a second terminal to attach
make clean # remove build/
CPUS=4 make qemu # boot with 4 virtual CPUs (exercises SMP paths)CFLAGS includes -Wall -Werror — any compiler warning fails the build.
User-space tests live under user/lab1–user/lab5. Each is built into build/user/<lab>/<name> and baked into fs.img.
Single test — boot with make qemu, wait for the $ prompt, then type the binary name:
$ fork-tree
Full lab suite — runs QEMU headlessly and greps serial output for pass/fail:
python3 test.py 2 # run all lab 2 tests
python3 test.py 4 # run all lab 4 tests| Directory | What it measures |
|---|---|
CacheSizeTest/ |
Memory access latency vs. array size to estimate cache hierarchy sizes |
TLBSizeTest/ |
Memory access latency vs. number of pages touched to estimate TLB size |
Run inside Linux/WSL (not QEMU) — see CacheSizeTest/run_cache.sh and TLBSizeTest/run_tlb.sh.
Detailed per-lab design notes are in docs/:
docs/design-lab2-multiprocessing.md— fork / wait / exitdocs/design-lab3-pipes.md— pipes / IPC