About the TUD:OS Demo CD Features of the TUD:OS Demo CD TUD:OS Screenshots Download the TUD:OS Demo CD Contact the TU Dresden OS Group
About the TUD:OS Demo CD
TUD:OS Screenshots
Download the TUD:OS Demo CD
Contact the TU Dresden OS Group
Driver Reuse In The L4 Environment

Driver Reuse In The L4 Environment

Thomas Friebel, Christian Helmuth

The Dream

The microkernel approach relocates all functionality from privileged (kernel) to unprivileged (user) CPU mode that need not to stay in the kernel for strong security or performance reasons. This paradigm effectively revokes unlimited access to the system's resources from components that do not neccessarily need this access.

One category of components considered are device drivers which account for the major portion of the complexity of modern operating systems. From security-related point of view, device drivers are considered less trustworthy than core OS components because they are provided by third-party (hardware) vendors. Against this background, device drivers reside in distinct protection domains above the microkernel and are constrained to use well-defined interfaces.

The resulting advantages are:

Controlled Interference Of Drivers

The separation into protection domains (i.e. address spaces) forces device drivers to use microkernel mechanisms for interaction with other system components like file systems. This effectively prevents malicious or defective drivers from accessing arbitrary memory locations. Leakage or integrity violations of information can be limited to the specific driver's domain. Also crashes of one driver can be restricted and do not neccessarily interfere with other system components.

Ease Of Debugging

As drivers run as ordinary tasks on-top of the microkernel, debugging becomes as easy as debugging normal programs.

The open question is: How do we get device drivers for all the fancy devices around? This demonstration details our approach to reuse existing device drivers.


DSweeper is a simple application for overwriting the data on your hard disk (i.e., sweeping data from your drives).

Be careful what you do! YOU presumably WILL LOSE YOUR DATA! This is the purpose of DSweeper!

A short manual

In the upper part of the main window you can choose the task to be done: First, if the data written to the selected partition are zeros or random. Additionally, verification of writes can be switched on. Below the options resides a list of partitions on your IDE hard drives. You may select the partitions you wish to sweep and press "Start" to begin.

The window title may read "DSweeper (readonly)", which is the default case in this demo, and no data will be written to your hard disk. If you intend to erase data from your disks, you have to edit the GRUB boot entry for DSweeper.

That's easy: Simply press the "e" button on the proper boot menu entry after GRUB comes up, select the line referencing dsweeper, press "e" again to edit this line, and remove the –readonly commandline switch. Then press "Enter" to accept your changes and "b" to boot the modified entry.

What's behind it?

There are three main invisible parts involved: First there is the block device driver framework (bddf), a central task managing all i/o requests and sending them to the appropriate disk driver, the second invisible part. In this example setup we use l4ata as the disk driver, which is the FreeBSD ATA driver compiled with dde_fbsd described later. The third main part is the i/o server (l4io). It manages the computer's i/o resources as interrupts, i/o ports, mapped device memory, and the pci bus configuration and it gives the required access rights to the responsible device drivers.

About Three Ways For Getting Drivers For A New OS

There are three main ways to get drivers for a new OS (let's call it the target OS).

Writing Drivers From Scratch

First, implementation from scratch with the help of device specifications is a way. (Driver source code for other operating systems—legacy OS from here on—may help a lot.) Using just the specifications is evidently the hardest way. Often they are incomplete, imprecise or not available at all. Sometimes the hardware simply doesn't behave as expected. So the aid (i.e., reuse) of other driver sources is very welcome.

If legacy drivers form the basis, we must be able to follow updates and bug fixes. The best way to achieve this goal is prevention of divergency or keeping changes small. This is achieved by the approaches described next.

Reusing Drivers With Their Kernels

Leaving legacy drivers in their environment by running a slightly modified legacy kernel as driver container in the target OS is an interesting alternative. For example, The DD/OS approach runs multiple linux kernels as driver hosts in an L4 environment. These Linuxes are called device driver operating systems (DD/OSs).

Now you have access to a galore of drivers with little effort once the legacy kernel is adapted to run on the target OS. Per device class you just need one stub on the legacy side accessing the driver and one on the target side offering access to it to the target applications, both communicating with each other.

The main drawback of this design originates from the legacy kernel. Higher independency between the drivers may be possible, if they all ran in their own driver container. This produces a higher memory footprint with DD/OS. Another drawback is the late switch to the target environment: Most of the work is done in the modified legacy kernel and features provided by the target system are not exploited. This is addressed by the next approach, device driver environments.

Reusing Drivers In A Rebuilt Environment (DDE)

This approach does not use the legacy kernel as the driver's environment. Instead we emulate the driver interface of the legacy kernel. This requires a clean interface definition and well-behaving drivers. Once having a DDE you get almost the whole bunch of legacy drivers, just by implementing an access stub per device class. At TU Dresden, we chose the DDE approach and will explain it in detail later.

Reusing Binary Drivers

All three approaches shown more or less involve access to legacy driver sources. But there is a multitude of drivers e.g. for the Microsoft Windows operating system which are only available as binary. A couple of projects out there struggle with emulation environments for MS Windows drivers with some success, but a sufficient emulation environment is always hard to achieve.

DDE Development At TU Dresden

TU Dresden's work with device drivers on microkernels dates back to the mid-90s when the L3 microkernel was still in use. Our work continued while we changed our research basis from L3 to L4 and supported more and more devices (e.g., SCSI drives and video cards). In 2001, we combined our experiences with results from the IBM Sawmill project and developed DDE Linux. After 4 years and a whole bunch of Linux 2.4 and 2.6 versions, we reviewed our code evolution and think it's time to take the next step.

First Approach: DDE Linux

In DDE Linux we implemented a very thin wrapping layer around Linux 2.4 drivers. The resulting framework allowed to compile and run unmodified source code drivers. It consists of two parts: a library and header files for the basic environment interfaces used by most drivers; and one library per device class satisfying its special requirements.

To date, we have implemented libraries for ATA (IDE), USB, network, input and simple sound (OSS) devices. We even have a DDE-based port of the Linux 2.4 TCP/IP stack.

For example, the (binary) sizes of the ATA framework's individual parts are about 40 kB for the basic environment common to all drivers, about 10 kB for ATA specific support, and about 100 kB for the Linux ATA driver. As you see, the biggest part of the DDE Linux is the common library, which is used by all drivers (for other device classes too). The class specific library is only very small.

We achieved porting the Linux ATA driver to L4 at a small fraction of the effort writing one from scratch. The small special library hints that the costs for supporting further device classes is expected to be very small!

Next step: DDE Kit / DDE FreeBSD

Currently, we work on support for drivers from another legacy system (we chose FreeBSD) to review our Linux work and compare it to the effort for FreeBSD. During this work, the idea of making it better somehow arises. We found two new paradigms as described in the next sections.

Cut At The Weakest Spot

This paradigm is: Prevent the implementation of the driver-to-kernel interface in the common library and use some of FreeBSD's kernel code where convenient. This means a little step into the direction of DD/OS but without having major parts of the legacy kernel attached to each driver.

In DDE FreeBSD frequently the legacy implemention of a driver-to-kernel interface is reused. This results in having to implement interfaces which are less special. And as about the half of them are not FreeBSD-specific the idea of a DDE Kit arose.

Encapsulate Services Needed By All Drivers (DDE Kit)

The DDE Kit provides the foundation of a DDE. It comprises all required functionality of the underlying system. This includes device access, resource reservation, interrupt handling, threads support, and more.

We now can leverage the DDE Kit for easier development of frameworks for other systems or for the development of L4 drivers from scratch. Combined with binary driver reuse the DDE Kit provides a proper basis for a DDE Windows as the next step.

...And The Benefits?

Figure codesizes shows the binary code sizes of the individual DDE components. As mentioned above nearly half of the code written for DDE FreeBSD was moved to the unspecific DDE Kit. This are 21 kB of (binary) code. About 190 kB of code reused from FreeBSD plus 25 kB newly developed for FreeBSD specifics (or wrapping to the DDE Kit) remain in the DDE FreeBSD common library. Taken together this is far more than the DDE Linux common library, which has a size of 43 kB.

Sizes of the particular DDE components.

What makes DDE FreeBSD large is the huge amount of legacy FreeBSD code. But this is mature code which should contain very few bugs. And as it is contributed it means no additional effort for us. When just comparing the size of code especially written for the DDEs we see it is only 2/3 (25 kB) compared to DDE Linux (43 kB). A 1/3 lower code complexity means 1/3 less time needed to develop and 1/3 less places for bugs to hide.


Our demonstration shows that the advantages of the microkernel approach can be exploited for secure and performant user-level device drivers. DDE keeps the engineering effort reasonably small and opens the wide range of drivers available as source code.

Next steps to go are:

  • Design and implementation of a complete driver framework with support for hotplugging, power management, and on-demand loading of drivers.

  • Deeper look into binary driver reuse.

  • Improvement of robustness and fault resilience of the framework.

We hope you enjoyed our demo and want to invite you to contact us.



Reboot the machine

Click here (in the Demo-CD version of this document) to reboot your machine.