Kernel Modules Autoload from Host in Rump


April 27, 2010 posted by Antti Kantee

Since early 2009 NetBSD and rump has supported execution of stock kernel module binaries in userspace on x86 architectures. Starting in -current as of today, kernel modules will automatically be loaded from the host into the rump kernel. For example, when mounting a file system in a rump kernel, support will be automatically loaded before mounting is attempted.

The first issue with autoloading host kernel modules in rump was kernel symbol renaming: to prevent collisions between the application and kernel C symbols, the rump build uses objcopy to prefix symbols with the string rumpns. While running objcopy on a prebuilt kernel module was possible without access to the module's source code, it was a manual step necessary to get a standard kernel module loaded. This was solved by adding a hook to the module loader to adjust the module's string table after it is loaded but before it is linked.

The second issue was that kernel modules had to be loaded manually by calling rump_sys_modctl(); in contrast kernel modules are commonly autoloaded when necessary. While the standard kernel routines included in a rump kernel would attempt to autoload the module, they would fail because the module files were not available within the rump file system namespace. With some improvements to the rump host file system, etfs, it is now possible to map the kernel module directory (e.g. /stand/i386/5.99.27/modules) inside the rump kernel.

Autoloading kernel modules from the host demonstrates a key feature and difference of rump-style lightweight service virtualization: only one full host installation is necessary (although the coexistence of multiple different rump kernel versions is of course possible). This should be contrasted with traditional heavyweight approaches to building virtual services, where each virtual service requires an entire OS installation and maintenance.

[3 comments]

 



Comments:

Hats off Antti, you deserve it. I was wondering what kind of "dependency" would be required to port RUMP to OSs with limited APIs, (including, but not limited to, L4-like microkernels), both in terms of requirements and work. I am well aware of Arnaud Ysmal work that applies to FreeBSD and GNU/Linux environments, but this is kind of different: the API is less rich, and may lack features you would expect in present general purpose OS. The approach taken today by some vendors to enrich the environment sitting above their microkernel is to port a full-fletched general purpose OS and paravirtualize it through their hypercall-like API, which provides routines similar to low level hardware routines. Such a port requires a lot of work, especially if your only interested in a small part of the OS, like specific fs code, or network/usb/pci stacks. Help, and/or pointers, would be very appreciated. Nonetheless, kuddos for your work Antti, it is darn impressive.

Posted by jean-Yves Migeon on April 27, 2010 at 09:02 AM UTC #

This might be a discussion better suited for a mailing list (apparently there's a 1000 char size limit), but I'll answer "shortly" here and we can do any potential further discussion on a list. First, I'd like to point out there are multiple facets to portability: 1) host NetBSD kernel servers on non-NetBSD 2) use non-NetBSD clients against NetBSD servers 3) create rump-like servers from non-NetBSD operating systems. I'm assuming you're talking about "1". Now, the portability for that case is defined in terms of the rump hypercall interface, which is known as rumpuser (librumpuser / rumpuser.h). The current interface and implementation are clearly geared toward hosting on POSIX-y type systems such as *BSD and Linux -- especially in the sense that rump tries to reuse everything it can from the host, e.g. locking and scheduling. If you want to run things directly on top of a very barebones microkernel interface, you'll need to fill in a number of missing pieces ... (cont)

Posted by Antti Kantee on April 27, 2010 at 04:34 PM UTC #

(cont) For minimum work, I'd say you'd want start with running on top of a more POSIX-like server on your microkernel or include deepers layers of the driver stack from NetBSD. The bottom line is still always the same: you need a way to access the hardware resource -- the storage backend for file systems, the wire for the network stack and the hardware for a device driver, etc. Also, you need other necessary software bits such as a way to allocate memory from the host. As for the common practice of porting an entire OS for some driver stack, well, part of the idea with rump was to show that a monolithic style OS splits easily into components which can be run independently. At any rate, hosting only the components you need will not be be harder than hosting an entire OS. The other benefit from componentization, which gets more interesting once you get more embedded, is that you're using a whole deal less of hardware resources for your drivers.

Posted by Antti Kantee on April 27, 2010 at 04:36 PM UTC #

Post a Comment:
Comments are closed for this entry.