|
Kinetic Operating System
Project Summary
Kinetic is an operating system which is written primarily in Haskell, a purely-functional programming language.
Kinetic is not the first operating system to be developed in Haskell; however, to my knowledge all previous efforts in this direction have had seriously limited scope (mostly academic and proof-of-concept systems). The long-term intention is for Kinetic to be a serious, useful operating system.
Goals and Philosophy
The Haskell type system is far more expressive than systems found in other popular languages. The type system is actually strong enough to type side effecting methods (in some sense). Kinetic is built on the belief that this type system can be used to guide the design of the operating system, especially with respect to the file system and host security.
Methods and techniques
Here are some notes on some of the techniques that I am employing in Kinetic's construction.
Operating System Construction in High Level Languages
As a language, Haskell requires a rather serious runtime environment (one which must provide memory management, support first-class functions, etc). Furthermore, the language is notoriously difficult to parse (it does not have a LALR1 grammar). As such, running Haskell code writes quite a bit of machinery.
Luckily that machinery already exists in several popular Haskell implementations. Unfortunately, all of these implementations are intended to be run on top of an existing operating system (such as Linux, Mac OS X, or Windows).
Rather than forking the source tree for an existing implementation, making changes to the code to allow it to run at a lower level, Kinetic takes a rather hackish approach: use linker magic to identify the POSIX calls used in the Linux build of the GHC runtime, and implement a minimal-functionality facade of these calls in C. In other words, Kinetic includes a stripped-down, stubbed-out POSIX interface -- just enough to support the GHC runtime. This allows us to use the runtime without forking the GHC source tree.
Links
Kinetic is a project by Tim Carstens.
Other people have worked on operating systems in Haskell, including hOp, a project by Jérémy Bobbio, and House, a project at Portland State University.
Project Status
May 7, 2007
More recent information about the project can be found at my blog.
April 2, 2007
At a friend's request, I've written up a short description of the method I use for getting GHC-compiled programs to load with Grub.
In unrelated news, I'm going to be taking a break from active code development to plan out the direction I'm moving in. This does not constitude the end of the project, but rather constitutes a greater commitment to getting the job done properly.
I will make more posts about the design issues as I progress in this effort.
March 13, 2007
I've been busy lately with the end of the academic quarter, so I haven't been able to post updates. Here's where we're at:
- I've started on the GUI in some meaningful sense. The datatypes are coming together, that sort of thing.
- There's a working mouse cursor. Not much, but it's fun to play with.
- I've completely rewritten my bitmap handling routines. They are blazingly fast now, although frankly I don't know what accounts for the performance difference.
Soon I'll be working on putting together some applications. Once I have that out of the way, I figure there'll be enough of a UI that I can begin developing some of the harder-to-debug stuff, like the filesystem and networking interfaces. (Good UI helps debugging!)
Here's an image, complete with the transparent mouse cursor:

February 17, 2007
I fixed the font rendering:

February 17, 2007
I decided to leave behind the Cirrus Logic chipset for the time being, and instead focus on two other tasks:
- Migrating Durand Miller's VBE-Grub patch to Grub 0.97.
- Writing a driver for the VMWare video adapter.
Both went swimmingly, although since I don't have a VBE driver for Kinetic, I cannot be sure that the VBE-Grub patch works (all I do know is that the "VBE Mode Info" flag is now set in the Multiboot header).
With a video adapter in hand, I realized that I needed a new way to write text to the display. While I could have simply used a bitmap font, I thought it would be more fun to use FreeType (a True Type library) -- and that's exactly what I did.
Here is a picture showing basic text rendering in Kinetic. The text looks messy because of my lazy color-depth translation:

February 10, 2007
PCI has been my latest thing.
I begin by writing some code for enumerating the bus -- a traditional start. Official PCI documentation is expensive, but my university library had a readable reference book on the shelves.
While my initial PCI code was written in C (which I find easier to debug using Bochs, owing to the fact that Bochs has support for debugging at the assembler level), I have since re-written the PCI infrastructure in Haskell.
My next ambition is to write a driver for the Cirrus Logic GD5446 chipset, which is what both Bochs and QEMU emulate. I have chosen not to implement a VESA driver at the time being for three reasons:
- Getting VBE information is inconvenient for me; my operating system has no other reason to implement Virtual 8086 support, which is necessary for protected-mode VBE operation.
- Since I use Grub as a boot loader, I should be able to get VBE information from the multiboot header that Grub provides my kernel. Unfortunately, Grub Legacy does not comply with this aspect of the multiboot standard, and during my tests of Grub 2 I saw no reason to conclude that it does, either.
- Besides which, users don't want VESA drivers for their operating system; VESA drivers are notorious for poor performance. So the policy will be to require users to write their own video drivers for the operating system. Since I am the only user, I think this is a fair requirement. Besides, VESA resolutions would be simply unforgivable on my nice monitor.
Here is a picture of Haskell-code enumerating the QEMU PCI bus:

February 3, 2007
I've been working in getting IRQ's handled in Haskell. Naturally, I started with a keyboard driver.
All glory to Jérémy Bobbio for hOp; I used his datatypes, and learned from his notes on getting interrupts to work in hOp.
My interrupt handling is not done in quite the same way as his, although I have tremendous appreciation for the notes he kept on his experience.
When an IRQ fires, a method written in C is invoked as the handler. The method maintains a global array of counters, with one element per interrupt. When an interrupt fires, this method increments the corresponding counter.
A thread in Haskell-land can then periodically check the counters. When it performs its check, it decrements the counter (not to go below zero). In this way the array simply maintains a count of how many exceptions need to be handled.
I do not expect this to perform very well, but it is not yet clear whether or not my doubts are correct (worse yet, it is not clear if my doubts under-estimate the problem!)
Here is a screenshot showing the key strokes as they come in:

January 27, 2007
The system is now in a state where it can run Haskell programs. The runtime's native scheduler is working, which allows us to fork as many threads as we want. Since Haskell is typesafe, we don't need to use IA32 memory protection to keep the threads from messing with one another, or to support data sharing between cooperative threads (so long as the runtime, and the POSIX stubs, don't cause any trouble).
Here is a screenshot showing Kinetic running 5 threads, each of which prints its thread ID. In this image, scheduling is cooperative.

The Haskell code for this output is here:
-- The Haskell kernel entry point
import Control.Concurrent( yield, forkIO )
import IO
thread :: Int -> IO ()
thread n = do putStr ((show n) ++ " ")
hFlush stdout
yield
thread n
launchThreads :: Int -> IO ()
launchThreads 0 = do yield
launchThreads 0
launchThreads n = do forkIO (thread n)
launchThreads (n - 1)
main :: IO ()
main = do putStrLn "Greetings from Ring 0: this is HASKELL"
launchThreads 5
Humble beginnings, indeed.
|