Commit Graph

6 Commits

Author SHA1 Message Date
AI
0c5aa72fd3 Add VFS subsystem and initrd filesystem driver (AI)
VFS subsystem (vfs.c/h):
- Mount table with up to 16 mount points, longest-prefix path matching.
- File descriptor table (256 entries, fds 0-2 reserved for std streams).
- Path resolution walks mount table then delegates to filesystem's
  finddir() for each path component.
- Operations: open, close, read, write, seek, readdir, stat.
- Each filesystem driver provides a vfs_fs_ops_t with callbacks.

Initrd filesystem driver (initrd_fs.c/h):
- Read-only VFS driver backed by the CPIO ramdisk.
- Mounted at '/initrd' during boot.
- Zero-copy reads: file data points directly into the CPIO archive
  memory, no allocation or copying needed.
- Supports readdir (flat iteration) and finddir (name lookup).

Bug fix: resolve_path was overwriting file-specific fs_data (set by
finddir, e.g. pointer to CPIO file data) with the mount's fs_data
(NULL). Fixed to preserve fs_data from finddir.

Verified in QEMU: kernel reads /initrd/README via VFS and prints its
contents. Ring 3 user process continues to work.
2026-02-23 12:23:32 +00:00
AI
3d5fb4c267 Add CPIO initial ramdisk with build infrastructure and parser (AI)
Build system changes:
- scripts/gen_initrd.sh packs all files from apps/ into a newc-format
  CPIO archive at build/isodir/boot/initrd.cpio.
- CMakeLists.txt adds 'initrd' target as ISO dependency. GRUB loads the
  archive as a Multiboot2 module via 'module2 /boot/initrd.cpio'.
- apps/README added as placeholder file for initial ramdisk content.

Kernel changes:
- kernel.c scans Multiboot2 tags for MULTIBOOT_TAG_TYPE_MODULE to find
  the initrd's physical address range, then passes it to cpio_init().
- cpio.c/h implements a parser for the SVR4/newc CPIO format:
  - cpio_init(): lists archive contents on startup
  - cpio_find(): look up a file by name (handles ./ prefix)
  - cpio_next(): iterate through all entries
  - cpio_count(): count files in archive
- The initrd lives in identity-mapped physical memory, so no additional
  mapping is needed to access it.

Verified in QEMU: GRUB loads the module at 0x0014A000, CPIO parser
finds the README file (38 bytes). All existing functionality (Ring 3
processes, syscalls) continues to work.
2026-02-23 12:16:24 +00:00
AI
71e2ae482a Implement Ring 3 process subsystem with syscalls and context switching (AI)
Add complete user-mode process support:

- TSS (tss.c/h): Task State Segment for Ring 3->0 transitions, installed
  as GDT entry 5 (selector 0x28). ESP0 updated per-process for kernel
  stack switching.

- Process management (process.c/h): Process table with up to 64 processes.
  process_create() clones kernel page directory, maps user code at
  0x08048000 and user stack at 0xBFFFF000, copies flat binary code.
  Round-robin scheduler via schedule_tick() modifies the interrupt frame
  in-place for zero-copy context switching.

- System calls (syscall.c/h): INT 0x80 dispatcher with 8 syscalls:
  SYS_EXIT, SYS_WRITE (to debug port + VGA), SYS_READ, SYS_FORK,
  SYS_GETPID, SYS_YIELD, SYS_WAITPID, SYS_EXEC. IDT gate at 0x80
  uses DPL=3 (flags 0xEE) so user code can invoke it.

- Assembly stubs (interrupts.S): isr128 for INT 0x80, tss_flush for
  loading the Task Register, enter_usermode for initial iret to Ring 3.

- Paging extensions (paging.c/h): paging_clone_directory() to create
  per-process page directories, paging_map_page_in() for mapping into
  non-active directories, paging_switch_directory() for CR3 switching.

- GDT expanded from 5 to 6 entries to accommodate TSS descriptor.
  gdt_set_gate() exposed in header for TSS initialization.

- ISR handler routes timer IRQ (32) to scheduler and INT 0x80 to
  syscall dispatcher. Exception handler now prints EIP/CS/ERR for
  debugging.

- Kernel boots a test user program that writes 'Hello from Ring 3!'
  via SYS_WRITE and exits with code 42 via SYS_EXIT. Verified working
  in QEMU.

Context switching approach: Timer/syscall interrupts save all registers
via the ISR stub. schedule_tick() copies saved_regs between PCBs and
overwrites the interrupt frame, so the existing iret restores the next
process's state without separate switch assembly.
2026-02-23 12:10:46 +00:00
AI
f63cd9eb3f Implement kernel memory allocator (kmalloc/kfree) and freestanding string library (AI)
- Added first-fit free-list allocator with block splitting and coalescing.
  Provides kmalloc(), kfree(), and kcalloc() for kernel-space dynamic memory.
- Each block carries an inline header with a magic value (0xCAFEBABE) for
  heap corruption detection, plus double-free checking.
- Memory is obtained from the paging subsystem in 4 KiB page increments.
  All allocations are 8-byte aligned with a 16-byte minimum block size.
- Created freestanding string.c with memset, memcpy, memmove, memcmp,
  strlen, strcmp, strncmp, strcpy, strncpy — replacing the unavailable
  libc implementations.
- Added documentation in docs/kmalloc.md.

Tested: kmalloc(64) returns 0xD0001010 (in kernel heap) and kfree succeeds.
Works with both 4 MiB and 128 MiB RAM.
2026-02-23 11:06:52 +00:00
AI
fb61ab7c15 Implement paging subsystem with identity mapping and kernel heap (AI)
- Created two-level x86 paging (page directory + page tables) with 4 KiB pages.
- Identity maps all detected physical memory in two phases:
  1) Static: first 16 MiB using 4 BSS-allocated page tables (avoids
     chicken-and-egg with PMM bitmap in BSS).
  2) Dynamic: memory above 16 MiB using PMM-allocated page tables,
     created before paging is enabled so physical addresses still work.
- Provides kernel heap at 0xD0000000–0xF0000000 for virtual page allocation.
- API: paging_map_page, paging_unmap_page, paging_alloc_page, paging_free_page,
  paging_get_physical.
- Added pmm_get_memory_size() to expose detected RAM for paging init.
- Kernel tests paging by allocating a virtual page, writing 0xDEADBEEF, and
  reading it back, then freeing it.
- Added documentation in docs/paging.md.

Tested: boots and passes paging test with both 4 MiB and 128 MiB RAM in QEMU.
2026-02-23 11:03:27 +00:00
AI
f2e7d6c5d7 Fix PMM: switch to Multiboot2 boot protocol and add documentation (AI)
- Changed grub.cfg from 'multiboot' to 'multiboot2' command. The PMM parses
  Multiboot2 tag structures, but GRUB was booting with Multiboot1 protocol,
  causing the memory map parsing to silently fail (all memory stayed marked
  as used, leading to OOM on every allocation).
- Fixed BITMAP_SIZE calculation to properly round up instead of truncating,
  ensuring the last few pages of the address space are covered.
- Fixed sign comparison warning in bitmap init loop.
- Added debug output to PMM init (mem_upper, region count) for diagnostics.
- Removed stale Multiboot1 magic constant and (void)addr cast from kernel.c.
- Added documentation for the interrupt subsystem and PMM in docs/.
- Checked off 'Implement a PIC handler' and 'Create a physical memory
  allocator' in the task list.

Tested: kernel boots in QEMU with both 4MB and 128MB RAM, PMM correctly
allocates from NORMAL zone (0x01000000) and DMA zone (0x00001000).
2026-02-23 10:57:56 +00:00