User Mode Drivers in EROS 2.0Recent attempts to port drivers to EROS have motivated the removal of drivers from the EROS kernel. This note describes the necessary changes to the EROS kernel in order to achieve this. IntroductionUser mode drivers are potentially more robust than their supervisor mode counterparts. Supporting them is a bit tricky, however:
I will address each of these issues in turn. Straightforward IssuesThe first five of these issues are straightforward in principle. Driver LoadWe will revise the bootstrap process in such a way that the bootstrap loader, in addition to loading the kernel, also loads an initial object range that contains the drivers. This range will be a ``well known'' object range. Objects in this object range are exempt from checkpoint, ageing, and such, and the drivers in them therefore will not be accidentally removed. These objects can be explicitly released from memory by the driver manager once all drivers have been configured. After this their pages are subject to removal by ageing. For the sake of simplicity, we will assume for the moment that no drivers will be released from memory in this way. For embedded and set-top devices, we probably want to build system images that contain only necessary drivers in any case. I/O RegistersWe assume that these programs will be privileged, in that they are permitted to directly manipulate I/O registers. This is accomplished either by initial capability calls that validate portions of the I/O register space or by simply gifting these processes with extraordinarily privileges on the grounds that they live within this distinguished object range and are therefore part of the operating system. User-Mode DMADrivers are expected to program DMA devices. We will implement a special kernel capability that allows a driver to say to the kernel: ``Here is a range of contiguous virtual pages. Arrange for them to be physically contiguous within the following physical address range and tell me what the resulting physical base address is. The resulting information is sufficient to allow the driver to directly program physical DMA devices. It is anticipated that some drivers will contrive to map these buffers in such a way that the driver virtual address is the same as the resulting physical address in order to avoid the need to translate between driver virtual and kernel physical addresses. Faulty HardwareUnfortunately, there is faulty hardware in the world. Some of this hardware requires that interrupts be disabled for reasons other than temporary mutual exclusions. The CMD640 PCI/IDE bridge for example, has a bug in which an interrupt occurring during data transfer can result in corrupted data being written to the disk. On such systems, we will provide means for driver processes to disable interrupts. This of course renders the entire system vulnerable, but it is a necessary response to the broken hardware. We can at least limit the number of drivers that require this authority. Interrupt DemultiplexingDrivers will register for the interrupts they wish to receive. The kernel will demultiplex interrupts and then wake up the appropriate process to handle the result. Checkpoint and the Object CacheFor a long time it stumped me how to move disk drivers out of the kernel. Charlie Landau asserted in December that he thought he saw how it might be done, but I could not convince myself that I was happy about the only solutions I could envision. It now appears that there is actually a very natural ``cut line'' in the design for this, and a perfectly reasonable approach to the implementation. The idea is to entirely remove all responsibility for disk I/O from the kernel. The kernel retains responsibility for checkpoint directory management, but at the very bottom level it performs upcalls to accomplish the following operations:
One or more processes sits outside of the kernel in the following loop:
for(;;) {
call kernel to get next upcall
process upcall
acknowledge completion and wait for next upcall
}
Why Use Upcalls?In other parts of the EROS kernel, a different approach to upcalls is used. When a process takes a fault, for example, the kernel synthesizes a keeper invocation by making it appear that the faulting process has directly invoked the keeper. Unfortunately, this approach cannot be used for driver upcalls because the drivers are not persistent. When a CALL occurs or is synthesized, the recipient gets a resume key to the caller. The problem here is that drivers are not persistent, so this resume capability can be lost. Also, if driver capabilities are simply start capabilities, there is no simple way to rescind them on restart. The problem is inherent in any call that crosses the boundary from persistent to non-persistent code. The solution is to arrange a rendevous mechanism within the kernel for rendevous. The driver calls into the kernel and is queued waiting for a response (i.e. a return from the kernel. When the client invokes the driver key, it is in turn queued waiting for a response and the inbound message is passed to the driver. Later, when the driver calls back into the kernel, it's inbound message is passed to the client as a response. Copyright 2001 by Jonathan Shapiro. All rights reserved. For terms of redistribution, see the GNU General Public License |