Movitz: A Common Lisp OS development platform

$Id: movitz.html,v 1.8 2004/07/08 00:12:43 ffjeld Exp $

Files

The latest los0 kernel image and its associated change-log and copying license can be found here. And there is the current technical documentation.

I'd be interested in receiving reports of crashes, and preferably reproducible ones. I know there are issues with non-US AT keyboards. If you have keyboard trouble, you might be able to solve it by saying :mapkey code where code is the ASCII value of the character you want some key to be mapped to.

If the built-in bootloader of los0.img doesn't work (x86 bootloading is a complicated business, apparently), please try loading it with GRUB. I've prepared a GRUB bootloader image that will load a kernel that is appended to it. That is, you can prepare a bootable floppy something like this:

 cat grub-bootloader.img los0.img >/dev/fd0 
The GRUB loader should also work on any other boot-devices it supports, such as a hard-drive, CD-ROM, or USB-pen. You probably need to look up the GRUB documentation for installation instructions. The file los0.img is a multiboot compliant kernel.

Introduction

The Movitz system aspires to be an implementation of ANSI Common Lisp that targets the ubiquitous x86 PC architecture "on the metal". That is, running without any operating system or other form of software environment. Movitz is a development platform for operating system kernels, embedded, and single-purpose applications. There can potentially be several completely different operating systems built using Movitz.

The Movitz system is two things:

The los0 kernel image

The los0 kernel image is the first instance of a Movitz kernel application, or MoKA, and contains the current development version of the Muerte. Los0 is a very minimal MoKA that is used to drive the development of Muerte. This system provides no run-time services beyond a typical lisp REPL listener, which may be used to interactively peek into your system; be it the lisp system per se or the hardware environment. Try apropos, for example. Some REPL top-level commands (mostly debugging-related) are :bt :pop :restart :trace :untrace :error :help :cpu-reset.

Hardware requirements are approximately: A 386 or better CPU with slightly more than 2 MB of RAM (the less you have, the sooner you run out..). The image file can be booted as a floppy image with a PC emulator like Bochs, VMware, or VirtualPC, as an actual floppy on a real machine (just cat the image file to the floppy device), or using GRUB or another Multiboot compliant bootloader.

Status

The compiler

The cross-compiler is fairly complete in terms of the basic mechanisms required by ANSI CL. However there are most likely bugs to be weeded out in the more exotic corners of it, like dynamic control-transfers and the like. In terms of code quality, in my opinion the compiler produces code that is reasonable yet far from "great". It is particularly lacking in the type-inference department. However, the machine-code produced tends to be shorter than any other x86 Common Lisp compilers I've compared it to.

ANSI Common Lisp

ANSI Common Lisp specifies a quite extensive set of functions, macros, and types, and these are not all implemented yet. But many are, and in general my mode of working is to write what to me is "natural" Common Lisp, and if some operator is not implemented in Muerte, I will implement it rather than avoid it. CLOS and quite a bit of MOP is supported in the cross-compiler. At run-time the support is weaker in the sense that there is for example no facilities for defining new classes or methods on-the fly. But the introspection is there, and make-instance and other generic functions will do what they are supposed to do.

Muerte

Aside from the ANSI Common Lisp library, Muerte consists of functions to manipulate the CPU and other hardware. There are primitive accessors like x86:io-port, x86:memref and x86:memref-int, x86:eflags, x86:control-register-hi20/lo12, x86:segment-register, x86:cpu-id, and x86:read-time-stamp-counter. CPU introspection is facilitated with x86:cpu-signature and x86:find-cpu-features. All in all, most basic functionality required to interface any hardware without resorting to inline assembly is either in place or can easily be added.

Garbage Collection

There is now preliminary support for GC in Muerte. This support is two things. Firstly, the object layouts, stack discipline, etc. are such that the system as such is amenable to scanning for GC purposes. Secondly, there are two functions in Muerte that are expectedly useful for implementing GC architectures: The los0 image currently uses these two functions to implement a rather simple Cheney-style stop-and-copy GC architecture. In short, two 256 KB buffers are set up, and the memory allocation primitives are changed to allocate from one of these buffers designated as "newspace". When newspace goes full, the roles of oldspace and newspace are switched, and the live objects in the (newly become) oldspace are evacuated into the (newly become) newspace. This evacuation is performed rather naively, namely by scanning the entire heap, which tends to be somewhere between one and two megabytes in los0. Note that under this simple scheme there is no way for objects to be promoted from the two 256 KB buffers, so you cannot have more than this amount of live, dynamically allocated data. You may trigger the GC process explicitly with (stop-and-copy). Note that there are still rough edges remaining this GC implementation. E.g. there is no support for code-vectors migrating yet, although this will only become an issue when new code-vectors are consed up (i.e. by incremental compilation of some sort).

About OS design in Common Lisp

Unlike the previous sections, this section is more or less loose thoughts about what will be rather than describing an existing system.

Layering

I expect Movitz software modules to be categorized broadly as follows:
Muerte level
This is lower-level functionality that depend solely on Muerte services. The idea at this level is to provide a very thin abstraction over the hardware, just enough to make it convenient to work with in lisp. This means a functional, stateless interface that makes as few assumptions about how it will be used as possible. At this level, "functional" (meaning free of side-effects) applies in a very strong sense, such that e.g. consing must be kept to an absolute minimum, and when consing can occur must be predictable. For example, make no assumptions about whether a hardware device will be used in interrupt-driven or polled mode. The idea is that modules at this level facilitate exploratory programming, and also it can be common to every MoKA.
MoKA level
This software utilizes the Muerte-level modules to build 3D desktop AI-enabled operating systems and the like.
Frode Vatvedt Fjeld