My goal during the last HelenOS Camp was to bring QEMU into mainline. Unfortunately, due to some issues with the to-be-merged code I had to abandon this effort and start thinking whether we are porting POSIX applications to HelenOS the right way.
TL;DR – see summary below.
Porting software to HelenOS now
Currently (August 2017) we port POSIX applications to HelenOS with help of
Coastline and libposix.
Coastline takes care of running the
configure & co. scripts with the right
libposix provides a POSIX-like interface to them.
libposix offers the same headers one would see in a UNIX-like distribution
and emulates its functionality via HelenOS native API.
This approach worked well so far because generally the requirements on the headers were low – i.e. the applications we ported had required only the basic functions and data types. After all, with rather minimal set of headers we were able to port GCC and Python.
Bringing QEMU to mainline
As stated earlier, my goal during the camp
was to finally integrate QEMU into HelenOS mainline
did the actual porting but his work was not merged yet.
Since the code changes were mostly located in
libposix, it was rather easy
to keep up with mainline changes and still get a functional
runnable inside HelenOS.
Jan had to add a lot of new headers because among the ported libraries were ncurses or SDL. Because the complexity of the headers started to pile up, headers were not written from scratch but taken from existing projects. But some of these headers are from GPL-licensed projects and such licensing would not mix well with BSD license we use.
Therefore I decided to postpone the integration and instead solve the issue of
Obviously, we can reuse headers from some BSD-licensed libraries.
The downside would be that we would import huge blobs of code into our repository.
But the current state is becoming unmaintainable because of many small workarounds.
For those not familiar with the situation, the problems we face when porting
POSIX software to HelenOS are rather subtle.
HelenOS offers some POSIX-like interfaces but often with deviations from the
standard – as a small example,
int, though the returned value is always zero.
HelenOS also offers
gettimeofday with the same signature except it returns
Seems like a good idea when the function cannot fail but it complicates
porting software that expects this function to be declared according to standard.
Better way to port software to HelenOS?
So I started thinking whether we cannot do it better.
When looking for a reasonable implementation of POSIX headers I came across a small
library called musl.
The authors describe it as
new standard library to power a new generation of
It is a complete implementation of a Linux basic C library including all the
necessary headers and implementation of standard functions.
The library looked pretty well maintained and rather small so I was thinking that
using their headers might be a solution for our POSIX emulation layer.
I was nicely surprised how well organized are the source codes of musl and it
occurred to me that we may try to use more than just the headers from this
So the big question was where it ends, i.e. what it requires from the operating
The answer is that in the end the library directly executes a system call
for operations that cannot be implemented in userspace.
This revelation – I admit it is not that big surprise when you think more about
it but it took me some time :-) – started a chain of thoughts in a completely
What if we would ditch
libposix completely in its current state and instead
implement a library that would emulate the Linux syscalls?
By several small patches to musl we would be able to replace the actual
etc. with a normal library call.
This function would then emulate the syscall via native HelenOS API and return
back the Linux-like response (error codes etc.).
I am wondering why this have not occured to us before...
Is this approach doable?
There are over 338 syscalls in Linux kernel.
But we do not definitely need to support all of them and some needs to be supported
My feeling so far is that if we would be able to support calls like
write we would be able to run quite a lot of the currently supported code.
The big disadvantage of this approach is that it would be rather easy to compile the
libmusl but things would break at run-time when the syscall
would not be implemented.
But it seems to me as a rather small drawback compared to the advantages.
We would not be hacking the headers to bypass bad
configure checks or providing
empty implementations for functionality we would not use anyway.
Some of the syscalls would be very difficult to implement.
fork() is plainly impossible (for GCC which is the only program
that actually needed it, we patched
ioctl() fully is too much work etc.
But some of the syscalls (
writev etc.) are trivial to implement.
And this approach does not impose any a priori restrictions on how much we want
to mimic the POSIX environment.
For example, we even could emulate opening of
/dev/random (which has
no equivalent in HelenOS) by patching the
open() syscall etc.
I played with this approach a little bit and so far it looks promising. I have not pushed any code yet but I hope to do that as soon as I organize the things in a reasonable way.
What worked for me is the following. I simple Hello-World program was compiled
against a patched
All the actual syscalls were replaced by a call to
that dispatches the call to the proper implementation.
After linking with
libmusl and the new HelenOS library providing the above-mentioned
function, it was possible to run the Hello-World inside HelenOS and it actually
printed the greeting to the terminal.
Last thing I implemented so far was the
open() interface but without support
O_CREAT so far. That seems to work well too.
I also tried compiling zlib against
libmusl and compiling it
with the new library.
That went well but it (as expected) failed on unimplemented call to
I am playing with the idea of using libmusl
(a C standard library for Linux) to replace
libposix in HelenOS.
The key idea is to replace actual syscalls in musl with a normal library call
to a function emulating Linux system calls.
This function would be provided by HelenOS and would delegate the
implementation to the native API of HelenOS.
Applications in Coastline would be linked against the patched version of
libmusl – thus using the standard POSIX interfaces during compilation but
actually calling the native HelenOS API during run-time.
So far, I am able to successfully compile and run a simple Hello World program and also compile (but not run yet) zlib.
Thanks for reading.