Building and Running
Everything you need to compile and launch the kernel.
Prerequisites
- GCC (native x86_64 or cross-compiler)
- GNU Make
- GRUB tools (grub-mkrescue, xorriso)
- QEMU (qemu-system-x86_64)
Build Instructions
make clean # Clean build
make # Build kernel
make iso # Create bootable ISO
make qemu # Run in QEMU (graphical)
make run # Run headless with serial output
make gdb # Debug with GDB
Output Files
build/kernel.elf- Kernel binarybuild/microkernel.iso- Bootable ISO imageserial.log- Serial output capture (when running with -serial file:serial.log)
WSL Setup (Windows)
If you are using Windows Subsystem for Linux (WSL), the easiest way is to use wsl directly:
# 1. Build the ISO
wsl make iso
# 2. Run in Terminal (Headless)
wsl make run-headless
# 3. Run with GUI (Requires X Server like VcXsrv installed on Windows)
wsl make run
How to Exit QEMU (Headless)
When running in headless mode, QEMU takes over your terminal. To exit:
- Press Ctrl + a (release keys)
- Press x
Automated Testing (Capture Output)
To run the kernel for a fixed time and save the output to a file:
wsl bash -c "timeout 15 qemu-system-x86_64 -cdrom build/microkernel.iso -serial file:serial.log -display none; cat serial.log"
Note: The "terminating on signal 15" message is normal. It means the timeout command successfully stopped QEMU after the specified duration.
Troubleshooting
Problem: make: command not found
Solution: Ensure you are running inside WSL or have Make installed.
Problem: QEMU not found
Solution: Install in WSL: sudo apt-get install qemu-system-x86
Problem: "GTK cannot open display"
Solution: You are trying to run graphical QEMU from a headless WSL instance. Use the headless command (serial output) or install a generic X server for Windows (like VcXsrv).
Shell Usage
Interactive Shell
The shell starts automatically and supports these commands:
shell> help # Show available commands
shell> server # Launch IPC server
shell> client # Launch IPC client
shell> keyboard_test # Test keyboard input
shell> exit # Exit shell
IPC Demo
The kernel automatically launches the IPC server and client at boot. You'll see:
[client] start
[server] got ping 1
[client] got pong 1
...
Kernel Components
kernel/
├── main.c - Kernel entry point and initialization
├── scheduler.c - Cooperative task scheduler
├── memory.c - Physical memory manager
├── syscall.c - System call dispatcher
├── ipc.c - Mailbox-based messaging
├── interrupts.c - IDT and interrupt handlers
├── keyboard.c - PS/2 keyboard driver
├── serial.c - Serial I/O functions
└── panic.c - Kernel panic handler
arch/x86_64/
├── boot.S - Multiboot2 header and bootstrap
├── gdt.S - GDT and TSS setup
├── context_switch.S - Task context switching
├── syscall_entry.S - System call entry point
├── interrupt.S - Interrupt stub handlers
├── user_*.S - User-space programs
└── userprog.S - User-mode entry helpers
include/
├── scheduler.h - Task management API
├── memory.h - Memory allocator API
├── syscall.h - Syscall numbers and interface
├── ipc.h - IPC function declarations
├── interrupts.h - Interrupt setup API
└── keyboard.h - Keyboard driver API
Memory Map
0x0000000000000000 - 0x0000000004000000 : Identity-mapped (64 MiB)
0x0000000000100000 - kernel .text/.data : Kernel code and data
0x00000000000B8000 : VGA text buffer
Higher half : User stacks and heaps
Task Scheduler
- Cooperative multitasking with explicit yield points
- Task creation with dynamic stack allocation
- Blocking/unblocking for synchronization
- Preference hints for responsive IPC
System Call Mechanism
- Uses x86_64 SYSCALL instruction for fast transitions
- Preserves user context across kernel entry
- Per-task kernel stacks for isolation
- Return values in RAX register
IPC Design
- Single-slot mailbox per task
- Synchronous send/receive primitives
- Sender blocks if receiver mailbox full
- Receiver blocks if no message available
- Automatic task wakeup on message delivery
Technical Details
Compiler Flags
-ffreestanding -O2 -Wall -Wextra -m64
-fno-stack-protector -fno-pic -fno-pie
-mno-red-zone -mno-mmx -mno-sse -mno-avx
-mno-80387 -msoft-float
Syscall Convention
- RAX: syscall number
- RDI: arg0
- RSI: arg1
- Return: RAX
Task Context Structure
struct context_t {
uint64_t r15, r14, r13, r12, rbx, rbp, rsp;
void* rip;
uint64_t rdi, rsi;
uint64_t first; // First-time flag
};