Skip to content

irqlevel/nos

Repository files navigation

nos

A hobby x86-64 operating system kernel written in C++20 and NASM. Code is partially written by AI models (Claude, GPT) with human control over architecture decisions, testing, and code review. Tested primarily in QEMU/KVM environments, including Google Cloud and Yandex Cloud VMs (MBR-based disk image, virtio devices). Real hardware support has not been tested.

Features

  • SMP — up to 8 CPUs with INIT/SIPI AP bootstrap
  • Preemptive multitasking — per-CPU task queues, round-robin scheduling, load-balanced task placement
  • Virtual memory — 4-level paging (4 KB pages), high-half kernel at 0xFFFF800001000000, TLB shootdown across CPUs via IPI
  • Page allocator — fixed-size block allocator (1–128 contiguous pages), pool allocator (32 B – 2 KB), new/delete support
  • ACPI — RSDP/RSDT/MADT parsing for LAPIC/IOAPIC discovery and IRQ→GSI routing
  • Interrupts — IDT with exception handlers, IOAPIC routing (edge + level-triggered), LAPIC IPI, PIC (remapped then disabled)
  • Drivers — serial (COM1), VGA text mode, PIT (10 ms tick, SeqLock-protected counters), RTC (CMOS wall clock), PS/2 keyboard (8042), PCI bus scan, LAPIC, IOAPIC, virtio-blk, virtio-net, virtio-scsi, virtio-rng (legacy + modern virtio-pci transport)
  • Block I/O — asynchronous, interrupt-driven block request queue with DMA slot pool, BlockRequest submission with WaitGroup completion, direct DMA from caller buffers (page-aligned), virtqueue locking (RawSpinLock) for safe interrupt/task concurrency, early-boot polling fallback, SoftIrq-based retry for ring-full conditions, block device abstraction, MBR partition discovery
  • Networking — virtio-net driver with asynchronous interrupt-driven TX/RX, software frame queues (256-entry TX/RX) in NetDevice base class, reference-counted NetFrame descriptors for zero-copy DMA, TX slot pool with bitmask allocation, SoftIrq-based TX retry and RX processing, IP routing (subnet mask + gateway from DHCP, off-subnet traffic forwarded to gateway), ARP (cache, request, reply, dump), IPv4/UDP transmit, ICMP echo (ping reply + send, per-type statistics), DHCP client with lease renewal (sets IP, subnet mask, gateway, DNS server), DNS resolver with 32-entry cache (A-record queries, name compression, DHCP-provided server), TCP (connection state machine, 3-way handshake, sequence/ack tracking, retransmission timers, MSS negotiation, send/receive ring buffers, graceful close with FIN exchange, RST handling, ephemeral port allocation, granular locking: Mutex for ports, RawSpinLock for pool and per-connection state, SoftIrq-driven timer processing), HTTP client (URL parsing, DNS resolution, TCP connection, request/response, redirect following for 301/302/303/307/308 with loop limit, wget shell command), UDP remote shell (execute kernel commands over the network), network device abstraction with per-protocol packet counters, MacAddress/IpAddress structs (IPv6-ready tagged union)
  • Filesystem — VFS layer with mount points and path resolution, ramfs (in-memory), nanofs (on-disk filesystem with 4 KB blocks, superblock with UUID, inode/data bitmaps, CRC32 checksums for superblock/inodes/data, file and recursive directory deletion, persistent across remount)
  • EntropyEntropySource interface, EntropySourceTable registry, virtio-rng hardware random number generator
  • Power management — ACPI S5 shutdown, keyboard controller reset/reboot
  • Interactive shell — trace output suppressed during shell session (dmesg only), restored on shutdown; commands: ps, cpu, bt <pid>, dmesg [filter], uptime, date, memusage, pci, disks, diskread, diskwrite, irqstat, net, arp, icmpstat, tcpstat, udpsend, ping, nslookup, dnsflush, dhcp, wget, random, format, mount, umount, ls, cat, write, mkdir, touch, del, panic, version, cls, help, poweroff, reboot
  • Timekeeping — TSC calibration via PIT channel 2 (multi-round median), KVM paravirt clock (kvmclock) for accurate VM time, RTC wall clock, layered clock source selection (kvmclock → calibrated TSC → PIT fallback), GetBootTime() / GetWallTimeSecs() API
  • Kernel infrastructure — spinlocks, mutexes, SeqLock (single-writer/multi-reader), atomics, wait groups, SoftIrq deferred processing, IPI tasks, timers, watchdog, stack traces with symbol resolution, dmesg ring buffer (512 KB, 2048 messages), panic handler with backtrace and CPU/task context, per-device interrupt statistics, AP startup diagnostics, virtual-to-physical address translation (4-level page table walk), byte-order helpers (Htons/Htonl/Ntohs/Ntohl)
  • Optimized stdlibMemSet, MemCpy, MemCmp, StrLen, StrCmp, StrStr implemented in x86-64 assembly using rep stosq/rep movsq/repe cmpsb/repne scasb
  • Boot tests — allocator, btree, ring buffer, stack trace, multitasking, contiguous page alloc (up to 128 pages), parsing helpers, block device table, memset, memcpy, memcmp, strlen, strcmp, strstr

Build

Native (requires clang, nasm, ld, grub-mkrescue):

make

Via Docker (works on macOS / Apple Silicon):

./scripts/build-iso-docker.sh

This produces nos.iso and bin/kernel64.elf (for GDB symbols).

Build a bootable qcow2 disk image (MBR, 2 partitions):

./scripts/build-disk.sh

This produces nos.qcow2 (1 GB, MBR, virtio-blk compatible, suitable for KVM-based public clouds including Google Cloud Compute Engine).

Run

With KVM (Linux):

qemu-system-x86_64 -enable-kvm -smp 8 -cdrom nos.iso -serial file:nos.log \
    -device isa-debug-exit,iobase=0xf4,iosize=0x04

Without KVM (macOS with TCG):

qemu-system-x86_64 -smp 2 -cdrom nos.iso -serial file:nos.log -s -vga std

Boot from disk image (with virtio-blk):

./scripts/qemu-disk.sh

Deploy to Google Cloud Compute Engine (select Skip OS adaptation when importing the image — the kernel already has the necessary drivers and no guest agent):

# Upload disk image to a GCS bucket
gcloud storage cp nos.qcow2 gs://YOUR_BUCKET/nos.qcow2

# Create a Compute Engine image from the disk (skip OS adaptation)
gcloud compute images create nos-image \
    --source-uri=gs://YOUR_BUCKET/nos.qcow2

# Launch a VM (serial console recommended)
gcloud compute instances create nos-vm \
    --image=nos-image \
    --machine-type=e2-small \
    --metadata=serial-port-enable=true

# Connect via serial console
gcloud compute connect-to-serial-port nos-vm

Debug

Start QEMU with -s (GDB server on port 1234), then:

gdb -ex "symbol-file bin/kernel64.elf" \
    -ex "set architecture i386:x86-64" \
    -ex "target remote :1234"

Kernel parameters

Pass via GRUB command line (edit build/grub.cfg):

  • smp=off — disable SMP, run on BSP only
  • console=serial — direct shell output to serial port only
  • console=vga — direct shell output to VGA only
  • dhcp=auto — start DHCP on eth0 automatically at boot
  • dhcp=off — disable DHCP entirely (even via shell command)
  • dhcp=on — enable DHCP only via shell command (default)
  • dns=on — enable DNS resolver (uses DHCP-provided DNS server; requires dhcp=auto)
  • udpshell=PORT — start UDP remote shell on the given port (e.g. udpshell=9000)

UDP remote shell

When udpshell=PORT is set, the kernel listens for commands on that UDP port. A lightweight protocol header (16 bytes: magic, sequence number, chunk index, flags, payload length) frames every packet, enabling the client to validate replies, reassemble multi-chunk responses in order, and detect the end of a response without relying on timeouts.

Connect with the included Python client:

python3 scripts/udpsh.py <vm-ip> [port] [timeout]
  • Default port is 9000, default timeout is 30 seconds (long enough for blocking commands like ping).
  • On protocol errors or timeouts, the client reconnects automatically and resets state.
  • All shell commands work over the UDP session (including blocking ones like ping).
  • Warning: the UDP shell has no authentication — anyone who can reach the port has full kernel shell access. Use only for testing or behind a firewall.

Shell commands

Command Description
cls Clear screen
cpu Dump CPU state
dmesg [filter] Dump kernel log (optional substring filter)
uptime Show uptime
date Show wall clock date and time (RTC + boot time)
ps Show tasks
bt <pid> Dump stack trace of a task (uses IPI for remote CPUs)
watchdog Show watchdog stats
memusage Show memory usage
pci Show PCI devices
disks List block devices
diskread <disk> <sector> Read and hex-dump a sector
diskwrite <disk> <sector> <hex> Write hex data to a sector
irqstat Show per-device interrupt counters
help List commands
net List network devices and per-protocol stats
arp Show ARP table
icmpstat Show ICMP statistics
tcpstat Show TCP connections and statistics
wget <url> Fetch a URL via HTTP GET (follows redirects)
udpsend <ip> <port> <msg> Send a UDP packet
ping <ip|hostname> Send 5 ICMP echo requests with RTT (resolves hostnames via DNS)
nslookup <hostname> Resolve hostname to IP via DNS
dnsflush Flush DNS cache
dhcp [dev] Obtain IP address via DHCP
random [len] Get random bytes as hex string
format nanofs <disk> Format disk with nanofs
mount ramfs <path> Mount a ramfs at path
mount nanofs <disk> <path> Mount nanofs from disk at path
umount <path> Unmount filesystem
mounts List mount points
ls <path> List directory contents
cat <path> Show file contents
write <path> <text> Write text to file (creates if needed)
mkdir <path> Create directory
touch <path> Create empty file
del <path> Remove file or directory
panic [type] Trigger kernel panic (direct, pagefault, divzero, ud)
version Show kernel version
poweroff / shutdown Power off (ACPI S5)
reboot Reset system (keyboard controller)

Project layout

boot/       Multiboot2 entry, 32→64-bit transition, AP trampoline
kernel/     Core: scheduling, tasks, interrupts, SoftIrq, shell, timers, timekeeping (TSC, kvmclock), locks, panic, symbol table
drivers/    Hardware: serial, VGA, PIT, RTC, 8042, PCI, PIC, LAPIC, IOAPIC, ACPI, virtio-blk, virtio-net, virtio-scsi, virtio-rng
block/      Block I/O: device abstraction, async request queue, MBR partition discovery
net/        Networking: device abstraction, protocol headers, ARP, ICMP, DHCP, DNS, TCP, HTTP client, UDP shell
fs/         Filesystem: VFS, ramfs, nanofs, block I/O helpers
mm/         Memory: page tables (4-level walk, VirtToPhys), page allocator, pool allocator
lib/        Utilities: list, vector, btree, ring buffer, bitmap, CRC32 checksum, stdlib
build/      Linker script, GRUB configs
scripts/    Build, run, debug, and GDB helpers