Virtual devices under Xen are provided by a split device driver
architecture. The illusion of the virtual device is provided by two
co-operating drivers: the frontend, which runs an the
unprivileged domain and the backend, which runs in a domain with
access to the real device hardware (often called a driver
domain; in practice domain 0 usually fulfills this function).
The frontend driver appears to the unprivileged guest as if it were a
real device, for instance a block or network device. It receives IO
requests from its kernel as usual, however since it does not have
access to the physical hardware of the system it must then issue
requests to the backend. The backend driver is responsible for
receiving these IO requests, verifying that they are safe and then
issuing them to the real device hardware. The backend driver appears
to its kernel as a normal user of in-kernel IO functionality. When
the IO completes the backend notifies the frontend that the data is
ready for use; the frontend is then able to report IO completion to
its own kernel.
Frontend drivers are designed to be simple; most of the complexity is
in the backend, which has responsibility for translating device
addresses, verifying that requests are well-formed and do not violate
isolation guarantees, etc.
Split drivers exchange requests and responses in shared memory, with
an event channel for asynchronous notifications of activity. When the
frontend driver comes up, it uses Xenstore to set up a shared memory
frame and an interdomain event channel for communications with the
backend. Once this connection is established, the two can communicate
directly by placing requests / responses into shared memory and then
sending notifications on the event channel. This separation of
notification from data transfer allows message batching, and results
in very efficient device access.
This chapter focuses on some individual split device interfaces
available to Xen guests.