Fork of the Genode OS framework
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1016 lines
44 KiB

==============================================
Release notes for the Genode OS Framework 9.11
==============================================
Genode Labs
In contrast to the previous release, which had been mainly about important
refinements and optimizations under the hood, the release 9.11 is focused on
new features.
Our brand new packet streaming framework enables the efficient communication of
bulk data between processes based on a shared-memory protocol and asynchronous
signalling. We put this new facility to use for the new NIC session interface.
This interface allows us to execute network drivers and network protocol stacks
in distinct processes. The most interesting current use case is the new
integration of the light-weight IP stack (lwIP) into Genode.
The most noticeable platform-related addition is the new support for the ARM
architecture to the OKL4 version of the framework.
As with every release, we refined recently introduced features and tightly
integrated them into our mainline development. The most prominent of these
features is dynamic linking support, which was introduced with the previous
release and has now become fully integrated in the framework and the build
system. Also our steady improvement of the Linux device-driver
environment yields fruit in the form of USB storage support. With regard to
Qt4, we are proud to announce the availability of the Qt4/Webkit library
on all kernels supported by Genode.
Furthermore, we added the paravirtualized Linux kernel called OKLinux to
the official Genode distribution. This variant of Linux can be executed
on top of the OKL4 version of Genode and provides a binary-compatible execution
environment for Linux programs alongside low-complexity native Genode
programs.
This document compiles these and more changes between the versions 9.08 and
9.11 of Genode. It contains new bits of documentation and tries to put our
development into a broader context.
Base framework
##############
The 'base-host' platform
========================
We added a new platform repository called 'base-host' to the Genode
distribution. This repository contains dummy implementations of
platform-specific Genode APIs to enable the compilation of Genode for the host
platform. Because the repository provides dummy implementations, most of the
generated binaries will not work. However, the repository serves two important
purposes. It documents all platform-specific APIs that must be filled out when
porting Genode to another platform, and it is the build environment for unit
tests executed on the host platform.
Signalling-framework refinements
================================
With our work on the packet-streaming facility described in Section
[Packet-stream interface], we discovered a not yet supported use case for the
signalling framework.
The original implementation expected one or more signal-handling threads
to block or poll for signals from potentially different sources and dispatch
them in the order of arrival.
Such a thread would instantiate one signal receiver associated with
potentially many signal contexts (representing different signal sources).
The new use case, however, requires one thread to be able to selectively handle
a subset of signal contexts at a time. The API already facilitated this
use case by a simple instantiation of multiple signal receivers and let one
thread handle signals for one or another signal source by querying the
different receivers.
Until now, this use case was not supported by the underlying implementation
because signals were submitted to signal receivers, which could only hold
one pending signal. A signal could only be supplied to a receiver if
there was no pending signal already stored at the receiver. Otherwise,
signal delivery for the complete process stalled. We have now changed
the implementation such that signals are always supplied to signal contexts
instead of receivers. This way, the order of signal arrival and signal
handling becomes completely decoupled and clears the way for a much more
flexible use of the signalling framework.
:Interface changes:
Because the capability for signal submission refers to a signal context
rather than a signal receiver, we changed the class names of the signal API
accordingly. The previously called 'Signal_receiver_capability' is now called
'Signal_context_capability'. We also streamlined the interface of core's SIGNAL
service according to this new naming scheme. The latter change, however, is
completely transparent at the Genode API level.
C++ runtime improvements
========================
The base framework of Genode is written in C++, but without a C runtime
underneath. The C++ support libraries, however, use to depend on certain
functions normally provided by the C library. Therefore, Genode has to provide
custom implementations of these functions. This C++ runtime environment is
encapsulated in the 'cxx' library. We use to complement the 'cxx' library as
needed.
One feature that was previously missing is proper synchronization of static
constructors. In contrast to constructors of global variables, which are
executed by the startup code before any other threads are created, static
constructors are executed lazily, potentially by different threads. A typical
static constructor looks like this:
! Some_object *get_some_object() {
! static Some_object o;
! return &o;
! }
When calling the function 'get_some_object' the first time, The instance of
'Some_object' is constructed at a static memory location. For all subsequent
calls of 'get_some_object', the once created object is not constructed again
but reused. This is a very handy alternative to global constructors when
objects inter-depend on each other. In contrast to the construction order
of global constructors, which is arbitrary, the call order of static constructors
is implicitly defined by the code such that object dependencies are recognised.
However, because static constructors are executed lazily, they may be called
by different threads. The previous version of 'cxx' had no synchronization
in place for protecting a static constructor from being concurrently
executed by more than one thread, resulting in a 'recursive_init_error'
run-time exception.
With the Genode workloads getting more advanced and dynamic, we have seen
this condition to trigger and have added proper support for guarded static
C++ constructors into the 'cxx' library.
Library-based AVL tree
======================
Our AVL-tree implementation in 'base/include/util/avl_tree.h' is a fundamental
data structure for the framework. It is used at numerous places such as
memory allocators, address-space layout management, and the server-object
framework. Up to now, this implementation was a big template, instantiated
for each data type to organize. Moreover, most operations were implemented
using inline functions. By statically profiling the layout of Genode's
binaries, we observed that this inline code ended up multiple times in
the binaries. However, the program logic of all those instances was essentially
the same (e.g., how to perform a tree rotation). Only the policy (i.e., the
sort criterion) differs. We now have re-implemented the AVL tree as two parts,
the actual AVL-tree algorithm, which is independent from any template
parameters and resides in a library called 'avl_tree', and a policy-dependent
front-end template class residing in the 'avl_tree.h' header file.
To our delight, this change reduced the average size of Genode's binaries
by 10%. For example, the core binary for OKL4 on x86 went from 305 KB
down to only 270 KB.
:Interface change:
The new AVL-tree implementation comes along with a slight API change. The
operation to remove a node from an AVL tree used to be a member function of the
'Avl_node' object to remove. This function is now being provided by the
'Avl_tree' taking an 'Avl_node' as argument. Because the 'Avl_tree' is a
container of 'Avl_node' objects, this change makes the AVL tree more consistent
with other container classes such as 'List' and 'Fifo'.
Initial support for the ARM architecture
########################################
Right from the start of the project, the portability of the framework was a
primary concern. This is reflected by the framework's unique capability to
seamlessly run on four different kernels. With regard to the portability
among different CPU architectures, however, the development was focused on the
x86 architecture as this architecture is most common. With the release 9.11,
the project moves beyond the x86 architecture by adding support ARM CPUs and an
exemplary ARM-based SoC platform, namely GTA01. Because of all current Genode
base platforms the OKL4 is the most widely used kernel on ARM-based devices,
we have focused our efforts on this kernel first. The 'base-okl4' repository
comes now with support for the ARM-based GTA01 platform as used for the
Openmoko project. We choose this platform because it is supported
out-of-the-box by the OKL4 2.1.1 distribution. The ARM-specific code that
we had to add to the framework is surprisingly little. It covers the assembly
startup code for executables, support code for atomic operations, and the
platform driver for GTA01. Because the OKL4 kernels provides abstractions
for all other CPU-specific peculiarities, the code for all framework libraries
and components are the same for ARM and x86. This also includes the C++
startup code and the linker script.
The procedure for trying out the new ARM support with the GTA01 platform using
Qemu is decribed at a dedicated Wiki page:
:Genode/OKL4 on the GTA01 platfrom:
[http://genode.org/community/wiki/GenodeOKL4OnTheGTA01Platform - Genode.org Community Wiki]
Both the OKL4 version 2.1.1 and the GTA01 chip are not the most current
platforms but this combination turned out to be good as starting point.
Because we use OKL4 2.1.1 on a regular basis on x86, using this kernel on ARM
is an evolutionary intermediate step towards moving on to more recent kernels.
:Limitiations:
* The platform driver for GTA01 is pretty limited. It is just as a
show case for running Genode on the Qemu-neo1973 emulator. The driver
is not tested on real hardware.
* This release contains the initial support, which currently covers the
base framework, the 'os', and the 'demo' repositories. Other repositories
such as 'libc', 'linux_drivers', and 'qt4' are not supported yet.
* Dynamic linking is not yet not supported on ARM
Paravirtualized Linux on Genode/OKL4
####################################
OKLinux is a para-virtualized version of the Linux kernel running on top of the
micro-kernel OKL4. It enables us to execute Linux applications in the Genode
environment side-by-side with low-complexity native Genode applications, which
can implement security-critical functions without relying on the
high-complexity Linux kernel. Compared with most existing virtualization
solutions including Xen and KVM, the trusted computing base for such
security-critical components is one or more magnitudes smaller (the OKL4 kernel
+ Genode base framework are less than 30,000 lines of code).
The original code of OKLinux relies on the Iguana framework - a bunch of
server components and libraries to simplify construction of applications
running on top of OKL4. The new 'oklinux' Genode repository contains a small
OKLinux support library, as well as a patch for OKLinux 2.6.23, that replaces
Iguana by the Genode framework. Nevertheless, our version of OKLinux stays to
be dependent on the OKL4 kernel, meaning that you can only use it in
combination with Genode running on top of OKL4.
Usage
=====
If you haven't build Genode for OKL4 yet, please refer to the following document:
:[http://genode.org/documentation/platforms/okl4 - Genode on the OKL4 microkernel]:
This page contains the information on how to build and use Genode with OKL4.
For building OKLinux for Genode, you first need to download and patch the
original sources. The top-level makefile of the 'oklinux' repository automates
this task. Just issue:
! make prepare
Afterwards you need to include the 'oklinux' repository into the Genode build
process. Just add the path to this directory to the 'REPOSITORIES' declaration
of the 'etc/build.conf' file within your build directory.
Now, you can change to your build directory and simply type:
! make oklinux
That's all. The 'bin/' directory within your build directory should now contain
a symbolic link to the 'vmlinux' binary.
To test your Linux binary, you also need to tweak the config file for init and
for the elfweaver tool. You will find examples for this in the 'config/'
directory of the 'oklinux' repository. Moreover, you will need to add a RAM disk
file to your setup as OKLinux for Genode only supports RAM disks by now.
RAM disk
========
OKLinux provides a special block device driver, which uses a RAM disk as
backing-store. You can specify your RAM disk file on the kernel command line of
Linux by setting the 'igms_name=' parameter.
If you use a RAM-disk file that contains only a file system you have to set the
root parameter on the kernel command line to '/dev/igms0'. If your RAM disk
contains a whole partition table, state '/dev/igms0pn', whereby n stands for
the partition number containing the root file system.
Kernel command line
===================
You can state the Linux kernel command line by using the XML config-file of the
init node that starts your Linux instance. In addition to the filename and
quota within the start section of Linux, you simply add the following:
! <config>
! <commandline>igms_name=ramdisk root=/dev/igms0p1</commandline>
! </config>
Configure Linux
===============
This OKLinux package contains only a minimal Linux configuration. Especially,
any hardware drivers are missing, as Genode/OKL4 doesn't allow direct hardware
access from Linux. Instead, Linux accesses hardware indirectly through Genode
services. The current version of OKLinux comes with stub drivers for connecting
Linux to Genode's 'Input_session', 'Timer_session', and 'Framebuffer_session'
interfaces and we plan to add support for more device classes in the future.
If you want to enable/disable options in Linux, you can simply do so by using
the normal Linux build system. You will find the '.config' file Linux is using
within the 'oklinux/' directory of your build directory. If you don't want to
tweak '.config' directly, you can also change to the 'oklinux/' directory of
your build directory and issue:
! ARCH=l4 SYSTEM=i386 make menuconfig
Then you will get the well known ncurses interface.
Troubleshooting
===============
If you run into problems when building OKLinux and you want the build process
to be somehow more verbose, you can build OKLinux this way:
! VERBOSE_LX_MK=1 make oklinux
Example
=======
The following screenshot shows Genode running on OKL4 with two instances
of OKLinux running. One instance booted the TinyCore Linux distribution
including the X Window System. The other instance booted a busybox-based
RAM Disk and runs with just about 16 MB of RAM. Each Linux kernel uses
a separate instance of the Liquid FB virtual frame buffer:
[image tinycore_busybox_screen]
The Genode process tree looks as follows (the figure omits usual Genode
components such as device drivers for PCI, PS/2, VESA, and the Timer):
[image tinycore_busybox]
The Linux Launcher node is just a slightly modified Init node with the only
difference being that requests for sessions to the Nitpicker GUI server or
to the timer are always delegated to the parent rather than to another
child.
Operating-system services and libraries
#######################################
Completed support for dynamic linking
=====================================
With the previous release, we introduced the initial version of a dynamic
linker for Genode. This version came in the form of a separate source-code
repository called 'ldso' containing the dynamic linker and the linker
scripts for building shared libraries and dynamically linked executables.
However, some pieces were still missing to make the dynamic linker
generally usable in practice. The Genode build system lacked proper support
for building and using shared libraries and the dynamic linker had been
only tested on the x86_32 platform on Pistachio and OKL4.
In the meanwhile, we filled these gaps. With the release 9.11, we completely
dissolved the dependency of the dynamic linker from the C library and,
thereby, could make the dynamic linker a regular part of the 'os' repository.
It now resides in the 'os/src/ldso' directory and supports all Genode base
platforms L4/Fiasco, L4ka::Pistachio, OKL4, and Linux on the x86_32 and
x86_64 architectures. We are especially delighted about the dynamic linker
functioning seamlessly on the Linux platform. Because 'ldso' uses only
the Genode API as back end, there are no platform-specific quirks needed.
:Usage:
To build a shared library instead of a regular static library, you just need to
declare 'SHARED_LIB = yes' in the library-description file. When doing so, a
'<libname>.lib.so' file will be generated and installed in the
'<build-dir>/bin/' directory. For building an executable that uses a shared
library, no special precautions are needed. The build system will automatically
detect the use of shared libraries, concludes that the binary must be
dynamically linked, and will use the correct linker script. When loading a
dynamically linked program, the dynamic linker 'lsdo' and all used shared
objects must be loaded as well.
:Integration with the framework:
On Genode, the 'process' library provides the API to create new processes from
ELF executables. The user of the 'process' library can register a capability to
a dataspace containing the dynamic linker via the function
'Process::dynamic_linker'. When creating a new process, the library first
revisits the ELF header of the executable to determine whether the binary is
statically or dynamically linked. If statically linked, the process library
proceeds with loading the ELF binary. Otherwise, it loads the dynamic linker as
registered beforehand. When the dynamic linker (ldso) starts up, it requests
the dataspace of the dynamically linked executable by opening a ROM session for
the magic file called 'binary'. Note that the dynamic linker does not even need
to know the real name of executable. Then ldso further loads all shared
libraries needed for the executable via ROM sessions with the names of the
respective shared object files and populates the local address space. After
having initialized the address space for the new executable, ldso jumps to the
executable's main function.
Packet-stream interface
=======================
Up to now, Genode provides synchronous IPC calls and asynchronous signals as
inter-process communication primitives. The IPC framework transfers message
payload by copying data between processes via the kernel. The signalling
mechanism provides semantics similar to interrupts but does not support the
transfer of message payloads. With the new packet-stream interface, we
complement those inter-process communication facilities with a mechanism
that carries payload over a shared memory block employing an asynchronous
data-flow protocol. It is geared towards large bulk payloads such as
network traffic, block-device data, video frames, sound samples, and USB
URB packets.
The packet-stream interface comes in the form of the single header file
'os/packet_stream.h' and supports the unidirectional streaming of bulk data
between processes via a shared-memory block. The public interface consists of
the two class templates 'Packet_stream_source', and 'Packet_stream_sink'. Both
communication parties agree on a policy with regard to the organization of the
communication buffer by specifying the same 'Packet_stream_policy' as template
argument.
[image packet_stream]
As illustrated in the Figure above, the communication buffer consists of
three parts, a submit queue, an acknowledgement queue, and a bulk buffer.
The submit queue contains packets generated by the source to be processed
by the sink. The acknowledgement queue contains packets that are processed
and acknowledged by the sink. The bulk buffer contains the actual payload.
The assignment of packets to bulk-buffer regions is performed by the
source.
The interplay between source and sink for processing a single packet looks
as follows:
# The source allocates a region of the bulk buffer for storing the packet
payload using 'alloc_packet'. It then requests the local start address of
the payload using 'packet_content' and fills the packet with data
# The source submits the packet to the submit queue via 'submit_packet'
# The sink requests a packet from the submit queue using 'get_packet',
determines the local start address of the payload using 'packet_content',
and processes the contained data
# After having finished the processing of the packet, the sink acknowledges
the packet using 'acknowledge_packet', placing the packet into the
acknowledgement queue
# The source reads the packet from the acknowledgement queue and releases
the packet using 'release_packet'. Thereby, the region of the bulk buffer
that was used by the packet becomes marked as free.
This protocol has four corner cases that are handled by signals:
:submit queue is full: when the source is trying to submit a new packet.
In this case, the source blocks and waits for the sink to remove packets
from the submit queue. If the sink observes such a condition (calling
'get_packet' on a full submit queue, it delivers a 'ready_to_submit'
signal to wake up the source.
:submit queue is empty: when the sink tries to obtain a packet via
'get_packet'. The sink is going to block. If the source places a
packet into an empty submit queue, it delivers a 'packet_avail'
signal to wake up the sink.
:acknowledgement queue is full: when the sink tries to acknowledge a packet
using 'acknowledge_packet'. The sink is going to block until the source
removes an acknowledged packet from the acknowledgement queue and delivers
a 'ready_to_ack' signal.
:acknowledgement queue is empty: when the source tries to obtain an
acknowledged packet using 'get_acked_packet'. In this case, the source
will block until the sink places another acknowledged packet into the
empty acknowledgement queue and delivers a 'ack_avail' signal.
These conditions can be avoided by querying the state of the submit and
acknowledge buffers using the functions 'packet_avail',
'ready_to_submit', 'ready_to_ack', and 'ack_avail'.
If bidirectional data exchange between two processes is desired, two pairs
of 'Packet_stream_source' and 'Packet_stream_sink' should be instantiated.
NIC-session interface
=====================
The NIC session interface is the first application of our new packet stream
facility. It allows executing network drivers as separate processes rather
than linked against the network protocol stack. A NIC session consists of
two packet streams, the transmission stream (TX) for sending packets and
the reception stream (RX) for receiving packets. Furthermore, each NIC
session comprises a simple RPC interface for requesting the MAC address of
the network adaptor and for defining signal handlers for the signals TX
ready-for-submit, TX acknowledgements-available, RX ready-to-ack, and RX
packet-available. By default, those signals are handled by default signal
handlers contained in blocking packet-stream functions. However, it is
possible to override the data-flow handlers to implement semantics similar
to the POSIX 'select' function, for example to wait for all possible
signals of multiple NIC sessions using only a single blocking function.
You can find the NIC-session interface as part of the 'os' repository
at 'os/include/nic_session/'.
Light-weight IP stack (lwIP)
============================
Our port of the light-weight IP stack (lwIP) builds upon the foundation
laid with the NIC-session interface.
The following Figure illustrates the integration of a networking
application with lwIP that uses the NIC-session interface as back end.
[image lwip]
The port of the lwIP stack resides in the new 'libports' repository
described in Section [New libports repository]. It comes with
two examples, a loopback demonstration and a minimalistic HTTP server.
The examples are located at the 'libports' repository at 'src/test/lwip/'.
The lwIP back-end acts as a client of the NIC-session interface.
For the server counterpart, we added a DDE-Linux based stand-alone
network driver for PCnet32 to the 'linux_drivers' repository.
For starting the HTTP-server test on L4ka::Pistachio, OKL4, and L4/Fiasco,
the following config file can be used:
! <config>
! <start>
! <filename>timer</filename>
! <ram_quota>512K</ram_quota>
! </start>
! <start>
! <filename>pci_drv</filename>
! <ram_quota>512K</ram_quota>
! </start>
! <start>
! <filename>nic_drv</filename>
! <ram_quota>512K</ram_quota>
! </start>
! <start>
! <filename>lwip_httpsrv_test</filename>
! <ram_quota>1M</ram_quota>
! </start>
! </config>
For trying out the example with Qemu, please refer to the instructions
given in the
[http://genode.org/documentation/release-notes/9.02#section-4 - description]
of the initial networking support added in Genode version 9.02.
MMX-based 2D blitting library
=============================
Previous Genode releases already featured a 2D blitting library with a
MMX-based optimization for x86_32. This optimization, however, was not enabled
by default. Starting with the current release, several graphics-related parts
of Genode will profit from our revisited version of this library, which is now
enabled for both x86_32 and x86_64 by default. From this change, you can expect
a definite performance boost of the Nitpicker GUI server and all
Scout-widget-based applications such as the tutorial browser and launchpad. The
library interface is located at 'os/include/blit/blit.h'. On architectures with
no MMX, a generic implementation of the interface is used as fall back, which
makes it safe to use the 'blit' interface for developing portable
applications.
Zero-footprint runtime for Ada/Spark
====================================
At Genode Labs, we are exploring the use of the Spark subset of Ada to
implement security-critical code and use Genode as development platform.
For this reason, we have added support for executing freestanding Ada
code on Genode. An example of the use of Ada on Genode can be found at
'base/src/test/ada'.
The program relies on the normal startup procedure of a Genode process.
Execution starts at the 'crt0' assembly entry provided by the startup library.
The 'crt0' code sets up the stack of the main thread and calls the '_main'
function implemented in the C++ portion of Genode's startup library. In turn,
the '_main' function calls 'main' of the actual program. The main function of
this example calls the Ada main procedure. The test further exercises the call
of C functions from Ada code. So the integration of Ada and C code is almost
seamless.
For building the Ada test program, you must have installed the GNU GNAT Ada
compiler. Right now, we are using the host version of this compiler, which
is save as long as we do not use advanced Ada features such as exceptions.
To enable building the test program, add 'gnat' to the 'SPECS' declaration
of your '<builddir>/etc/specs.conf'. Otherwise, the Genode build system
will skip the target.
Please note that the current version of this program does not use 'gnatbind'.
Therefore, package elaboration is not executed.
Misc improvements of OS-level services and libraries
====================================================
:Init:
Fixed quota-limitation problem in init. There was a race between the
call of 'env()->ram_session()->avail_quota()' and already running children
that donated quota via init to a server. During the quota transfer, child
quota gets temporarily transferred to init to be further transferred to
the server. In the worst case, such temporary quota was then assigned to
the last child when limiting its quota to 'avail_quota()'. We solved this
problem by deferring the start of child programs until all quota calculations
are finished.
:Nitpicker GUI server:
Prevent superfluous screen updates when switching clicking on different
views of the same session, making the GUI more responsive.
New libports repository
#######################
With proper shared-library support in place and with our C runtime getting
more and more mature, we feel an increased desire to port existing popular
libraries to Genode. For this purpose, we have now introduced a dedicated
source-code repository called 'libports'. Following the approach taken
with our Qt4 porting effort, this repository does not contain actual source
code but a mechanism to download upstream library source codes and adapting
them to Genode. This way, we can easily keep track of the adaptions needed
for Genode and update libraries to later versions.
:Usage:
At the root of the 'libports' repository, there is a 'Makefile' automating
the task of downloading and preparing the library source codes. By just
typing 'make', you get an overview of the available libraries and further
instructions.
In the common case, you might just want to prepare all libraries by issuing:
! make prepare
Alternatively, you can select one particular library to prepare by
specifying the base name of a library (wihout the version number) as
command-line argument:
! make prepare LIB=freetype
After having prepared the 'libports' repository, we are ready to include
the repository into the build process by appending it to the 'REPOSITORIES'
declaration of your '<build-dir>/etc/build.conf' file.
:Under the hood:
For each library, there is a file contained in the 'libports/ports/'
subdirectory. The file is named after the library and contains the
library-specific rules for downloading the source code and installing
header files.
For reference, we have included ports of *Freetype2* and *Jpeg*. Note that
currently, these ports serve mainly the purpose of illustrating the use of the
'libports' repository and are not thoroughly tested. However, we have
successfully used them with Qt4.
:How does 'libports' relate to the other repositories?:
The 'libports' repository is meant as a place for porting popular libraries
that usually expect a POSIX-like environment - similar to the environment
provided by Genode's 'libc' repository. So 'libports' depends on 'libc' and,
consequently, on the repositories 'libc' depends on, most specifically the 'os'
repository. Because the dynamic linker is now a regular part of the 'os'
repository, libraries contained in 'libports' can (and should) be built as
shared libraries.
Device drivers
##############
Device-driver environment
=========================
We steadily improve our device-driver environment for executing Linux drivers
directly on Genode. For this release, we updated the Linux environment to the
Linux kernel version 2.6.20.21, and improved several parts of the
Linux-specific code, in particular the handling timers and tasklets.
In the DDE Kit, we made the 'free()' function compatible with C99 (accepting a
NULL pointer as argument) and fixed a memory leak.
USB storage
===========
We extended our USB stack with the driver infrastructure needed for
accessing USB storage devices. The USB stack is ported from the Linux
kernel using the Linux device-driver environment. Our Genode-specific
support code consists of two parts:
* We added emulation code for the Linux SCSI protocol layer as relied
on by the Linux USB stack. The currently supported SCSI commands are INQUIRY,
READ_10, WRITE_10, and READ_CAPACITY. Furthermore, we added a custom block
interface at 'linux_drivers/include/dde_linux26/block.h', which still has a
number of limitations (thread safe, synchronous, single block r/w requests
only).
* For the file-system layer, we ported the
[http://elm-chan.org/fsw/ff/00index_e.html - FatFs R0.07e library]
to Genode. This library allows us to access the directories and files of the
FAT file system on the USB device. It has been ported using our new
'libports' repository.
The new USB storage support can be tested using a test program supplied with
the 'linux_drivers' repository. It runs on all base platforms except on Linux.
The source code of the test is located at
'src/src/test/dde_linux26_usbstorage'. For compiling, you need to download the
'libffat' first. From the 'libports' repository, you can issue:
! make prepare LIB=ffat
Furthermore, you must ensure that both the 'libports' and 'linux_drivers'
repositories are specified in the 'REPOSITORIES' declaration in your
'<builddir>/etc/build.conf' file. Because of the dependency of the USB-storage
test from libffat, the program is not built by default until explicitely
enabled by stating that 'libffat' is available. This must be done by extending
the 'SPECS' variable in your '<builddir>/etc/specs.conf':
! SPECS += libffat
After these preparations, you can build the test program from your
build directory:
! make test/dde_linux26_usbstorage
For executing the test, you need to specify Genode's 'timer' and 'pci_drv'
alongside the 'test-dde_linux26_usbstorage' program. The test program
will access an attached USB storage device, output the root directory
content and load the first 16 bytes of the first file. You can try this
out on Qemu by using a virtual USB storage device. First create a
disk image with a FAT file system:
! dd if=/dev/zero of=<usb-device-file> count=2048
! mkfs.vfat <usb-device-file>
! mount -oloop <usb-device-file> <mount-dir>
! cp <some data> <mount-dir>
! umount <mount-dir>
Then you can attach this disk image to Qemu using the arguments
'-usb -usbdevice disk:<usb-device-file>'.
PS/2 mouse and keyboard driver
==============================
We improved Genode's native PS/2 driver to be more robust against delays at
startup. During the time after the startup of the PS/2 driver until a
client connects, incoming input events used to fill up and eventually overflow
the event queue. Now, we start sampling input events only after a client
connects to the PS/2 driver.
Furthermore, we have added support for the Intellimouse ImPS/2 and ExPS/2
protocol extensions to support mice with a vertical scroll wheel and
5-button mouses. The improvement required no changes of the 'Input::Event'
interface. Scroll-wheel events are reported as 'WHEEL' events with the wheel
count delivered as 'ry' value. The buttons correspond to the key codes
'BTN_LEFT', 'BTN_RIGHT', 'BTN_MIDDLE', 'BTN_SIDE', 'BTN_EXTRA'.
Regarding the keyboard driver, we do not print messages on the occurrence of
key-repeat events any longer. These messages tended to significantly slow down
keyboard-based applications such as the OKLinux console.
NIC driver implementing the NIC-session interface
=================================================
We added a new NIC driver using the Linux Device Driver Environment, which
implements the server side of the new NIC-session interface described in
Section [NIC-session interface]. The currently used Linux driver is 'pcnet'
that is implemented in Qemu. Nevertheless, it should be straight forward to
add other Linux network drivers the same way.
Qt4 and Webkit
##############
We have extended our Qt4 port with Webkit support, which is one of the most
complex components of Qt4. One particularly interesting point was the dependency
of the JavaScript engine from the C++ standard template library. The Genode
tool chain, however, already features the STL headers, which worked out nicely
once we figured out a way to wrest the information about the STL header
location from the compiler.
Because Qt4 applications have exceedingly large binary sizes relying on static
linking, we put Genode's newly available shared-library support to good use by
declaring all Qt4 libraries as shared objects. This way, Qt4 applications have
now become reasonably small. For example, the binary of the Tetrix example went
from over 10MB down to about 600KB.
Since the Genode release 9.11, Qt4 depends on the 'libports' repository,
specifically on the 'freetype2' and 'jpeg' libraries. Please make sure
that you called the top-level Makefile of the 'libports' repository
for those preparing those libraries and that your 'REPOSITORIES' declaration
contains the 'libports' repository.
Applications
############
Seamless Xvfb integration into Genode on Linux
==============================================
Xvfb is a virtual X server that uses a plain file as frame buffer instead of a
physical screen. The 'xvfb' glue program makes an Xvfb session available to the
Linux version of Genode such that both native Genode programs and X clients can
run seamlessly integrated in one Nitpicker session. Using the 'xvfb' glue
program contained in the 'os/src/app/xvfb' directory. Because Xvfb is executed
as Nitpicker client, it is possible to integrate multiple instances of Xvfb
into the same Nitpicker session.
[image xvfb_screen]
The scenario above uses two instances of Xvfb, which are displayed by the
Nitpicker GUI server executed on Genode. Each Xvfb process is connected
to Genode via a xvfb adaptor program, which is hybrid using both the Linux
API (for accessing the virtual frame buffer and performing its role as
X client) and the Genode API (for its role as Nitpicker client).
[image xvfb]
:Preconditions for compiling:
The xvfb adaptor tracks dirty screen regions using the X damage extension
and injects user-input events into the X server using the X test extension.
So you need the development packages of both extensions to compile it. The
Debian package for the X damage extension is called 'libxdamage-dev'. The
X test extension is normally installed by default or resides in a package
called 'libxtst-dev'. Furthermore you need to enhance your 'SPECS' declaration
in your '<builddir>/etc/specs.conf' file as follows:
! SPECS += x11 xdamage xtest
:Usage:
First start Xvfb using the following command-line arguments:
! Xvfb :1 -fbdir /tmp -screen 0 1024x768x16
While Xvfb is running, '/tmp/Xvfb_screen0' will contain the content of the X
server's frame buffer. This file must be specified for the 'xvfb' declaration
in the config file. In addition, the display of X server instance must be
declared via the 'display' tag. For example:
! <config>
! <display>:1</display>
! <xvfb>/tmp/Xvfb_screen0</xvfb>
! </config>
:Known Limitations:
* With the current version, some key codes are not mapped correctly.
* The screen mode of Nitpicker and the Xvfb session must be the same.
Only modes with 16bit color depth are supported.
Backdrop application
====================
For the Genode Live CD, we added a simple backdrop application to the 'demo'
repository, residing in 'src/app/backdrop'. It uses libpng to display a PNG
image as background of the Nitpicker GUI server.
:Usage:
You have to specify the name of the PNG file to be used as background
image via a declaration in your config file:
! <config>
! <image>background.png</image>
! </config>
:Limitations:
The PNG file is expected to be equal to the screen size. No scaling
or tiling is supported.
Extended configurability of native applications
===============================================
:Launchpad:
By default, launchpad displays a preconfigured list of programs and their
respective default memory quotas. The user can tweak the memory quota
for each entry with mouse and then start a program by clicking on its
name. As an alternative to using the default list, you can define the list
manually by supplying a configuration to Launchpad. The following example
configuration tells launchpad to display a list of two launcher entries:
!<config>
! <launcher>
! <filename>sdl_pathfind</filename>
! <ram_quota>10M</ram_quota>
! </launcher>
! <launcher>
! <filename>liquid_fb</filename>
! <ram_quota>10M</ram_quota>
! </launcher>
! <launcher>
! <filename>init</filename>
! <ram_quota>10M</ram_quota>
! <config>
! <start>
! <filename>hello</filename>
! <ram_quota>1M</ram_quota>
! </start>
! </config>
! </launcher>
!</config>
To use this configuration for a Launchpad started via init, you can
simply insert the launchpad configuration into the '<start>' node
of the launchpad entry in init's 'config' file.
:Liquid frame buffer:
Liquid frame buffer is an implementation of the frame buffer interface
running as a client of the Nitpicker GUI server. It supports the
following configuration options. The example shows the default
values.
! <config>
!
! <!-- enable the animated background,
! valid values or 'on' and 'off' -->
! <animate>on</animate>
!
! <!-- the initial window position and
! size of the virtual frame buffer -->
! <x>400</x>
! <y>270</y>
! <width>500</width>
! <height>400</height>
!
! <!-- set the window title -->
! <title>Liquid Framebuffer</title>
!
! </config>
Because Liquid frame buffer creates the virtual frame-buffer window at
start time, not at session-creation time, sufficient memory resources must
be provided when starting the program. Consequently, the client does not
need to donate memory for the frame buffer backing store.
Liquid frame buffer supports only one client. If multiple virtual frame
buffers are needed, multiple instances of the program should be used.
Misc improvements of native applications
========================================
* Fixed keyboard handling in Liquid FB, now all keyboard events are directed
to the window content, which makes Liquid FB more appropriate for hosting
an OKLinux console.
* Replaced slow pixel copy code of the scout widget set with the MMX-based 2D
blitting library and thereby improved the graphics performance of
applications such as launchpad, liquid FB, and scout.
* Defer creation of Nitpicker view to the first buffer refresh. This avoids
artifacts when moving the mouse over designated view area during at the
startup of a scout application.
Platform-specific changes
#########################
:L4ka::Pistachio:
We further extended our work regarding *write-combined access to I/O* memory
to the L4ka::Pistachio base platform. So this platform can now also enjoy the
performance boost that we experienced on the L4/Fiasco platform when enabling
write-combined I/O for the frame buffer.
:Linux:
To enable the dynamic linker to work on Linux the same way as on the other
platforms, we enhanced the Linux-specific *local region manager* to handle an
optional local address and offset when attaching a dataspace.
Thread destruction on Linux works asynchronous by a sending a signal
via the 'tgkill' system call to the thread to be killed. Unfortunately, the
Linux kernel delivers signals only in the kernel-entry path. This means that
after calling 'tgkill', the to-be-killed thread still moves on until it enters
the kernel (either by issuing a system call or when being preempted). This has
the side effect that the thread continues to access its stack for a while. If
killing a thread in the local address space and immediately freeing the stack
of the killed thread by using the 'munmap' system call, the process would
ultimately receive a segmentation fault. To solve this problem, we need to
ensure that the to-be-killed thread is really not executing any instructions
anymore before freeing the stack. We do this by repetitively issuing 'tgkill'
for the thread until an EINVAL error is returned.
:OKL4:
We changed the serial output of core to use the OKL4 kernel debugger for
printing the output of core instead of poking the comports directly. This way,
the console is not anymore x86-specific but platform-independent.
Build system
############
* For debugging Genode applications using the GDB stub of Qemu,
applications should use distinct virtual memory ranges. Otherwise,
breakpoints set in one program would trigger when another program
accesses the breakpointed virtual address. Therefore, we have
introduced the 'LD_TEXT_ADDR' variable to the build system.
A value assigned to this variable in a 'target.mk' file overrides
the default link address.
* The integration of dynamic linking support into the build system
led to some architectural changes. Most importantly, the final linking stage
is now performed by a separate 'make' instance executing 'base/mk/link.mk'.
However, this change has no implications on the use of the build system.
* Generate symbols for marking the end of binary data linked via the
'SRC_BIN' mechanism. The start and end of binary data are marked by the
symbols '_binary_<name>_start' and '_binary_<name>_end'.
* Use 'AS_OPT' also for linking binary data, which is important to make
the resulting object file always compatible with the compiled objects.
This is important on architectures with non-unified calling conventions.