Skip to main content

Testing in QEMU

QEMU is the recommended emulator for testing Portix OS during development due to its speed and debugging capabilities.

Quick Start

Build and run in one command:
python scripts/build.py --mode=raw --run
This will:
  1. Build the kernel and disk image
  2. Launch QEMU with appropriate flags
  3. Show serial output in the console

Manual QEMU Launch

For more control, build first and run manually:
qemu-system-x86_64 \
  -drive format=raw,file=build/portix.img \
  -m 128M \
  -serial stdio \
  -no-reboot \
  -no-shutdown

QEMU Flags Explained

FlagPurpose
-m 128MAllocate 128 MB of RAM
-serial stdioRoute COM1 to console
-no-rebootHalt on kernel panic instead of rebooting
-no-shutdownKeep QEMU open after shutdown
-d int,cpu_resetLog interrupts and CPU resets
-D logfileWrite debug log to file
-sStart GDB server on port 1234
-SPause on startup (wait for GDB)
The -serial stdio flag is important for seeing kernel debug output. Portix writes diagnostic messages to COM1 (0x3F8).

Testing in VirtualBox

VirtualBox provides a more realistic test environment closer to real hardware.

Creating a VM

1

Build VDI image

python scripts/build.py --mode=vdi
2

Create new VM

Open VirtualBox and create a new VM:
  • Name: Portix OS
  • Type: Other
  • Version: Other/Unknown (64-bit)
  • Memory: 128 MB
  • Hard disk: Use existing (select build/dist/portix.vdi)
3

Configure VM

Under Settings:
  • System → Motherboard: Disable EFI, enable I/O APIC
  • System → Processor: 1 CPU
  • Display → Screen: 8 MB video memory
  • Storage: Ensure disk is on IDE controller
4

Boot the VM

Click Start. You should see:
  1. BIOS screen
  2. Bootloader loading stage 2
  3. Transition to Long Mode
  4. Portix UI with tabs

Testing with ISO

Alternatively, use the ISO image:
python scripts/build.py --mode=iso
Then attach build/dist/portix.iso as a CD-ROM in VirtualBox settings.
Make sure “Enable EFI” is disabled in System → Motherboard. Portix uses BIOS boot, not UEFI.

Debugging with GDB

QEMU supports remote debugging via GDB.

Setup

1

Start QEMU with GDB server

qemu-system-x86_64 \
  -drive format=raw,file=build/portix.img \
  -m 128M \
  -s -S
This starts QEMU paused, waiting for GDB on port 1234.
2

Connect GDB

In another terminal:
gdb target/x86_64-portix/release/kernel
(gdb) target remote localhost:1234
(gdb) break rust_main
(gdb) continue
3

Debug the kernel

Use GDB commands:
  • break function_name - Set breakpoint
  • continue - Resume execution
  • step - Step into
  • next - Step over
  • info registers - Show CPU state
  • x/10i $rip - Disassemble at instruction pointer

Useful GDB Commands

# Break at kernel entry
break _start

# Break at IDT initialization
break init_idt

# Examine memory
x/100x 0x100000

# Show backtrace
backtrace

# Print variable
print variable_name
Use layout asm in GDB for a split-screen view with assembly and source.

Serial Port Debugging

Portix sends diagnostic output to COM1 (serial port 0x3F8).

Viewing Serial Output

When running with --run, serial output appears in the console:
python scripts/build.py --mode=raw --run
Output is also saved to build/logs/serial.log:
tail -f build/logs/serial.log

Adding Debug Messages

In your Rust code:
use crate::drivers::serial;

serial::log("TAG", "Debug message");
serial::write_str("Direct output\n");
Or use the serial logger levels:
serial::log_level(Level::Info, "INFO", "System initialized");
serial::log_level(Level::Warn, "MEM", "Low memory");
serial::log_level(Level::Error, "ATA", "Drive not found");

Testing Different Boot Modes

ISO (CD-ROM Boot)

Test El Torito bootable CD:
python scripts/build.py --mode=iso --run
Expected behavior:
  • QEMU boots from CD-ROM
  • El Torito HD emulation loads bootloader
  • System boots identically to disk image

Ventoy Simulation

Test Ventoy compatibility:
python scripts/build.py --mode=ventoy-sim
This creates a larger disk image with the kernel offset by 2048 sectors, simulating how Ventoy loads ISOs.

Performance Testing

Measuring Boot Time

Add timing code to the kernel:
let boot_start = time::pit::ticks();
// ... initialization ...
let boot_end = time::pit::ticks();
let boot_ms = (boot_end - boot_start) * 10; // PIT runs at 100 Hz
serial::log("BOOT", &format!("Completed in {} ms", boot_ms));

Memory Allocation Performance

Test allocator speed:
use crate::mem::allocator::ALLOC_STATS;

let before_allocs = ALLOC_STATS.total_allocs.load(Ordering::Relaxed);
let start = time::pit::ticks();

// Allocate 1000 blocks
for _ in 0..1000 {
    let layout = Layout::from_size_align(4096, 4096).unwrap();
    let ptr = unsafe { alloc::alloc::alloc(layout) };
    unsafe { alloc::alloc::dealloc(ptr, layout) };
}

let end = time::pit::ticks();
let after_allocs = ALLOC_STATS.total_allocs.load(Ordering::Relaxed);
let ops_per_sec = (after_allocs - before_allocs) * 100 / (end - start).max(1);
serial::log("PERF", &format!("{} allocs/sec", ops_per_sec));

Common Issues

  • Check that boot sector ends with 0x55AA
  • Verify stage2 LBA is correct in boot.bin
  • Try -boot c instead of auto-detection
  • Enable interrupt logging: -d int -D qemu.log
  • Check IDT initialization in arch/idt.rs
  • Verify GDT is set up correctly
  • Check for stack overflow
  • Disable EFI in VM settings
  • Verify video memory is at least 8 MB
  • Check that framebuffer is initialized
  • Try with ‘VBoxVGA’ graphics controller
  • Verify COM1 initialization: drivers::serial::init()
  • Check that -serial stdio is passed to QEMU
  • Look for output in build/logs/serial.log
  • Check page tables are identity-mapped
  • Verify kernel is loaded at correct address
  • Use GDB to examine CR2 (fault address)
info registers cr2

Testing Checklist

Before submitting changes, verify:
  • Kernel builds without warnings
  • Boots successfully in QEMU
  • Boots successfully in VirtualBox
  • Serial output shows no errors
  • All tabs are accessible (F1-F5)
  • Keyboard input works
  • Mouse cursor moves
  • Terminal accepts commands
  • File explorer shows FAT32 contents
  • No memory leaks (check allocator stats)
  • No triple faults or panics

Next Steps

Contributing

Ready to contribute? Read the guidelines

Architecture

Understand the system architecture

Build docs developers (and LLMs) love