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 binary
  • build/microkernel.iso - Bootable ISO image
  • serial.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:

  1. Press Ctrl + a (release keys)
  2. 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
};