mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-25 08:21:08 +00:00
1048 lines
50 KiB
Plaintext
1048 lines
50 KiB
Plaintext
|
|
||
|
|
||
|
===============================================
|
||
|
Release notes for the Genode OS Framework 14.11
|
||
|
===============================================
|
||
|
|
||
|
Genode Labs
|
||
|
|
||
|
|
||
|
|
||
|
With version 14.11 of the Genode OS framework, we are happy to close one of
|
||
|
the last functional gaps that prevented us from using Genode for our
|
||
|
day-to-day computing needs, namely wireless networking. With the availability
|
||
|
of the Intel wireless stack, Genode becomes suddenly useful on most modern
|
||
|
laptops. With the wireless stack being one of the most complex driver stacks
|
||
|
ported to the framework ever, the undertaking was extremely challenging.
|
||
|
Section [Intel wireless stack] tells the story of how we managed to transplant
|
||
|
the driver stack from Linux to Genode.
|
||
|
|
||
|
The second highlight of the release is the new implementation of a trading
|
||
|
scheme for CPU resources. When Genode was originally designed in 2006, we
|
||
|
envisioned to trade CPU resources between components similarly to how memory
|
||
|
is managed throughout Genode. However, the schedulers of the existing base
|
||
|
platforms did not allow us to realize this idea - until now. With the new
|
||
|
scheduler of our custom base-hw kernel that is described in Section
|
||
|
[Trading CPU time between components using the HW kernel], Genode becomes
|
||
|
finally able to not just assign priorities to subsystems, as already supported
|
||
|
on most kernels of the L4 family, but also to guarantee the provisioning of
|
||
|
processing time to subsystems. This way, we can achieve low interrupt
|
||
|
latencies for untrusted driver code like huge 3rd-party driver stacks, which
|
||
|
would normally require us to assign a high priority (with the risk of starving
|
||
|
other subsystems) to the component. It also allows Genode users to partition
|
||
|
the CPU time between different subsystems in a straight-forward way.
|
||
|
|
||
|
Further highlights of version 14.11 are a new dynamic linker with a code
|
||
|
complexity of less than 20% of the old one, VirtualBox version 4.3.16 with
|
||
|
support for regular vbox configuration files, networking for the Raspberry Pi,
|
||
|
and new GUI components.
|
||
|
|
||
|
|
||
|
Intel wireless stack
|
||
|
####################
|
||
|
|
||
|
Since the very beginning, it was our primary goal to develop the Genode OS
|
||
|
Framework as the basis for a usable general-purpose OS. To achieve this goal,
|
||
|
we have to overcome various obstacles, device-driver support for common
|
||
|
hardware being one of the most tricky jobs. Over the years, we accumulated
|
||
|
driver support for essential devices (PS/2, LAN adapters, USB, ATA/SATA). We
|
||
|
even dared to port the madwifi driver to provide proof-of-concept wireless
|
||
|
network support for Atheros chipsets. Alas, recent Intel-based notebooks come
|
||
|
with wireless chipsets from Intel like the IWL6xxx almost exclusively. Up to
|
||
|
now, Genode lacked support for these devices but since we had great success
|
||
|
with porting existing drivers from Linux in the past, we approached this issue
|
||
|
in classical fashion. We decided to port the _iwlwifi_ driver as well as its
|
||
|
wireless stack from Linux to Genode using the DDE-Linux approach. In addition,
|
||
|
we also ported the _WPA supplicant_ application to enable Wi-Fi Protected
|
||
|
Access (WPA).
|
||
|
|
||
|
In the following, we tell our war story of about six months of struggle,
|
||
|
setbacks, and adventures. We start with presenting our initially vague idea of
|
||
|
a Genode component that would enable us to access protected wireless networks.
|
||
|
The overview is followed by the description of the many steps that were needed
|
||
|
to turn our vague idea into a working component. Finally, we give a glimpse on
|
||
|
the future of the driver and provide quick instructions for using it.
|
||
|
|
||
|
|
||
|
Component overview
|
||
|
==================
|
||
|
|
||
|
[image wifi]
|
||
|
|
||
|
The first figure depicts the _wifi_drv_ component, which consists of four
|
||
|
parts. The first part is the iwlwifi driver, which manages the hardware by
|
||
|
communicating with the firmware that runs on the wireless card. Second, there
|
||
|
is the wireless stack _mac80211_, which performs all IEEE 802.11 related
|
||
|
networking operations including the translation of IEEE 802.11 radio frames to
|
||
|
ordinary 802.3 ethernet frames. Furthermore, there is the WPA supplicant,
|
||
|
which handles the authentication of a client at the access point. Last but not
|
||
|
least, the component has to interface with Genode clients. Therefore, the
|
||
|
wifi_drv implements the NIC session interface, which is used by the TCP/IP
|
||
|
stack to send and receive ethernet frames.
|
||
|
|
||
|
Since wireless networking itself is a comprehensive field, we decided early on
|
||
|
to reuse as much functionality as possible. The following sections will
|
||
|
describe the steps taken in more detail.
|
||
|
|
||
|
|
||
|
Driver
|
||
|
======
|
||
|
|
||
|
In the classical DDE-Linux manner, we started by porting the iwlwifi driver.
|
||
|
Porting a Linux driver is a laborious but essentially a straightforward task.
|
||
|
All needed source files must be added to the _dde_linux_ repository. These
|
||
|
files are normally selected by examining Linux's build configuration for the
|
||
|
driver in Makefile and Kconfig file types. The next step is to create a Linux
|
||
|
emulation environment for the driver. The central piece of this environment is
|
||
|
the _lx_emul.h_ header file. It combines all declarations and data structures,
|
||
|
which are scattered over many header files in the original Linux sources, into
|
||
|
a single file.
|
||
|
|
||
|
Several times during the creation of the emulation environment, a decision has
|
||
|
to be taken whether the original Linux header is used or the declaration is
|
||
|
added to the emulation header. Since we have ported Linux code to Genode
|
||
|
before, e.g., the USB stack and TCP/IP stack, we developed a sense for which
|
||
|
parts of Linux should be taken from the original header files and which parts
|
||
|
are better provided by the emulation header. We also learned by experience
|
||
|
that it is best to keep the number of used original header files as low as
|
||
|
possible. Otherwise future updates become complex and tiresome. The emulation
|
||
|
environment is completed iteratively by extending the header file after each
|
||
|
compile pass. In the end the linker sends his greetings with a long list of
|
||
|
undefined symbols. At this point, we just use a dummy implementation for each
|
||
|
undefined symbol like the following:
|
||
|
|
||
|
!typedef long DUMMY;
|
||
|
!#define DUMMY(retval, name) \
|
||
|
! DUMMY name(void) { \
|
||
|
! if (SHOW_DUMMY) \
|
||
|
! PDBG( #name " called (from %p) not implemented",\
|
||
|
! __builtin_return_address(0)); \
|
||
|
! return retval; \
|
||
|
!}
|
||
|
!
|
||
|
!DUMMY(0, kmalloc)
|
||
|
|
||
|
Most of the symbols the compiler complains about are not needed by our port
|
||
|
anyway. These are merely functions the vanilla Linux kernel uses for
|
||
|
accounting or rather internal book keeping of resources as well as checking
|
||
|
permissions, which are not needed inside our driver component. However, we can
|
||
|
use these dummies to trace the function calls when we execute the component.
|
||
|
Hence, the decision whether to implement or to ignore the function can be
|
||
|
postponed.
|
||
|
|
||
|
The fundamental functionality required by the iwlwifi driver boils down to the
|
||
|
usual PCIe resource allocation, IRQ handling, and DMA mapping as well as
|
||
|
regular memory allocation. On that account, it is worth mentioning that we use
|
||
|
the vanilla 'skbuff' implementation for network-packet buffer management from
|
||
|
Linux. Though we have previously implemented this functionality specifically
|
||
|
for our USB network driver, we saved us the trouble this time. An sk_buff is
|
||
|
allocated by the driver if it receives a packet and is passed to the wireless
|
||
|
stack. The stack, in return, submits sk_buffs to the driver to transmit
|
||
|
packets.
|
||
|
|
||
|
Nowadays, most work in the Linux kernel is done in workqueues in an
|
||
|
asynchronous way by using multiple kernel threads. By contrast, we try to
|
||
|
minimize the usage of threads in our driver ports to minimize the emulation
|
||
|
effort of the manifold synchronization primitives provided by the Linux kernel
|
||
|
API. In fact, we employ cooperative tasks to implement the concurrent
|
||
|
execution of code. Although this approach is more complex because preemption
|
||
|
points must be defined manually, it is worthwhile since debugging becomes much
|
||
|
easier with the absence of actual thread concurrency. In addition, we get away
|
||
|
with implementing certain synchronization primitives like mutexes or the whole
|
||
|
RCU handling in a much simpler way. As a prominent example of simplification,
|
||
|
atomic operations may be implemented as straight assignment statements.
|
||
|
|
||
|
In the original Linux implementation, loading the firmware of the wireless
|
||
|
card is an asynchronous operation to mitigate the effect of delays due to
|
||
|
file-system operations. On Genode, we access the firmware directly via a ROM
|
||
|
connection in the driver server with minimal side effects on other system
|
||
|
servers. Therefore, we execute the assigned callback function directly
|
||
|
accepting the possible delay at the ROM server.
|
||
|
|
||
|
The iwlwifi driver implements the network-device operations needed by the
|
||
|
wireless stack. After the driver loaded the firmware, it initializes the
|
||
|
device and registers itself at the wireless stack.
|
||
|
|
||
|
When using cooperative tasks, it is still important to provide the expected
|
||
|
behavior and semantics of the original execution environment. The iwlwifi
|
||
|
driver handles an IRQ by using the _threaded_irq_ mechanism. Meant as a
|
||
|
replacement for the 'tasklet' mechanism, the top-half is executed in the
|
||
|
interrupt context whereas the bottom-half is executed in a dedicated kernel
|
||
|
thread. For this purpose, our port adds an IRQ task that mimics these
|
||
|
semantics. Up to now, we did not add priorities to our cooperative tasks. In
|
||
|
the usb_drv component, all tasks have the same priority. Unfortunately, we did
|
||
|
not get away that easily in the wifi_drv component and had to employ a
|
||
|
scheduler with priorities.
|
||
|
|
||
|
|
||
|
Mac80211 stack
|
||
|
==============
|
||
|
|
||
|
With the iwlwifi driver experiencing its first successful compilation, it was
|
||
|
time to port the wireless stack of Linux to Genode. The stack consists of the
|
||
|
_mac80211_ layer that abstracts the device handling and takes charge of
|
||
|
converting the 802.11 frames to 802.3 frames. It also handles various
|
||
|
management tasks like beacon frames and rate control. The design of the stack
|
||
|
is highly asynchronous and event driven. In a nutshell, the stack adds
|
||
|
received requests to a workqueue for delayed processing and, hence, remains
|
||
|
recipient for further requests at all times. On request completion, the
|
||
|
originating component will get notified. Received packets in form of sk_buffs
|
||
|
are monitored by the wireless stack and passed to other subsystems by calling
|
||
|
'netif_receive_skb()'.
|
||
|
|
||
|
Most requests are issued by the _cfg80211_ layer, which manages requests from
|
||
|
userspace via a netlink-bus based interface called _nl80211_. For this reason,
|
||
|
we added support for AF_NETLINK by adding the corresponding source files to
|
||
|
the wifi_drv component. While doing so it became clear that we would need to
|
||
|
provide an interface for using netlink from the WPA supplicant. On that
|
||
|
account, we created the 'Socket_call' interface.
|
||
|
|
||
|
|
||
|
Configuration
|
||
|
=============
|
||
|
|
||
|
As mentioned before, the configuration of network devices on Linux is done by
|
||
|
using the Netlink API nowadays. In the context of wireless networking, it
|
||
|
replaces the old 'ioctl()' based _Wireless Extension_ interface with nl80211.
|
||
|
Nl80211 enables the user to configure all wireless related properties
|
||
|
including association with an access point (AP) and scanning for available
|
||
|
networks.
|
||
|
|
||
|
Support for using protected wireless networks on Linux is split between the
|
||
|
kernel and the user space. The so-called supplicant that handles
|
||
|
authentication against a given access point runs in user space whereas the
|
||
|
cryptographic operations on bulk traffic are executed in the kernel. On Linux,
|
||
|
the WPA supplicant is used for the user-space work.
|
||
|
|
||
|
The supplicant scans for available networks and tries to authenticate at a
|
||
|
known network retrieved from the configuration file. After a suitable network
|
||
|
was discovered, the supplicant tries to associate and authenticate at the
|
||
|
access point of the network. If this undertaking is successful, the actual
|
||
|
IEEE 802.1X authentication takes place. Up to this point, the whole
|
||
|
communication with the AP is done unencrypted. While performing the
|
||
|
authentication, the WPA supplicant needs access to the raw EAPoL ethernet
|
||
|
frames, which is provided by Linux via the AF_PACKET protocol. This protocol
|
||
|
is used by the WPA supplicant in its 'l2_packet' back end and, therefore, must
|
||
|
be provided by our driver, too. Since we already implemented the Socket_call
|
||
|
interface, enabling AF_PACKET was a straight-forward procedure. The driver
|
||
|
initializes the af_packet protocol family and switches incoming traffic to its
|
||
|
protocol hook in case of EAPoL frames. All other packets are passed to our NIC
|
||
|
session front end.
|
||
|
|
||
|
Since the WPA supplicant is normally executed in userspace using the _libnl_
|
||
|
library, it depends on a working libc. The Genode libc is a port of the
|
||
|
FreeBSD libc whereas the nl80211 back end of the WPA supplicant expects a
|
||
|
Linux-based user land, i.e., glibc. Therefore, we decided to split up the
|
||
|
supplicant into separate modules, one for the back end and one for the front
|
||
|
end. We created a port of libnl, which uses a specially tailored Linux user
|
||
|
emulation environment similar to the emulation of the kernel environment in
|
||
|
DDE Linux. The libnl emulation implements various socket related functions
|
||
|
like 'socket', 'bind', 'sendto', and 'recvfrom'. These socket functions are
|
||
|
mapped to the internal Socket_call interface, which talks to the kernel parts.
|
||
|
The nl80211 back end driver is linked against this static libnl library. The
|
||
|
WPA supplicant on the other hand is linked against Genode's regular libc. To
|
||
|
make sure that each part can only access the symbols that it is supposed to
|
||
|
see on linking, we use symbol maps like the following for
|
||
|
_wpa_driver_nl80211.lib.so_.
|
||
|
|
||
|
!{
|
||
|
! global:
|
||
|
! /* array containing all drivers, from drivers.c */
|
||
|
! wpa_drivers;
|
||
|
! /* ethernet frame handling, from l2_packet_linux.c */
|
||
|
! l2_packet_*;
|
||
|
! poll;
|
||
|
! local:
|
||
|
! *;
|
||
|
!};
|
||
|
|
||
|
The _wpa_drivers_ array is used by the WPA supplicant to access its internal
|
||
|
driver back end and functions. The 'l2_packet_*' functions are used by the
|
||
|
EAPoL authentication-handling code. The 'poll' function is required by the
|
||
|
supplicant's event handling and therefore mandatory. All file descriptors as
|
||
|
well as sockets opened by the back end are processed by the WPA supplicant.
|
||
|
All other symbols are kept local to prevent the runtime linker from running
|
||
|
into symbol clashes.
|
||
|
|
||
|
|
||
|
NIC session front end
|
||
|
=====================
|
||
|
|
||
|
The front end connects the wifi_drv component to Genode clients. When the
|
||
|
TCP/IP stack of an application wants to send an ethernet frame, it calls the
|
||
|
'Nic::Driver::tx()' method. The component takes the frame and puts it into a
|
||
|
freshly allocated sk_buff. After that, it calls the 'ndo_start_xmit()'
|
||
|
function. This function is part of the 'struct netdev_ops' and is implemented
|
||
|
by the wireless stack. On packet reception, the wireless stack will pass on
|
||
|
the 'sk_buff' by calling 'netif_receive_skb()'. The front end extracts all
|
||
|
data it needs from this 'sk_buff' and copies it into the packet stream.
|
||
|
|
||
|
During development of this complex interplay between the NIC session front end
|
||
|
and the driver, we also had to cope with Linux-internal semantics of the
|
||
|
interface. One prominent example is the handling of head room in the protocol
|
||
|
header data in the sk_buff. Shrinking or expanding the head room at the right
|
||
|
places is crucial. Otherwise, the driver will produce corrupt packets.
|
||
|
|
||
|
|
||
|
The final picture
|
||
|
=================
|
||
|
|
||
|
In summary, it can be stated that the 'wifi_drv' turned out to be more complex
|
||
|
than we anticipated after our first investigations. The final structure of our
|
||
|
port looks like follows.
|
||
|
|
||
|
[image wifi_complete]
|
||
|
|
||
|
The figure depicts our new component that uses three threads: The first thread
|
||
|
executes the WPA supplicant's code, another thread executes the whole Linux
|
||
|
kernel code, and the last thread acts as IRQ handler. The Linux thread
|
||
|
implements a cooperative task model for concurrent kernel tasks, namely the
|
||
|
'irq' task that runs on the highest priority, the 'timer' task, the 'work'
|
||
|
task, the 'socket_call' task, and the 'linux' task.
|
||
|
|
||
|
|
||
|
Roundup
|
||
|
=======
|
||
|
|
||
|
In its current state, the wifi_drv is tested with Intel wireless 6205 and 6300
|
||
|
cards and performs reasonable well for an unoptimized component. Other cards
|
||
|
might also work and could be enabled by editing
|
||
|
_src/lib/wifi/drivers/net/wireless/iwlwifi/pcie/drv.c_ in the
|
||
|
_dde_linux/contrib_ directory manually. The driver does not support changing
|
||
|
the network at the moment. This is merely a limitation of the current
|
||
|
NIC-session interface, though. The link state is not forwarded to the TCP/IP
|
||
|
stack, which therefore will not send a new DHCP request. But, transparent
|
||
|
changes among access points within the same LAN without network
|
||
|
reconfiguration are possible.
|
||
|
|
||
|
The current version of the wifi_drv is one of the most voluminous drivers
|
||
|
ported to date. All in all, it contains about 215,000 lines of 3rd-party code.
|
||
|
The code written to connect this code to Genode amounts to about 8,500 lines
|
||
|
of code while the 'lx_emul.h' header alone takes 3,245 lines. Porting the
|
||
|
whole stack raises the opportunity to enable other wireless drivers in the
|
||
|
future with minimal effort. Furthermore, it should be possible to enable more
|
||
|
userland tools that use the nl80211 interface, for example, a dedicated
|
||
|
wireless-network scanner or even hostapd.
|
||
|
|
||
|
Prior to the wifi_drv component, all ported drivers more or less used the
|
||
|
DDE-Kit library to perform low-level tasks, e.g., PCI, IRQ, and memory
|
||
|
handling. The original idea behind DDE Kit was to provide a C-based API to
|
||
|
ease the porting of drivers, which are mostly written in C whereas Genode is
|
||
|
written in C++. During porting the wireless stack, however, we disregarded DDE
|
||
|
Kit at all and implemented the needed functionality by using Genode primitives
|
||
|
directly. We realized that using a more generic interface like DDE Kit has no
|
||
|
advantages because we had to circumvent it more than once in the past. It
|
||
|
became more of a burden than a blessing. Also, we recognized that the idea of
|
||
|
creating a synergy among various projects utilizing DDE-Linux drivers by
|
||
|
providing a common DDE Kit interface did not came to fruition. So we see no
|
||
|
benefit in using DDE Kit in future driver ports in the future.
|
||
|
|
||
|
In the future, we plan to address the necessary optimization of the driver
|
||
|
component and also want to add a simpler front end to configure the WPA
|
||
|
supplicant. For now, we utilize the regular POSIX front end. Furthermore, the
|
||
|
user has to specify the network prior to starting the driver. A mechanism,
|
||
|
which uses a report session to notify the user about all available networks
|
||
|
and that is able to change the configuration of the WPA supplicant on the fly
|
||
|
is currently under progress.
|
||
|
|
||
|
|
||
|
Usage
|
||
|
=====
|
||
|
|
||
|
The following instructions may help you to get started because using the
|
||
|
driver is somewhat laborious at the moment. For building the driver, you have
|
||
|
to add _drivers/wifi_ and _drivers/rtc_ to the build_components list in your
|
||
|
run script in addition to the normally required components.
|
||
|
|
||
|
For starting the driver, you may use the following configuration snippet as a
|
||
|
starting point:
|
||
|
|
||
|
!<start name="wifi_drv">
|
||
|
! <resource name="RAM" quantum="32M"/>
|
||
|
! <provides><service name="Nic"/></provides>
|
||
|
! <config>
|
||
|
! <libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc">
|
||
|
! <vfs>
|
||
|
! <inline name="wpa_supplicant.conf">
|
||
|
!network={
|
||
|
! ssid="foobar"
|
||
|
! key_mgmt=WPA-PSK
|
||
|
! psk="foobarfoobar"
|
||
|
!}
|
||
|
! </inline>
|
||
|
! <dir name="dev"> <log/> <rtc/>
|
||
|
! <jitterentropy name="random"/>
|
||
|
! <jitterentropy name="urandom"/>
|
||
|
! </dir>
|
||
|
! </vfs>
|
||
|
! </libc>
|
||
|
! </config>
|
||
|
! <route>
|
||
|
! <service name="Rtc"> <any-child /> </service>
|
||
|
! <any-service> <parent/> <any-child /> </any-service>
|
||
|
! </route>
|
||
|
!</start
|
||
|
|
||
|
Since we are using 'wpa_supplicant' to handle all network management, we have
|
||
|
to configure it. As mentioned before, we use the common POSIX configuration
|
||
|
file format for this purpose, and therefore use the same configuration syntax
|
||
|
as on any other OS. By convention, our port of the WPA supplicant is looking
|
||
|
for the configuration in '/wpa_supplicant.conf'. It is provided by creating an
|
||
|
inline file in the VFS configuration section. We provide a _/dev_ directory
|
||
|
populated with all required virtual devices. These devices are needed by
|
||
|
various parts of the WPA supplicant.
|
||
|
|
||
|
To run the driver, we need to add the following binaries to the list of boot
|
||
|
modules:
|
||
|
|
||
|
!rtc_drv vfs_jitterentropy.lib.so
|
||
|
!libc.lib.so libcrypto.lib.so libssl.lib.so
|
||
|
!wifi.lib.so wpa_supplicant.lib.so wpa_driver_nl80211.lib.so
|
||
|
!wifi_drv
|
||
|
|
||
|
Furthermore all Intel wireless cards supported by the 'iwlwifi' driver need a
|
||
|
specific firmware to work. You can download the archives containing the
|
||
|
firmware from [http://wireless.kernel.org/en/users/Drivers/iwlwifi]. The
|
||
|
firmware image also has to be added to the boot module list. If the firmware
|
||
|
is missing, the driver will complain and print an error message:
|
||
|
|
||
|
!Could not open file "iwlwifi-6000-6.ucode"
|
||
|
|
||
|
A exemplary run script can be found in _repos/dde_linux/run/wifi.run_.
|
||
|
|
||
|
|
||
|
Trading CPU time between components using the HW kernel
|
||
|
#######################################################
|
||
|
|
||
|
Up to the last Genode release, CPU scheduling in the HW-kernel was a matter of
|
||
|
absolute priority bands, each doing a round-robin schedule over all tasks with
|
||
|
the respective priority. While being pretty fast and manageable, this scheme
|
||
|
also had its disadvantages: First, there was no way to prevent
|
||
|
high-prioritized tasks from starving less important ones. Second, CPU time
|
||
|
could not be granted to tasks and passed between them by the means of quota.
|
||
|
To cope with these problems without much loss of performance, we decided to
|
||
|
come up with a new scheduler whose design was developed with the new feature
|
||
|
set in mind right from the start.
|
||
|
|
||
|
The new scheduler introduces the distinction between high-throughput-oriented
|
||
|
scheduling contexts - which we shortly call "fills" - and low-latency-oriented
|
||
|
scheduling contexts - called "claims". Examples for a typical fill would be
|
||
|
the processing of a GCC job or the rendering computations of a sophisticated
|
||
|
graphics program. They shall obtain as much CPU time as the system can spare
|
||
|
but there is no demand for a high responsiveness. In contrast, a good example
|
||
|
for the claim category would be a typical GUI-software stack covering the
|
||
|
control flow from user-input drivers through a chain of GUI components to the
|
||
|
drivers of the graphical output. Another example is a user-level device driver
|
||
|
that has to quickly respond to sporadic interrupts but is otherwise untrusted.
|
||
|
The low latency of such components is a key factor for usability and quality
|
||
|
of service. Besides introducing the distinction between "claim" and "fill"
|
||
|
scheduling contexts, we introduced the notion of a so-called "super period",
|
||
|
i.e., in the current version it is one second. The entire super period
|
||
|
corresponds to 100% of the CPU time of one CPU. Portions of it can be assigned
|
||
|
to scheduling contexts. A CPU quota thereby corresponds to a percentage of the
|
||
|
super period.
|
||
|
|
||
|
At the beginning of a super period, each claim has its full amount of assigned
|
||
|
CPU quota. The priority defines the absolute scheduling order within the super
|
||
|
period among those claims that are active and have quota left. As long as
|
||
|
there exist such claims, the scheduler stays in the claim mode and the quota
|
||
|
of the scheduled claims decreases. At the end of a super period, the quota of
|
||
|
all claims gets refreshed to the initial value. Every time the scheduler can't
|
||
|
find an active claim with CPU-quota left, it switches to the fill mode. Fills
|
||
|
are scheduled in a simple round-robin fashion with identical time slices. The
|
||
|
proceeding of the super period doesn't affect the scheduling order and
|
||
|
time-slices of this mode. The concept of quota and priority that is
|
||
|
implemented through the claim mode aligns nicely with Genode's way of
|
||
|
hierarchical resource management: Through CPU-sessions, each process becomes
|
||
|
able to assign portions of its CPU time and subranges of its priority band to
|
||
|
its children without knowing the global means of CPU time or priority.
|
||
|
|
||
|
Whereas the management of priorities was already existent at the thread and
|
||
|
CPU-session API, the management of CPU quota is new to these components. While
|
||
|
extending Genode's resource trading to CPU time, we closely followed the
|
||
|
existing patterns of how RAM quota is managed among RAM sessions. In the init
|
||
|
configuration, one can configure the assignment of CPU time via "resource"
|
||
|
tags that have the attribute "name" set to "CPU" and the attribute "quantum"
|
||
|
set to the percentage of CPU quota that init shall assign. The pattern is the
|
||
|
same as when donating RAM quota.
|
||
|
|
||
|
! <start name="test">
|
||
|
! <resource name="CPU" quantum="75"/>
|
||
|
! </start>
|
||
|
|
||
|
This example configuration would cause init to try donating 75% of its CPU
|
||
|
quota to the child "test". Be aware that init and core do not preserve CPU
|
||
|
quota for their own requirements by default as it is done with RAM quota.
|
||
|
Hence, the configuration should consider such preservations if required. If no
|
||
|
preservation is configured, init and core depend on someone not using its
|
||
|
quota to the full extend or someone donating its quota temporarily on, e.g.,
|
||
|
IPC to a core service.
|
||
|
|
||
|
! <start name="init2">
|
||
|
! <resource name="CPU" quantum="50"/>
|
||
|
! ...
|
||
|
! <config>
|
||
|
! ...
|
||
|
! <start name="test">
|
||
|
! <resource name="CPU" quantum="50"/>
|
||
|
! </start>
|
||
|
! </config>
|
||
|
! <start>
|
||
|
|
||
|
This example configuration would result in process "init2" receiving 50% of
|
||
|
the CPU quota and process "test" receiving 50% of the CPU quota of "init2". So
|
||
|
both processes have 25% of the overall CPU time at disposal.
|
||
|
|
||
|
Once a process owns CPU quota, the process can apply it at the construction of
|
||
|
local threads. For this purpose, the thread constructor has been enhanced by
|
||
|
an argument that indicates the percentage of the program's CPU quota that
|
||
|
shall be assigned. So 'Thread(33, "test")' would cause the backing CPU session
|
||
|
to try granting 33% of the component's CPU quota to the new thread "test".
|
||
|
Note that the CPU quota of a thread can't be altered after construction for
|
||
|
now. A new thread participates in CPU scheduling with a context for only the
|
||
|
fill mode if the CPU quota is specified with 0 or not at all to the thread
|
||
|
constructor. That doesn't mean that such threads are never scheduled. But they
|
||
|
have no guarantee to receive CPU time during a super period and their priority
|
||
|
is ignored at all. If a thread gets constructed with a quota greater than 0,
|
||
|
it participates in CPU scheduling with a context for both claim and fill mode.
|
||
|
The claim context then uses the specified quota and priority as mentioned
|
||
|
earlier.
|
||
|
|
||
|
|
||
|
Base framework
|
||
|
##############
|
||
|
|
||
|
New dynamic linker
|
||
|
==================
|
||
|
|
||
|
In 2010, we added dynamic linking support to Genode. This enabled Genode to
|
||
|
load and share libraries among programs at runtime. Since, at the time, we did
|
||
|
not have a whole lot of experience with dynamic linking and dynamic ELF
|
||
|
loading, we decided to port FreeBSD's linker (rtld) to Genode. Up to this
|
||
|
point, the old linker has served its purpose well on all supported kernels and
|
||
|
hardware architectures.
|
||
|
|
||
|
Nevertheless, we were a little worried because it was hard to understand the
|
||
|
linker's internals and we did not want to trust a vital piece of code that we
|
||
|
could not comprehend in full. Also, the old linker heavily depended on libc
|
||
|
and C-style POSIX semantics, which we had to emulate in order to get the
|
||
|
program working.
|
||
|
|
||
|
As one of Genode's midterm goals is making most Genode applications binary
|
||
|
compatible for microkernels that support the same hardware architecture and
|
||
|
for the reasons above, we decided to implement a Genode specific linker. Our
|
||
|
future goal is to keep all kernel-dependent code within the linker (making it
|
||
|
kernel dependent) and to link Genode applications against this new version of
|
||
|
the linker (thus, making them kernel independent).
|
||
|
|
||
|
Genode's new dynamic linker can be found in _repos/base/src/lib/ldso_. It is a
|
||
|
drop-in replacement for the old linker, which has been removed from Genode's
|
||
|
source tree. The linker provides all the functionality the FreeBSD version
|
||
|
did: Loading and construction of shared libraries, a shared-object interface
|
||
|
(_repos/base/include/base/shared_object.h_) that is comparable to the DL
|
||
|
interface (dlopen, dlsym and friends), link map, and GDB debugging support.
|
||
|
The linker is entirely written in C++ and with a code size of about 1800 lines
|
||
|
significantly smaller then the old version with about 8000 code lines
|
||
|
including the emulation layer.
|
||
|
|
||
|
|
||
|
Low-level OS infrastructure
|
||
|
###########################
|
||
|
|
||
|
Graphics helpers for operating on alpha channels
|
||
|
================================================
|
||
|
|
||
|
For realizing graphical applications that are security critical, we wish to
|
||
|
avoid the complexity of sophisticated tool kits like Qt5. To ease the
|
||
|
development of such Genode-specific graphical applications, we introduced a
|
||
|
few common low-level interfaces and utilities for graphics in
|
||
|
[http://genode.org/documentation/release-notes/14.02#Unified_interfaces_for_graphics - version 14.02].
|
||
|
|
||
|
The current version refines those utilities with added support for layering
|
||
|
graphics using alpha channels. There is a new ALPHA8 pixel format that can be
|
||
|
used to apply graphics operations on alpha-channels. Furthermore, the new
|
||
|
'Texture_rgb565' and 'Texture_rgb888' types provide pixel conversion functions
|
||
|
for those common texture formats. This way, ordered dithering is automatically
|
||
|
applied when importing pixel data to a RGB565 texture.
|
||
|
|
||
|
|
||
|
Nitpicker GUI server
|
||
|
====================
|
||
|
|
||
|
The fundamental premise of the Nitpicker GUI server is to isolate GUI clients
|
||
|
from each other. However, there are situations where the user wants to issue
|
||
|
operations spanning multiple clients, for example hiding all views of a
|
||
|
subsystem regardless of how many clients are running within the subsystem.
|
||
|
|
||
|
Such operations should be applied to the global view stack to maintain the
|
||
|
global view stacking order when hiding and subsequently un-hiding subsystems.
|
||
|
To realize this functionality, nitpicker's session interface has been enhanced
|
||
|
by a new 'session_control' function. The function takes a session label and an
|
||
|
operation as arguments, and performs a control operation on one or multiple
|
||
|
sessions. The label is used to select the sessions, on which the operation is
|
||
|
applied. Internally, nitpicker creates a selector string by concatenating
|
||
|
the caller's session label with the supplied label argument. A session is
|
||
|
selected for the operation if its label starts with the selector string.
|
||
|
Thereby, the operation is limited to the caller session or any child session
|
||
|
of the caller. The supported control operations are the hiding of sessions,
|
||
|
the un-hiding of sessions, and the move of session views to the front of the
|
||
|
view stack while maintaining their partial order.
|
||
|
|
||
|
To enable the user to unambiguously identify the applications on screen,
|
||
|
nitpicker provides an X-ray mode that can be activated by the user at any
|
||
|
time. To enable a trusted application such as a panel to respond to the
|
||
|
activation of the X-ray mode, nitpicker has gained an option to report the
|
||
|
currently active mode to a report session. Furthermore, the user-input
|
||
|
handling was slightly refined to accommodate such trusted applications. While
|
||
|
X-ray mode is active, nitpicker filters motion events that are not referring
|
||
|
to the currently focused domain. However, domains configured as xray="no"
|
||
|
(such as a panel) need to obtain motion events regardless of the xray mode. So
|
||
|
we relaxed the motion-event filtering to accommodate such clients.
|
||
|
|
||
|
|
||
|
Nitpicker fader
|
||
|
===============
|
||
|
|
||
|
Some graphical applications should not be visible at all times but only when
|
||
|
needed, for example an on-screen display that is visible only when the user
|
||
|
changes the volume. To realize such applications on top of nitpicker,
|
||
|
nitpicker could provide support for toggling the visibility of views. But
|
||
|
adding view fading to nitpicker would increase nitpicker's complexity just for
|
||
|
the sake of visual presentation. Also, the fading/unfading would be limited to
|
||
|
whatever support nitpicker would provide. Alternatively, the fading could be
|
||
|
implemented in the respective nitpicker client. But this way, each client that
|
||
|
could potentially be used in an on-demand way had to be enhanced with a fading
|
||
|
feature. For example, an on-demand visible terminal could be useful in some
|
||
|
scenarios. So the terminal had to be enhanced.
|
||
|
|
||
|
Being component-based, Genode provides another alternative: The introduction
|
||
|
of a separate component that wraps the nitpicker session interface. The new
|
||
|
nit_fader sits in-between nitpicker and a client, and applies alpha-blending
|
||
|
to the client's virtual framebuffer. It is entirely optional and requires no
|
||
|
changes in nitpicker or any client. Because it can be instantiated per client,
|
||
|
it does not compromise the security of nitpicker. Even though it can access
|
||
|
the pixel data and the user input designated for a particular client, it
|
||
|
cannot leak this information to other clients. Therefore, the implementation
|
||
|
complexity of this component is not critical for confidentiality.
|
||
|
|
||
|
[image nit_fader_screenshot]
|
||
|
|
||
|
The current version of nit_fader obtains the alpha-blending value from its
|
||
|
configuration. It is able to dynamically respond to configuration changes. If
|
||
|
the configured alpha value changes, it performs a smooth transition between
|
||
|
the old and the new alpha value.
|
||
|
|
||
|
|
||
|
Growing tool kit for low-complexity GUI applications
|
||
|
====================================================
|
||
|
|
||
|
With the current release, we continue our line of GUI-related work started in
|
||
|
[http://genode.org/documentation/release-notes/14.08#New_GUI_architecture - version 14.08].
|
||
|
As a side product of implementing low-complexity GUI components directly on
|
||
|
Genode instead of using existing GUI tool kits, a library of common utilities
|
||
|
is evolving. The utilities are not strictly GUI-related but also cover the
|
||
|
construction of multi-process applications.
|
||
|
|
||
|
|
||
|
:'gems/animator.h':
|
||
|
|
||
|
A utility for the smooth interpolation between two integer values. As the
|
||
|
interpolation is not linear, it is suitable for fading effects. It is used
|
||
|
by the scout widgets, the window decorator, the new nit_fader, and the
|
||
|
new menu view.
|
||
|
|
||
|
:'gems/chunky_texture.h':
|
||
|
|
||
|
A texture with its backing store allocated from a RAM session.
|
||
|
|
||
|
:'gems/file.h':
|
||
|
|
||
|
A simple utility for obtaining the content of a file as a buffer.
|
||
|
|
||
|
:'gems/local_reporter.h':
|
||
|
|
||
|
A utility for creating reports to a local report session. It is useful for
|
||
|
components that host a local report service, for example the window manager
|
||
|
or the new launcher application.
|
||
|
|
||
|
:'gems/png_image.h':
|
||
|
|
||
|
A utility that provides the pixel data of a PNG image as a texture. Its
|
||
|
main purpose is hiding the peculiarities of libpng and the life-time
|
||
|
management of the involved memory allocations behind a simple interface.
|
||
|
|
||
|
:'gems/report_rom_slave.h':
|
||
|
|
||
|
A utility for instantiating a local report-rom service as a child process.
|
||
|
It is used by the window manager and the new launcher application.
|
||
|
|
||
|
:'gems/single_session_service.h':
|
||
|
|
||
|
A utility for providing a locally implemented session as a service to a
|
||
|
child process. It is useful for virtualizing services when hosting other
|
||
|
components as child processes.
|
||
|
|
||
|
:'gems/texture_utils.h':
|
||
|
|
||
|
Utilities for scaling a texture and for converting textures between
|
||
|
different pixel formats.
|
||
|
|
||
|
:'gems/wrapped_nitpicker_session.h':
|
||
|
|
||
|
A default implementation of a wrapped nitpicker session that can be used to
|
||
|
selectively override a few functions of nitpicker's session interface while
|
||
|
delegating all other functions to the wrapped nitpicker session.
|
||
|
|
||
|
:'gems/xml_anchor.h':
|
||
|
|
||
|
A utility for converting an "anchor" XML attribute to a convenient object.
|
||
|
|
||
|
:'cli_monitor/ram.h':
|
||
|
|
||
|
A utility for managing RAM among a number of child processes.
|
||
|
|
||
|
:'cli_monitor/child.h':
|
||
|
|
||
|
A utility for creating child processes while dynamically managing their
|
||
|
RAM resources.
|
||
|
|
||
|
As a note of caution, the API of those utilities should not be expected to be
|
||
|
stable. It is likely to change during the further evolution of Genode's GUI
|
||
|
architecture.
|
||
|
|
||
|
|
||
|
New menu view application
|
||
|
=========================
|
||
|
|
||
|
The new menu view application generates a simple dialog of widgets and reports
|
||
|
the hovered element. It is meant to be embedded into applications that require
|
||
|
simple GUIs but don't want to deal with the complexities of a full-blown
|
||
|
widget set.
|
||
|
|
||
|
The menu view takes a description of the dialog in the form of a ROM session
|
||
|
with XML data, for example:
|
||
|
|
||
|
! <dialog>
|
||
|
! <frame>
|
||
|
! <vbox>
|
||
|
! <button name="virtualbox">
|
||
|
! <label text="VirtualBox"/>
|
||
|
! </button>
|
||
|
! <button name="toolchain" hovered="yes">
|
||
|
! <label text="Tool chain"/>
|
||
|
! </button>
|
||
|
! <button name="log" hovered="yes" selected="yes">
|
||
|
! <label text="Log window"/>
|
||
|
! </button>
|
||
|
! <button name="config" selected="yes">
|
||
|
! <label text="Configuration"/>
|
||
|
! </button>
|
||
|
! </vbox>
|
||
|
! </frame>
|
||
|
! </dialog>
|
||
|
|
||
|
Given such a description, it renders a pixel representation of the dialog and
|
||
|
provides the result to a nitpicker session. The application dynamically
|
||
|
responds to changes of the XML model and thereby applies state transitions of
|
||
|
dialog elements. It does not perform any application logic. Even the hovering
|
||
|
of dialog elements is out of the scope of the menu view. However, the menu
|
||
|
view receives user input for its nitpicker session. It evaluates the user
|
||
|
input to determine the currently hovered widget and reports this information
|
||
|
to a report session. This way, the parent process of a menu view can implement
|
||
|
arbitrary application logic of a GUI application without dealing with any
|
||
|
graphical operations.
|
||
|
|
||
|
In the current form, the menu view is limited to fulfill the requirements of
|
||
|
the new launcher application. Hence, it solely provides a frame, button, and
|
||
|
label widget as well as a vertical box-layout widget. For experimenting with
|
||
|
the new menu view, there exists a run script at _gems/run/menu_view.run_.
|
||
|
|
||
|
|
||
|
New launcher application
|
||
|
========================
|
||
|
|
||
|
The new launcher application located at _gems/src/app/launcher/_ is a poster
|
||
|
child of a multi-process GUI application on Genode. Similar to the existing
|
||
|
launchpad, it can be used to dynamically start and kill subsystems. But in
|
||
|
contrast to the launchpad, which contained a widget library, the new launcher
|
||
|
delegates the (potentially complex and bug-prone) graphics processing to a
|
||
|
sandboxed child process (the menu view). The launcher is able to toggle
|
||
|
visibility of the dialog using the new nit_fader component, which is
|
||
|
instantiated as a child process as well. Thanks to this multi-process
|
||
|
technique, the complexity of the actual launcher, which needs to be ultimately
|
||
|
trusted by all launched subsystems, remains low and thereby trustworthy.
|
||
|
|
||
|
In addition to being able to start and kill subsystems, the launcher uses
|
||
|
nitpicker's new session-control interface (see Section [Nitpicker GUI server])
|
||
|
for toggling the visibility of subsystems. The new launcher can be explored
|
||
|
with the run script _gems/run/launcher.run_.
|
||
|
|
||
|
|
||
|
New input merger
|
||
|
================
|
||
|
|
||
|
The new input merger component allows the aggregation of user-input events
|
||
|
from an arbitrary number of sources. The aggregated stream of events is
|
||
|
provided as a single input session. Thereby, it allows the merging of user
|
||
|
input of multiple device drivers such as USB HID and PS/2 into one stream to
|
||
|
be consumed by a single component such as the nitpicker GUI server.
|
||
|
|
||
|
The input merger is located at _os/src/server/input_merger/_. Please refer to
|
||
|
the accompanied README file for configuring the component.
|
||
|
|
||
|
|
||
|
Libraries and applications
|
||
|
##########################
|
||
|
|
||
|
Improved Qt5 integration
|
||
|
========================
|
||
|
|
||
|
Genode's Qt5 support received optimizations as well as the ability for Qt5
|
||
|
application to participate in the window-resizing protocol of the window
|
||
|
manager. So, Qt5 windows can be resized by dragging their respective window
|
||
|
borders.
|
||
|
|
||
|
|
||
|
Runtime environments
|
||
|
####################
|
||
|
|
||
|
VirtualBox
|
||
|
==========
|
||
|
|
||
|
Since the last release, we intensively tested and stabilized VirtualBox on
|
||
|
Genode. We found several issues regarding the FPU handling and virtual TLB
|
||
|
flush handling, which caused VMs to just stop after a while. Additionally, we
|
||
|
enabled the missing VM-reboot feature and improved the handling of those VM
|
||
|
exits that caused the recompiler of VirtualBox to be used unnecessarily. As
|
||
|
the result of our stability improvements, we have become able to run VMs on
|
||
|
VirtualBox 4.2 for days without any trouble.
|
||
|
|
||
|
The second part of our work on VirtualBox deals with upgrading from version
|
||
|
4.2.24 to a recent 4.3 version. Our motivation was twofold: On the one hand,
|
||
|
VirtualBox 4.3 supports Windows 8 and multi-touch input pretty well, and on
|
||
|
the other hand, the (user) front end we used in our 4.2 port has limited
|
||
|
support to configure all the variations of virtual hardware setups that we
|
||
|
desire.
|
||
|
|
||
|
With the port to version 4.3.16 of VirtualBox, we now support the
|
||
|
configuration of VMs using VirtualBox .vbox files. These files are generated
|
||
|
as a result of creating and configuring a VM in the VirtualBox GUI. Such .vbox
|
||
|
files contain all features the virtual hardware should provide to a Guest VM.
|
||
|
In principal, a user of VirtualBox on Windows/Linux/MacOS is now able to
|
||
|
transfer the very same VM configuration over to Genode. An example
|
||
|
configuration for a setup with a shared folder between Guest VM and the Genode
|
||
|
world as well as networking looks as follows.
|
||
|
|
||
|
! ...
|
||
|
! <start name="ram_fs">
|
||
|
! ...
|
||
|
! </start>
|
||
|
! <start name="nic_drv">
|
||
|
! ...
|
||
|
! </start>
|
||
|
! ...
|
||
|
! <start name="virtualbox">
|
||
|
! <resource name="RAM" quantum="2G"/
|
||
|
! <config vbox_file="my.vbox" vm_name="MyVM">
|
||
|
! <libc stdout="/dev/log" stderr="/dev/log">
|
||
|
! <vfs>
|
||
|
! <dir name="dev"> <log/> </dir>
|
||
|
! <rom name="my.vbox" />
|
||
|
! <dir name="vbox"> <fs label="share_with_vbox"/> </dir>
|
||
|
! </config>
|
||
|
! <route>
|
||
|
! <service name="File_system">
|
||
|
! <if-arg key="label" value="share_with_vbox" /> <child name="ram_fs"/>
|
||
|
! </service>
|
||
|
! </route>
|
||
|
! </start>
|
||
|
! ...
|
||
|
|
||
|
The corresponding my.vbox looks like this:
|
||
|
|
||
|
! ...
|
||
|
! <VirtualBox ...>
|
||
|
! <Machine ...>
|
||
|
! <Hardware ...>
|
||
|
! ...
|
||
|
! <SharedFolders>
|
||
|
! <SharedFolder name="genode" hostPath="/vbox" writable="true" autoMount="true"/>
|
||
|
! <SharedFolders>
|
||
|
! <Network>
|
||
|
! <Adapter slot="0" enabled="false" MACAddress="0800271D7901" cable="true" speed="0" type="82540EM">
|
||
|
! <HostInterface/>
|
||
|
! </Adapter>
|
||
|
! ...
|
||
|
! </Network>
|
||
|
! ...
|
||
|
! </Hardware ...>
|
||
|
! </Machine ...>
|
||
|
! ...
|
||
|
! </VirtualBox>
|
||
|
|
||
|
In Genode, the ram_fs server is used to provide a directory called "/vbox" to
|
||
|
the VirtualBox VMM instance. In the Guest VM, this directory will appear as
|
||
|
"genode" and is mounted writable. As network adapter, we support E1000 and
|
||
|
PCNet. As network back end (provided by the host, which is Genode) we
|
||
|
currently support solely the "HostInterface" XML tag, which uses a
|
||
|
Genode-specific implementation using Genode's NIC-session interface. The MAC
|
||
|
address configured in the .vbox file remains unused. Instead, the MAC address
|
||
|
provided by the NIC server will be used. MAC addresses can be configured e.g.
|
||
|
in the Genode bridge directly for each NIC client.
|
||
|
|
||
|
|
||
|
Updated Seoul virtual machine monitor
|
||
|
=====================================
|
||
|
|
||
|
During Genode's Hack-and-Hike event, we met our long-term friend and former
|
||
|
university colleague Bernhard Kauer. Besides the nice time during the event,
|
||
|
it was also beneficial for the Seoul VMM on Genode. Bernhard reported about
|
||
|
his work on extending the virtual BIOS emulation in his Vancouver VMM. With
|
||
|
his recent changes, the VGA model becomes able to detect and emulate VESA
|
||
|
switching attempts as performed by code inside the VM. Xorg servers as well as
|
||
|
Genode use the x86emu library to emulate 16bit code of the Video BIOS provided
|
||
|
by the graphics card and system BIOS. Normally, this code contains
|
||
|
vendor-specific real mode instructions to perform the VESA mode switching.
|
||
|
Because the original version of Seoul did not provide any real-mode code as
|
||
|
Video BIOS, X.org's VESA driver could not work.
|
||
|
|
||
|
To benefit from Bernhard's work, we ported his changes over to the Seoul VMM,
|
||
|
which turned out to be easily doable since Seoul originated from Vancouver.
|
||
|
With the changes in place, we are now able to easily reuse existing Linux VMs
|
||
|
and we are also able to boot graphical Genode setups in Seoul. The run script
|
||
|
_repos/ports/run/seoul-genode.run_ showcases how to start Genode x86 setups
|
||
|
created by any other Genode run script directly as Guest VM inside Seoul.
|
||
|
|
||
|
|
||
|
Device drivers
|
||
|
##############
|
||
|
|
||
|
DDE Linux
|
||
|
=========
|
||
|
|
||
|
With the addition of the WIFI driver to the DDE Linux repository, we decided
|
||
|
to do some cleanup within DDE Linux. First of all, we did not want to share
|
||
|
any Linux files between the drivers. So we moved the USB stack, LXIP, and the
|
||
|
WIFI drivers to different _src/lib/_ directories within _contrib/dde_linux/_.
|
||
|
So, we are now able to individually update the used kernel version for a
|
||
|
single DDE Linux driver with no side effects to other ported drivers. We
|
||
|
mostly update drivers to gain support for recent hardware like the WIFI
|
||
|
driver. After the split, we reverted LXIP to Linux version 3.9. because it
|
||
|
generally runs more stable and is better tested with this kernel version.
|
||
|
|
||
|
|
||
|
Raspberry Pi
|
||
|
============
|
||
|
|
||
|
Genode added principle support for the Raspberry Pi one year ago in
|
||
|
[http://genode.org/documentation/release-notes/13.11#Raspberry_Pi - version 13.11].
|
||
|
Back then, the driver support covered the interrupt controller, timer, UART,
|
||
|
display, and USB. The latter was particularly challenging because the DWC-OTG
|
||
|
USB host controller lacked public documentation. Hence, we ported the driver
|
||
|
from the official Raspberry-Pi Linux kernel, which principally allowed Genode
|
||
|
to support HID devices and thereby enabled interactive applications. However,
|
||
|
the USB driver dramatically impeded the performance of the system because the
|
||
|
host controller triggered an interrupt for each USB microframe, which results
|
||
|
in a rate of 8000 interrupts per second. This is already pretty bad for an OS
|
||
|
based on a monolithic kernel but it is overkill for a microkernel-based system
|
||
|
where each interrupt is delivered as an IPC message with the associated
|
||
|
context-switch costs.
|
||
|
|
||
|
:In-kernel USB SOF interrupt filtering:
|
||
|
|
||
|
For Linux, the Raspberry Pi developers relieved the problem by adding a fast
|
||
|
path for the highly frequent USB start-of-frame (SOF) interrupts. Each USB
|
||
|
interrupt is served by a low-footprint routine executed as a so-called "fast
|
||
|
interrupt" (FIQ) handler. Only if the frame number reaches a value that is
|
||
|
scheduled by the USB driver, the handler will trigger an artificial interrupt
|
||
|
to activate the actual USB driver. Those "interesting" interrupts occur at a
|
||
|
rate that is more than an order of magnitude lower than the SOF interrupt
|
||
|
rate.
|
||
|
|
||
|
Unfortunately, this optimization cannot be used as is on Genode where the USB
|
||
|
driver lives in user land and lacks the privileges to install a FIQ handler.
|
||
|
But the approach to hide SOF interrupts from the USB driver was worth
|
||
|
investigating. We decided to split the USB driver into two parts. One part is
|
||
|
the actual driver ported from Linux but without the FIQ optimization. With
|
||
|
more than 30,000 lines of code, this part is highly complex but it lives as an
|
||
|
unprivileged user process. The second part is a small USB SOF filter routine
|
||
|
that is integrated into the interrupt-controller driver in the base-hw
|
||
|
microkernel. The filter adds merely 100 lines of code to the kernel. Both the
|
||
|
USB driver and the in-kernel SOF filter access the physical DWC-OTG
|
||
|
controller. Each time when the USB driver schedules a micro frame, it writes
|
||
|
the frame number to an unused scratch register of the host controller. When an
|
||
|
USB interrupt comes in, the in-kernel SOF filter compares the current frame
|
||
|
number with the number reported by the USB driver. Only if the current frame
|
||
|
corresponds to the next scheduled frame, the filter propagates the interrupt
|
||
|
to the user-level USB driver. This way, the USB driver is activated only for
|
||
|
handling interesting events. Even though this optimization is not as
|
||
|
sophisticated as the FIQ optimization found in the Linux kernel, it is highly
|
||
|
effective compared to the original version while staying true to the
|
||
|
microkernel architecture.
|
||
|
|
||
|
With the USB SOF filter in place, the interactive performance of Genode on the
|
||
|
Raspberry Pi has reached a decent level. Furthermore, we could enable
|
||
|
networking. Using lwIP running separated from the USB network driver, netperf
|
||
|
reports a throughput of 50 MBit/second, which we find acceptable for this
|
||
|
platform.
|
||
|
|
||
|
:Framebuffer driver:
|
||
|
|
||
|
To accommodate the use of translucent nitpicker views as well as SDL
|
||
|
applications such as Supertux, we enhanced the framebuffer driver with an
|
||
|
configurable buffered mode. If enabled, the driver keeps the client pixels in
|
||
|
a separate pixel buffer that is copied to the physical frame buffer not before
|
||
|
the client explicitly issues a refresh operation. This way, intermediate
|
||
|
drawing states remain hidden from the user.
|
||
|
|
||
|
|
||
|
Default mode selection of VESA driver
|
||
|
=====================================
|
||
|
|
||
|
Unless explicitly configured to a specific resolution, the VESA driver used to
|
||
|
set a mode of 1024x768. When using a Genode system image across machines with
|
||
|
different displays, we had to provide different configurations to accommodate
|
||
|
the variety of displays. Because we longed for a way to let Genode
|
||
|
automatically adapt to the native display resolution, we changed the VESA
|
||
|
driver to pick the video mode with the highest resolution from the list of
|
||
|
available modes.
|
||
|
|
||
|
This works well if Genode is used on laptops because the native display
|
||
|
resolution is typically reported as the highest available mode. Unfortunately,
|
||
|
when using VGA, the highest available mode usually exceeds the native
|
||
|
resolution of the connected output device such as a data projector. In this
|
||
|
case, the default mode can be overridden by explicitly specifying a mode in
|
||
|
the configuration.
|
||
|
|
||
|
|
||
|
Build system and tools
|
||
|
######################
|
||
|
|
||
|
Updated tool chain
|
||
|
==================
|
||
|
|
||
|
The tool-chain has been updated to version 4.7.4, which fixes problems with
|
||
|
executing the tool-chain build script on the current version of Ubuntu Linux.
|
||
|
|
||
|
|
||
|
Improved tooling for using Intel AMT
|
||
|
====================================
|
||
|
|
||
|
We use Intel Active Management Technology (AMT) on diverse native test
|
||
|
hardware to forward serial output over network (SOL) to developer machines and
|
||
|
to power-on, reset, and power-off test machines. Until now, we used the tool
|
||
|
amttool, which uses a SOAP EOI protocol for communication. Newer hardware with
|
||
|
AMT version 9 or higher dropped the support for SOAP EOI - read
|
||
|
[https://software.intel.com/en-us/blogs/2012/12/01/intel-amt-wsman-interface-is-replacing-the-soapeoi-interface - a blog entry by Intel]
|
||
|
for more details - switched to the
|
||
|
[http://www.dmtf.org/standards/wsman - WSMAN interface]. The tool wsman on
|
||
|
Linux speaks the protocol and can be used as a replacement. We integrated the
|
||
|
support of wsman into our run tool infrastructure and use it by default if
|
||
|
installed - otherwise amttool will be used. Of course, you can enforce your
|
||
|
preferred tool by setting the RUN_OPT variable in your build.conf file or as
|
||
|
an environment variable accordingly, e.g.
|
||
|
|
||
|
! RUN_OPT="--target amt --amt-tool wsman" make run/printf
|
||
|
or
|
||
|
! RUN_OPT="--target amt --amt-tool amttool" make run/printf
|