Recently I began working on my master thesis. For this I have to get familiar with the [Xen hypervisor][xen] and its implementation of drivers.
As the documentation on its implementation is quite sparse I want to write down some of my findings, so others don't have to re-read and re-learn everything.
In this post I'll focus on how to get a minimal *driver* in a paravirtualized VM running. Following posts will then focus on how to do communication through event channels and shared memory
These are all things I need for the project I am working on, so I need to figure out how this works anyway.
### Background
The Xen hypervisor is only a minimal hypervisor implementation, which is booted and then boots a special Linux machine, the so-called **dom0**.
This **dom0** is most often just a regular Linux distribution such as Ubuntu.
Using Xen-specific tools it is then possible to launch additional virtual machines (VMs). These are called **domU**.
In the default case, **dom0** is responsible to acutally talk to the hardware attached to a machine, such as hard disks and the network card.
However, VMs of course also need some way to store data or generate network traffic.
In Xen this is handled by virtual devices attached to the **domU**.
Generic drivers then proxy data that should be written to disk or network packets to send out through the **dom0** to the actual device.
These drivers follow a *split-driver* model, where one part of the driver, the backend, resides in the **dom0** and the other half, the frontend,
is a module in the **domU** machine.
Both parts can be implemented as kernel modules and be loaded dynamically.
What's not documented as clearly as it should be:
Activation of the *virtual device* and thus invoking the right methods of the kernel module is done by writing data to the [XenStore][xenstore].
For actual hardware this is already handled automatically. For your own custom *virtual device* this can be done manually.
[xen]: https://www.xenproject.org/
[xenstore]: https://wiki.xen.org/wiki/XenStore
### A minimal driver
Our driver won't do anything useful besides saying "Hello" and showing a message when it is activated.
The boilderplate for this example is quite huge, the full code can also be found in [the `xen-split-driver-example` repository][xen-split-driver-example].
I assume you already have a Xen host, you are connected to the **dom0** and have at least one **domU** running.
The frontend driver resides in `mydevicefront.c`:
~~~c
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_ALERT */
#include <xen/xen.h> /* We are doing something with Xen */
#include <xen/xenbus.h>
// The function is called on activation of the device
static int mydevicefront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
{
printk(KERN_NOTICE "Probe called. We are good to go.\n");
return 0;
}
// This defines the name of the devices the driver reacts to