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.
274 lines
12 KiB
274 lines
12 KiB
|
|
================================== |
|
Genode on the Codezero microkernel |
|
================================== |
|
|
|
|
|
Norman Feske |
|
|
|
|
|
Codezero is a microkernel primarily targeted at ARM-based embedded systems. |
|
It is developed by the British company B-Labs. |
|
|
|
:B-Labs website: |
|
|
|
[http://b-labs.co.uk] |
|
|
|
The Codezero kernel was first made publicly available in summer 2009. The |
|
latest version, documentation, and community resources are available at the |
|
project website: |
|
|
|
:Codezero project website: |
|
|
|
[http://l4dev.org] |
|
|
|
As highlighted by the name of the project website, the design of the kernel is |
|
closely related to the family of L4 microkernels. In short, the kernel provides |
|
a minimalistic set of functionality for managing address spaces, threads, and |
|
communication between threads, but leaves complicated policy and device access |
|
to user-level components. |
|
|
|
|
|
Using Genode with Codezero |
|
########################## |
|
|
|
For using Codezero, please ensure to have Git, SCons, and Python installed as |
|
these tools are required for downloading and building the kernel. Furthermore, |
|
you will need to install the tool chain for ARM. For instructions on how to |
|
download and install the tool chain, please refer to: |
|
|
|
:[http://genode.org/download/tool-chain]: |
|
Genode tool-chain |
|
|
|
To download the Codezero kernel and integrate it with Genode, issue |
|
|
|
! make prepare |
|
|
|
from the 'base-codezero/' directory. The Codezero kernel is fully supported by |
|
Genode's run mechanism. Therefore, you can run Genode scenarios using Qemu |
|
directly from the build directory. For a quick test, let's create a build |
|
directory for Codezero on the VersatilePB926 platform using Genode's |
|
'create_builddir' tool: |
|
|
|
! <genode-dir>/tool/create_builddir codezero_vpb926 BUILD_DIR=<build_dir> |
|
|
|
To execute the graphical Genode demo, change to the new created build directory |
|
and issue: |
|
|
|
! make run/demo |
|
|
|
|
|
Characteristics of the kernel |
|
############################# |
|
|
|
To put Codezero in relation to other L4 kernels, here is a quick summary on the |
|
most important design aspects as implemented with the version 0.3, and on how |
|
our port of Genode relates to them: |
|
|
|
* In the line of the original L4 interface, the kernel uses global name spaces |
|
for kernel objects such as threads and address spaces. |
|
|
|
* For the interaction between a user thread and the kernel, the concept of |
|
user-level thread-control blocks (UTCB) is used. A UTCB is a small |
|
thread-specific region in the thread's virtual address space, which is |
|
always mapped. Hence the access to the UTCB can never raise a page fault, |
|
which makes it perfect for the kernel to access system-call arguments, |
|
in particular IPC payload copied from/to user threads. In contrast to other |
|
L4 kernels, the location of UTCBs within the virtual address space is managed |
|
by the user land. |
|
|
|
On Genode, core keeps track of the UTCB locations for all user threads. |
|
This way, the physical backing store for the UTCB can be properly accounted |
|
to the corresponding protection domain. |
|
|
|
* The kernel provides three kinds of synchronous inter-process communication |
|
(IPC): Short IPC carries payload in CPU registers only. Full IPC copies |
|
message payload via the UTCBs of the communicating parties. Extended IPC |
|
transfers a variable-sized message from/to arbitrary locations of the |
|
sender/receiver address spaces. During an extended IPC, page fault may |
|
occur. |
|
|
|
Genode solely relies on extended IPC, leaving the other IPC mechanisms to |
|
future optimizations. |
|
|
|
* The scheduling of threads is based on hard priorities. Threads with the |
|
same priority are executed in a round-robin fashion. The kernel supports |
|
time-slice-based preemption. |
|
|
|
Genode does not support Codezero priorities yet. |
|
|
|
* The original L4 interface leaves open the question on how to manage |
|
and account kernel resources such as the memory used for page tables. |
|
Codezero makes the accounting of such resources explicit, enables the |
|
user-land to manage them in a responsible way, and prevent kernel-resource |
|
denial-of-service problems. |
|
|
|
* In contrast to the original L4.v2 and L4.x0 interfaces, the kernel provides |
|
no time source in the form of IPC timeouts to the user land. A time source |
|
must be provided by a user-space timer driver. Genode employs such a timer |
|
services on all platforms so that it is not effected by this limitation. |
|
|
|
In several ways, Codezero goes beyond the known L4 interfaces. The most |
|
noticeable addition is the support for so-called containers. A container is |
|
similar to a virtual machine. It is an execution environment that holds a set |
|
of physical resources such as RAM and devices. The number of containers and the |
|
physical resources assigned to them is static and is to be defined at build |
|
time. The code executed inside a container can be roughly classified into two |
|
cases. First, there are static programs that require strong isolation from the |
|
rest of the system but no classical operating-system infrastructure, for |
|
example special-purpose telecommunication stacks or cryptographic functionality |
|
of an embedded device. Second, there a kernel-like workload, which use the L4 |
|
interface to substructure the container into address spaces, for example a |
|
paravirtualized Linux kernel that uses Codezero address spaces to protect Linux |
|
processes. Genode runs inside a container and facilitates Codezero's L4 |
|
interface to implement its multi-server architecture. |
|
|
|
|
|
Behind the scenes |
|
################# |
|
|
|
The 'make prepare' mechanism checks out the kernel source code from the |
|
upstream Git repository to 'base-codezero/contrib'. When building the kernel |
|
from within a Genode build directory via 'make kernel', this directory won't be |
|
touched by the Genode build system. Instead, a snapshot of the 'contrib' |
|
directory is taken to '<build-dir>/kernel/codezero'. This is the place where |
|
the Codezero configuration and build processes are executed. By working with a |
|
build-directory-local snapshot, we ensure that the source tree remains |
|
untouched at all times. After having taken the snapshot, the Codezero kernel is |
|
configured using a configuration template specific for the hardware platform. |
|
The configuration comes in the form of a CML file located at |
|
'base-codezero/config/'. There is one CML file per supported platform named |
|
'<platform>.cml'. The configured Codezero build directory will reside at |
|
'<build-dir>/kernel/codezero/build/'. Finally, the Codezero build system is |
|
invoked to build the kernel. |
|
|
|
The two stages of building Codezero |
|
=================================== |
|
|
|
The Codezero build system always performs the compilation of the kernel and the |
|
so-called containers as well as the integration of all these components into a |
|
final ELF image as one operation. When building just the kernel via 'make |
|
kernel', the final image will contain the default container0 that comes with |
|
the Codezero distribution. For integrating Genode into the final image, the |
|
content of the container0 must be replaced by the Genode binaries followed by |
|
another execution of 'kernel/codezero/build.py'. Now, the single-image will be |
|
re-created, including the Genode binaries. When using Genode's run mechanism, |
|
these steps are automated for you. For reference, please review the Codezero |
|
run environment at 'base-codezero/run/env'. |
|
|
|
By first building the kernel with Codezero's default container ('make kernel') |
|
and later replacing the container's content with Genode binaries, we |
|
optimize the work flow for building Genode components. The kernel is compiled |
|
only once, but the (quick) re-linking of the final image is done every time a |
|
run script is executed. |
|
|
|
In the run environment, you will see that we forcefully remove a file called |
|
'cinfo.c' from the build-directory-local snapshot of the Codezero source tree. |
|
This file is generated automatically by the Codezero build system and linked |
|
against the kernel. It contains the parameters of the containers executed on |
|
the kernel. Because we change the content of container0 each time when |
|
executing a run script, those parameter change. So we have to enforce to |
|
re-generation of the 'cinfo.c' file. |
|
|
|
How Genode ROM modules are passed into the final image |
|
====================================================== |
|
|
|
The Codezero build system picks up any ELF files residing the container's |
|
directory wheres the file called 'main.elf' is considered to be the roottask |
|
(in Codezero speak called pager) of the container. For Genode, 'main.elf' |
|
corresponds to the core executable. All other boot modules are merged into an |
|
ELF file, which we merely use as a container for these binary data. This ELF |
|
file is linked such that it gets loaded directly after the core image (this is |
|
how core finds the boot modules). The process of archiving all boot modules |
|
into the single ELF file is automated via the 'base-codezero/tool/gen_romfs' |
|
tool. In the container's directory, the merged file is called 'modules.elf'. |
|
|
|
Adapting the source code of the kernel |
|
====================================== |
|
|
|
For debugging and development you might desire to change the kernel code |
|
at times. You can safely do so within the 'base-codezero/contrib/' directory. |
|
When issuing the next 'make kernel' from the Genode build directory, your |
|
changes will be picked up. However, when working with run scripts, the kernel |
|
is not revisited each time. The kernel gets built only once if the |
|
'<build-dir>/kernel' directory does not exist, yet. If you work on the kernel |
|
source tree and wish to conveniently test the kernel with a run script, use |
|
|
|
! make kernel run/<run-script> |
|
|
|
This way, you make sure to rebuild the kernel prior executing the steps |
|
described in the run script. |
|
|
|
Tweaking the kernel configuration |
|
================================= |
|
|
|
The kernel configuration can be tweaked within '<build-dir>/kernel/codezero'. |
|
Just change to this directory and issue './build.py -C'. The next time you |
|
build the kernel via 'make kernel' your configuration will be applied. |
|
If you want to conserve your custom configuration, just copy the file |
|
'<build-dir>/kernel/codezero/build/config.cml'. |
|
|
|
Parameters of 'vpb926.cml' explained |
|
==================================== |
|
|
|
The default configuration for the VersatilePB926 platform as found at |
|
'base-codzero/config/vpb926.cml' is paramaterized as follows: |
|
|
|
:Default pager parameters: |
|
! 0x40000 Pager LMA |
|
! 0x100000 Pager VMA |
|
These values are important because they are currently hard-wired in the |
|
linker script used by Genode. If you need to adopt these values, make |
|
sure to also update the Genode linker script located at |
|
'base-codezero/src/platform/genode.ld'. |
|
|
|
:Physical Memory Regions: |
|
! 1 Number of Physical Regions |
|
! 0x40000 Physical Region 0 Start Address |
|
! 0x4000000 Physical Region 0 End Address |
|
We only use 64MB of memory. The physical memory between 0 and 0x40000 is |
|
used by the kernel. |
|
|
|
:Virtual Memory Regions: |
|
! 1 Number of Virtual Regions |
|
! 0x0 Virtual Region 0 Start Address |
|
! 0x50000000 Virtual Region 0 End Address |
|
It is important to choose the end address such that the virtual memory |
|
covers the thread context area. The context area is defined at |
|
'base/include/base/thread.h'. |
|
|
|
|
|
Limitations |
|
########### |
|
|
|
At the current stage, the Genode version for Codezero is primarily geared |
|
towards the developers of Codezero as a workload to stress their kernel. It |
|
still has a number of limitations that would affect the real-world use: |
|
|
|
* Because the only platform supported out of the box by the official Codezero |
|
source tree is the ARM-based Versatilebp board, Genode is currently tied to |
|
this hardware platform. |
|
|
|
* The current timer driver at 'os/src/drivers/timer/codezero/' is a dummy |
|
driver that just yields the CPU time instead of blocking. Is is not |
|
suitable as time source. |
|
|
|
* The PL110 framebuffer driver at 'os/src/drivers/framebuffer/pl110/' |
|
does only support the LCD display as provided by Qemu but it is not tested on |
|
real hardware. |
|
|
|
* Even though Codezero provides priority-based scheduling, Genode does not |
|
allow assigning priorities to Codezero processes, yet. |
|
|
|
As always, these limitations will be addressed as needed. |
|
|
|
|
|
Thanks |
|
###### |
|
|
|
We want to thank the main developer of Codezero Bahadir Balban for his great |
|
responsiveness to our feature requests and questions. Without his help, the |
|
porting effort would have taken much more effort. We hope that our framework |
|
will be of value to the Codezero community. |
|
|
|
|
|
|