Driver Reuse In The L4 Environment
Thomas Friebel, Christian Helmuth
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
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
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
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
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
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
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
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
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
- ...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
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.