Booting LKL inside Haiku
The first milestone in this GSoC journey to building a generic file system driver based on Linux kernel code is booting LKL (Linux Kernel Library) inside Haiku.
For the short attention span: it works :)
... KERN: KDiskDeviceManager::_AddDiskSystem() done: No error KERN: file system: file_systems/iso9660/v1 KERN: KDiskDeviceManager::_AddDiskSystem(file_systems/iso9660/v1) KERN: KDiskDeviceManager::_AddDiskSystem() done: No error KERN: lklhaikufs: unhandled pheader type 0x4 KERN: file system: file_systems/lklhaikufs/v1 KERN: KDiskDeviceManager::_AddDiskSystem(file_systems/lklhaikufs/v1) KERN: khaiku_env_timer:: LKL_TIMER_INIT KERN: [lkl-console] Linux version 2.6.29 (gringo@lethe) (gcc version 4.4.4 (GCC) ) #10 Fri Jun 18 14:45:38 EEST 2010 KERN: [lkl-console] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 KERN: [lkl-console] Kernel command line: KERN: [lkl-console] lkl: IRQs initialized KERN: [lkl-console] PID hash table entries: 256 (order: 8, 1024 bytes) KERN: [lkl-console] lkl: timer initialized KERN: [lkl-console] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) KERN: [lkl-console] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) KERN: [lkl-console] Memory available: 64900k/65536k RAM, (862k kernel code, 270k data) KERN: [lkl-console] Mount-cache hash table entries: 512 KERN: [lkl-console] bio: create slabThese are messages from /var/log/syslog that are generated when Haiku searches for available file system add-ons. One of those drivers is my lklhaikufs driver. Messages with [lkl-console] are from LKL (similar to what you see when a normal Linux kernel boots) :)at 0 KERN: [lkl-console] io scheduler noop registered (default) KERN: [lkl-console] lkl: syscall interface initialized KERN: [lkl-console] console [lkl_console0] enabled KERN: [lkl-console] Warning: unable to open an initial console. KERN: [lkl-console] Switched to NOHz mode on CPU #0 KERN: [lkl-console] System halted. KERN: khaiku_env_timer:: LKL_TIMER_SHUTDOWN KERN: [lkl-console] lkl: IRQs freed KERN: lkl: halt user callback called KERN: KDiskDeviceManager::_AddDiskSystem() done: No error KERN: file system: file_systems/nfs/v1 KERN: KDiskDeviceManager::_AddDiskSystem(file_systems/nfs/v1) ...
Porting LKL to the Haiku kernel API
To boot LKL inside Haiku, first I have port LKL to a new pseudo-architecture. For this project I have two choices:
- write a user space file system driver (similar to googlefs) and port LKL to the Haiku system call API (or a higher level library)
- write a kernel space file system driver and port LKL to Haiku's kernel API.
Porting details
Porting LKL is much simpler than porting the whole Linux kernel to a new architecture. Much of the low-level details are already taken care of by the portable LKL layer. One only needs to provide a set of runtime environment dependent primitives that cannot be (efficiently) emulated in a portable manner:- memory management routines
- synchronization primitives
- thread management
- time and timer generators
- a (screen/log) printing routine
Memory management
Because LKL does not require memory protection mechanisms (there will be no processes running in the LKL operating system – all calls are considered from kernel space), support for memory management becomes trivial: LKL just needs a physical memory pool that the Linux kernel can use for its memory allocation needs. The poll of memory will be managed by the kernel using a mix of buddy, SLUB/SLAB/SLOB/SLQB/SL*B algorithms just like on a normal system. This pool will only be used for buffers and structures dynamically allocated by the kernel. The kernel code and
statically allocated data will not be part of this poll as they are managed by Haiku's kernel add-on loader (see src/system/kernel/elf.cpp: load_kernel_add_on()
).
The file system driver does not need to interact with interrupts or anything like that, so it does not have any special requirements. This greatly simplifies my work: as memory does not need to be locked (lock_memory
) or unlocked in RAM at various times, the memory support can be reduced to malloc
and free
(we all know that malloc
or any kind of access (read/write/execute) to a unlocked memory address can block, don't we?).
Threading support
LKL needs threading support because the Linux kernel uses threads for internal house-keeping, like processing I/O requests or running softirqs, tasklets or workqueues and journaling tasks.
Starting/stopping threads from Haiku's kernel is similar to other more familiar APIs (e.g. POSIX): spawn_kernel_thread
takes a function f
and a generic pointer arg
as arguments and creates a new thread that will execute f(arg)
.
Two things should be noted here:
- threads are initially suspended, you need to call
resume_thread
to actually run the thread's code. This differs from the traditional POSIX API and I spent some time investigating why my threads were never running :P. - threads (as other Haiku kernel resources – e.g. semaphores) can be given a name. This helps a lot in KDL trips
Semaphore support
Haiku's semaphore API is very straight forward: create_sem
, delete_sem
, acquire_sem
and release_sem
should be self-explanatory.
However there's a catch: releasing a semaphore automatically invokes Haiku's scheduler, and this shouldn't be done in a number of contexts like when interrupts are disabled. Unfortunately the legacy BeOS docs license forbids improvements and such a warning cannot be written in release_sem's documentation. It's important to replace release_sem(s)
calls with release_sem_etc(s, 1, B_DO_NOT_RESCHEDULE)
if this can be called in such a context.
Time and timers
LKL needs to know the current time (not the time since starting the computer, but the absolute time – as in a wall clock) for a variety of tasks, but for this driver we need it to set a valid time stamp on files. For this LKL uses real_time_clock_usecs
which returns the time since start of the Unix epoch (January 1st 1970) in microseconds.
Any operating system needs a functioning timer interrupt to function properly. Linux support two categories of programmable interrupt timer (PIC) chips: timers that fire periodically or timers that can efficiently be programmed to fire at various moments and stop firing in certain intervals. We simulate the second kind of PICs in Haiku, thus generating a smaller amount of LKL-interrupts (not real hardware interrupts), for a lower overhead:
KERN: [lkl-console] Switched to NOHz mode on CPU #0Now that the LKL boots and shuts down correctly, we have to build the file system driver that uses it :)