Tags: vkoskiv/minima
Tags
meta: tag version 0.1.0 Big jump in versions, going from 0.0.10 -> 0.1.0, primarily because of how neat my new VFS layer is. I've had a lot of fun mounting floppies and memfs filesystems and testing stuff. Many bugs still remain, but that's to be expected at this stage. :]
kernel: implement 8237 DMA controller support & floppy read command The floppy driver can now read data off a floppy disk on bare metal, which is really exciting! The osdev guide[1] I found did a really good job of filling in the gaps that were left by the official Intel 8272 docs. Plenty of things are still missing. There is no block device layer, and the VFS stuff is still all in the userspace prototype code under fs/ext2. Next steps are to fill in & test more FDC commands, and to put more of the drive-specific parameters in the floppy_drive struct instead of hard-coding them. At the moment, this can only read a full cylinder (2 tracks) off a 1.44MB disk. It doesn't set the datarate for 720k disks correctly yet, or even probe for the media type. I'll also start tracking the recently added VERSION string starting from this commit. While the initial commit of this repository is from 2021, most of my work from 2021-2025 was short experiments, with long idle gaps in between. In other words, I rushed to write code without having the required knowledge to properly debug things :] I'm retroactively assigning the following versions for significant milestones up to this point: - 0.0.1: initial commit + early experiments (a4d4c8a, 2021-2025) - 0.0.2: protected mode, custom bootloader (9752a01, 2024-08-15) - 0.0.3: userspace ext2 filesystem parser (7cfb93c, 2024-11-27) - 0.0.4: page tables + higher-half kernel (6ce3569, 2025-07-22) - 0.0.5: cleaned up old code, PIT & timer support (6e91ed0, 2026-02-05) - 0.0.6: *actually* figure out GDT, dbg cmds (f835fd4, 2026-02-07) - 0.0.7: page frame allocator + kmalloc() (eca927b, 2026-02-15) - 0.0.8: task switching (7f428f2, 2026-02-16) - 0.0.9: user mode & first syscalls (43a5062 & b55f0ed, 2026-02-22) - 0.0.10: floppy driver reads tracks on bare metal (2026-03-06) [1]: http://forum.osdev.org/viewtopic.php?t=13538
kernel: add syscall support Add support for specifying privileges for IRQs, and add a new IRQ 0x80 with user privileges, and implement do_syscall() that handles dispatching. Nothing new about the design, it approximates what most *nix systems do here. Usermode program sets eax to the desired syscall number, sets an optional 0-6 arguments in ebx, ecx, edx, esi, edi and ebp, and invokes interrupt 0x80 to perform the syscall. The return value should be placed in eax, but that part isn't wired up yet. Syscall table has two syscalls that just dump arguments in a kprintf(). Very exciting addition! I can now trivially start adding stuff, probably starting with exit() so I don't have to manually kill usermode tasks. Maybe a sleep() would be useful too? I'd like to come up with syscalls myself instead of copying other systems (linux), though I might end up regretting that. We'll see.
kernel: Implement task switching Buggy and barely functional, but it works. Press '9' to spawn a task, and 'o' to kill the last task created. There is no locking of any kind yet, which is why the background tasks just write directly to the VGA framebuffer for now, bypassing kprintf() machinery. The tasks just flash random ASCII characters at the top of the screen, with increasingly long sleep() calls between iterations multiplied by the X coord. Very basic sleep is also in place. sleep() just sets a deadline and the scheduler checks the deadline has elapsed before resuming a task. Not very accurate, of course, but it's a good start.
kernel: Implement virtual memory mapping and kmalloc()/kfree() I've wanted to get this far for a long time, and now it works. It's probably far from optimal, of course, but I can now kmalloc() and kfree() stuff, meaning I can finally move on to building other interesting things. Few notes: kmalloc() checks if the allocation is <= PAGE_SIZE and calls to pf_alloc() if that is the case. kfree() then checks the pointer it receives to see if it's in the page frame allocator range, that is, (>=PFA_VIRT_OFFSET), and calls pf_free(). The fallback for both is to call into the brand new vmalloc()/vmfree(), which map out virtual address space, and allocate/free page frames as needed. No demand paging of any kind yet, though that shouldn't be too hard to add.
kernel: Finally resolve mystery triple faults
This had me stumped for a long time, until I noticed that it was
faulting on an access to the physical address of the GDT that is loaded
in the bootloader in mbr.S before jumping to stage0 in _start.c. I added
a hacky subroutine that just loads a fixed 'correct' virtual address,
which works as long as I don't change the layout of the bootloader. TODO
is to properly fix that by actually establishing a new GDT and loading
the virtual address of it.
After I fixed that, I noticed that page faults were still triple
faulting, and that as because I moved all of mman.o to the .stage0
section in 1db8d83f0 ("kernel: Actually set up and enable paging"),
which caused that code to move into low memory. I fixed it here by
shuffling mman.c code around, so now the critical stuff that sets up
page tables and the physical memory map lives in _start.o directly (with
careful attention paid to layout to preserve the jump from Cursed
Bootloader).
Now I can remove identity mapping, flush TLB and everything still works!
I added rudimentary command handling with keyboard number keys to
trigger different events, like unmapping identity, dumping the page
directory and keys to cause read/write page faults. Quite happy with
this, I think I can finally move forward to implementing more
interesting things!
kernel: Actually set up and enable paging I think I had this working the last time I tried it, but it relied on multiboot semantics, and I didn't really understand enough yet. Now we map to 0xC0000000 and successfully jump to it. Bochs helped a ton while debugging this :^)
Abandon multiboot in favour of Cursed Bootloader Cursed Bootloader is written in 16-bit real mode x86, is extremely bugprone and lacking in features, but manages to boot this thing on actual hardware. It has the distinct advantage of fitting into a boot sector, which means I can target my ancient hardware. Currently targeting my 486DX2-66 with 32MB of RAM :] The boot sector code uses BIOS interrupts to load the raw elf image into RAM, and then we set up protected mode and jump to and offset in there to get to _start(). This was inspired by the way I saw it being done in SerenityOS back in the day. Needless to say, this is very much not recommended.
PreviousNext