Release notes for version 22.05

This commit is contained in:
Norman Feske 2022-05-23 15:39:27 +02:00
parent a037fac5c5
commit 33a51ee20d

775
doc/release_notes/22-05.txt Normal file
View File

@ -0,0 +1,775 @@
===============================================
Release notes for the Genode OS Framework 22.05
===============================================
Genode Labs
The Genode release 22.05 stays true to this year's
[https://genode.org/about/road-map - roadmap].
According to the plan, we continue our tradition of revising the framework's
documentation as part of the May release. Since last year, the Genode
Foundations book is accompanied with the Genode Platforms document that
covers low-level topics. The second revision has just doubled in size
(Section [Updated and new documentation]).
Functionality-wise, the added support for WireGuard-based virtual private
networks is certainly the flagship feature of the release.
Section [WireGuard] briefly introduces the new component while leaving
in-depth information to a
[https://genodians.org/m-stein/2022-05-26-wireguard-1 - dedicated article].
Among the other topics of the release, our continued work on device drivers
stands out. We managed to bring Genode's lineup of PC drivers ported from the
Linux kernel up to the kernel version 5.14.21 using Genode's unique DDE-Linux
porting approach.
As described by Section [New generation of DDE-Linux-based PC drivers], this
work comprises complex drivers like the wireless LAN stack including Intel's
Wifi driver and the latest Intel display driver. At the framework's side, the
modernization of Genode's platform driver for PC hardware is in full swing.
Even though not yet used by default, the new driver has reached feature parity
with the original PC-specific platform driver while sharing much of its code
base with the growing number of ARM platform drivers such as the FPGA-aware
platform-driver for Xilinx Zynq (Section [Xilinx Zynq]).
Regarding the PinePhone, Genode 22.05 introduces the basic ability to issue
and receive phone calls, which entails the proper routing of audio signals and
controlling the LTE modem. Furthermore, in anticipation of implementing
advanced energy-management strategies, the release features a custom developed
firmware for the PinePhone's system-control processor. Both topics are
outlined in Section [PinePhone] while further details and examples are given
in dedicated articles.
The release is wrapped up by usability improvements of the framework's
light-weight event-tracing mechanism, low-level optimizations, and API
refinements.
WireGuard
#########
[https://www.wireguard.com/ - WireGuard] is a protocol for encrypted, virtual
private networks (VPNs) with the goal of bringing ease-of-use and
state-of-the-art network security together. Furthermore, it is designed to be
implemented both light-weighted and highly performant at the same time. For
years now, we were keen to support WireGuard as a native standard solution for
peer-to-peer network encryption. With Genode 22.05, we could finally
accomplish that goal.
After we had considered various implementations as starting point, we chose to
port the Linux kernel implementation of WireGuard using our modernized
DDE-Linux tool set. The outcome is a user-land component that acts as client
to one NIC session and one uplink session. At the uplink session, the
WireGuard component plays the role of a VPN-internal network device that
communicates plain-text with the VPN participants. At the NIC session,
however, the component drives an encrypted UDP tunnel through the public
network towards other WireGuard instances.
In Genode, a WireGuard instance receives its parameters through the component
configuration with the peer configuration being re-configurable:
! <config private_key="0CtU34qsl97IGiYKSO4tMaF/SJvy04zzeQkhZEbZSk0="
! listen_port="49001">
!
! <peer public_key="GrvyALPZ3PQ2AWM+ovxJqnxSqKpmTyqUui5jH+C8I0E="
! endpoint_ip="10.1.2.1"
! endpoint_port="49002"
! allowed_ip="10.0.9.2/32" />
!
! </config>
A typical integration scenario would use two instances of Genode's NIC router.
One router serves the public network side of WireGuard and connects to the
internet via the device driver whereas the other router uses the private
network side of WireGuard as uplink interface. In this scenario, there is no
way around the WireGuard tunnel towards the Internet even when looking only at
components and sessions. Alternatively, we could accomplish the same goal with
only one router instance in contexts that allow us to trust in the integrity
of the router's own security domains.
[image wireguard_integration]
A typical integration scenario for WireGuard
For more details on how to integrate and route WireGuard in Genode, you may
refer to the new run scripts _wg_ping_inwards.run_, _wg_ping_outwards.run_,
_wg_lighttpd.run_, and _wg_fetchurl.run_, which are located at
_repos/dde_linux/run/_.
Please be aware that this is the first official version of the WireGuard
component. Although we are convinced of the quality of the underlying
time-tested Linux implementation, we strongly recommend against basing
security-critical scenarios on Genode's port before it had the time to mature
through real-world testing as well.
For the whole story behind the new WireGuard support in Genode, have a look at
the following dedicated article at [https://genodians.org]:
:Bringing WireGuard to Genode:
[https://genodians.org/m-stein/2022-05-26-wireguard-1]
New generation of DDE-Linux-based PC drivers
############################################
With the
[https://genode.org/documentation/release-notes/22.02#New_Linux-device-driver_environment_for_PC_drivers - previous release],
we started to apply the
[https://genode.org/documentation/release-notes/21.08#Linux-device-driver_environment_re-imagined - new DDE Linux approach]
to Linux-based PC drivers.
The first driver to be converted was the USB host-controller driver. In the
current release, we finished up this line of work. By now, all remaining
Linux-based PC drivers have been converted and updated. Those drivers now
share the same kernel version 5.14.21. The ports and configuration reside in
the _pc_ repository.
Based on the groundwork laid by the USB host-controller driver, we started
working on the Intel display and Intel wireless drivers. With the stumbling
blocks already out of the way, namely the x86 support in DDE Linux, we could
focus entirely on the intricacies of each driver.
In case of the Intel display driver, we could eliminate all our patches to the
kernel that we previously needed to manage the display connectors. Due to the
update, we gained support for newer Intel Gen11 and Gen12 graphics generations
as found in recent Intel CPUs. The old driver has been removed and the new
driver is now called _pc_intel_fb_drv_. Its configuration, however, remained
compatible and is documented in detail in the README of the driver.
The Intel wireless driver also profited from the version update as it now
supports 802.11ax capable devices. In particular, the driver was tested with
Intel Wi-Fi6 AX201 cards. The driver's unique physique - where the component
not only incorporates the driver but also the supporting user-land supplicant -
required changes to the way the Linux emulation environment is initialized.
We utilize a new VFS 'wifi' plugin that is executed during the component
start-up to prepare the emulation environment.
The following snippet shows how to configure the driver:
!<start name="pc_wifi_drv" caps="250">
! <resource name="RAM" quantum="32M"/>
! <provides><service name="Nic"/></provides>
! <config>
! <libc stdout="/dev/null" stderr="/dev/null" rtc="/dev/rtc"/>
! <vfs>
! <dir name="dev">
! <log/> <null/> <rtc/> <wifi/>
! <jitterentropy name="random"/>
! <jitterentropy name="urandom"/>
! </dir>
! </vfs>
! </config>
! <route>
! <service name="Rtc"> <any-child /> </service>
! <any-service> <parent/> <any-child /> </any-service>
! </route>
!</start
Apart from the added VFS plugin, the configuration remained unchanged.
So using the new driver is opaque to the user. The old driver was removed
and the new driver is now called _pc_wifi_drv_. Instead of preparing the
'dde_linux' port, the 'libnl' and 'wpa_supplicant' ports are now required for
building the driver.
! tool/ports/prepare libnl wpa_supplicant
Additionally to both driver updates, we wrapped up working on the USB
host-controller driver component by enabling the UHCI host-controller driver.
Support for such controllers was omitted in the previous release and
supporting the driver required us to add I/O port support to the 'lx_kit' for
x86. With this remaining feature gap closed, the _legacy_pc_usb_host_drv_
driver component has been removed in favour of the new one. Furthermore, the
Genode C-API for USB glue code, which was initially copied from the i.MX8 USB
host-controller driver, was consolidated and moved into the _dde_linux_
repository where it now is referenced by all recent USB host-controller
drivers.
With all updated drivers in place, it was time to make inventory and
de-duplicate the drivers since each driver accumulated redundant bits and
pieces of code. This consolidation effort simplified things greatly. We moved
most of the code shared by all drivers into a separate 'pc_lx_emul' library,
which is the back bone of those ported drivers. Since not all of them require
the same sophistication when it comes to the kernel API emulation, we followed
the same modular pattern already established in the _dde_linux_ repository,
which allows for mixing and matching of the available dummy implementations
individually per driver.
Updated and new documentation
#############################
Genode Platforms
----------------
The second revision of the "Genode Platforms" document condenses two years of
practical work with enabling Genode on a new hardware platform, taking the
PinePhone as concrete example. Compared to the first version published one
year ago, the content has doubled. Among the new topics are
: <div class="visualClear"><!-- --></div>
: <p>
: <div style="clear: both; float: left; margin-right:20px;">
: <a class="internal-link" href="https://genode.org">
: <img class="image-inline" src="https://genode.org/documentation/genode-platforms-title.png">
: </a>
: </div>
: </p>
* Working with bare-bones Linux kernels,
* Network driver based on DDE-Linux,
* Display and touchscreen,
* Clocks, resets, and power controls, and
* Modem control and telephony.
:Second revision of the Genode Platforms document:
[https://genode.org/documentation/genode-platforms-22-05.pdf]
Genode Foundations
------------------
The "Genode Foundations" book received its annual update. It is available at
the [https://genode.org] website as a PDF document and an online version.
The most noteworthy additions and changes are:
: <div class="visualClear"><!-- --></div>
: <p>
: <div style="clear: both; float: left; margin-right:20px;">
: <a class="internal-link" href="https://genode.org">
: <img class="image-inline" src="https://genode.org/documentation/genode-foundations-title.png">
: </a>
: </div>
: </p>
* Revised under-the-hood section about the base-hw kernel,
* Adaptation to changed repository structure (pc repository, SoC-specific
repositories),
* Updated API documentation, and
* Adjusted package-management description.
: <div class="visualClear"><!-- --></div>
To examine the changes in detail, please refer to the book's
[https://github.com/nfeske/genode-manual/commits/master - revision history].
Base framework and OS-level infrastructure
##########################################
Revised tracing facilities
==========================
Even though a light-weight event tracing mechanism has been with Genode since
[https://genode.org/documentation/release-notes/13.08#Light-weight_event_tracing - version 13.08],
in practice, this powerful tool remains sparingly used because it is arguable
less convenient than plain old debug instrumentation.
The trace-logger component introduced later in
[https://genode.org/documentation/release-notes/18.02#New_trace-logging_component - version 18.02]
tried to lower the barrier, but tracing remains being an underused feature.
The current release brings a number of usability improvements that will
hopefully make the tool more attractive for routine use.
Concise human-oriented output format
------------------------------------
First, we changed the output format of the trace logger to become better
suitable for human consumption, reducing syntactic noise and filtering out
repetitive information. For example, when instrumenting the VFS server in
Sculpt using the new GENODE_TRACE_TSC utility (see below), the trace logger
now generates tabular output as follows.
! Report 4
!
! PD "init -> runtime -> arch_vbox6 -> vbox -> " ----------------
! Thread "vCPU" at (0,0) total:12909024 recent:989229
! Thread "vCPU" at (1,0) total:5643234 recent:786437
!
! PD "init -> runtime -> ahci-0.fs" -----------------------------
! Thread "ahci-0.fs" at (0,0) total:910497 recent:6335
! Thread "ep" at (0,0) total:0 recent:0
! 71919692932: TSC process_packets: 8005M (4998 calls, last 4932K)
! 71921558516: TSC process_packets: 8006M (4999 calls, last 1596K)
! 71922760220: TSC process_packets: 8007M (5000 calls, last 1006K)
! 71929853586: TSC process_packets: 8009M (5001 calls, last 1840K)
! 71931315246: TSC process_packets: 8011M (5002 calls, last 1253K)
! 72127999920: TSC process_packets: 8016M (5003 calls, last 5606K)
! 72129568198: TSC process_packets: 8018M (5004 calls, last 1345K)
! 77161908178: TSC process_packets: 8029M (5005 calls, last 11349K)
! 77643225736: TSC process_packets: 8029M (5006 calls, last 217K)
! 89422100594: TSC process_packets: 8035M (5007 calls, last 5656K)
! 89422123632: TSC process_packets: 8035M (5008 calls, last 1342)
! Thread "signal handler" at (0,0) total:36329 recent:3001
! Thread "signal_proxy" at (0,0) total:51838 recent:13099
! Thread "pdaemon" at (0,0) total:97184 recent:332
! Thread "vdrain" at (0,0) total:1266 recent:286
! Thread "vrele" at (0,0) total:1904 recent:516
!
! PD "init -> runtime -> nic_drv" -------------------------------
! Thread "nic_drv" at (0,0) total:34044 recent:897
! Thread "signal handler" at (0,0) total:369 recent:142
!
! ...
Subjects that belong to the same protection domain are grouped together.
The formerly optional affinity and activity options have been removed.
These pieces of information are now unconditionally displayed. The trace
entries belonging to a thread appear as slightly indented. Trace subjects with
no activity do not produce any output. This way, the new version can be easily
used to capture CPU usage of all threads over time, as a possible alternative
to the top tool, which gives only momentarily sampled information.
Straight-forward trace logging with Sculpt OS
---------------------------------------------
Second, we added the trace-logger utility to the default set of packages along
with an optional launcher. With this change, only two steps are needed to use
the tracing mechanism with the
[https://genode.org/documentation/release-notes/22.02#Framework_for_special-purpose_Sculpt-based_operating_systems - modularized Sculpt]:
# Add 'trace_logger' to the 'launcher:' list of the .sculpt file
# Either manually select the 'trace_logger' from the '+' menu,
or add the following entry to the deploy configuration:
! <start name="trace_logger"/>
By default, the trace logger is configured to trace all threads executed in
the runtime subsystem and to print a report every 10 seconds. This default
policy can be refined in the launcher's '<config>' node. Note that the trace
logger does not respond to configuration changes during runtime. Changes come
into effect not before restarting the component.
Capturing performance measurements as trace events
--------------------------------------------------
Finally, to leverage the high efficiency of the tracing mechanism for
performance analysis, we complement the convenient
[https://genodians.org/nfeske/2021-04-07-performance - GENODE_LOG_TSC]
measurement device provided by _base/log.h_ with new versions that target the
trace buffer. The new macros GENODE_TRACE_TSC and GENODE_TRACE_TSC_NAMED
thereby simplify the capturing of highly accurate time-stamp-counter-based
measurements for performance-critical code paths that prohibit the use of
regular log messages.
Memcpy and memset optimization
==============================
With the improving support for the Zynq-7000 SoC, it was time to collect a few
basic performance metrics. For the purpose of evaluating memory throughput,
there exists a test suite in _libports/run/memcpy.run_. It takes a couple of
measurements for different memcpy and memset implementations. There also
exists a Makefile in _libports/src/test/memcpy/linux_ to build a similar test
suite for Linux that serves as a baseline. By comparing the results, we get an
indicator of whether our board support is setting up the hardware correctly.
Looking at the numbers for the Zynq-7000 SoC, however, we were puzzled about
why we achieved significantly less memcpy throughput on Genode than on Linux.
This eventually sparked an in-depth investigation of memcpy implementations
and of the Cortex-A9's memory subsystem.
As it turned out, the major difference was caused by our Linux tests hitting
the kernel's copy-on-write optimization and, therefore, accidentally mimicking
a memset scenario rather than a memcpy scenario. Nevertheless, in the
debugging process, we were able to identify a few low-hanging fruits for
general optimization of Genode's memset and memcpy implementations: Replacing
the bytewise memset implementation with a wordwise memset yielded a speedup of
~6 on Cortex-A9 (base-hw) and x86 (base-linux). Similarly, we achieved a
memcpy speedup of ~3 on x86. On arm_v7, we also experimented with the
preloading instruction (pld) and L2 prefetching. On Zynq-7000 (Cortex-A9), we
gained a speedup of ~2-3 by tuning these parameters.
Extended black-hole component
=============================
The black-hole component introduced in
[https://genode.org/documentation/release-notes/22.02#Black-hole_server_component - version 22.02]
provides pseudo services for commonly used session interfaces and is thereby
able to satisfy the resource requirements of a component without handing out
real resources. This is especially useful for deploying highly flexible
subsystems like VirtualBox, which supports many host-guest integration
features, most of which are desired only in a few scenarios. For example, to
shield a virtual machine from the network, the NIC session requested by the
VirtualBox instance can simply be assigned to the black-hole server while
keeping the network configuration of the virtual machine untouched.
The current release extends the black-hole component to cover ROM, GPU, and
USB services in addition to the already supported NIC, uplink, audio, capture,
and event services. The ROM service hands out a static '<empty/>' XML node.
The USB and GPU services accept the creation of new sessions but respond in a
denying way to any invocation of the session interfaces. The black-hole server
is located at _os/src/server/black_hole/_.
Refined low-level block I/O interfaces
======================================
In the original version of the 'Block::Connection::Job' API introduced in
[https://genode.org/documentation/release-notes/19.05#Modernized_block-storage_interfaces - version 19.05],
split read/write operations were rather difficult to accommodate and remained
largely unsupported by clients of the block-session interface. In practice,
this limitation was side-stepped by dimensioning the default I/O buffer sizes
large enough to avoid splitting. The current release addresses this limitation
by changing the meaning of the 'offset' parameter of the
'produce_write_content' and 'consume_read_result' hook functions. The value
used to reflect the absolute byte position. In the new version, it is relative
to the job's operation.
_This API change requires the adaptation of existing block-session clients._
We adapted all block-session clients accordingly, including part_block,
vfs/rump, vfs/fatfs, and Genode's ARM virtual machine monitor. Those
components thereby became able to work with arbitrary block I/O buffer sizes.
Improved touch-event support
============================
Until recently, Genode's GUI stack largely relied on the notion of an absolute
pointer position. For targeting touch-screen devices, our initial approach
was the translation of touch events to absolute motion events using the
event-filter component
([https://genode.org/documentation/release-notes/21.11#Event_filter_for_converting_touch_to_pointer_input - version 21.11]).
However, the event types are subtly different, which creates uncertainties.
Whereas a pointer has always a defined (most recent) position that can be used
to infer a hovered UI element in any situation, touch input yields a valid
position only while touching. Because both event types are different after all,
the conversion of touch input to pointer motion can only be an intermediate
solution. The current release enhances several components of Genode's GUI
stack with the ability to handle touch events directly.
In particular, the nitpicker GUI server has become able to take touch events
into consideration for steering the keyboard focus and the routing of
input-event sequences. The window-manager component (wm) has been enhanced to
transform touch events similarly to motion events by using one virtual
coordinate system per window. Finally, the menu-view component, which
implements the rudimentary widget set as used by Sculpt OS' administrative
user interface, evaluates touch events for generating hover reports now.
Combined, these changes make the existing GUI stack fit for our anticipated
touch-screen based usage scenarios such as the user interface for Genode on
the PinePhone.
Platform driver
===============
The architecture-independent platform driver that unified the platform API since
[https://genode.org/documentation/release-notes/22.02#Platform_driver - release 22.02],
still missed some features to replace the deprecated x86-specific variant.
Most importantly, it was not aware of PCI devices and their special treatment.
PCI decode component
--------------------
The platform driver is a central resource multiplexer in the system, and
literally all device drivers depend on it. Therefore, it is crucial to keep it
as simple as possible to minimize its code complexity. To facilitate
PCI-device resource handling of the platform driver, we introduce a new
component called _pci_decode_. It examines information delivered by the ACPI
driver about the location of the PCI configuration spaces of PCI host bridges,
as well as additional interrupt re-routing information, and finally probes for
all available PCI devices, and their functions. Dependent on additional
kernel-related facilities, e.g., whether the micro-kernel supports
message-signaled interrupts, it finally publishes a report about all PCI
devices and their related resources.
An example report looks like the following:
! <devices>
! <device name="00:02.0" type="pci">
! <pci-config address="0xf8010000" bus="0x0" device="0x2" function="0x0"
! vendor_id="0x8086" device_id="0x1616" class="0x30000"
! bridge="no"/>
! <io_mem address="0xf0000000" size="0x1000000"/>
! <io_mem address="0xe0000000" size="0x10000000"/>
! <io_port_range address="0x3000" size="0xffff0040"/>
! <irq type="msi" number="11"/>
! </device>
!
! ...
! </devices>
The device and resource description in this report is compatible with the
device configuration patterns already used by the platform driver before.
Devices ROM
-----------
To better cope with device information gathered at runtime, like the one
provided by the PCI decoder, the platform driver no longer retrieves the device
information from its configuration. Instead, it requests a devices ROM
explicitly. The policy information about which devices are assigned to which
client remains an integral part of the platform driver's configuration.
The devices ROM is requested via the label "devices" by default. If one needs
to name the ROM differently, one can state the label in the configuration:
! <config devices_rom="config"/>
Using the example above, the former behavior can be emulated. It prompts the
platform driver to obtain both its policy configuration and device information
from the same "config" ROM.
Static device information for a specific SoC respectively board does now
reside in the SoC-specific repositories within the _board/_ directory.
For instance, the device information for the MNT Reform 2 resides in the
genode-imx repository under _board/mnt_reform2/devices_. All scenarios and
test-scripts can refer to this central file.
Report facility
---------------
The platform driver can report its current view on devices as well as its
configuration. An external management component might monitor this information
to dynamically apply policies. With the following configuration switches, one
can enable the reports "config" and "devices":
! <config>
! <report devices="yes" config="yes"/>
! ...
! </config>
Interrupt configuration
-----------------------
The need for additional information to set up interrupts appropriately led to
changes in the interrupt resource description consumed by the platform driver.
It can now parse additional attributes, like mode, type, and polarity. It
distinguishes "msi" and "legacy" as type, "high" and "low" as polarity,
"level" and "edge" as mode. Dependent on the stated information in the devices
ROM, the platform driver will open the IRQ session for the client accordingly.
I/O ports
---------
A new resource type in the device description interpreted by the platform
driver is the I/O port range. It looks like the following:
! <devices>
! <device name="00:1f.2" type="pci">
! ...
! <io_port_range address="0x3080" size="0x8"/>
! ...
! </device>
! ...
! </devices>
The generic platform API's device interface got extended to deliver an IO_PORTS
session capability for a given index. The index is dependent on which I/O port
ranges are stated for a given device.
The helper utility 'Platform::Device::Io_port_range' simplifies the usage of
I/O ports by device driver clients. It can be found in
_repos/os/include/platform_session/device.h_.
DMA protection
--------------
The generic platform driver now uses device PDs and attaches all DMA buffers
requested by a client to it. Moreover, it assigns PCI devices to the device PD
too. On the NOVA kernel, this information is used to
configure the IOMMU correspondingly.
PCI device clients
------------------
The platform API and its utilities no longer differentiate between PCI and
non-PCI devices. However, under the hood, the platform driver performs
additional initialization steps once a PCI device gets acquired. Dependent on
the resources assigned to the device, the platform driver enables I/O and
memory access in the PCI configuration space of the device. Moreover, it
enables bus-master access for DMA transfers.
To assign PCI devices to a client, the policy rules in the platform driver can
refer to it either by a device/vendor ID tuple, or by stating a PCI class.
The PCI class names are the same supported by the previous x86-specific
platform driver. Of course, one can still refer to any device via its unique
name. Here is an example for a policy set:
! <config>
! <policy label="usb_drv -> ">
! <pci class="USB"/>
! </policy>
! <policy label="nvme_drv -> ">
! <pci vendor_id="0x1987" device_id="0x5007"/>
! </policy>
! <policy label="ps2_drv -> ">
! <device name="ps2"/>
! </policy>
! </config>
Wait for platform device availability
-------------------------------------
Now that device information can be gathered dynamically at runtime it might
happen that a client opens a session to the platform driver before the device
becomes available. As long as a valid policy is defined for the client, the
platform driver will establish the connection, but deliver an empty devices
ROM to the client.
To simplify the usage by device drivers, the utilities to acquire a device
from the platform driver in 'Platform::Device' and 'Platform::Connection' will
wait for the availability of the device. This is done by implicitly
registering a signal handler for devices ROM updates at the platform driver
when the acquisition failed, and waiting for ROM updates until the device is
available.
Any signal handler that was registered before gets lost in this case.
The developer of a device driver shall register a devices ROM signal handler
once its devices were acquired, or shall only acquire devices known to be
available, after inspecting the devices ROM independently.
Platforms
#########
PinePhone
=========
Telephony
~~~~~~~~~
The current release introduces the principle ability to issue and receive
voice calls with the PinePhone. This work involved two topics. First, we had
to tackle the integration, configuration, and operation of the LTE modem. The
second piece of the puzzle was the configuration of the audio paths between
the mic, the speaker, and the modem. Since the complexity of those topics
would exceed the scope of the release documentation, the technical details are
covered in a dedicated article.
:Pine fun - Telephony _(Roger, Roger?)_:
[https://genodians.org/ssumpf/2022-05-09-telephony]
[image pinephone_telephony]
The image above illustrates a simple system exemplified by the
[https://github.com/genodelabs/genode-allwinner/blob/master/run/modem_pinephone.run - modem_pinephone.run]
script. It allows a terminal emulator on a host machine connected to the
serial connector of the PinePhone to interact with the command interface of
the modem, e.g., allowing the user to unlock the SIM card via the 'AT+CPIN'
command, or to issue a call using the 'ATD' command.
Custom system-control processor (SCP) firmware
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Battery lifetime is one of the most pressing concerns for mobile phones. While
exploring the PinePhone hardware, we discovered early on that the key for
sophisticated energy management lies in the so-called system control processor
(SCP), which is a low-power companion microcontroller that complements the
high-performance application processor. The SCP can remain active even if the
device is visibly switched off.
Surprisingly, even though its designated purpose is rather narrow, the SCP is
a freely programmable general-purpose CPU (called AR100) with ultimate access
to every corner of the SoC. It can control all peripherals including the
modem, and access the entirety of physical memory.
In contrast to most consumer devices, which operate their SCPs with
proprietary firmware, the PinePhone gives users the freedom to use an
open-source firmware called [https://github.com/crust-firmware/crust - Crust].
Moreover, the Crust developers thoroughly documented their findings of the
[https://linux-sunxi.org/AR100 - AR100 limitations] and its
[https://linux-sunxi.org/AR100/HardwareSharing - interplay with the ARM CPU].
Given that the Crust firmware was specifically developed to augment a
Linux-based OS with suspend-resume functionality, its fixed-function feature
set is rather constrained. For running Genode on the PinePhone, we'd like to
move more freely, e.g., letting the SCP interact with the modem while the
application processor is powered off. To break free from the limitations of a
fixed-function feature set of an SCP firmware implemented in C, we explored
the opportunity to deploy a minimal-complexity Forth interpreter as the basis
for a custom SCP firmware. The story behind this line of development is
covered by the following dedicated article:
:Darling, I FORTHified my PinePhone!:
[https://genodians.org/nfeske/2022-03-29-pinephone-forth]
Inter-communication between SCP and ARM
---------------------------------------
To enable a tight interplay of Genode with the SCP, we introduce a new
[https://github.com/genodelabs/genode-allwinner/tree/master/include/scp_session - interface] and
[https://github.com/genodelabs/genode-allwinner/tree/master/src/drivers/scp/a64 - driver]
for supplying and invoking custom functionality to the SCP at runtime.
The new "Scp" service allows clients to supply snippets of Forth code for
execution at the SCP and retrieve the result. Both the program and the result
are constrained to 1000 bytes. Hence, the loading of larger programs may need
multiple subsequent 'Scp::Connection::execute' calls.
As illustrated by the example
[https://github.com/genodelabs/genode-allwinner/blob/master/run/a64_scp_drv.run - a64_scp_drv.run]
script, the mechanism supports multiple clients. Since the SCP's state is
global, however, all clients are expected to behave cooperatively. Given the
SCP's ultimate power, SCP clients must be fully trusted anyway.
As a nice tidbit for development, the PinePhone-specific SCP firmware features
a break-in debug shell for interactive use over UART that can be activated by
briefly connecting the INT and GND
[https://wiki.pine64.org/index.php/PinePhone#Pogo_pins - pogo pins].
Note that this interactive debugging facility works independently from the
application processor. Hence, it can be invoked at any time, e.g., to inspect
any hardware register while running a regular Linux distribution on the phone.
NXP i.MX8
=========
Analogously to the PCI decoder introduced in Section [Platform driver], a
component to retrieve PCI information on the i.MX 8MQ is part of this release.
It reports all PCI devices found behind the PCI Express host controller(s)
detected. In contrast to the PCI decoder, it has to initialize the PCI Express
host controller first, and needs device resources from the platform driver to
do so before. The component resides in the
[https://github.com/genodelabs/genode-imx - genode-imx]
repository and is called _imx8mq_pci_host_drv_.
Xilinx Zynq
===========
For the Zynq-7000 SoCs, we focused on two main topics in this release. First,
we leveraged the aforementioned improvements on the generic platform driver to
handle the (dis)appearance of devices in consequence of FPGA reconfiguration.
Second, we applied our new DDE Linux approach in order to port the SD-card
driver.
The platform driver for the Xilinx Zynq is now available in the
[https://github.com/genodelabs/genode-zynq - genode-zynq] repository as
_src/zynq_platform_drv_. The default devices ROMs are provided by the
_raw/<board>-devices_ archives. In addition to the generic driver, it features
the readout of clock frequencies. You can use _zynq_clocks.run_ to dump the
frequencies of all clocks.
Since the Xilinx Zynq comprises an FPGA that can be reconfigured at run time,
we also need to handle the appearance and disappearance of devices. For this
purpose, we added a driver manager that consumes the platform driver's devices
report and launches respectively kills device drivers accordingly. This
scenario is accompanied by the _pkg/drivers_fpga-zynq_ archive that assembles
the _devices_ ROM for the platform driver depending on the FPGA's
reconfiguration state. The figure below illustrates this scenario: The
subsystem provided by the _pkg/drivers_fpga-zynq_ archive is a replacement for
the platform driver. It consumes the _fpga.bit_ ROM that contains the FPGA's
bitstream. Once the bitstream has been loaded, the _fpga_devices_ ROM is
merged with the _devices_ ROM provided by the _raw/<board>-devices_ archive.
The _policy_ ROM contains the config of the internal zynq_platform_driver
(policies and reporting config). By enabling device reporting, the
zynq_driver_manager is able to react upon device changes and updates the
_init.config_ for a drivers subsystem accordingly. An example is available in
_run/zynq_driver_manager.run_.
[image zynq_driver_manager]
As a prerequisite for porting the first driver for the Zynq following our new
DDE Linux approach, we added a zynq_linux target that builds a stripped-down
Linux kernel for the Xilinx Zynq. Although Xilinx provides its own vendor
kernel, most drivers have been mainlined. To eliminate version mismatch
issues, we therefore use our mainline Linux port from _repos/dde_linux_
instead. With this foundation, we were able to port the SD card driver, which
is now available as _src/zynq_sd_card_drv_.