mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
275 lines
12 KiB
Plaintext
275 lines
12 KiB
Plaintext
|
|
==================================
|
|
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.com]
|
|
|
|
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.
|
|
|
|
|