I am shipping soon!
I improved some messages, so that the kernel looks more polished to new users.
I released a new version, which is what I am shipping soon (if nothing goes wrong). It includes an interactive CLI, which was made possible with the new keyboard driver. I improved the scrolling performance a lot, which I personally really enjoy! Finally, I fixed a bug when printing numbers, so the printed memory map now has (mostly) correct addresses.
The kernel is now interactive!
I added a demo CLI (you can see it on the screenshot) where you can exit properly, run tests or view the old demo!
I had to fix some bugs with the keyboard driver, but now I think it works okay enough that the CLI is stable (previously, it kept parts from the old buffer when reading it again)
I want to add more features to the CLI, such as setting the log level. As you can see on the screenshot, the debug output disturbs the CLI.
I FINALLY get interrupts from the keyboard!
The problem was, that I mistook the IRQ number for the interrupt vector when calling my own function!
Now I can start expanding my keyboard driver. Currently, it already prints the pressed keys to the screen, as you can see on the screen shot.
After I finished the interrupt stuff, I can focus on improving the TTY in other areas, like the performance. I am using now memset() and memcpy() functions when scrolling the frame buffer, which itself is not an improvement: I optimized the two functions to use copy 8-byte blocks ad uint64_t instead of each byte individually, which made a significant difference. Scrolling with KVM acceleration is now almost instant on my PC, and without it is as fast as it was before with acceleration.
I want to improve the TTY with things like buffering, which should improve the performance even more.
When I have a solid TTY, I can rework the demo and ship again.
I am still far away from getting interrupts from the keyboard, but I am still learning much and making progress on other parts of the kernel!
I added support for mapping pages manually, which means that I can program now the APICs! While debugging this, I also improved my Page Fault handler, which you can see on the screenshot.
The APIC driver should now be able to configure IRQs on the I/O APIC to get delivered to the local APIC, but I can’t test it as I still don’t know why I can’t get interrupts from the keyboard :-(
I am still working on getting interrupts from the keyboard, which is my main goal before the next ship. I currently suspect that my PS/2 driver is broken.
I prefer this devlog format, so I will stick to it.
As I explained earlier, I need to configure the APIC to get interrupts. I think I only need the I/O APIC and not the local APIC, if I understand the limine documentation correctly. But when trying to access it’s registers, I got a page fault. It seems like I need to manually map the registers to virtual memory, which brings me to…
I need to do what I already feared when starting to write the PMM, manually editing page tables. I am working on a function which will map pages (Including the I/O APIC registers) to virtual addresses. For this, I need to walk the complete paging structure:
PML4 (from cr3) -> PDPT -> PD -> PT
I can already parse it until I have the PT’s address, but when accessing the PT I get a page fault, as you can see on the screenshot.
I just wanted to post this update so that the next devlog is not too long. I will continue to work on the PMM, until I can access the I/O APIC’s registers.
I did not post for some time, so this devlog will be relatively long.
I wanted to get the PIC to work, but as I had no idea why it didn’t work I thought that the PS/2 Controller might not be in a functioning state. So, I wrote a PS/2 driver which initializes the Controller, and also detects connected devices!
After that, I finally found out that limine already sets up the APIC, which means that the PIC is no longer functional. So I decided that my next big goal is to learn how ACPI and APIC work…
As you can see on the screenshots, I started working on an ACPI driver, which is already able to find tables like the MADT, which I need to find the APICs
This does not have anything to do with the progress of my project, but I learned how to use UEFI in QEMU, so that I can debug my ACPI driver better.
I will have to learn now how APICs work, so that I can get interrupts from the keyboard. Then, I can improve the keyboard driver, which should make the kernel way more fun to use!
I have finished implementing the memory manager!
free() will now call pmm_free() to free unused pages. At the moment it does not make any difference, but if I want to extend the PMM it will have saved me the work.
Also, I split the demo from the main function so that it is more maintainable.
Log messages with the log level DEBUG will now only appear in debug builds. This made the output much more readable, as you can see in the screenshots.
I have added a simple memory manager to my kernel! It was only possible with the help from kmos, a project I found while voting. I didn’t know how to start writing a physical memory manager, but in that kernel I found that I have to use the limine HHDM request to have simple access to physical addresses.
Then I could implement the rest completely myself.
The last thing left to do until I’m satisfied with my memory manager, is to free pages in the PMM after using free()
Now I am actually shipping! I had a bug that occured only when compiling with optimization level 2 or higher (which I used in the release CI). As I am working now on a Debian machine, I made it also compile on Debian stable by not requiring a new objcopy version.
On the screenshot you can see the bug.
I will ship the kernel now for the first time! I added a libk (like a libc but for the kernel) and implemented some cool functions like printf(), which I could use for cool error messages with hex numbers like the one on the screenshot.
I sadly don’t have much to say, because I did make almost no progress. I am trying to use the PIC to get interrupts from the keyboard, but it doesn’t work for some reason. Maybe I will try to use APIC instead, but it’s more complicated.
I finally figured out how I can integrate the external library! Now I can skip instructions when an interrupt is executed and continue execution
I just wanted to implement an interrupt handler specific to divide error, but it turned out to be way more difficult than I thought!
To continue execution after the interrupt, I have to manually increment the instruction pointer manually. But to know by which amount, I need to now the size of the whole instruction. To find it I wanted to use a library called Zydis, but I could not get it to compile, because clang generates calls to memset() and memcpy(). As I can not link with the standard library, I will have to find a solution tomorrow.
I added a demo to show the features of my kernel. The kernel is almost ready for the first ship!
After giving up on the memory manager, I added logging and very basic interrupt handling. I will ship the project when I have a demo of all the features and published ISOs.
As I have now a very basic way to interact with the kernel, I will try to move on to more complex topics. At the moment I try to understand how memory management exactly works (specifically, how to write a physical memory manager), but it’s difficult to find information about it. Until now, I have requested a memory map from limine and can display it in a table.
I implemented enter key press detection before doing anything else, so that I can interact somehow with the kernel. I did it with IO Ports instead of interrupts for now (because I don’t know how to set up interrupts), which means it only works with PS/2 Keyboards. Luckily, qemu shows the keyboard as a PS/2 Keyboard.
I have added a normal font which makes things way simpler. I also improved the general tty: scrolling, new lines and tabs work now!