Compare commits

..

81 Commits

Author SHA1 Message Date
Christian Helmuth
4188427596 version: 21.11 2021-11-30 14:34:09 +01:00
Norman Feske
ea6f90ec17 News item for version 21.11 2021-11-30 14:32:17 +01:00
Norman Feske
c528cd7819 Release notes for version 21.11 2021-11-30 14:32:17 +01:00
Christian Helmuth
92b7be4d11 depot: update recipe hashes 2021-11-30 12:08:54 +01:00
Christian Helmuth
13dab699b1 base: invalidate entire range on VM-session detach
The requested guest-physical memory range may comprise multiple attached
dataspace regions, which must all be detached. This is not required for
the current vbox5 implementation, but for vbox6 as the current API
suggests these semantics.

This commit can be seen as intermediate fix as a real fix should change
the API to prevent long-running detach loops in core that may lock out
requests by other components.
2021-11-29 15:11:53 +01:00
Stefan Kalkowski
7eb3da71b5 base-hw: check managing_system property for SMC
* When issuing a secure-monitor-call on behalf of a PD session client
  first check the permission via the 'managing_system' property.

Fix #4321
2021-11-29 15:11:53 +01:00
Stefan Kalkowski
14de84fae6 base: be more restrictive with 'managing_system'
* Only give managing_system permission when all parent nodes of the
  corresponding component agree in doing so.
* Move the physical memory constrains heuristic from sandbox library to core

Fix #4335
2021-11-29 15:11:53 +01:00
Johannes Schlatow
916683b6d6 platform_drv(arm): fix cap and memory leaks
* Track all caps and ram quotas of the sub-sessions properly
* Release DMA buffers, it is not done implicitely when destroying
  the Constrained_ram_allocator
* Do not replenish quota before really releasing memory from
  the allocator

Issue #4330
2021-11-29 15:11:53 +01:00
Johannes Schlatow
e256969489 platform_drv(arm): fix destruction order
The Session_component must be destroyed before updating the device
model because the Session_component must also release all previously
acquired devices. If the device model is updated before, the devices
might have been removed.

Issue #4330
2021-11-29 15:11:53 +01:00
Johannes Schlatow
7a2826a2fe base: fix use after free in Genode::Heap
Fixes genodelabs/genode#4334
2021-11-29 15:11:53 +01:00
Alexander Boettcher
45cebd774d cpu_balancer: avoid dynamic policy allocation
Pre-allocate all possible type of policy objects as part of the thread meta
state to avoid increased memory consumption due to different policy object
sizes. The cpu_balancer accounts the memory per client and can't forward
potentially occurring out-of-ram exceptions during config-ROM update phases.

Fixes #4333
2021-11-29 15:11:53 +01:00
Alexander Boettcher
1f58b05255 cpu_balancer: limit mem increase on config update
The commits avoids reading in and allocating memory for all potentially
threads, which are potentially currently not existent (but configured in the
policy beforehand). Instead the policy is read in and evaluated when a thread
is created and policy changes are solely applied to existing/running threads.
By this the commit avoids the increase of memory consumption during the
evaluation of policies during config ROM updates.

Issue #4333
2021-11-29 15:11:53 +01:00
Piotr Tworek
30b3ad218f virt_qemu: Use VirtIO fb driver instead of ramfb.
This driver should be better suited for VirtIO based board like
qemu_virt.
2021-11-29 15:11:53 +01:00
Piotr Tworek
7c1888644a os: Add VirtIO framebuffer driver.
This implements the necessary bits to provide 2D framebuffer support on
top of VirtIO GPU device as implemented in Qemu. I don't know if any
other implementation of this specific device exists.

Compared to the ramfb driver which already exists in Genode Virtio FB driver
has one major benefit. It allows Qemu window to be dynamically resized at
runtime. The driver will treat this as resolution change and act accordingly.
Ramfb driver can currently only use the hardcoded 1024x768 screen size. Changing
screen resolution might not sound like a big deal, but it is rather useful to
run Genode on Qemu in full screen mode.
2021-11-29 15:11:53 +01:00
Piotr Tworek
2ec9e69fd4 os: Add support for reading VirtIO responses.
Some more advanced devices like VirtIO GPU do expect they can receive
responses to VirtIO commands they issue via VirtIO queue. Such responses
are not sent via a separate device writeable queue. Instead the driver
is expected to queue some additional descriptors and buffers which the
device can then use to provide the reply.

This patch adds support for such write-data-read-response opeartion to
Genode VirtIO::Queue implementation. The implementation is pretty simple
and does not support any fancy features like receiving the response
asynchronously. Instead the operation will use caller provided callback
to wait for the device to process the command. Once this callback
returns the write-data-read-response VirtIO::Queue function will invoke
another callback passing received response as argument.
2021-11-29 15:11:53 +01:00
Christian Helmuth
0bb0ac079a sculpt: version 21.11 2021-11-29 15:11:53 +01:00
Josef Söntgen
fcc236d906 libports: add mesa_gpu-etnaviv recipe
Similar to the existing 'mesa_gpu' pkgs add one for 'etnaviv'
as well.

Issue #4329.
2021-11-29 15:11:53 +01:00
Josef Söntgen
17da7c88d0 import-libdrm: fix building etnaviv as recipe
Make sure all needed headers are found when building via depot.

Issue #4329.
2021-11-29 15:11:53 +01:00
Josef Söntgen
4d93187d31 libdrm: introduce Gpu session for etnaviv
* The Gpu session back end translates all DRM API requests of the
  client into matching Gpu session operations.

* Enable ioctl for etnaviv

Fixes #4329.
2021-11-29 15:11:53 +01:00
Josef Söntgen
645e51dc1d gpu: add information for etnaviv driver
Mesa queries information about the underlying device and this header
denotes the layout of the information. It is also used by the driver
itself to populate the 'info_dataspace'.

Issue #4329.
2021-11-29 15:11:52 +01:00
Josef Söntgen
8155505b41 mesa/etnaviv: guard unmapImage call
We may call this function only in case mapImage was successful.

Issue #4329.
2021-11-29 15:11:52 +01:00
Josef Söntgen
d39af2206c mesa_gpu-etnaviv: etnaviv already part of mesa
Since the parts of the 'etnaviv' library are already part of the
'mesa.lib.so' that is normally loaded along-side remove the
duplication here.

Issue #4329.
2021-11-29 15:11:52 +01:00
Norman Feske
133d21ad38 event_filter: add touch-click filter
This filter bridges the gap between a touchscreen driver, which
generates raw touch events and traditional GUI applications that expect
a pointer (absolute motion, press/release of the left mouse button).

Fixes #4332
2021-11-29 15:11:52 +01:00
Norman Feske
09d020508c depot: recipes for pin-control/state session APIs
Issue #4315
2021-11-29 15:11:52 +01:00
Norman Feske
dc39a8db62 base: introduce Allocator::try_alloc
This patch changes the 'Allocator' interface to the use of 'Attempt'
return values instead of using exceptions for propagating errors.

To largely uphold compatibility with components using the original
exception-based interface - in particluar use cases where an 'Allocator'
is passed to the 'new' operator - the traditional 'alloc' is still
supported. But it existes merely as a wrapper around the new
'try_alloc'.

Issue #4324
2021-11-29 15:11:52 +01:00
Christian Helmuth
9591e6caee vbox6: CPU halt/wakeup via RTSEMEVENTMULTI
The former use of Pthread conditionals did not cover the corner case of
early wakeups just before halting the CPU. These wakeups were simply
lost which resulted in sporadic halts of about 500 ms (the maximum timeout
of all halts in VirtualBox). RTSEMEVENTMULTI preserves early wakeups
and effectively prevents the CPU from halting.

Additionally, we now wakeup the target CPU on VMMR0_DO_GVMM_SCHED_POLL
and, thus, mimic the behavior of the original implementation slightly
better,

Slightly related to #4313
2021-11-29 15:10:53 +01:00
Johannes Schlatow
a65807ff08 rom_filter: optionally skip top-level node
Since the top-level node of the output ROM is always generated by the
rom_filter, there is no way to pass-through the content of an input ROM
without wrapping in an addition XML node.

genodelabs/genode#4326
2021-11-29 15:10:53 +01:00
Josef Söntgen
059c7ed74a dde_linux: prevent debug message in memory backend
The Allocator_avl back end will display diagnostic messages if the
address to be freed is not at the beginning of a block. This happens
regulary when 'struct page' objects are not freed in allocation order.

Issue #4325.
2021-11-29 15:10:53 +01:00
Josef Söntgen
98385a7658 allocator_avl: return 0 for improper size_at call
In case the given address is not the start of a block bail instead of
making improper size assumptions.

Issue #4325.
2021-11-29 15:10:53 +01:00
Josef Söntgen
49bf58a2ae lx_kit: free dataspace interface
Allow for freeing of manually managed dataspaces.

Fixes #4325.
2021-11-29 15:10:53 +01:00
Josef Söntgen
327ec61ee3 lx_kit: get buffer dataspace from virt addr
Introduce a method to access the dataspace capability of the underlying
backing store for a memory allocation. This is necessary for drivers
where the memory is managed manually and the capability needs to be
given to a client.

Issue #4325.
2021-11-29 15:10:53 +01:00
Josef Söntgen
cd7a65a313 dde_linux: extended pgtable header for etnaviv
The 'pgprot_noncached' function is referenced by the driver code.

Issue #4325.
2021-11-29 15:10:53 +01:00
Stefan Kalkowski
23514bf5c2 dde_linux: add runqueues symbol for -O0 build 2021-11-29 15:10:53 +01:00
Christian Helmuth
974627f700 vbox6: adapt to GUI framebuffer size on startup
Explicitly, adapt to current framebuffer/window size after
initialization finished. This ensures the use of the correct framebuffer
dimensions in scenarios without a window manager.

Thanks to Raphael for the patch.
2021-11-29 15:10:53 +01:00
Norman Feske
3b456e0037 test/resource_request: ignore spurious requests
This patch makes the test less dependent on the rate of state updates by
calculating the upgraded quota from the values found in the state report
instead of simply increasing the '_ram_quota' for each incoming report.
2021-11-29 15:10:53 +01:00
Norman Feske
231ac187fe base: introduce Ram_allocator::try_alloc
This patch replaces the 'Ram_allocator::alloc' RPC function by a
'try_alloc' function, which reflects errors as 'Attempt' return value
instead of an exception.

Issue #4322
Issue #3612
2021-11-29 15:10:53 +01:00
Norman Feske
959bcae557 base: add util/attempt.h utility
Fixes #4322
2021-11-29 15:10:52 +01:00
Norman Feske
694dff8a5c base: sort symbols/ld with LC_COLLATE=C 2021-11-29 15:10:52 +01:00
Christian Helmuth
68caa26407 virt_qemu: use "-device ramfb"
Issue #4282
2021-11-29 15:10:52 +01:00
Norman Feske
4cfd954e1e Remove dependency from 'which' utility
Debian declared the 'which' utility as deprecated.

Fixes #4319
2021-11-29 15:10:52 +01:00
Norman Feske
293d545b97 sandbox: use Genode::update_list_model_from_xml
This patch replaces the former local implementation by the function
provided in 'util/list_model.h'.

Issue #4317
2021-11-29 15:10:52 +01:00
Norman Feske
4df7e6adde util/list_model.h: Add update_list_model_from_xml
The new 'update_list_model_from_xml' function template simplifies the
use of the list model utility by alleviating the need for implementing a
custom policy class for each model. Instead, the transformation is done
using a few lambda functions given directly as arguments.

Issue #4317
2021-11-29 15:10:52 +01:00
Norman Feske
449f647e58 dde_linux: lx_emul interface for GPIO pin access
This patch introduces the lx_emul/pin.h interface that enables GPIO stub
drivers to interact with Genode's Pin_control and IRQ sessions via a
simple C API.

Fixes #4316
2021-11-29 15:10:52 +01:00
Norman Feske
f2a627c107 os: Pin_control and Pin_state session interfaces
The new interfaces are meant to gradually replace the existing
Gpio_session interface.

- Each session refers to a single pin.
- The session types distiguish the direction of the signal as input or
  output.
- Pin coordinates can be selected via session labels.
- GPIO interrupts are covered by the regular IRQ session interface.

The interfaces are accompanied by framework utilities and interfaces:

- os/pin_driver.h
- pin_control_session/component.h
- pin_state_session/component.h

These headers relieve GPIO drivers from implementing boilerplate code by
providing device-agnostic portions. The A64 pio driver serves as
reference for using those utilities.

  https://github.com/nfeske/genode-allwinner/tree/master/src/drivers/pin/a64

Fixes #4315
2021-11-29 15:10:52 +01:00
Johannes Schlatow
2ecb09ba7e tool/run: move nic model to qemu_args file
Always instantiating a network device with id `net0`, removes the need to call
append_qemu_nic_args in run scripts unless we want to add forwarding
rules.

genodelabs/genode#4311
2021-11-29 15:10:52 +01:00
Johannes Schlatow
522a1cdc5b tool/run: read board-specific qemu args from file
Allow specifying additional qemu arguments for externally supported boards
(e.g. zynq_qemu) by adding a `qemu_args` file in the board-property directory.

The syntax of the qemu_args file is as follows:
- Arguments can appear in a single line or in multiple lines as the
  lines will be appended (separated by a whitespace) to the global
  qemu_args variable.
- If the line is prepended with a `foobar:` expression. The arguments
  are only added if the foobar spec is present.

Note, that a `-m` argument specified in the qemu_args file will
override the arguments provided by the run scripts.

genodelabs/genode#4311
2021-11-29 15:10:52 +01:00
Johannes Schlatow
c0c2ed2bf5 tool/run: make qemu RAM sanity check more robust
First, the former implementation has only considered the pure numerical
variant of the -m argument. Yet, qemu also allows specifying the amount
of memory by `-m 1G`, `-m size=1G` and more.

Second, the default amount of memory for BOARD=pc was 512M (800M in case of okl4).
Since the depot_autopilot.run also required at least 768M on all
platforms it seems reasonable to take 800M as a default value for BOARD=pc and
thereby remove the special treatment of okl4.

genodelabs/genode#4311
2021-11-29 15:10:52 +01:00
Alexander Boettcher
c774272366 vbox5/6: set ia32_tsc_aux for rdtscp usage
Fixes #4314
2021-11-29 15:10:52 +01:00
Alexander Boettcher
533015b93e nova: support transfer of IA32_TSC_AUX MSR for vCPUs
The 32-bit MSR is returned by rdtscp in ecx register and used to detect
the CPU ID the timestamp was taken on.

Issue #4314
2021-11-29 15:10:52 +01:00
Alexander Boettcher
f4e52863c0 vbox6: exit on rdtsc and rdtscp (intel)
Otherwise Windows 10 shows 50 Ghz frequency in task manager and other
strange things may happen.

Issue #1769
Issue #4314
Fixes #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
7a06633173 nova: FPU handling for vCPUs in VM session
- request FPU state on VM exit in portal config

- transfer FPU state on VM entry

- save fpu state early

  Avoid any FPU instructions (for example during base API calls), which
  use the FPU and overwrite FPU registers holding the guest vCPU FPU
  state.

- don't save fpu state of EP

Issue #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
1a79bf2be2 vbox6: avoid race for NEM state checking
The commit avoids the race between checking for the NEM state and the decision
to notify (poke) the NEM backend (nem.cc).

- ever notify about POKE flag for remote vCPU
- check synchronized for NEM state
- store recheck flag and apply on next switch_to_hw

Issue #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
3701733c8f vbox6: add POKE calls in TM for remote vCPUs
and return to VMM if TM_TIMER flag is set

Issue #4313
2021-11-29 15:10:52 +01:00
Christian Helmuth
5a21431c31 vbox6: check for pending IRQs in sup_vcpu
Issue #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
00eadf9791 vbox6: adjust TPR handling according to HMVMXR0
Issue #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
33bf926b50 vbox6: add SIPI patch improving vCPU startup
Issue #4313
2021-11-29 15:10:52 +01:00
Alexander Boettcher
4798ffd055 vbox6: initialize more vcpu state in sup_vm.cc
Issue #4313
2021-11-29 15:10:51 +01:00
Christian Helmuth
228d1c27b7 vbox6: fix npt_ept fault calculation
Issue #4313
2021-11-29 15:10:51 +01:00
Alexander Boettcher
68878ca98a vbox6: implement SUPSemEventMulti*() functions
Issue #4313
2021-11-29 15:10:51 +01:00
Alexander Boettcher
28db5cadee vbox5: generic - discharge by default
intr_state and actv_state are now charged only if required and with
valid values.

Issue #4313
2021-11-29 15:10:51 +01:00
Alexander Boettcher
8d5903cba9 vbox6: avoid unintended state transfer on hw enter
intr_state and actv_state are now charged only if required and with
valid values.

Issue #4313
2021-11-29 15:10:51 +01:00
Alexander Boettcher
74a8a801e4 nova: report vCPU prio & quantum in trace conn
Issue #4313
2021-11-29 15:10:51 +01:00
Stefan Kalkowski
b12b0ed93d imx8q_evk: remove board support from repository
Moved to separate repo at https://github.com/skalk/genode-imx/

Fix #4301
2021-11-29 15:10:51 +01:00
Johannes Schlatow
7917c5d9ec Remove zynq_qemu platform and zynq nic driver
Moved to separate repo at https://github.com/jschlatow/genode-zynq

Fixes genodelabs/genode#4280
2021-11-29 15:10:51 +01:00
Josef Söntgen
6ecae6adb3 qemu-usb: increase USB2/3 root ports to 8 each
In the default setting the number of root ports is set to 4. This
also limits the number of USB host devices that may be attached to
the VM. Since the USB webcam shares the slots, that leaves us with
only 3 available USB2 slots to attach USB host devices. Depending on
the use-case that might not be enough.

This commit statically increases the number of ports to 8 each and
adapts the qemu-usb glue-code accordingly.

Many thanks to Raphael for initial investigation and workaround.

Fixes #4310.
2021-11-29 15:10:51 +01:00
Stefan Kalkowski
6d991313b1 nvme_drv: get I/O resources from platform API only
Do not use the I/O memory service from core directly,
but instead use the I/O resources the platform session
provides to the driver anyway.

Fix #4309
2021-11-29 15:10:51 +01:00
Stefan Kalkowski
43ef9b5a3a platform_drv: do not account IOMEM as ram quota
Accidentally, the size of IOMEM dataspace got accounted within the
implementation of the platform driver for ARM. Instead we should
only account a bit for the metadata and paging of the I/O memory.

Fix #4307
2021-11-29 15:10:51 +01:00
Johannes Schlatow
87bb81cd66 nic: add _custom_conn_tx_ack_avail_handler()
The custom ack avail handler is required for zero-copy nic drivers (e.g.
the zynq nic driver), which must release the corresponding DMA buffers.

Fixes genodelabs/genode#4277
2021-11-29 15:10:51 +01:00
Tomasz Gajewski
332cfb38c1 usb_host: fix MMU fault on rpi2 and rpi3 2021-11-29 15:10:51 +01:00
Norman Feske
275479867d window_layouter: handle decorator margins at start
This patch adds a missing call of '_handle_decorator_margins' at
construction time. Up to commit "report_rom: versioning and explicit
notification" this problem was masked by an unconditional signal, which
implicitely triggered the call.

Issue #4274
Fixes #4306
2021-11-29 15:10:51 +01:00
Piotr Tworek
4f1e9fd256 os: Use VirtIO input drivers for virt_qemu.
This makes Genode's interactive test scenarios run on virt_qemu board
actually interactive.

Issue #4282
2021-11-29 15:10:51 +01:00
Piotr Tworek
80d11ca751 tool: Add keyboard and mouse devices to virt_qemu.
Now that we have appropriate native driver for them add keyboard and
mouse devices to virt_qemu machine. Make sure qemu exposes those new
devices in modern, VirtIO 1.0 mode. At leasts qemu 5.1.0 still uses
pre 1.0 mode in default setup.

Issue #4282
2021-11-29 15:10:51 +01:00
Piotr Tworek
60f1a1a554 os: Add VirtIO input driver.
This component can service Qemu VirtIO mouse, keyboard and tablet
devices. The implementation is based on VirtIO 1.1 device spec. Its
described in section 5.8 "Input Device".

Issue #4282
2021-11-29 15:10:51 +01:00
Josef Söntgen
851d96de8a Fix misleading DosBox snippet in porting-guide
The included 'target.mk' snippet of DosBox suggests to use the contrib
source directory directly to reference source files.

Fixes #4305.
2021-11-29 15:10:50 +01:00
Tomasz Gajewski
ecb1a6187c ssh_terminal: moved to genode world
Fixes #4258
2021-11-29 15:10:50 +01:00
Sebastian Sumpf
d4a6342295 tool_chain: remove Go support from bootstrap compiler
Fixes #4292
2021-11-29 15:10:50 +01:00
Piotr Tworek
a10903a197 libm: fix undefined __isinff / __isinfl symbol references
Those symbols are not satisfied by any code or dependency of libm. As
result calling cprojf function will always crash on Genode. This crash
can be turned into link time error by adding --no-undefined to LD_OPT.

This patch provides the missing symbols by including isninf.c in libm
build.

Fixes #4299
2021-11-29 15:10:50 +01:00
Piotr Tworek
c38c2a6455 cxx: missing operator delete with align_val_t arg
When rebasing my local branch on top of sculpt-21.10 tag I've noticed
two problems.

The code in new_delete.cc does not include new header file. This works
fine with GCC, but fails with clang because std::align_val_t type is
not defined anywhere according to clang. It looks like GCC pulls this
header indirectly somehow.

The second problem can be seen if one disallows undefined symbols in
executables and shared_libraries. This can be seen with both GCC and
clang by adding --no-undefined to LD_OPT. With such change in place core
fails to link due to:

ld.lld: error: undefined symbol: operator delete(void*, std::align_val_t)
>>> referenced by thread.h:448 (/home/tworaz/devel/genode/repos/base-hw/src/core/kernel/thread.h:448)
>>>               thread.o:(Kernel::Core_main_thread::~Core_main_thread()) in archive debug/core-hw-virt_qemu.a
>>> referenced by thread.h:448 (/home/tworaz/devel/genode/repos/base-hw/src/core/kernel/thread.h:448)
>>>               thread.o:(non-virtual thunk to Kernel::Core_main_thread::~Core_main_thread()) in archive debug/core-hw-virt_qemu.a
>>> did you mean: operator delete(void*, unsigned long, std::align_val_t)
>>> defined in: debug/core-hw-virt_qemu.a(supc++.o)

If the code would somehow manage call such undefined symbol it'd crash.
Since I generally prefer link time failures to runtime crashes I link
all genode binaries with --no-undefined.

To fix this problem just add a dummy implementation of missing delete
operator.

Fixes #4298
2021-11-29 15:10:50 +01:00
Piotr Tworek
e748efacd8 reconstructible: Fix alignas specifier placement.
Alignas should be placed before the type. Placing it after it works for
GCC, but fails when building the same codee with clang. The error
message is:

reconstructible.h:48:27: error: 'alignas' attribute cannot be applied to types
    char _space[sizeof(MT)] alignas(sizeof(addr_t));
                            ^
Issue #4298
2021-10-15 15:45:52 +02:00
Christian Helmuth
42ff902576 vbox6: settings version 1.18-genode in machine.vbox6
At least the audio backend depends on the correct .vbox settings version
for VirtualBox 6.1 which is 1.18 as of VirtualBox.xidl.
2021-10-15 12:17:05 +02:00
Norman Feske
7e2716800b News item for Sculpt 21.10 2021-10-14 14:40:08 +02:00
864 changed files with 7962 additions and 18711 deletions

View File

@@ -1 +1 @@
21.08
21.11

View File

@@ -4,6 +4,95 @@
===========
Genode OS Framework release 21.11 | 2021-11-30
##############################################
| Genode 21.11 puts the spotlight on device drivers. Interactive Genode
| scenarios come to the Pinephone, hardware-accelerated graphics becomes
| available on Intel Gen9+ and Vivante GPUs, and Xilnx Zynq receives
| new love.
The previous release presented our new take on porting drivers from Linux, and
the architectural integration of hardware-accelerated graphics in Genode-based
systems. The just released version 21.11 is the continuation of both topics.
Thanks to our streamlined approach for transplanting Linux drivers to Genode, we
were able to reuse the Pinephone's Linux drivers for the display and
touchscreen without modification. But, in contrast to running those drivers in
the Linux kernel, we are walking on new ground by confining each driver in a
separate sandbox.
With our GPU line of work, we followed two major directions during the release
cycle. For one, we applied our architectural approach to a second GPU vendor
besides Intel, namely the Vivante GPU as used by the i.MX SoC family.
Combined with the etnaviv Gallium driver of the Mesa library, Genode thereby
becomes able to render graphics with hardware acceleration on the MNT Reform
open-hardware laptop. The second branch is the promised extension of our
custom Intel GPU multiplexer to GPUs of generation 9 or newer. Thereby, GPU
support has now become a regular feature of the Genode-based Sculpt OS that
can be taken for a spin on commodity PC hardware.
Regarding 32-bit ARM platforms, the current release revives our engagement
with Xilinx Zynq devices, which combine FPGA fabric with a 32-bit ARM CPU.
In particular, the release brings the framework to the USRP E310 board,
opening new hardware-software co-design opportunities.
Besides the many hardware-related topics outlined above, two functional
improvements stand out. First, the Genode version of VirtualBox 6 has reached
feature parity with version 5. Both versions can now be used interchangeably
on Sculpt OS. Finally, libSDL2 got upgraded with support for audio and OpenGL,
which is a nice pathway for hosting games on Genode.
The new version is described in full detail by the
[https:/documentation/release-notes/21.11 - release documentation of version 21.11...]
Sculpt OS release 21.10 | 2021-10-14
####################################
| Sculpt OS version 21.10 introduces GPU-accelerated graphics on Intel,
| media playback in the web browser, VirtualBox 6, and USB webcam support.
At the first glance, the just released Sculpt 21.10 looks and feels nearly
identical to the time-tested previous version 21.03. However, a look at the
installable packages reveals a firework of exciting new features.
First and technically most exciting, the new version enables the use of
hardware-accelerated graphics on Intel GPUs, paving the ground for
graphics-intensive applications and games. The GPU support is based on the
combination of the Mesa library stack with our custom GPU multiplexer
as featured in
[https://genode.org/documentation/release-notes/21.08#Advancing_GPU_driver_stack - Genode 21.08].
_Note that this fresh new feature should best be regarded as experimental_
_and be used with caution._
Second, our port of the Chromium-based Falkon web browser has become able to
present media content like videos and sound. Look out for the browser in the
tools menu of cproc's depot. It is accompanied with a ready-to-use audio
driver and a mixer component. In cases where audio output is not desired, the
browser - or any other component that requests audio output - can be connected
to a new component called black hole, which merely mimics an audio driver
without any audible effect.
Third, with the addition of the new file-vault component, Sculpt now provides
an easy way to setup and use an encrypted file store using our custom CBE
block encrypter as underlying crypto container. The file vault is especially
useful in combination with the recall-fs component that provides each client
with a distinct storage compartment.
Finally, the support for USB webcams as introduced with
[https://genode.org/documentation/release-notes/21.05#Webcam_support - Genode 21.05]
has entered Sculpt OS in the form of a new webcam package. The webcam support
can best be combined with our new port of VirtualBox 6 that is available in
addition to VirtualBox version 5. With Sculpt 21.10, both VirtualBox versions
can be used in parallel.
Sculpt OS 21.10 is available as ready-to-use system image at the
[https://genode.org/download/sculpt - Sculpt download page] and is accompanied
with updated [https://genode.org/documentation/articles/sculpt-21-10 - documentation].
More details about individual new features of Sculpt 21.10 will be covered
soon by dedicated articles at [https://genodians.org].
Genode OS Framework release 21.08 | 2021-08-31
##############################################

View File

@@ -289,9 +289,9 @@ Examining the log file leaves us with the following list of source files:
! FILTER_OUT_dos = cdrom_aspi_win32.cpp cdrom_ioctl_linux.cpp cdrom_ioctl_os2.cpp \
! cdrom_ioctl_win32.cpp
! SRC_CC_dos = $(filter-out $(FILTER_OUT_dos), \
! $(notdir $(wildcard $(DOSBOX_DIR)/src/*.cpp)))
! $(notdir $(wildcard $(DOSBOX_DIR)/src/dos/*.cpp)))
! […]
! SRC_CC = $(DOSBOX_DIR)/src/dosbox.cpp
! SRC_CC = $(notdir $(DOSBOX_DIR)/src/dosbox.cpp)
! SRC_CC += $(SRC_CC_cpu) $(SRC_CC_debug) $(SRC_CC_dos) $(SRC_CC_fpu) \
! $(SRC_CC_gui) $(SRC_CC_hw) $(SRC_CC_hw_ser) $(SRC_CC_ints) \
! $(SRC_CC_ints) $(SRC_CC_misc) $(SRC_CC_shell)

835
doc/release_notes/21-11.txt Normal file
View File

@@ -0,0 +1,835 @@
===============================================
Release notes for the Genode OS Framework 21.11
===============================================
Genode Labs
Version 21.11 of the Genode OS Framework puts device drivers into the
spotlight. Where to begin? Back in
[https://genode.org/news/road-map-for-2021 - January], we envisioned Genode
running on the Pinephone. With the current release, the first interactive
Genode scenarios become alive on this platform. Unlike the regular Linux-based
systems used on the Pinephone, we are walking on new ground by running each
individual driver in a dedicated sandbox.
Speaking of 64-bit ARM platforms, Genode's support for the i.MX8 SoC family
received a new USB host driver as well as the first version of the Vivante GPU
driver. The latter is a continuation of our GPU-related work presented in the
[https://genode.org/documentation/release-notes/21.08#Advancing_GPU_driver_stack - previous release],
which proves that our approach of integrating hardware-accelerated graphics
into the framework's architecture is applicable across different GPU vendors.
As promised three months ago, we have also taken our custom Intel GPU
multiplexer to Gen9 or newer devices. In fact, GPU support has now become a
regular feature of the Genode-based Sculpt OS that can be taken for a spin on
commodity PC hardware.
Even though most efforts are nowadays spent on 64-bit platforms, we have
revived Genode's support for Xilinx Zynq devices in aspiration of future
hardware-software co-design work. Those chips combine FPGA fabric with 32-bit
ARM cores and thereby allow us to explore the combination of reconfigurable
hardware with Genode's component architecture.
For users who prefer the comforts of virtual hardware over the tinkering with
physical devices, new drivers for VirtIO input and graphics open up the use of
interactive Genode systems on Qemu's "virt" platform.
Besides the predominant device-driver topics of the release, one other
highlight is the feature completion of Genode's version of VirtualBox 6 on PC
platforms, which has now reached parity with the time-tested version 5. Now,
features like shared folders, shared clipboard, sound, or USB pass-through
have become readily available.
A little kingdom for each SoC family
####################################
With the number of supported boards and CPU architectures growing, our
existing maintenance structure of the central Genode code repository becomes
increasingly nonviable. We made the following observations.
First, with respect to drivers ported from Linux, each SoC tends to refer
to a different _flavour_ of the Linux kernel. This so-called vendor kernel
may be a specific version with a blessed kernel configuration, or even a
hard fork. In the past, we tried harmonizing drivers across SoCs by using
the vanilla Linux kernel as common ground. But in practice, this common
ground seems to be walked-on by only a few. Devices are shipped with vendor
kernels after all. To get the best supported drivers for a given hardware,
we have to port the drivers from the respective vendor kernel.
This realization, in turn, faces us with the problem of a growing number
of vendor kernels we have to work with whenever extending Genode's hardware
support to a new SoC. But there are only so many Linux kernels one can juggle
with.
Second, when using one monolithic code base for all SoCs, the coordination of
the code repository becomes a bottleneck when it comes to reviewing and
merging contributions, and the nurturing of a consistent level of quality
assurance. In the case of Genode, this responsibility is shared by two head
maintainers. However, their expertise lies in the Genode framework, not in the
peculiarities of specific SoC hardware. Hence, the review of such SoC-related
contributions must remain at surface level. But the burden of responsibility
still rests on the two.
Third, we ultimately want to encourage 3rd parties - like hardware vendors -
to supplement SoC support for Genode independently from us. Forcing such
independent developers to funnel their results into our code base is not
always natural and may even be legally impeded by Genode's need for a
[https://genode.org/community/contributions#Genode_Contributors_Agreement - contributor's agreement].
We want to avoid such artificial friction.
The consequence of these observations is the need to modularize our code base
around the idea of giving each SoC family a little kingdom of their own. We
envision a code repository with a different maintainer for each SoC family. As
a prerequisite, we had to cleanly separate SoC-specific code from the generic
code that will remain in the main Genode repository. To stress this approach,
each of four developers picked a dedicated SoC family and went with it. Stefan
Kalkowski took the i.MX-related code to his
[https://github.com/skalk/genode-imx - genode-imx] repository,
Johannes Schlatow took the Xilinx Zynq code to his
[https://github.com/jschlatow/genode-zynq - genode-zynq] repository,
Norman Feske
maintains the Allwinner code for the Pinephone in
his [https://github.com/nfeske/genode-allwinner - genode-allwinner]
repository, and Sebastian Sumpf gave the RISC-V support a new home
at his [https://github.com/ssumpf/genode-riscv - genode-riscv] repository.
By looking at this modularization from four different perspectives at the same
time, we reached satisfying interfaces between the generic and SoC-specific
code. We found that this maintenance model works as anticipated. In
particular, we hoped that each SoC can be shepherded by a single person
without stress. This turned out to be true.
We also found that the taken approach gives each maintainer a sense of
autonomy that was not possible with one monolithic code base. This is
particularly fruitful when drafting generic utilities for the eventual
inclusion into Genode's main repository. The drafts can first receive a test
of time at individual SoC repositories before integrating them into the common
code base, the pin I/O interfaces described in
Section [Pin I/O session interfaces] being a good example.
The supportive tooling for each SoC tends to differ between vendors, speaking
of custom system-image formats, boot loaders, or firmware. The SoC-specific
repositories provide a natural home for hosting such tools, custom work-flow
scripts, and configurations.
With this exploratory phase completed, we plan to move the SoC-specific
repositories - that currently reside at each maintainer's GitHub account -
under the banner of [https://github.com/genodelabs - genodelabs] during the
next release cycle.
NXP i.MX family
===============
Support for the family of i.MX SoC related boards is located in the
[https://github.com/skalk/genode-imx - genode-imx] repository.
By now, it contains far-reaching support for the i.MX 8M Quad evaluation kit,
and the MNT Reform2.
Besides the basic kernel support for Genode's custom base-hw microkernel,
it contains drivers for using SD and eMMC cards, HDMI, and MIPI-DSI connected
displays, Ethernet, and USB connected devices. Moreover, we are proud to
introduce support for the Vivante GPU used by the i.MX 8M SoC. All mentioned
device drivers were ported using the
[https://genode.org/documentation/release-notes/21.08#Linux-device-driver_environment_re-imagined - re-imagined approach to port Linux drivers]
that was introduced in the previous release.
To obtain a ready-to-use SD-card when testing an arbitrary run-script
scenario, it is sufficient to add the following value to the 'RUN_OPT'
variable:
! RUN_OPT += --include image/imx8mq_mmc
Depending on which board you've chosen, it will build the corresponding u-boot
bootloader, file system, Genode system image, and integrate those parts into
one SD-card image.
Xilinx Zynq
===========
Basic platform support for the Zynq-7000 SoC has already been added to Genode
with
[https://genode.org/documentation/release-notes/15.11#Xilinx_Zynq-7000 - release 15.11].
While the virtualized zynq_qemu board support resided in the main Genode
repository and was regularly tested, support files for real Zynq-hardware were
living in segregation within the Genode-world repository.
By creating a new realm in form of a
[https://github.com/jschlatow/genode-zynq - genode-zynq repository], we were
able to consolidate the Zynq-specific board support and drivers in one place.
Furthermore, we are currently intensifying our work on this platform and
documenting the journey on
[https://genodians.org/jschlatow/2021-11-29-zynq-guide-1 - genodians.org].
This particularly includes building ready-to-use SD card images with u-boot
and supporting run-time re-configuration of the FPGA.
In order to use the zynq repository, you only need to create a clone at
_repos/zynq_, create a new build directory for arm_v7a and uncomment the
corresponding line in your etc/build.conf. Step-by-step instructions for
individual boards can be found at _repos/zynq/doc/_.
Allwinner A64 (Pinephone)
=========================
During the release cycle, Genode's support for the Allwinner A64 SoC, and
the Pinephone in particular, made big leaps forward. The corresponding code
is hosted in the dedicated
[https://github.com/nfeske/genode-allwinner - genode-allwinner] repository.
First, the Linux version taken as the basis for ported device drivers has been
updated to 5.14.1 in order to support the revision v2 of the Pine-A64-LTS
board, which features a different Ethernet PHY, namely the Motorcomm YT8511
PHY. Genode's 'pine_a64lts' board supports both board revisions now.
To enable touchscreen input on the Pinephone, the corresponding driver for the
Goodix touchscreen controller has been ported from the Linux kernel. It
complements the framebuffer driver that we introduced with the previous
release. Combined, both drivers enable the use of Genode's regular interactive
scenarios based on the 'drivers_interactive' package. The biggest technical
challenge was the untangling of both drivers from the clock, reset, and power
control units (CCU, RSB, PMIC). Those low-level platform configurations are
now handled by a new A64-specific version of the platform driver.
[image pinephone_touch]
Genode's nano-3D example responding to touch input
The improved driver support is accompanied with new tooling for booting Genode
on the Pinephone, either via USB fastboot, or via SD-card. Both options are
described in the following Genodians article.
:Booting Genode on the Pinephone:
[https://genodians.org/nfeske/2021-09-20-pine-fun-pinephone-boot]
RISC-V
======
RISC-V board support for the base-hw kernel is now located at the
[https://github.com/ssumpf/genode-riscv - genode-riscv] repository. Currently,
the repository contains support for the
[https://hensoldt-cyber.com/mig-v - MiG-V] SoC including kernel specific parts
as well as a driver for MiG-V's network-interface controller.
Base framework and OS-level infrastructure
##########################################
New pattern for C++ error handling
==================================
Genode employs C++ exceptions for propagating errors, which is true to the
language. However, the use and the mechanics of C++ exceptions comes with its
own bag of problems. The current release introduces a new error-handling
pattern in the form of the so-called 'Attempt' utility. Its name reflects its
designated use as a carrier for return values. This new utility is described
by a dedicated article at Genodians.org:
:An 'Attempt' to avoid C++ exceptions:
[https://genodians.org/nfeske/2021-11-26-attempt-no-exceptions]
During the release cycle, we applied the 'Attempt' pattern to Genode's
low-level memory-allocation code, namely core's PD session interface (for the
allocation of RAM dataspaces), and the code related to the generic 'Allocator'
interface (for the allocation of bytes). The latter is an extensive change,
touching all implementations of this interface.
To largely uphold compatibility with components using the original
exception-based interface as a mere client - in particular use cases where an
'Allocator' is passed to the 'new' operator - the traditional 'alloc' is still
supported. But it exists merely as a wrapper around the new 'try_alloc'.
However, the change does not preserve compatibility with the original
'Range_allocator' interface. So uses of this interface must be adapted.
Pin I/O session interfaces
==========================
On ARM-based SoCs, the use of general-purpose I/O (GPIO) pins is omnipresent.
Traditionally, Genode features the "Gpio" session interface for this purpose.
This interface allows a client to access an individual pin. Once assigned to a
pin, the session grants the client the full responsibility for the pin. In
particular the direction of the I/O pin is laid into the hands of the client.
We later realized that the wiring and thereby the direction of a pin is
ultimately a board-level decision. Wrongly operating an input pin in output
mode can easily result in a short-circuit. Therefore, the client of an
individual pin should better not be burdened with the responsibility to
control the pin direction or pull resistors. To address this concern, it is
best to split the roles of GPIO pins into clear-cut session interfaces.
Those roles are:
* The sensing of the state of a GPIO pin, e.g., detecting whether a button is
pressed or not: operating a pin as an input signal. This role is now covered
by the "Pin_state" session interface with the single RPC function
! bool state() const;
By calling this function, the client can request the state of the pin.
That's it.
* Controlling the signal level of a pin: operating a pin as an output signal.
This role is now addressed by the "Pin_control" session interface that
provides an interface of only one rather unsurprising RPC function
! void state(bool);
* Receiving a notification of a change of the signal level of a GPIO pin:
operating a pin as an interrupt source. This role can be represented by
Genode's existing IRQ session interface - the same interface as provided by
Genode's core for GIC interrupts.
Since each pin corresponds to a separate session, per-pin access control
becomes possible by Genode's regular session-routing mechanisms.
In contrast to the original GPIO session, the role of each pin as output and
input becomes explicit. A client can no longer drive a pin that is an input
signal unless explicitly permitted.
The interfaces were created and time-tested in the context of our
Pinephone-related development, in particular during the work described in the
following two articles.
:Device access from the user level:
[https://genodians.org/nfeske/2021-03-17-pine-fun-device-access]
:One Platform driver to rule them all:
[https://genodians.org/nfeske/2021-04-29-platform-driver]
Pin-driver framework
--------------------
In real-world system scenarios, a variety of different components must
decidedly interact with individual GPIO pins. This is where a so-called pin
driver enters the picture. This component provides the pin-state, pin-control,
and IRQ services. Analogously to how the platform driver safeguards the access
to device resources by different - mutually distrusting - device drivers, the
pin driver's job is the safeguarding of GPIO pins.
To ease the implementation of such pin drivers, the new session interfaces are
accompanied by a set of new utilities in
[https://github.com/genodelabs/genode/blob/staging/repos/os/include/os/pin_driver.h - os/pin_driver.h].
The use of these utilities is best illustrated by the
[https://github.com/nfeske/genode-allwinner/tree/master/src/drivers/pin/a64 - pin driver for the A64 SoC].
Time-multiplexed pin direction
------------------------------
There exist rare use cases for changing the direction of an I/O pin during
runtime. For example, the Goodix touchscreen controller as found in the
Pinephone monitors the state of its interrupt signal during reset. During its
normal operation, this signal is driven by the touchscreen controller but
during reset, it is driven by the host to send one bit of information (I2C
address selection). We support this time-multiplexed use of one pin as both
input and output by the means of session lifetimes. The pin driver switches
the pin into output mode not before a client establishes a pin-control session
referring to this pin. The client can thereby control the direction by
creating or closing its pin-control session.
Genode C APIs
=============
USB host-controller service API
-------------------------------
While porting the Linux driver for the Designware USB host-controller used
within the i.MX 8M SoC, we introduced a new C API to serve Genode USB clients
from C driver ports. It enables drivers to:
* Announce and release USB devices,
* Ask for a session handle of an open session via the bus/device ID pair,
* Ask for a single USB request via a session handle,
* Acknowledge a USB request via a session and request handle, and
* Notify potential USB clients that I/O progress has been made.
You can find the new C API under _repos/os/include/genode_c_api/usb.h_. A
working example driver can be found within the 'genode-imx' repository under
_src/drivers/usb_host/imx8mq_.
Touchscreen driver API
----------------------
To accommodate input drivers written in C, like the ones ported from the Linux
kernel, we need a clean way to connect C code with Genode's event session
interface.
The current release introduces a C API to be used by input drivers to generate
Genode events. The interface is located at
_repos/os/include/genode_c_api/event.h_ whereas the implementation resides at
_repos/os/src/lib/genode_c_api/event.cc_.
The initial version is limited to multitouch events only.
As of now, it is used by the Goodix touchscreen driver for the Pinephone.
Event filter for converting touch to pointer input
==================================================
Unlike traditional pointer devices, touchscreens have no notion of a pointer
position, hovering, or mouse buttons. E.g., without touching, there is no
position. There exists a gap between those devices and regular GUI
applications, which respond to pointer events in terms of hovering motion (in
screen coordinates) and mouse clicks. Genode's existing touchscreen drivers
try to bridge this gap by translating touch input to pointer events in rather
pragmatic ways. This is not optimal for two reasons.
First, putting the burden of emulating traditional pointer devices on the
touchscreen drivers not only inflates their complexity but is also unnatural
when the calibration of touch coordinates to screen coordinates comes into
play. In this case, the touchscreen driver must be made aware of the display
resolution. Second, the heuristics of how touch events are best translated
into pointer events tend to differ from driver to driver, or between Genode
use cases. Any intelligence that is builtin in the drivers stands in the way
of interchanging the drivers or enhancing the translation across all drivers
(e.g., adding two-finger-scroll).
To solve this problem in a clean way, we added a new optional filter for
translating touch events to pointer events to Genode's event-filter component
(first introduced in
[https://genode.org/documentation/release-notes/17.02#Input-event_filter - 17.02]
as input filter, reworked in
[https://genode.org/documentation/release-notes/20.08#Replacing_the_input_filter_with_an_event_filter - 20.08]).
The new filter comes in the form of a new '<touch-click>' node in the filter's
'<output>' definition. For example, the configuration of the event filter that
sits in-between the Goodix touchscreen driver for the Pinephone and the
nitpicker GUI server looks as follows.
! <config>
! <output>
! <touch-click>
! <input name="touch"/>
! </touch-click>
! </output>
! <policy label="touch" input="touch"/>
! </config>
The filter augments touch events with artificial absolute motion and mouse
click/clack events as understood by regular GUI applications. The original
touch events are preserved, enabling touch-aware applications to interpret
touch gestures.
Device drivers
##############
Hardware-accelerated graphics
=============================
Generic GPU-session interface
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we introduced the GPU session initially, it was modeled after the
perceived requirements of the Linux i915 DRM back end. In the meantime, with
the enablement of a more recent Mesa version and the addition of Vivante as
another GPU family, we learned that some of those requirements are obsolete.
First, we replaced the 'info' RPC by an information ROM dataspace to overcome
the following limitations.
* The amount of data that can be transferred in an RPC is constrained by the
underlying base platform,
* Most information never changes during run time but must be copied
nonetheless when using an RPC interface,
* The information presented differs depending on the used GPU device.
With the introduction of Vivante, the original Intel-centric implementation no
longer suffices.
* Sequence numbers of GPU execution buffers are not GPU-specific and, thus,
should be part of the generic GPU session interface.
Currently, the GPU-specific information is presented in binary format, which
is specified in _gpu/info_intel.h_ resp. _gpu/info_etnaviv.h_ for the Vivante
GPU. We entertain the idea to replace the current representation by an
XML-based ROM in the future to render the interface binary agnostic and also
backwards-compatible. The information ROM can be accessed via the
'attached_info' client API function.
Furthermore, we replaced the usage of heavy-weight dataspace capabilities with
light-weight client-local identifiers called 'Buffer_id' within the API. In
case the client requires a capability (e.g., for mapping the buffer in its
address space) it uses the corresponding ID to request it from the server.
With upcoming support for other driver back ends, we need to take their
requirements into account as well. We introduced abstractions that further
encapsulate the device-specific state and operations. The changes in this
release represent only the first consolidation steps of Genode's GPU support
and we will continue this work during the next months.
Intel GPU support for Gen9 and newer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As mentioned in the
[https://genode.org/documentation/release-notes/21.08#Advancing_GPU_driver_stack - 21.08]
release notes, we were fiercely working on Intel GPU Gen9+ support because
Gen8 (Broadwell) was the only stable running GPU on Genode at the time. For
Gen9+, we experienced severe GPU hangs after an undefined amount of rendering
passes. As promised in the previous release, we dove right in and were able to
identify the main causes of this behavior. This led to working Gen9+ support in
[https://genode.org/documentation/articles/sculpt-21-10#GPU - Sculpt OS release 21.10].
To go into a little more detail, we had to look into workarounds as described by the
[https://01.org/sites/default/files/documentation/intel-gfx-prm-osrc-skl-vol16-workarounds_0.pdf - Intel documentation]
and the Linux kernel driver, and determine known workarounds that only apply
to Gen9 and above. After many iterations, we found one workaround that fixed
our GPU hang issue and now apply it during GPU initialization. Additionally,
we found the hardware context sizes (a memory region where the GPU stores its
state) vary between GPU generations, where Gen9 requires more space than Gen8.
Additionally, we found that some features like tiling or client mappings
through the global-graphics translation table are not required by our updated
Mesa 21.0.0 Iris Gallium driver. Since these resources are global and were
split between multiple GPU client applications, not using them lifts the
limits formerly imposed by the partitioning.
For the Sculpt integration, we added GPU-service support and are providing
various packages. A summary on how to test GPU acceleration on Sculpt can be
found at the following Genodians article.
:Test driving Sculpt's 3D support:
[https://genodians.org/ssumpf/2021-10-25-glmark2]
Vivante GPUs (i.MX8)
~~~~~~~~~~~~~~~~~~~~
With the previous release, we already foresaw adding support for Vivante
GPUs as found in i.MX8 SoCs by show-casing a work-in-progress driver
component based on the Linux 'etnaviv' DRM driver and using the also ported
'etnaviv' Gallium driver.
This driver component is now available in an updated fashion in the
[https://github.com/skalk/genode-imx - genode-imx] repository that
encapsulates support for the family of i.MX8 SoCs for Genode. In contrast to
our first prototype, the driver now relies completely on the new DDE Linux
approach and re-uses the existing 'lx_emul' and 'lx_kit' libraries. At the
moment, the driver does not make use of a C-API to Genode services for
accessing the GPU service like the other new DDE Linux drivers do but
implements the session directly. We decided against prematurely introducing
such an C-API while the GPU session itself is still in flux.
[image glmark_mnt_reform]
Glmark running via the ported Vivante GPU driver on the MNT Reform laptop
Briefly touching on the current implementation of the driver, we had to extend
the 'lx_kit' API slightly to implement the buffer-object allocation. Also, we
added a special-purpose interface called 'lx_drm' that comprises all Linux DRM
I/O controls that need to be performed for implementing the GPU session and
itself is a simple layer on top of 'drm_ioctl'.
The 'lx_drm' functions are executed within the context of an emulated Linux
kernel thread executed under a cooperative user-level scheduling scheme.
However, since the GPU session is based on synchronous RPCs and we do not know
in advance if a call into the ported driver code blocks at some point, we had
to ensure the RPC returns not before the operation completed. The completion
of operations may include several blocking states and concurrent event
handling (e.g., hardware interrupts).
For the time being, the driver component is still being worked on. We are, for
example, investigating overall performance regressions. Nevertheless, the
driver is functionally complete and currently supports one client at a time.
In addition to the driver component, we cleaned up the existing 'etnaviv'
libdrm back end and created a Sculpt pkg called *mesa_gpu-etnaviv* analogous
to the pkgs for 'iris' and 'softpipe' back ends. The most visible change is
the switch from the ad-hoc DRM session to the GPU session.
All in all, we are now at a stage were we can work on optimizing the graphics
stack on the Vivante GPU and are in particular looking forward to porting the
next Linux driver. After all, by doing so, we can flesh out and maybe
generalize the 'lx_drm' API so that for other drivers the porting effort gets
reduced even further.
VirtIO input and framebuffer drivers
====================================
_This section was co-authored by Piotr Tworek who created the_
_VirtIO driver support. Thanks Piotr for the welcome contribution!_
Over the
[https://genode.org/documentation/release-notes/21.02#VirtIO_block_devices_for_virtual_machines_on_ARM - previous]
[https://genode.org/documentation/release-notes/21.08#RAM_framebuffer_driver_for_Qemu - releases]
of Genode this year, the framework received steadily improved driver support
for virtual devices as supported by Qemu. The primary motivation behind this
line of work is the use of virtual hardware as an experimentation ground for
Genode on the AARCH64 and RISC-V architectures. The use of virtual hardware
nicely side-steps the costs and (un-)availability of suitable devices, and
avoids the extra effort that is usually involved when working with real
hardware. The current release further advances the virtual-device support by
the introduction of VirtIO input and graphics drivers.
VirtIO input
------------
The new input driver can service Qemu VirtIO mouse, keyboard, and tablet
devices. The implementation is based on the VirtIO 1.1 device specification,
Section 5.8 "Input Device". The driver can service three separate device
types, namely mouse, keyboard, and tablet. The main difference between mouse
and tablet devices is that the former produces relative events whereas the
latter produces absolute motion events.
By default, the driver tries to attach to the first VirtIO input device of any
of the listed types. Such behavior would pose a bit of a problem since in
Genode, we'd like to know that a specific instance of the driver will attach
only to a mouse for example. This way, we can define proper policies for it.
To allow such behavior, the VirtIO input driver has one configuration key
called 'match_product', which accepts the values of "mouse", "keyboard",
"tablet", and "any" (default). Using this config key, one can accomplish
exactly what is needed to tell the driver to only attach to a VirtIO input
device if it's of "match_product" type.
VirtIO framebuffer
------------------
The new VirtIO framebuffer driver implements the necessary bits to provide 2D
framebuffer support on top of a VirtIO GPU device as provided by Qemu. Compared
to the ramfb driver, which was introduced in Genode
[https://genode.org/documentation/release-notes/21.08#RAM_framebuffer_driver_for_Qemu - 21.08],
the VirtIO framebuffer driver has one major benefit: It allows the Qemu window
to be dynamically resized at runtime. The driver will treat this as resolution
change and act accordingly. In contrast to the VirtIO input driver, the
framebuffer driver does not support any extra config options.
Practical use
-------------
Thanks to the new drivers, the drivers_interactive package for the 'virt_qemu'
board has become fully interactively usable. The drivers subsystem spawns two
instances of virtio_input. One attaches to a keyboard device and the second to
a mouse. This is what the default virt_qemu board exposes. At this time, the
tablet device is not instantiated by default but it might become useful in the
future for testing Genode's touch support.
Make sure that Qemu exposes those new devices in the modern VirtIO 1.0 mode.
Versions up to Qemu 5.1.0 still use pre-1.0 mode in the default setup.
One thing to keep in mind is that the VirtIO framebuffer driver will change
the resolution of the virtual display whenever the Qemu window is resized.
This means that for high resolution screens, one might have to tweak the
default RAM quota for the driver. The default should be enough for 1080p
screens, but not much more than that.
Linux device-driver environment
===============================
While working on Linux device-driver ports that use the new DDE Linux
environment introduced in
[https://genode.org/documentation/release-notes/21.08#Linux-device-driver_environment_re-imagined - release 21.08],
we stumbled across some inaccuracies and missing pieces of the former
implementation.
For instance, kworker threads were blocked unconditionally before. But the
original Linux kernel semantics includes corner-cases that delay kworker
suspension. By adding them, we circumvent potential deadlocks. The cache
maintenance operations got optimized by checking the read/write direction of
the device with regard to DMA memory more accurately. Moreover, we had to
learn that on ARM the minimal alignment for all allocations within Linux have
to be of cache-line granularity.
Feature-wise, a new API got introduced to access the pin-control service and
IRQ sessions offered by it. This is useful when a Linux driver directly
depends on GPIO settings respectively uses GPIO pins as interrupt source.
Libraries and Applications
##########################
Feature completion of VirtualBox 6
==================================
With [https://genode.org/documentation/articles/sculpt-21-10 - Sculpt OS 21.10],
we released VirtualBox version 6 as experimental alternative to the existing
port of version 5. We also switched to version 6 as daily driver on our
development machines at Genode Labs. These steps yielded the following
improvements during the past Genode release cycle.
The integration features shared folders, shared clipboard, and guest
mouse-pointer shape were fully enabled. Most guest-integration modules in
VirtualBox are implemented as shared libraries/objects, which are loaded at
runtime on demand. Following our goal to keep changes to the upstream code
minimal, our version of VirtualBox 6 now provides VBoxSharedClipboard and
VBoxSharedFolders as dedicated libraries that must be integrated into the
system as follows. Note, the libraries are accessed by the VirtualBox code as
files before loading but must also be available as ROMs to our runtime dynamic
linker.
! <start name="virtualbox6">
! <config vbox_file="machine.vbox6">
! <vfs>
! <!-- original file names of shared objects -->
! <rom name="VBoxSharedClipboard.so"/>
! <rom name="VBoxSharedFolders.so"/>
! </vfs>
! </config>
! <route>
! <!-- map file names to Genode shared-object naming scheme -->
! <service name="ROM" label="VBoxSharedClipboard.so">
! <parent label="virtualbox6-sharedclipboard.lib.so"/> </service>
! <service name="ROM" label="VBoxSharedFolders.so">
! <parent label="virtualbox6-sharedfolders.lib.so"/> </service>
! </route>
! </start>
As depicted in the configuration snippet above, we use the file extension
_.vbox6_ for VirtualBox 6 configuration files. The background is that there
are some subtle incompatibilities in VirtualBox 6 with settings we used in
version 5. For example, the version of the configuration file must be set to
1.18+ for maximum compatibility of virtual-device configuration and guest
operating systems. An example configuration is provided by the pkg/vbox6 depot
archive and specifies the version like follows.
! <VirtualBox xmlns="http://www.virtualbox.org/" version="1.18-genode">
Unlike VirtualBox 5, the current version does not implement a custom Audio
back end for Genode but uses the existing OSS back end of the original
implementation. The feature can be enabled in .vbox and runtime configuration.
We recommend using the HDA controller.
! <AudioAdapter controller="HDA" driver="OSS" enabled="true" enabledOut="true" enabledIn="false"/>
! <start name="virtualbox6">
! <config>
! <vfs>
! <dir name="dev"> <oss name="dsp"/> </dir>
! <vfs>
! </config>
! </start>
More device-related improvements are the reporting of mouse-wheel events, the
support of up to 8 pass-through USB devices via the virtual XHCI USB3
controller, and a ready-to-use Sculpt package to capture webcam streams in the
VM (genodelabs/pkg/vbox6-capture).
Finally, this release includes a whole lot of stability improvements to bring
VirtualBox 6 on par with version 5 in daily use like robust machine state
handling including the FPU, fixed corner cases in the AHCI model and
Startup-IPI implementation as well as enhanced timeout and CPU wakeup
handling.
Sculpt OS for 64-bit ARM in addition to x86
===========================================
Up until now, the Genode-based [https://genode.org/download/sculpt - Sculpt OS]
was primarily targeted at the 64-bit x86 architecture. However, since the
hardware support of 64-bit ARM platforms like i.MX8 has reached almost feature
parity with the PC platform, it was time to introduce the notion of CPU
architectures to package index files.
In Sculpt OS, software packages are provided in a federated way from any
number of package providers. Each provider offers a so-called _index_ that
enlists the available package versions blessed for a specific Sculpt OS
release. See the release notes for Genode
[https://genode.org/documentation/release-notes/19.02#Announcing_software_packages - 19.02]
for more details.
Starting with [https://genode.org/news/sculpt-os-release-21.10 - Sculpt OS 21.10]
released in October, each index file features a declaration of the CPU
architectures supported by the package provider.
! <index>
! <supports arch="x86_64"/>
! <supports arch="arm_v8a"/>
! ...
Sculpt uses this information to decide whether to display the index or not by
comparing the architecture of the running machine with these declarations.
Individual entries of an index file can be tagged as being specific for one
architecture.
! <pkg path="mesa_gpu-intel" info="Intel GPU driver (IRIS)" arch="x86_64"/>
This annotation can also be specified for a sub index.
! <index name="Virtual machines" arch="x86_64">
! ...
! </index>
Thanks to this approach, most packages - which are architecture-agnostic - can
be offered for both x64_64 and arm_v8a with almost no manual work. In fact,
starting with Sculpt 21.10, all default packages offered by Genode Labs are
available for both architectures.
Audio and OpenGL support for libSDL2
====================================
With this release, we extend the features of our SDL2 port by enabling audio
support via the OSS back end and added basic support for using OpenGL.
Re-using the existing OSS back end via our VFS OSS plugin is in contrast to
how we enabled audio in our SDL1 port where we use Genode's audio-out
session directly. Instead of having to add a Genode specific back end to each
ported software, it is more reasonable to have just one implementation of a
somewhat common interface for which the back end already exists.
The OpenGL support, on the other hand, has not been thoroughly tested yet
but works well enough for one or the other game. It still suffers from the
same limitation as the normal video back end where resizing the window during
runtime is not supported. This feature is yet to be implemented.
Additionally, we made SDL2 now to use its existing pthread back ends,
rather than using the generic fallback ones, as we deem the current pthread
support in Genode sufficient.
SSH terminal moved to Genode world repository
=============================================
The SSH terminal component now resides in the world repository. When we
initially introduced this component, it complemented the existing TCP
terminal. Rather than using plain TCP to access a terminal server the
connection is secured by the SSH protocol.
In the meantime the component itself incorporated more and more features
that were not anticipated in the initial design. Since we have not used
the component much ourselves lately, albeit some features are tested in our
nightly CI, we decided to move it to the world repository.
On a different note, the component now features new support for SFTP that
enables one to access a Genode file system via SSH. Thanks to Tomasz Gajewski
for this welcome contribution.
Build system and tools
######################
Moving the platform-specific board support into extra repositories made it
necessary to review the run tool with respect to virtualized platforms. For
running Genode within Qemu, the run tool used to assemble the Qemu command
line depending on the target board. In order to achieve a clean cut between
the main repository hosting this part of the run tool and the
platform-specific repositories, we came up with a way to specify the Qemu
arguments outside the main repository.
The solution follows along our approach of how we already specify the
architecture and link address of a target board in distinct files within a
board-property directory _board/<board_name>/_. Similarly, the board-specific
Qemu arguments are now provided in a _board/<board_name>/qemu_args_ file. This
file may contain one or multiple lines that will be appended to the command
line generated by the run tool. Because it is required by virt_qemu, it is
possible to restrict particular arguments to a certain spec, e.g. arm_v8a, by
prefixing the line with 'arm_v8a:'. Note, that any '-m *' argument, which
specifies the amount of RAM, provided within a _qemu_args_ file will override
any memory setting provided in the run scripts.
Moreover, the _qemu_args_ file is obliged with instantiating a network
controller since this is also specific to the platform. For the zynq_qemu
board, e.g., this is achieved by the following arguments:
! -net nic,model=cadence_gem,netdev=net0 -netdev user,id=net0
Always instantiating a network device removes the need to call
'append_qemu_nic_args' in the run scripts. However, you can still use this
function to add forwarding rules to the netdev with id _net0_.

View File

@@ -1 +1 @@
2021-10-13 05c76f8a5e76e0cc76fd7336c7cf63836ecec35d
2021-11-29 dc3dc62ee3267db5cab87426b73323828cbc8d15

View File

@@ -38,61 +38,67 @@ static inline bool can_use_super_page(addr_t, size_t)
}
addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
addr_t Io_mem_session_component::_map_local(addr_t phys_base, size_t size)
{
using namespace Fiasco;
auto map_io_region = [] (addr_t phys_base, addr_t local_base, size_t size)
{
using namespace Fiasco;
l4_threadid_t const sigma0 = sigma0_threadid;
unsigned offset = 0;
while (size) {
/*
* Call sigma0 for I/O region
*/
/* special case for page0, which is RAM in sigma0/x86 */
l4_umword_t const request = (phys_base + offset == 0)
? SIGMA0_REQ_FPAGE_RAM
: SIGMA0_REQ_FPAGE_IOMEM;
size_t const size_log2 = can_use_super_page(phys_base + offset, size)
? get_super_page_size_log2()
: get_page_size_log2();
l4_umword_t dw0 = 0, dw1 = 0;
l4_msgdope_t result { };
l4_msgtag_t tag { };
int const err =
l4_ipc_call_tag(sigma0,
L4_IPC_SHORT_MSG,
request,
l4_fpage(phys_base + offset, size_log2, 0, 0).fpage,
l4_msgtag(L4_MSGTAG_SIGMA0, 0, 0, 0),
L4_IPC_MAPMSG(local_base + offset, size_log2),
&dw0, &dw1,
L4_IPC_NEVER, &result, &tag);
if (err || !l4_ipc_fpage_received(result)) {
error("map_local failed err=", err, " "
"(", l4_ipc_fpage_received(result), ")");
return;
}
offset += 1 << size_log2;
size -= 1 << size_log2;
}
};
/* align large I/O dataspaces on a super-page boundary within core */
size_t alignment = (size >= get_super_page_size()) ? get_super_page_size_log2()
: get_page_size_log2();
size_t align = (size >= get_super_page_size()) ? get_super_page_size_log2()
: get_page_size_log2();
/* find appropriate region for mapping */
void *local_base = 0;
if (platform().region_alloc().alloc_aligned(size, &local_base, alignment).error())
return 0;
return platform().region_alloc().alloc_aligned(size, align).convert<addr_t>(
/* call sigma0 for I/O region */
int err;
l4_umword_t request;
l4_umword_t dw0, dw1;
l4_msgdope_t result;
l4_msgtag_t tag;
[&] (void *ptr) {
addr_t const core_local_base = (addr_t)ptr;
map_io_region(phys_base, core_local_base, size);
return core_local_base; },
l4_threadid_t sigma0 = sigma0_threadid;
unsigned offset = 0;
while (size) {
/* FIXME what about caching demands? */
/* FIXME what about read / write? */
/* special case for page0, which is RAM in sigma0/x86 */
if (base + offset == 0)
request = SIGMA0_REQ_FPAGE_RAM;
else
request = SIGMA0_REQ_FPAGE_IOMEM;
size_t page_size_log2 = get_page_size_log2();
if (can_use_super_page(base + offset, size))
page_size_log2 = get_super_page_size_log2();
err = l4_ipc_call_tag(sigma0,
L4_IPC_SHORT_MSG,
request,
l4_fpage(base + offset, page_size_log2, 0, 0).fpage,
l4_msgtag(L4_MSGTAG_SIGMA0, 0, 0, 0),
L4_IPC_MAPMSG((addr_t)local_base + offset, page_size_log2),
&dw0, &dw1,
L4_IPC_NEVER, &result, &tag);
if (err || !l4_ipc_fpage_received(result)) {
error("map_local failed err=", err, " "
"(", l4_ipc_fpage_received(result), ")");
return 0;
}
offset += 1 << page_size_log2;
size -= 1 << page_size_log2;
}
return (addr_t)local_base;
[&] (Range_allocator::Alloc_error) -> addr_t {
error("core-local mapping of memory-mapped I/O range failed");
return 0; });
}

View File

@@ -130,7 +130,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
if (msi)
throw Service_denied();
if (irq_alloc.alloc_addr(1, _irq_number).error()) {
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable IRQ ", _irq_number, " requested");
throw Service_denied();
}

View File

@@ -445,51 +445,42 @@ Platform::Platform()
fiasco_register_thread_name(core_thread.native_thread_id(),
core_thread.name().string());
/* core log as ROM module */
auto export_page_as_rom_module = [&] (auto rom_name, auto content_fn)
{
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const log_size = pages << get_page_size_log2();
size_t const size = 1 << get_page_size_log2();
ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result(
ram_alloc().alloc_aligned(log_size, &phys_ptr, get_page_size_log2());
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
[&] (void *phys_ptr) {
void * const core_local_ptr = phys_ptr;
addr_t const core_local_addr = phys_addr;
/* core-local memory is one-to-one mapped physical RAM */
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
void * const core_local_ptr = phys_ptr;
/* let one page free after the log buffer */
region_alloc().remove_range(core_local_addr, log_size + get_page_size());
region_alloc().remove_range((addr_t)core_local_ptr, size);
memset(core_local_ptr, 0, size);
content_fn(core_local_ptr, size);
memset(core_local_ptr, 0, log_size);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, size, rom_name));
},
[&] (Range_allocator::Alloc_error) {
warning("failed to export ", rom_name, " as ROM module"); }
);
};
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
"core_log"));
init_core_log(Core_log_range { core_local_addr, log_size } );
}
/* core log as ROM module */
export_page_as_rom_module("core_log",
[&] (void *core_local_ptr, size_t size) {
init_core_log(Core_log_range { (addr_t)core_local_ptr, size } ); });
/* export platform specific infos */
{
void * phys_ptr = nullptr;
size_t const size = 1 << get_page_size_log2();
if (ram_alloc().alloc_aligned(size, &phys_ptr,
get_page_size_log2()).ok()) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const core_local_addr = phys_addr;
region_alloc().remove_range(core_local_addr, size);
Genode::Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
size, "platform_info", [&] ()
{
xml.node("kernel", [&] () { xml.attribute("name", "fiasco"); });
});
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"platform_info"));
}
}
export_page_as_rom_module("platform_info",
[&] (void *core_local_ptr, size_t size) {
Xml_generator xml(reinterpret_cast<char *>(core_local_ptr),
size, "platform_info",
[&] () {
xml.node("kernel", [&] () {
xml.attribute("name", "fiasco"); }); }); });
}

View File

@@ -1 +1 @@
2021-10-13 0e3f2b9302333cb9bcabfb933a0ab142f41d070c
2021-11-29 86ebd8f9b9c153fc0eb7ef7ef7604116f8438e04

View File

@@ -1 +1 @@
2021-10-13 af7ceb5c77e20a66ed9f394526766b31a205d89d
2021-11-29 731498ebe667555a14fdcbf3c1cab33e227fb036

View File

@@ -1 +1 @@
2021-10-13 62af5bc4ad5747f1552f1c03882f756ec7f1d63c
2021-11-29 ae5de8b6bf4f21e2cdc74151aff195c56f74032e

View File

@@ -1 +1 @@
2021-10-13 6bd8c055af6f1031539124d93164d0ae24f956c8
2021-11-29 6f4c635c08bbdd5610c157fd001955de4a2fb81e

View File

@@ -1 +1 @@
2021-10-13 dabb150f6be49ee72d2d5db160e8885ac7faddd0
2021-11-29 af285a52c89b07a1cfd2c03dac4905d8d7a498e3

View File

@@ -34,14 +34,18 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
: get_page_size_log2();
/* find appropriate region for mapping */
void *local_base = 0;
if (platform().region_alloc().alloc_aligned(size, &local_base, alignment).error())
return 0;
return platform().region_alloc().alloc_aligned(size, alignment).convert<addr_t>(
if (!map_local_io(base, (addr_t)local_base, size >> get_page_size_log2())) {
error("map_local_io failed");
return 0;
}
[&] (void *local_base) {
if (!map_local_io(base, (addr_t)local_base, size >> get_page_size_log2())) {
error("map_local_io failed");
platform().region_alloc().free(local_base, base);
return 0UL;
}
return (addr_t)local_base;
},
return (addr_t)local_base;
[&] (Range_allocator::Alloc_error) {
error("allocation of virtual memory for local I/O mapping failed");
return 0UL; });
}

View File

@@ -196,7 +196,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
}
msi_alloc.set(_irq_number, 1);
} else {
if (irq_alloc.alloc_addr(1, _irq_number).error()) {
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable IRQ ", _irq_number, " requested");
throw Service_denied();
}

View File

@@ -467,75 +467,68 @@ Platform::Platform()
core_thread.pager(_sigma0);
_core_pd->bind_thread(core_thread);
/* export x86 platform specific infos */
auto export_page_as_rom_module = [&] (auto rom_name, auto content_fn)
{
void * core_local_ptr = nullptr;
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const align = get_page_size_log2();
size_t const size = pages << get_page_size_log2();
size_t const pages = 1;
size_t const align = get_page_size_log2();
size_t const bytes = pages << get_page_size_log2();
ram_alloc().alloc_aligned(bytes, align).with_result(
if (ram_alloc().alloc_aligned(size, &phys_ptr, align).error())
return;
[&] (void *phys_ptr) {
if (region_alloc().alloc_aligned(size, &core_local_ptr, align).error())
return;
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
region_alloc().alloc_aligned(bytes, align).with_result(
[&] (void *core_local_ptr) {
if (!map_local(phys_addr, core_local_addr, pages))
return;
if (!map_local(phys_addr, (addr_t)core_local_ptr, pages)) {
warning("map_local failed while exporting ",
rom_name, " as ROM module");
ram_alloc().free(phys_ptr, bytes);
region_alloc().free(core_local_ptr, bytes);
return;
}
memset(core_local_ptr, 0, size);
memset(core_local_ptr, 0, bytes);
content_fn((char *)core_local_ptr, bytes);
Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
pages << get_page_size_log2(),
"platform_info", [&] ()
{
xml.node("kernel", [&] () {
xml.attribute("name", "foc");
xml.attribute("acpi", true);
xml.attribute("msi" , true);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, bytes, rom_name));
},
[&] (Range_allocator::Alloc_error) {
warning("failed allocate virtual memory to export ",
rom_name, " as ROM module");
ram_alloc().free(phys_ptr, bytes);
}
);
},
[&] (Range_allocator::Alloc_error) {
warning("failed to export ", rom_name, " as ROM module"); }
);
};
export_page_as_rom_module("platform_info",
[&] (char *core_local_ptr, size_t size) {
Xml_generator xml(core_local_ptr, size, "platform_info", [&] ()
{
xml.node("kernel", [&] () {
xml.attribute("name", "foc");
xml.attribute("acpi", true);
xml.attribute("msi" , true);
});
xml.node("hardware", [&] () {
_setup_platform_info(xml, sigma0_map_kip()); });
xml.node("affinity-space", [&] () {
xml.attribute("width", affinity_space().width());
xml.attribute("height", affinity_space().height()); });
});
xml.node("hardware", [&] () {
_setup_platform_info(xml, sigma0_map_kip()); });
}
);
xml.node("affinity-space", [&] () {
xml.attribute("width", affinity_space().width());
xml.attribute("height", affinity_space().height()); });
});
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"platform_info"));
}
/* core log as ROM module */
{
void * core_local_ptr = nullptr;
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const align = get_page_size_log2();
size_t const size = pages << get_page_size_log2();
if (ram_alloc().alloc_aligned(size, &phys_ptr, align).error())
return;
if (region_alloc().alloc_aligned(size, &core_local_ptr, align).error())
return;
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
if (!map_local(phys_addr, core_local_addr, pages))
return;
memset(core_local_ptr, 0, size);
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"core_log"));
init_core_log(Core_log_range { core_local_addr, size } );
}
export_page_as_rom_module("core_log",
[&] (char *core_local_ptr, size_t size) {
init_core_log(Core_log_range { (addr_t)core_local_ptr, size } ); });
Affinity::Space const cpus = affinity_space();

View File

@@ -198,11 +198,9 @@ unsigned long Cap_id_allocator::alloc()
{
Mutex::Guard lock_guard(_mutex);
void *id = nullptr;
if (_id_alloc.alloc(CAP_ID_OFFSET, &id))
return (unsigned long) id;
throw Out_of_ids();
return _id_alloc.try_alloc(CAP_ID_OFFSET).convert<unsigned long>(
[&] (void *id) { return (unsigned long)id; },
[&] (Range_allocator::Alloc_error) -> unsigned long { throw Out_of_ids(); });
}

View File

@@ -1 +0,0 @@
arm_v8a

View File

@@ -1 +0,0 @@
0x40010000

View File

@@ -1 +0,0 @@
arm_v7a

View File

@@ -1 +0,0 @@
0x00100000

View File

@@ -1,14 +0,0 @@
REP_INC_DIR += src/bootstrap/board/zynq_qemu
SRC_S += bootstrap/spec/arm/crt0.s
SRC_CC += bootstrap/board/zynq_qemu/platform.cc
SRC_CC += bootstrap/spec/arm/cpu.cc
SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc
SRC_CC += bootstrap/spec/arm/gicv2.cc
SRC_CC += bootstrap/spec/arm/arm_v7_cpu.cc
SRC_CC += hw/spec/32bit/memory_map.cc
NR_OF_CPUS = 1
include $(call select_from_repositories,lib/mk/bootstrap-hw.inc)

View File

@@ -1,11 +0,0 @@
#
# \brief Build config for Genodes core process
# \author Johannes Schlatow
# \date 2014-12-15
#
# add C++ sources
SRC_CC += platform_services.cc
# include less specific configuration
include $(call select_from_repositories,lib/mk/spec/cortex_a9/core-hw.inc)

View File

@@ -1,13 +0,0 @@
#
# \brief Build config for Genodes core process
# \author Johannes Schlatow
# \date 2014-12-15
#
# add include paths
REP_INC_DIR += src/core/board/zynq_qemu
NR_OF_CPUS = 1
# include less specific configuration
include $(call select_from_repositories,lib/mk/spec/arm_v7/core-hw-zynq.inc)

View File

@@ -1,14 +0,0 @@
REP_INC_DIR += src/bootstrap/board/imx8q_evk
SRC_CC += bootstrap/board/imx8q_evk/platform.cc
SRC_CC += bootstrap/spec/arm/gicv3.cc
SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc
SRC_CC += lib/base/arm_64/kernel/interface.cc
SRC_CC += spec/64bit/memory_map.cc
SRC_S += bootstrap/spec/arm_64/crt0.s
NR_OF_CPUS = 4
vpath spec/64bit/memory_map.cc $(call select_from_repositories,src/lib/hw)
include $(call select_from_repositories,lib/mk/bootstrap-hw.inc)

View File

@@ -1,19 +0,0 @@
REP_INC_DIR += src/core/board/imx8q_evk
REP_INC_DIR += src/core/spec/arm/virtualization
# add C++ sources
SRC_CC += kernel/vm_thread_on.cc
SRC_CC += spec/arm/gicv3.cc
SRC_CC += spec/arm_v8/virtualization/kernel/vm.cc
SRC_CC += spec/arm/virtualization/platform_services.cc
SRC_CC += spec/arm/virtualization/vm_session_component.cc
SRC_CC += vm_session_common.cc
SRC_CC += vm_session_component.cc
#add assembly sources
SRC_S += spec/arm_v8/virtualization/exception_vector.s
NR_OF_CPUS = 4
# include less specific configuration
include $(call select_from_repositories,lib/mk/spec/arm_v8/core-hw.inc)

View File

@@ -1 +1 @@
2021-10-13 11943f5bc31d6ebd43c67e008cf12cc7e2ca2934
2021-11-29 b165dd50f62e2d73910c5ecf28315c6589368409

View File

@@ -1 +1 @@
2021-10-13 69215f704c6797b15bcacfc11a2709d5b65019e9
2021-11-29 8640feb279f3a881867f809ae912975347c0b1b8

View File

@@ -1 +1 @@
2021-10-13 78f942508805ec6afc8d75550d5b67f38664b5f6
2021-11-29 a01852908262310fc409888a30b4765af289aa31

View File

@@ -1 +1 @@
2021-10-13 85df38295bad953fc194078cc22d31f1acfa4c08
2021-11-29 17cbcd9ba4667f79e4aba4798b413f081c22de40

View File

@@ -1 +0,0 @@
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -1 +0,0 @@
2021-10-13 e23737af156d1967b1d59c690b62f5538856a85c

View File

@@ -1,2 +0,0 @@
base-hw
base

View File

@@ -1 +1 @@
2021-10-13 cf4e82d22cc8f343aa16f5b996e4cf3cc9608d69
2021-11-29 dfa1d469c3fc106655d9a50920daffd1dd89677a

View File

@@ -1 +1 @@
2021-10-13 ec5754c900404b3d4e1594fa5e36630afb58df0e
2021-11-29 fbf5af570d706af8f13ea996fd720c529d594497

View File

@@ -1 +1 @@
2021-10-13 910b8cd795a9326fc0b3fcd9afef8d35abd60c8b
2021-11-29 52defb3af4f16f183ef35f5956079711053ff753

View File

@@ -1 +1 @@
2021-10-13 67dab318aac08eb348e660cfe11c711a9aea1198
2021-11-29 065c3a960169cb275938c657083d377e8a86ad35

View File

@@ -1 +1 @@
2021-10-13 e43c142340fd7f0fcae846c5203c308fe50a979e
2021-11-29 5e42f43a7df531cdf5c8cec4b8b292c930456955

View File

@@ -1 +1 @@
2021-10-13 ae6959ca0ea79c0b8611c7e4a56e5cdb634cfaf1
2021-11-29 d458f8d92ed61428b73297d8b0e45de09e2e3456

View File

@@ -1 +1 @@
2021-10-13 0aed7db811134981a69cf1f4bb5cef3ba7e9a7c2
2021-11-29 860f33fd363c0518df12ea1260b5140da88dbddf

View File

@@ -1 +0,0 @@
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -1 +0,0 @@
2021-10-13 3233ce8f7b5f3246ace4fbdf810b1632cb147a1a

View File

@@ -1,2 +0,0 @@
base-hw
base

View File

@@ -1,34 +0,0 @@
/*
* \brief Board driver for bootstrap
* \author Stefan Kalkowski
* \date 2019-06-12
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _BOOTSTRAP__SPEC__IMX8Q_EVK__BOARD_H_
#define _BOOTSTRAP__SPEC__IMX8Q_EVK__BOARD_H_
#include <hw/spec/arm_64/imx8q_evk_board.h>
#include <hw/spec/arm_64/cpu.h>
#include <hw/spec/arm/gicv3.h>
#include <hw/spec/arm/lpae.h>
namespace Board {
using namespace Hw::Imx8q_evk_board;
struct Cpu : Hw::Arm_64_cpu
{
static void wake_up_all_cpus(void*);
};
using Hw::Pic;
};
#endif /* _BOOTSTRAP__SPEC__IMX8Q_EVK__BOARD_H_ */

View File

@@ -1,231 +0,0 @@
/*
* \brief Platform implementations specific for base-hw and i.MX8Q EVK
* \author Stefan Kalkowski
* \date 2019-06-12
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <platform.h>
/**
* Leave out the first page (being 0x0) from bootstraps RAM allocator,
* some code does not feel happy with addresses being zero
*/
Bootstrap::Platform::Board::Board()
:
early_ram_regions(Memory_region { ::Board::RAM_BASE, ::Board::RAM_SIZE }),
late_ram_regions(Memory_region { }),
core_mmio(Memory_region { ::Board::UART_BASE, ::Board::UART_SIZE },
Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE,
::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE },
Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE,
::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE })
{
::Board::Pic pic {};
static volatile unsigned long iomux_values[][2] {
// IOMUXC
{ 0x30330064, 0x6 },
{ 0x30330140, 0x0 },
{ 0x30330144, 0x0 },
{ 0x30330148, 0x0 },
{ 0x3033014C, 0x0 },
{ 0x30330150, 0x0 },
{ 0x30330154, 0x0 },
{ 0x30330158, 0x0 },
{ 0x30330180, 0x2 },
{ 0x30330184, 0x0 },
{ 0x30330188, 0x0 },
{ 0x3033018C, 0x0 },
{ 0x30330190, 0x0 },
{ 0x30330194, 0x0 },
{ 0x30330198, 0x0 },
{ 0x3033019C, 0x0 },
{ 0x303301A0, 0x0 },
{ 0x303301A4, 0x0 },
{ 0x303301A8, 0x0 },
{ 0x303301AC, 0x0 },
{ 0x303301BC, 0x0 },
{ 0x303301C0, 0x0 },
{ 0x303301C4, 0x0 },
{ 0x303301C8, 0x0 },
{ 0x303301E8, 0x0 },
{ 0x303301EC, 0x0 },
{ 0x303301FC, 0x1 },
{ 0x30330200, 0x1 },
{ 0x3033021C, 0x10 }, /* Enable SION I2c2_scl */
{ 0x30330220, 0x10 }, /* Enable SION I2c2_sda */
{ 0x30330224, 0x10 },
{ 0x30330228, 0x10 },
{ 0x3033022C, 0x12 },
{ 0x30330230, 0x12 },
{ 0x30330244, 0x0 },
{ 0x30330248, 0x0 },
{ 0x3033029C, 0x19 },
{ 0x303302A4, 0x19 },
{ 0x303302A8, 0x19 },
{ 0x303302B0, 0xD6 },
{ 0x303302C0, 0x4F },
{ 0x303302C4, 0x16 },
{ 0x303302CC, 0x59 },
{ 0x30330308, 0x9F },
{ 0x3033030C, 0xDF },
{ 0x30330310, 0xDF },
{ 0x30330314, 0xDF },
{ 0x30330318, 0xDF },
{ 0x3033031C, 0xDF },
{ 0x30330320, 0xDF },
{ 0x30330324, 0xDF },
{ 0x30330328, 0xDF },
{ 0x3033032C, 0xDF },
{ 0x30330334, 0x9f },
{ 0x3033033C, 0x83 },
{ 0x30330340, 0xC3 },
{ 0x30330344, 0xC3 },
{ 0x30330348, 0xC3 },
{ 0x3033034C, 0xC3 },
{ 0x30330350, 0xC3 },
{ 0x30330368, 0x59 },
{ 0x30330370, 0x19 },
{ 0x3033039C, 0x19 },
{ 0x303303A0, 0x19 },
{ 0x303303A4, 0x19 },
{ 0x303303A8, 0xD6 },
{ 0x303303AC, 0xD6 },
{ 0x303303B0, 0xD6 },
{ 0x303303B4, 0xD6 },
{ 0x303303B8, 0xD6 },
{ 0x303303BC, 0xD6 },
{ 0x303303C0, 0xD6 },
{ 0x303303E8, 0xD6 },
{ 0x303303EC, 0xD6 },
{ 0x303303F0, 0xD6 },
{ 0x303303F4, 0xD6 },
{ 0x303303F8, 0xD6 },
{ 0x303303FC, 0xD6 },
{ 0x30330400, 0xD6 },
{ 0x30330404, 0xD6 },
{ 0x30330408, 0xD6 },
{ 0x3033040C, 0xD6 },
{ 0x30330410, 0xD6 },
{ 0x30330414, 0xD6 },
{ 0x30330424, 0xD6 },
{ 0x30330428, 0xD6 },
{ 0x3033042C, 0xD6 },
{ 0x30330430, 0xD6 },
{ 0x30330450, 0xD6 },
{ 0x30330454, 0xD6 },
{ 0x30330460, 0x19 },
{ 0x30330464, 0x49 },
{ 0x30330468, 0x49 },
{ 0x3033046C, 0x16 },
{ 0x30330484, 0x67 }, /* I2c2_scl pullup resistor 40 ohm */
{ 0x30330488, 0x67 }, /* I2c2_sda pullup resistor 40 ohm */
{ 0x3033048C, 0x67 },
{ 0x30330490, 0x67 },
{ 0x30330494, 0x76 },
{ 0x30330498, 0x76 },
{ 0x3033049C, 0x49 },
{ 0x303304A0, 0x49 },
{ 0x303304AC, 0x49 },
{ 0x303304B0, 0x49 },
{ 0x303304C8, 0x1 },
{ 0x303304CC, 0x4 },
{ 0x30330500, 0x1 },
{ 0x30330504, 0x2 },
{ 0x30340038, 0x49409600 },
{ 0x30340040, 0x49409200 },
{ 0x30340034, 0x4 }, /* MIPI mux selector */
/*
{ 0x30340060, 0x180800 },
{ 0x30340064, 0x6400520 },
{ 0x30340068, 0x0A }, */
};
struct Gpio_reg : Genode::Mmio
{
Gpio_reg(Genode::addr_t const mmio_base)
: Genode::Mmio(mmio_base) { }
struct Data : Register<0x0, 32> {};
struct Dir : Register<0x4, 32> {};
struct Int_conf_0 : Register<0xc, 32> {};
struct Int_conf_1 : Register<0x10, 32> {};
struct Int_mask : Register<0x14, 32> {};
struct Int_stat : Register<0x18, 32> {};
};
struct Ccm_reg : Genode::Mmio
{
Ccm_reg(Genode::addr_t const mmio_base)
: Genode::Mmio(mmio_base) { }
struct Target_root_0 : Register<0x8000, 32> {};
};
struct Pll_reg : Genode::Mmio
{
Pll_reg(Genode::addr_t const mmio_base)
: Genode::Mmio(mmio_base) { }
struct Pll_arm_0 : Register<0x28, 32> {};
struct Pll_arm_1 : Register<0x2c, 32> {};
};
unsigned num_values = sizeof(iomux_values) / (2*sizeof(unsigned long));
for (unsigned i = 0; i < num_values; i++)
*((volatile Genode::uint32_t*)iomux_values[i][0]) = (Genode::uint32_t)iomux_values[i][1];
Ccm_reg ccm(0x30380000);
Ccm_reg pll(0x30360000);
/* configure GPIO PIN 13 of GPIO 1 for high voltage */
Gpio_reg regulator(0x30200000);
regulator.write<Gpio_reg::Int_conf_0>(0);
regulator.write<Gpio_reg::Int_conf_1>(0);
regulator.write<Gpio_reg::Int_mask>(0x1000);
regulator.write<Gpio_reg::Int_stat>(0xffffffff);
regulator.write<Gpio_reg::Dir>(0x2328);
regulator.write<Gpio_reg::Data>(0x9f40);
ccm.write<Ccm_reg::Target_root_0>(0x14000000);
pll.write<Pll_reg::Pll_arm_1>(0x4a);
unsigned long v = pll.read<Pll_reg::Pll_arm_0>();
pll.write<Pll_reg::Pll_arm_0>(v & 0xffffffe0);
v = pll.read<Pll_reg::Pll_arm_0>();
pll.write<Pll_reg::Pll_arm_0>(v | (1<<12));
while (!(pll.read<Pll_reg::Pll_arm_0>() & (1<<11))) { ; }
v = pll.read<Pll_reg::Pll_arm_0>();
pll.write<Pll_reg::Pll_arm_0>(v ^ (1<<12));
ccm.write<Ccm_reg::Target_root_0>(0x11000000);
}
void Board::Cpu::wake_up_all_cpus(void * ip)
{
enum Function_id { CPU_ON = 0xC4000003 };
unsigned long result = 0;
for (unsigned i = 1; i < NR_OF_CPUS; i++) {
asm volatile("mov x0, %1 \n"
"mov x1, %2 \n"
"mov x2, %3 \n"
"mov x3, %2 \n"
"smc #0 \n"
"mov %0, x0 \n"
: "=r" (result) : "r" (CPU_ON), "r" (i), "r" (ip)
: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
"x8", "x9", "x10", "x11", "x12", "x13", "x14");
}
}

View File

@@ -1,30 +0,0 @@
/*
* \brief Zynq specific board definitions
* \author Stefan Kalkowski
* \date 2017-02-20
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_
#define _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_
#include <hw/spec/arm/zynq_qemu_board.h>
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Zynq_qemu_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = false;
}
#endif /* _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_ */

View File

@@ -1,53 +0,0 @@
/*
* \brief Platform implementations specific for base-hw and Zynq
* \author Johannes Schlatow
* \author Stefan Kalkowski
* \date 2014-12-15
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* core includes */
#include <platform.h>
using namespace Board;
Bootstrap::Platform::Board::Board()
:
early_ram_regions(Memory_region { RAM_0_BASE + 0x1000,
RAM_0_SIZE - 0x1000 }),
late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }),
core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE,
CORTEX_A9_PRIVATE_MEM_SIZE },
Memory_region { UART_BASE,
UART_SIZE },
Memory_region { PL310_MMIO_BASE,
PL310_MMIO_SIZE })
{ }
bool Cpu::errata(Board::Cpu::Errata) { return false; }
void Cpu::wake_up_all_cpus(void* ip)
{
struct Wakeup_generator : Genode::Mmio
{
struct Core1_boot_addr : Register<0x0, 32> { };
Wakeup_generator(void * const ip) : Mmio(CORE1_ENTRY)
{
write<Core1_boot_addr>((Genode::addr_t)ip);
}
};
Wakeup_generator wgen(ip);
asm volatile("dsb\n"
"sev\n");
}

View File

@@ -30,19 +30,16 @@ extern unsigned _bss_end;
void * Platform::Ram_allocator::alloc_aligned(size_t size, unsigned align)
{
using namespace Genode;
using namespace Hw;
void * ret;
assert(Base::alloc_aligned(round_page(size), &ret,
max(align, get_page_size_log2())).ok());
return ret;
}
return Base::alloc_aligned(Hw::round_page(size),
max(align, get_page_size_log2())).convert<void *>(
bool Platform::Ram_allocator::alloc(size_t size, void **out_addr)
{
*out_addr = alloc_aligned(size, 0);
return true;
[&] (void *ptr) { return ptr; },
[&] (Ram_allocator::Alloc_error e) -> void *
{
error("bootstrap RAM allocation failed, error=", e);
assert(false);
});
}

View File

@@ -53,8 +53,13 @@ class Bootstrap::Platform
};
class Ram_allocator : public Genode::Allocator_avl_base
class Ram_allocator : private Genode::Allocator_avl_base
{
/*
* 'Ram_allocator' is derived from 'Allocator_avl_base' to access
* the protected 'slab_block_size'.
*/
private:
using Base = Genode::Allocator_avl_base;
@@ -73,8 +78,7 @@ class Bootstrap::Platform
{ }
void * alloc_aligned(size_t size, unsigned align);
bool alloc(size_t size, void **out_addr) override;
void * alloc(size_t size) { return Allocator::alloc(size); }
void * alloc(size_t size) { return alloc_aligned(size, 0); }
void add(Memory_region const &);
void remove(Memory_region const &);

View File

@@ -1,43 +0,0 @@
/*
* \brief Board driver for core
* \author Stefan Kalkowski
* \date 2019-06-12
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CORE__SPEC__IMX8Q_EVK__BOARD_H_
#define _CORE__SPEC__IMX8Q_EVK__BOARD_H_
/* base-hw internal includes */
#include <hw/spec/arm_64/imx8q_evk_board.h>
/* base-hw Core includes */
#include <spec/arm/generic_timer.h>
#include <spec/arm/virtualization/gicv3.h>
#include <spec/arm_v8/cpu.h>
/* base-hw includes */
#include <spec/arm_64/cpu/vm_state_virtualization.h>
/* base-hw Core includes */
#include <spec/arm/virtualization/board.h>
namespace Board {
using namespace Hw::Imx8q_evk_board;
enum {
TIMER_IRQ = 14 + 16,
VT_TIMER_IRQ = 11 + 16,
VT_MAINTAINANCE_IRQ = 9 + 16,
VCPU_MAX = 16
};
};
#endif /* _CORE__SPEC__IMX8Q_EVK__BOARD_H_ */

View File

@@ -1,37 +0,0 @@
/*
* \brief Board driver for core on Zynq
* \author Johannes Schlatow
* \author Stefan Kalkowski
* \author Martin Stein
* \date 2014-06-02
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _CORE__SPEC__ZYNQ_QEMU__BOARD_H_
#define _CORE__SPEC__ZYNQ_QEMU__BOARD_H_
/* base-hw internal includes */
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/zynq_qemu_board.h>
/* base-hw Core includes */
#include <spec/arm/cortex_a9_private_timer.h>
#include <spec/cortex_a9/cpu.h>
namespace Board {
using namespace Hw::Zynq_qemu_board;
class Global_interrupt_controller { };
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
L2_cache & l2_cache();
}
#endif /* _CORE__SPEC__ZYNQ_QEMU__BOARD_H_ */

View File

@@ -29,12 +29,15 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Region_map::Local_addr, bool, bool writeable)
{
auto lambda = [&] (Dataspace_component *ds) -> Local_addr {
if (!ds)
return _ep.apply(ds_cap, [&] (Dataspace_component *ds_ptr) -> Local_addr {
if (!ds_ptr)
throw Invalid_dataspace();
Dataspace_component &ds = *ds_ptr;
if (size == 0)
size = ds->size();
size = ds.size();
size_t page_rounded_size = (size + get_page_size() - 1) & get_page_mask();
@@ -48,10 +51,13 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
return nullptr;
}
unsigned const align = get_page_size_log2();
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform().region_alloc().alloc_aligned(page_rounded_size, &virt_addr,
get_page_size_log2()).ok()) {
Allocator::Alloc_result virt =
platform().region_alloc().alloc_aligned(page_rounded_size, align);
if (virt.failed()) {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return nullptr;
@@ -61,16 +67,23 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
/* map the dataspace's physical pages to corresponding virtual addresses */
unsigned num_pages = page_rounded_size >> get_page_size_log2();
Page_flags const flags { (writeable && ds->writable()) ? RW : RO,
Page_flags const flags { (writeable && ds.writable()) ? RW : RO,
NO_EXEC, KERN, GLOBAL,
ds->io_mem() ? DEVICE : RAM,
ds->cacheability() };
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages, flags))
return nullptr;
ds.io_mem() ? DEVICE : RAM,
ds.cacheability() };
return virt_addr;
};
return _ep.apply(ds_cap, lambda);
return virt.convert<Local_addr>(
[&] (void *virt_addr) -> void * {
if (map_local(ds.phys_addr(), (addr_t)virt_addr, num_pages, flags))
return virt_addr;
platform().region_alloc().free(virt_addr, page_rounded_size);
return nullptr; },
[&] (Allocator::Alloc_error) {
return nullptr; });
});
}

View File

@@ -57,8 +57,8 @@ class Genode::Cpu_thread_allocator : public Allocator
** Allocator interface **
*************************/
bool alloc(size_t size, void **out_addr) override {
return _alloc.alloc(size, out_addr); }
Alloc_result try_alloc(size_t size) override {
return _alloc.alloc(size); }
void free(void *addr, size_t size) override {
_alloc.free(addr, size); }

View File

@@ -78,7 +78,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
}
/* allocate interrupt */
if (_irq_alloc.alloc_addr(1, _irq_number).error()) {
if (_irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable interrupt ", _irq_number, " requested");
throw Service_denied();
}

View File

@@ -35,10 +35,41 @@ using namespace Kernel;
void Thread::_ipc_alloc_recv_caps(unsigned cap_count)
{
Genode::Allocator &slab = pd().platform_pd().capability_slab();
using Allocator = Genode::Allocator;
Allocator &slab = pd().platform_pd().capability_slab();
for (unsigned i = 0; i < cap_count; i++) {
if (_obj_id_ref_ptr[i] == nullptr)
_obj_id_ref_ptr[i] = slab.alloc(sizeof(Object_identity_reference));
if (_obj_id_ref_ptr[i] != nullptr)
continue;
slab.try_alloc(sizeof(Object_identity_reference)).with_result(
[&] (void *ptr) {
_obj_id_ref_ptr[i] = ptr; },
[&] (Allocator::Alloc_error e) {
switch (e) {
case Allocator::Alloc_error::DENIED:
/*
* Slab is exhausted, reflect condition to the client.
*/
throw Genode::Out_of_ram();
case Allocator::Alloc_error::OUT_OF_CAPS:
case Allocator::Alloc_error::OUT_OF_RAM:
/*
* These conditions cannot happen because the slab
* does not try to grow automatically. It is
* explicitely expanded by the client as response to
* the 'Out_of_ram' condition above.
*/
Genode::raw("unexpected recv_caps allocation failure");
}
}
);
}
_ipc_rcv_caps = cap_count;
}

View File

@@ -112,28 +112,46 @@ void Platform::_init_platform_info()
{
unsigned const pages = 1;
size_t const rom_size = pages << get_page_size_log2();
void *phys_ptr = nullptr;
void *virt_ptr = nullptr;
const char *rom_name = "platform_info";
if (!ram_alloc().alloc(get_page_size(), &phys_ptr)) {
error("could not setup platform_info ROM - ram allocation error");
return;
}
struct Guard
{
Range_allocator &phys_alloc;
Range_allocator &virt_alloc;
if (!region_alloc().alloc(rom_size, &virt_ptr)) {
error("could not setup platform_info ROM - region allocation error");
ram_alloc().free(phys_ptr);
return;
}
struct {
void *phys_ptr = nullptr;
void *virt_ptr = nullptr;
};
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const virt_addr = reinterpret_cast<addr_t>(virt_ptr);
Guard(Range_allocator &phys_alloc, Range_allocator &virt_alloc)
: phys_alloc(phys_alloc), virt_alloc(virt_alloc) { }
~Guard()
{
if (phys_ptr) phys_alloc.free(phys_ptr);
if (virt_ptr) virt_alloc.free(phys_ptr);
}
} guard { ram_alloc(), region_alloc() };
ram_alloc().try_alloc(get_page_size()).with_result(
[&] (void *ptr) { guard.phys_ptr = ptr; },
[&] (Allocator::Alloc_error) {
error("could not setup platform_info ROM - RAM allocation error"); });
region_alloc().try_alloc(rom_size).with_result(
[&] (void *ptr) { guard.virt_ptr = ptr; },
[&] (Allocator::Alloc_error) {
error("could not setup platform_info ROM - region allocation error"); });
if (!guard.phys_ptr || !guard.virt_ptr)
return;
addr_t const phys_addr = reinterpret_cast<addr_t>(guard.phys_ptr);
addr_t const virt_addr = reinterpret_cast<addr_t>(guard.virt_ptr);
if (!map_local(phys_addr, virt_addr, pages, Hw::PAGE_FLAGS_KERN_DATA)) {
error("could not setup platform_info ROM - map error");
region_alloc().free(virt_ptr);
ram_alloc().free(phys_ptr);
return;
}
@@ -156,10 +174,11 @@ void Platform::_init_platform_info()
return;
}
region_alloc().free(virt_ptr);
_rom_fs.insert(
new (core_mem_alloc()) Rom_module(phys_addr, rom_size, rom_name));
/* keep phys allocation but let guard revert virt allocation */
guard.phys_ptr = nullptr;
}
@@ -203,25 +222,32 @@ Platform::Platform()
/* core log as ROM module */
{
void * core_local_ptr = nullptr;
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const log_size = pages << get_page_size_log2();
unsigned const align = get_page_size_log2();
ram_alloc().alloc_aligned(log_size, &phys_ptr, get_page_size_log2());
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
ram_alloc().alloc_aligned(log_size, align).with_result(
/* let one page free after the log buffer */
region_alloc().alloc_aligned(log_size, &core_local_ptr, get_page_size_log2());
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
[&] (void *phys) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys);
map_local(phys_addr, core_local_addr, pages);
memset(core_local_ptr, 0, log_size);
region_alloc().alloc_aligned(log_size, align). with_result(
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
"core_log"));
[&] (void *ptr) {
init_core_log(Core_log_range { core_local_addr, log_size } );
map_local(phys_addr, (addr_t)ptr, pages);
memset(ptr, 0, log_size);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, log_size, "core_log"));
init_core_log(Core_log_range { (addr_t)ptr, log_size } );
},
[&] (Range_allocator::Alloc_error) { /* ignored */ }
);
},
[&] (Range_allocator::Alloc_error) { }
);
}
class Idle_thread_trace_source : public Trace::Source::Info_accessor,

View File

@@ -37,11 +37,16 @@ Core_mem_allocator &Hw::Address_space::_cma()
void *Hw::Address_space::_table_alloc()
{
void * ret = nullptr;
if (!_cma().alloc_aligned(sizeof(Page_table), (void**)&ret,
Page_table::ALIGNM_LOG2).ok())
throw Insufficient_ram_quota();
return ret;
unsigned const align = Page_table::ALIGNM_LOG2;
return _cma().alloc_aligned(sizeof(Page_table), align).convert<void *>(
[&] (void *ptr) {
return ptr; },
[&] (Range_allocator::Alloc_result) -> void * {
/* XXX distinguish error conditions */
throw Insufficient_ram_quota(); });
}
@@ -134,10 +139,15 @@ Cap_space::Cap_space() : _slab(nullptr, &_initial_sb) { }
void Cap_space::upgrade_slab(Allocator &alloc)
{
void * block = nullptr;
if (!alloc.alloc(SLAB_SIZE, &block))
throw Out_of_ram();
_slab.insert_sb(block);
alloc.try_alloc(SLAB_SIZE).with_result(
[&] (void *ptr) {
_slab.insert_sb(ptr); },
[&] (Allocator::Alloc_error) {
/* XXX distinguish error conditions */
throw Out_of_ram();
});
}

View File

@@ -71,13 +71,18 @@ Platform_thread::Platform_thread(Label const &label, Native_utcb &utcb)
_kobj(_kobj.CALLED_FROM_CORE, _label.string())
{
/* create UTCB for a core thread */
void *utcb_phys;
if (!platform().ram_alloc().alloc(sizeof(Native_utcb), &utcb_phys)) {
error("failed to allocate UTCB");
throw Out_of_ram();
}
map_local((addr_t)utcb_phys, (addr_t)_utcb_core_addr,
sizeof(Native_utcb) / get_page_size());
platform().ram_alloc().try_alloc(sizeof(Native_utcb)).with_result(
[&] (void *utcb_phys) {
map_local((addr_t)utcb_phys, (addr_t)_utcb_core_addr,
sizeof(Native_utcb) / get_page_size());
},
[&] (Range_allocator::Alloc_error) {
error("failed to allocate UTCB");
/* XXX distinguish error conditions */
throw Out_of_ram();
}
);
}

View File

@@ -33,30 +33,40 @@ void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds)
{
size_t page_rounded_size = (ds.size() + get_page_size() - 1) & get_page_mask();
struct Guard
{
Range_allocator &virt_alloc;
struct { void *virt_ptr = nullptr; };
Guard(Range_allocator &virt_alloc) : virt_alloc(virt_alloc) { }
~Guard() { if (virt_ptr) virt_alloc.free(virt_ptr); }
} guard(platform().region_alloc());
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform().region_alloc().alloc(page_rounded_size, &virt_addr)) {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
platform().region_alloc().try_alloc(page_rounded_size).with_result(
[&] (void *ptr) { guard.virt_ptr = ptr; },
[&] (Range_allocator::Alloc_error e) {
error("could not allocate virtual address range in core of size ",
page_rounded_size, ", error=", e); });
if (!guard.virt_ptr)
return;
}
/* map the dataspace's physical pages to corresponding virtual addresses */
size_t num_pages = page_rounded_size >> get_page_size_log2();
if (!map_local(ds.phys_addr(), (addr_t)virt_addr, num_pages)) {
if (!map_local(ds.phys_addr(), (addr_t)guard.virt_ptr, num_pages)) {
error("core-local memory mapping failed");
return;
}
/* dependent on the architecture, cache maintainance might be necessary */
Cpu::clear_memory_region((addr_t)virt_addr, page_rounded_size,
Cpu::clear_memory_region((addr_t)guard.virt_ptr, page_rounded_size,
ds.cacheability() != CACHED);
/* unmap dataspace from core */
if (!unmap_local((addr_t)virt_addr, num_pages))
error("could not unmap core-local address range at ", virt_addr);
/* free core's virtual address space */
platform().region_alloc().free(virt_addr, page_rounded_size);
if (!unmap_local((addr_t)guard.virt_ptr, num_pages))
error("could not unmap core-local address range at ", guard.virt_ptr);
}

View File

@@ -86,22 +86,28 @@ class Genode::Rpc_cap_factory
{
Mutex::Guard guard(_mutex);
/* allocate kernel object */
Kobject * obj;
if (!_slab.alloc(sizeof(Kobject), (void**)&obj))
throw Allocator::Out_of_memory();
construct_at<Kobject>(obj, ep);
return _slab.try_alloc(sizeof(Kobject)).convert<Native_capability>(
if (!obj->cap.valid()) {
raw("Invalid entrypoint ", (addr_t)Capability_space::capid(ep),
" for allocating a capability!");
destroy(&_slab, obj);
return Native_capability();
}
[&] (void *ptr) {
/* store it in the list and return result */
_list.insert(obj);
return obj->cap;
/* create kernel object */
Kobject &obj = *construct_at<Kobject>(ptr, ep);
if (!obj.cap.valid()) {
raw("Invalid entrypoint ", (addr_t)Capability_space::capid(ep),
" for allocating a capability!");
destroy(&_slab, &obj);
return Native_capability();
}
/* store it in the list and return result */
_list.insert(&obj);
return obj.cap;
},
[&] (Allocator::Alloc_error) -> Native_capability {
/* XXX distinguish error conditions */
throw Allocator::Out_of_memory();
});
}
void free(Native_capability cap)

View File

@@ -43,16 +43,20 @@ void Genode::platform_add_local_services(Rpc_entrypoint &ep,
Hw::Mm::hypervisor_exception_vector().size / get_page_size(),
Hw::PAGE_FLAGS_KERN_TEXT);
void * stack = nullptr;
assert(platform().ram_alloc().alloc_aligned(Hw::Mm::hypervisor_stack().size,
(void**)&stack,
get_page_size_log2()).ok());
map_local((addr_t)stack,
Hw::Mm::hypervisor_stack().base,
Hw::Mm::hypervisor_stack().size / get_page_size(),
Hw::PAGE_FLAGS_KERN_DATA);
platform().ram_alloc().alloc_aligned(Hw::Mm::hypervisor_stack().size,
get_page_size_log2()).with_result(
[&] (void *stack) {
map_local((addr_t)stack,
Hw::Mm::hypervisor_stack().base,
Hw::Mm::hypervisor_stack().size / get_page_size(),
Hw::PAGE_FLAGS_KERN_DATA);
static Vm_root vm_root(ep, sh, core_env().ram_allocator(),
core_env().local_rm(), trace_sources);
static Core_service<Vm_session_component> vm_service(services, vm_root);
static Vm_root vm_root(ep, sh, core_env().ram_allocator(),
core_env().local_rm(), trace_sources);
static Core_service<Vm_session_component> vm_service(services, vm_root);
},
[&] (Range_allocator::Alloc_error) {
warning("failed to allocate hypervisor stack for VM service");
}
);
}

View File

@@ -73,14 +73,17 @@ void Vm_session_component::_detach_vm_memory(addr_t vm_addr, size_t size)
void * Vm_session_component::_alloc_table()
{
void * table;
/* get some aligned space for the translation table */
if (!cma().alloc_aligned(sizeof(Board::Vm_page_table), (void**)&table,
Board::Vm_page_table::ALIGNM_LOG2).ok()) {
error("failed to allocate kernel object");
throw Insufficient_ram_quota();
}
return table;
return cma().alloc_aligned(sizeof(Board::Vm_page_table),
Board::Vm_page_table::ALIGNM_LOG2).convert<void *>(
[&] (void *table_ptr) {
return table_ptr; },
[&] (Range_allocator::Alloc_error) -> void * {
/* XXX handle individual error conditions */
error("failed to allocate kernel object");
throw Insufficient_ram_quota(); }
);
}

View File

@@ -21,8 +21,14 @@ using State = Genode::Pd_session::Managing_system_state;
State Pd_session_component::managing_system(State const & s)
{
static constexpr addr_t SMCCC_NOT_SUPPORTED = 0xffffffffUL;
State ret;
ret.r[0] = Hw::Psci_smc_functor::call(s.r[0], s.r[1], s.r[2], s.r[3]);
ret.r[0] = (_managing_system == Managing_system::DENIED)
? SMCCC_NOT_SUPPORTED
: Hw::Psci_smc_functor::call(s.r[0], s.r[1], s.r[2], s.r[3]);
return ret;
}

View File

@@ -1,35 +0,0 @@
/*
* \brief Zynq specific board definitions
* \author Stefan Kalkowski
* \date 2019-05-16
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_
#define _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_
#include <drivers/defs/zynq_qemu.h>
#include <drivers/uart/xilinx.h>
#include <hw/spec/arm/cortex_a9.h>
#include <hw/spec/arm/pl310.h>
#include <hw/spec/arm/boot_info.h>
namespace Hw::Zynq_qemu_board {
using namespace Zynq_qemu;
using L2_cache = Hw::Pl310;
using Cpu_mmio = Hw::Cortex_a9_mmio<CORTEX_A9_PRIVATE_MEM_BASE>;
using Serial = Genode::Xilinx_uart;
enum {
UART_BASE = UART_0_MMIO_BASE,
};
}
#endif /* _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_ */

View File

@@ -1,45 +0,0 @@
/*
* \brief Board definitions for i.MX8 Quad EVK
* \author Stefan Kalkowski
* \date 2019-06-12
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__INCLUDE__HW__SPEC__ARM_64__IMX8Q_EVK__BOARD_H_
#define _SRC__INCLUDE__HW__SPEC__ARM_64__IMX8Q_EVK__BOARD_H_
#include <drivers/uart/imx.h>
#include <hw/spec/arm/boot_info.h>
namespace Hw::Imx8q_evk_board {
using Serial = Genode::Imx_uart;
enum {
RAM_BASE = 0x40000000,
RAM_SIZE = 0xc0000000,
UART_BASE = 0x30860000,
UART_SIZE = 0x1000,
UART_CLOCK = 250000000,
};
namespace Cpu_mmio {
enum {
IRQ_CONTROLLER_DISTR_BASE = 0x38800000,
IRQ_CONTROLLER_DISTR_SIZE = 0x10000,
IRQ_CONTROLLER_VT_CPU_BASE = 0x31020000,
IRQ_CONTROLLER_VT_CPU_SIZE = 0x2000,
IRQ_CONTROLLER_REDIST_BASE = 0x38880000,
IRQ_CONTROLLER_REDIST_SIZE = 0xc0000,
};
};
};
#endif /* _SRC__INCLUDE__HW__SPEC__ARM_64__IMX8Q_EVK__BOARD_H_ */

View File

@@ -2,6 +2,10 @@ SRC_CC += lx_hybrid.cc new_delete.cc capability_space.cc
SRC_CC += signal_transmitter.cc signal.cc
SRC_C += libgcc.c
# new_delete.cc uses libsupc++ which means we need to access
# its include directory.
STDINC := yes
vpath new_delete.cc $(BASE_DIR)/src/lib/cxx
vpath lx_hybrid.cc $(REP_DIR)/src/lib/lx_hybrid
vpath libgcc.c $(REP_DIR)/src/lib/lx_hybrid

View File

@@ -1 +1 @@
2021-10-13 52a921d570e363144984ebf4e4f9a9386fa5864a
2021-11-29 dcaadcb8b692ac78060694d86ea4340fd18d87b3

View File

@@ -1 +1 @@
2021-10-13 0cfcfb0e903ca534510e38c6bbbcc0815e76af59
2021-11-29 a6c8044ea55fc0e02e5a37d968751e530a640b9a

View File

@@ -64,22 +64,21 @@ class Genode::Platform : public Platform_generic
struct Dummy_allocator : Range_allocator
{
void free(void *, size_t) override { ASSERT_NEVER_CALLED; }
bool need_size_for_free() const override { ASSERT_NEVER_CALLED; }
size_t consumed() const override { ASSERT_NEVER_CALLED; }
size_t overhead(size_t) const override { ASSERT_NEVER_CALLED; }
int add_range (addr_t, size_t ) override { ASSERT_NEVER_CALLED; }
int remove_range(addr_t, size_t ) override { ASSERT_NEVER_CALLED; }
void free(void *) override { ASSERT_NEVER_CALLED; }
size_t avail() const override { ASSERT_NEVER_CALLED; }
bool valid_addr(addr_t ) const override { ASSERT_NEVER_CALLED; }
bool alloc(size_t, void **) override { ASSERT_NEVER_CALLED; }
void free(void *, size_t) override { ASSERT_NEVER_CALLED; }
bool need_size_for_free() const override { ASSERT_NEVER_CALLED; }
size_t consumed() const override { ASSERT_NEVER_CALLED; }
size_t overhead(size_t) const override { ASSERT_NEVER_CALLED; }
Range_result add_range (addr_t, size_t ) override { ASSERT_NEVER_CALLED; }
Range_result remove_range(addr_t, size_t ) override { ASSERT_NEVER_CALLED; }
void free(void *) override { ASSERT_NEVER_CALLED; }
size_t avail() const override { ASSERT_NEVER_CALLED; }
bool valid_addr(addr_t ) const override { ASSERT_NEVER_CALLED; }
Alloc_result try_alloc(size_t) override { ASSERT_NEVER_CALLED; }
Alloc_result alloc_addr(size_t, addr_t) override { ASSERT_NEVER_CALLED; }
Alloc_return alloc_aligned(size_t, void **, unsigned, Range) override
Alloc_result alloc_aligned(size_t, unsigned, Range) override
{ ASSERT_NEVER_CALLED; }
Alloc_return alloc_addr(size_t, addr_t) override
{ ASSERT_NEVER_CALLED; }
} _dummy_alloc { };
@@ -88,25 +87,31 @@ class Genode::Platform : public Platform_generic
*/
struct Pseudo_ram_allocator : Range_allocator
{
bool alloc(size_t, void **out_addr) override
Alloc_result try_alloc(size_t) override
{
*out_addr = 0;
return true;
return nullptr;
}
Alloc_return alloc_aligned(size_t, void **out, unsigned, Range) override
Alloc_result alloc_aligned(size_t, unsigned, Range) override
{
*out = 0;
return Alloc_return::OK;
return nullptr;
}
Alloc_return alloc_addr(size_t, addr_t) override
Alloc_result alloc_addr(size_t, addr_t) override
{
return Alloc_return::OK;
return nullptr;
}
Range_result add_range(addr_t, size_t) override
{
return Range_ok();
}
Range_result remove_range(addr_t, size_t) override
{
return Range_ok();
}
int add_range(addr_t, size_t) override { return 0; }
int remove_range(addr_t, size_t) override { return 0; }
void free(void *) override { }
void free(void *, size_t) override { }
size_t avail() const override { return ram_quota_from_env(); }

View File

@@ -79,7 +79,7 @@ class Stack_area_region_map : public Genode::Region_map
struct Stack_area_ram_allocator : Genode::Ram_allocator
{
Genode::Ram_dataspace_capability alloc(Genode::size_t, Genode::Cache) override {
Alloc_result try_alloc(Genode::size_t, Genode::Cache) override {
return Genode::Ram_dataspace_capability(); }
void free(Genode::Ram_dataspace_capability) override { }

View File

@@ -410,11 +410,7 @@ namespace {
{
typedef Genode::size_t size_t;
bool alloc(size_t size, void **out_addr) override
{
*out_addr = malloc(size);
return true;
}
Alloc_result try_alloc(size_t size) override { return malloc(size); }
void free(void *addr, size_t) override { ::free(addr); }

View File

@@ -51,9 +51,9 @@ Main::Main(Env &env) : heap(env.ram(), env.rm())
/* induce initial heap expansion to remove RM noise */
if (1) {
void *addr;
heap.alloc(0x100000, &addr);
heap.free(addr, 0);
heap.try_alloc(0x100000).with_result(
[&] (void *ptr) { heap.free(ptr, 0); },
[&] (Allocator::Alloc_error) { });
}
addr_t beg((addr_t)&blob_beg);

View File

@@ -316,6 +316,7 @@ namespace Nova {
R8_R15 = 1U << 22, /* R8 .. R15 */
SYSCALL_SWAPGS = 1U << 23, /* SYSCALL and SWAPGS MSRs */
TPR = 1U << 24, /* TPR and TPR threshold */
TSC_AUX = 1U << 25, /* IA32_TSC_AUX used by rdtscp */
FPU = 1U << 31, /* FPU state */
IRQ = EFL | STA | INJ | TSC,
@@ -590,7 +591,7 @@ namespace Nova {
mword_t reserved1;
#endif
} gdtr, idtr;
unsigned long long tsc_val, tsc_off;
unsigned long long tsc_val, tsc_off, tsc_aux;
} __attribute__((packed));
mword_t mr[(4096 - 4 * sizeof(mword_t)) / sizeof(mword_t)];
};

View File

@@ -1 +1 @@
2ff8c9abf7389a2bdb7e0aa8aa4d2fec688c51af
b06f9132099cd798147f6951f27a5d3a17f28fa4

View File

@@ -4,7 +4,7 @@ DOWNLOADS := nova.git
# r10 branch
URL(nova) := https://github.com/alex-ab/NOVA.git
REV(nova) := 5c64bba1ee59902eb2a4ce4abe4b867eaf085dac
REV(nova) := 825c1f94c82ae03f554c02b91430eca6983329da
DIR(nova) := src/kernel/nova
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))

View File

@@ -1 +1 @@
2021-05-09 7e538243f9886048199e49cec7643674585b164c
2021-11-29 768f505c4774de780119b4f18b648ff08ae1a596

View File

@@ -1 +1 @@
2021-10-14 a5d63836f2a18ac99fc43addb018f014a03b0ebc
2021-11-29 80e3a0a005973ab010f5c63e0373073f7e2f4fba

View File

@@ -39,8 +39,12 @@ static inline void * alloc_region(Dataspace_component &ds, const size_t size)
void *virt_addr = 0;
size_t align_log2 = log2(ds.size());
for (; align_log2 >= get_page_size_log2(); align_log2--) {
if (platform().region_alloc().alloc_aligned(size,
&virt_addr, align_log2).ok())
platform().region_alloc().alloc_aligned(size, align_log2).with_result(
[&] (void *ptr) { virt_addr = ptr; },
[&] (Allocator::Alloc_error) { });
if (virt_addr)
break;
}

View File

@@ -69,33 +69,36 @@ static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
Genode::Signal_context_capability sig_cap)
{
void * virt = 0;
if (platform().region_alloc().alloc_aligned(4096, &virt, 12).error())
return false;
return platform().region_alloc().alloc_aligned(4096, 12).convert<bool>(
Genode::addr_t virt_addr = reinterpret_cast<Genode::addr_t>(virt);
if (!virt_addr)
return false;
[&] (void *virt_ptr) {
using Nova::Rights;
using Nova::Utcb;
addr_t const virt_addr = reinterpret_cast<addr_t>(virt_ptr);
Nova::Mem_crd phys_crd(phys_mem >> 12, 0, Rights(true, false, false));
Nova::Mem_crd virt_crd(virt_addr >> 12, 0, Rights(true, false, false));
Utcb &utcb = *reinterpret_cast<Utcb *>(Thread::myself()->utcb());
using Nova::Rights;
using Nova::Utcb;
if (map_local_phys_to_virt(utcb, phys_crd, virt_crd, platform_specific().core_pd_sel())) {
platform().region_alloc().free(virt, 4096);
return false;
}
Nova::Mem_crd phys_crd(phys_mem >> 12, 0, Rights(true, false, false));
Nova::Mem_crd virt_crd(virt_addr >> 12, 0, Rights(true, false, false));
/* try to assign MSI to device */
bool res = associate(irq_sel, msi_addr, msi_data, sig_cap, virt_addr);
Utcb &utcb = *reinterpret_cast<Utcb *>(Thread::myself()->utcb());
unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true)));
platform().region_alloc().free(virt, 4096);
if (map_local_phys_to_virt(utcb, phys_crd, virt_crd, platform_specific().core_pd_sel())) {
platform().region_alloc().free(virt_ptr, 4096);
return false;
}
return res;
/* try to assign MSI to device */
bool res = associate(irq_sel, msi_addr, msi_data, sig_cap, virt_addr);
unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true)));
platform().region_alloc().free(virt_ptr, 4096);
return res;
},
[&] (Range_allocator::Alloc_error) {
return false;
});
}
@@ -217,7 +220,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
throw Service_denied();
}
if (irq_alloc.alloc_addr(1, irq_number).error()) {
if (irq_alloc.alloc_addr(1, irq_number).failed()) {
error("unavailable IRQ ", irq_number, " requested");
throw Service_denied();
}

View File

@@ -80,18 +80,21 @@ addr_t Platform::_map_pages(addr_t const phys_addr, addr_t const pages,
addr_t const size = pages << get_page_size_log2();
/* try to reserve contiguous virtual area */
void *core_local_ptr = nullptr;
if (region_alloc().alloc_aligned(size + (guard_page ? get_page_size() : 0),
&core_local_ptr, get_page_size_log2()).error())
return 0;
return region_alloc().alloc_aligned(size + (guard_page ? get_page_size() : 0),
get_page_size_log2()).convert<addr_t>(
[&] (void *core_local_ptr) {
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
int res = map_local(_core_pd_sel, *__main_thread_utcb, phys_addr,
core_local_addr, pages,
Nova::Rights(true, true, false), true);
int res = map_local(_core_pd_sel, *__main_thread_utcb, phys_addr,
core_local_addr, pages,
Nova::Rights(true, true, false), true);
return res ? 0 : core_local_addr;
return res ? 0 : core_local_addr;
},
[&] (Allocator::Alloc_error) {
return 0UL; });
}
@@ -661,126 +664,113 @@ Platform::Platform()
_init_rom_modules();
auto export_pages_as_rom_module = [&] (auto rom_name, size_t pages, auto content_fn)
{
/* export x86 platform specific infos */
size_t const bytes = pages << get_page_size_log2();
ram_alloc().alloc_aligned(bytes, get_page_size_log2()).with_result(
unsigned const pages = 1;
void * phys_ptr = nullptr;
if (ram_alloc().alloc_aligned(get_page_size(), &phys_ptr,
get_page_size_log2()).ok()) {
[&] (void *phys_ptr) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const core_local_addr = _map_pages(phys_addr, pages);
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
char * const core_local_ptr = (char *)_map_pages(phys_addr, pages);
if (!core_local_addr) {
ram_alloc().free(phys_ptr);
} else {
if (!core_local_ptr) {
warning("failed to export ", rom_name, " as ROM module");
ram_alloc().free(phys_ptr, bytes);
return;
}
Genode::Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
pages << get_page_size_log2(),
"platform_info", [&] ()
{
xml.node("kernel", [&] () {
xml.attribute("name", "nova");
xml.attribute("acpi", true);
xml.attribute("msi" , true);
memset(core_local_ptr, 0, bytes);
content_fn(core_local_ptr, bytes);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, bytes, rom_name));
/* leave the ROM backing store mapped within core */
},
[&] (Range_allocator::Alloc_error) {
warning("failed to allocate physical memory for exporting ",
rom_name, " as ROM module"); });
};
export_pages_as_rom_module("platform_info", 1,
[&] (char * const ptr, size_t const size) {
Xml_generator xml(ptr, size, "platform_info", [&] ()
{
xml.node("kernel", [&] () {
xml.attribute("name", "nova");
xml.attribute("acpi", true);
xml.attribute("msi" , true);
});
if (efi_sys_tab_phy) {
xml.node("efi-system-table", [&] () {
xml.attribute("address", String<32>(Hex(efi_sys_tab_phy)));
});
if (efi_sys_tab_phy) {
xml.node("efi-system-table", [&] () {
xml.attribute("address", String<32>(Hex(efi_sys_tab_phy)));
});
}
xml.node("acpi", [&] () {
}
xml.node("acpi", [&] () {
xml.attribute("revision", 2); /* XXX */
xml.attribute("revision", 2); /* XXX */
if (rsdt)
xml.attribute("rsdt", String<32>(Hex(rsdt)));
if (rsdt)
xml.attribute("rsdt", String<32>(Hex(rsdt)));
if (xsdt)
xml.attribute("xsdt", String<32>(Hex(xsdt)));
if (xsdt)
xml.attribute("xsdt", String<32>(Hex(xsdt)));
});
xml.node("affinity-space", [&] () {
xml.attribute("width", _cpus.width());
xml.attribute("height", _cpus.height());
});
xml.node("boot", [&] () {
if (!boot_fb)
return;
if (!efi_boot && (Resolution::Type::get(boot_fb->size) != Resolution::Type::VGA_TEXT))
return;
xml.node("framebuffer", [&] () {
xml.attribute("phys", String<32>(Hex(boot_fb->addr)));
xml.attribute("width", Resolution::Width::get(boot_fb->size));
xml.attribute("height", Resolution::Height::get(boot_fb->size));
xml.attribute("bpp", Resolution::Bpp::get(boot_fb->size));
xml.attribute("type", Resolution::Type::get(boot_fb->size));
xml.attribute("pitch", boot_fb->aux);
});
xml.node("affinity-space", [&] () {
xml.attribute("width", _cpus.width());
xml.attribute("height", _cpus.height());
});
xml.node("hardware", [&] () {
xml.node("features", [&] () {
xml.attribute("svm", hip.has_feature_svm());
xml.attribute("vmx", hip.has_feature_vmx());
});
xml.node("boot", [&] () {
if (!boot_fb)
return;
if (!efi_boot && (Resolution::Type::get(boot_fb->size) != Resolution::Type::VGA_TEXT))
return;
xml.node("framebuffer", [&] () {
xml.attribute("phys", String<32>(Hex(boot_fb->addr)));
xml.attribute("width", Resolution::Width::get(boot_fb->size));
xml.attribute("height", Resolution::Height::get(boot_fb->size));
xml.attribute("bpp", Resolution::Bpp::get(boot_fb->size));
xml.attribute("type", Resolution::Type::get(boot_fb->size));
xml.attribute("pitch", boot_fb->aux);
});
xml.node("tsc", [&] () {
xml.attribute("invariant", cpuid_invariant_tsc());
xml.attribute("freq_khz" , hip.tsc_freq);
});
xml.node("hardware", [&] () {
xml.node("features", [&] () {
xml.attribute("svm", hip.has_feature_svm());
xml.attribute("vmx", hip.has_feature_vmx());
});
xml.node("tsc", [&] () {
xml.attribute("invariant", cpuid_invariant_tsc());
xml.attribute("freq_khz" , hip.tsc_freq);
});
xml.node("cpus", [&] () {
hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i) {
xml.node("cpu", [&] () {
xml.attribute("id", i);
xml.attribute("package", cpu.package);
xml.attribute("core", cpu.core);
xml.attribute("thread", cpu.thread);
xml.attribute("family", String<5>(Hex(cpu.family)));
xml.attribute("model", String<5>(Hex(cpu.model)));
xml.attribute("stepping", String<5>(Hex(cpu.stepping)));
xml.attribute("platform", String<5>(Hex(cpu.platform)));
xml.attribute("patch", String<12>(Hex(cpu.patch)));
});
xml.node("cpus", [&] () {
hip.for_each_enabled_cpu([&](Hip::Cpu_desc const &cpu, unsigned i) {
xml.node("cpu", [&] () {
xml.attribute("id", i);
xml.attribute("package", cpu.package);
xml.attribute("core", cpu.core);
xml.attribute("thread", cpu.thread);
xml.attribute("family", String<5>(Hex(cpu.family)));
xml.attribute("model", String<5>(Hex(cpu.model)));
xml.attribute("stepping", String<5>(Hex(cpu.stepping)));
xml.attribute("platform", String<5>(Hex(cpu.platform)));
xml.attribute("patch", String<12>(Hex(cpu.patch)));
});
});
});
});
unmap_local(*__main_thread_utcb, core_local_addr, pages);
region_alloc().free(reinterpret_cast<void *>(core_local_addr),
pages * get_page_size());
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, pages * get_page_size(),
"platform_info"));
}
});
}
}
);
/* core log as ROM module */
{
void * phys_ptr = nullptr;
unsigned const pages = 4;
size_t const log_size = pages << get_page_size_log2();
if (ram_alloc().alloc_aligned(log_size, &phys_ptr,
get_page_size_log2()).ok()) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const virt = _map_pages(phys_addr, pages, true);
if (virt) {
memset(reinterpret_cast<void *>(virt), 0, log_size);
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
"core_log"));
init_core_log( Core_log_range { virt, log_size } );
} else
ram_alloc().free(phys_ptr);
}
}
export_pages_as_rom_module("core_log", 4,
[&] (char * const ptr, size_t const size) {
init_core_log( Core_log_range { (addr_t)ptr, size } );
});
/* export hypervisor log memory */
if (hyp_log && hyp_log_size)
@@ -831,8 +821,12 @@ Platform::Platform()
for (unsigned i = 0; i < 32; i++)
{
void * phys_ptr = nullptr;
if (ram_alloc().alloc_aligned(get_page_size(), &phys_ptr,
get_page_size_log2()).error())
ram_alloc().alloc_aligned(get_page_size(), get_page_size_log2()).with_result(
[&] (void *ptr) { phys_ptr = ptr; },
[&] (Range_allocator::Alloc_error) { /* covered by nullptr test below */ });
if (phys_ptr == nullptr)
break;
addr_t phys_addr = reinterpret_cast<addr_t>(phys_ptr);

View File

@@ -40,12 +40,17 @@ static inline void * alloc_region(Dataspace_component &ds, const size_t size)
void *virt_addr = 0;
size_t align_log2 = log2(ds.size());
for (; align_log2 >= get_page_size_log2(); align_log2--) {
if (platform().region_alloc().alloc_aligned(size,
&virt_addr, align_log2).ok())
break;
platform().region_alloc().alloc_aligned(size, align_log2).with_result(
[&] (void *ptr) { virt_addr = ptr; },
[&] (Range_allocator::Alloc_error) { /* try next iteration */ }
);
if (virt_addr)
return virt_addr;
}
return virt_addr;
error("alloc_region of size ", size, " unexpectedly failed");
return nullptr;
}

View File

@@ -92,7 +92,8 @@ Trace::Source::Info Vm_session_component::Vcpu::trace_source_info() const
warning("sc_ctrl failed res=", res);
return { _label, String<5>("vCPU"),
Trace::Execution_time(sc_time, sc_time),
Trace::Execution_time(sc_time, sc_time,
Nova::Qpd::DEFAULT_QUANTUM, _priority),
_location };
}

View File

@@ -31,7 +31,7 @@ CC_OPT += -DCONFIG_MEMORY_DYN_MIN=0x1c00000 \
CC_OPT_PIC :=
ifeq ($(filter-out $(SPECS),32bit),)
override CC_MARCH = -m32
CC_WARN += -Wframe-larger-than=96
CC_WARN += -Wframe-larger-than=104
CC_OPT += -mpreferred-stack-boundary=2 -mregparm=3
else
ifeq ($(filter-out $(SPECS),64bit),)

View File

@@ -64,17 +64,16 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
Vcpu_state _vcpu_state __attribute__((aligned(0x10))) { };
uint8_t _fpu_ep[512] __attribute__((aligned(0x10)));
enum Remote_state_requested {
NONE = 0,
PAUSE = 1,
RUN = 2
} _remote { NONE };
inline void _read_nova_state(Nova::Utcb &utcb, unsigned exit_reason);
inline void _read_nova_state(Nova::Utcb &, unsigned exit_reason,
uint8_t const &);
inline void _write_nova_state(Nova::Utcb &utcb);
inline void _write_nova_state(Nova::Utcb &);
addr_t _sm_sel() const {
return Nova::NUM_INITIAL_PT_RESERVED + _id_elem.id().value * 4; }
@@ -82,7 +81,8 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
addr_t _ec_sel() const { return _sm_sel() + 1; }
/**
* NOVA badge with 16-bit exit reason and 16-bit artificial vCPU I
* NOVA badge with 15-bit exit reason, 1-bit fpu usage and
* 16-bit artificial vCPU I
*/
struct Badge
{
@@ -91,15 +91,19 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
Badge(unsigned long value)
: _value((uint32_t)value) { }
Badge(uint16_t vcpu_id, uint16_t exit_reason)
: _value((uint32_t)(vcpu_id << 16) | exit_reason) { }
Badge(uint16_t vcpu_id, uint16_t exit_reason, bool fpu_usage)
: _value((uint32_t)(vcpu_id << 16) |
(exit_reason & 0x7fffu) |
(fpu_usage ? 0x8000u : 0u)
) { }
uint16_t exit_reason() const { return (uint16_t)( _value & 0xffff); }
uint16_t exit_reason() const { return (uint16_t)( _value & 0x7fff); }
uint16_t vcpu_id() const { return (uint16_t)((_value >> 16) & 0xffff); }
bool fpu_usage() const { return _value & 0x8000; }
uint32_t value() const { return _value; }
};
bool _handle_exit(Nova::Utcb &utcb, uint16_t exit_reason);
bool _handle_exit(Nova::Utcb &, uint16_t exit_reason, uint8_t const &);
__attribute__((regparm(1))) static void _exit_entry(addr_t badge);
@@ -109,8 +113,6 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
(void)exit;
(void)config;
return Nova::Mtd(Nova::Mtd::ALL);
Genode::addr_t mtd = 0;
mtd |= Nova::Mtd::ACDB;
@@ -133,6 +135,7 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
mtd |= Nova::Mtd::INJ;
mtd |= Nova::Mtd::STA;
mtd |= Nova::Mtd::TSC;
mtd |= Nova::Mtd::TSC_AUX;
mtd |= Nova::Mtd::EFER;
mtd |= Nova::Mtd::PDPTE;
mtd |= Nova::Mtd::SYSCALL_SWAPGS;
@@ -172,7 +175,8 @@ struct Nova_vcpu : Rpc_client<Vm_session::Native_vcpu>, Noncopyable
};
void Nova_vcpu::_read_nova_state(Nova::Utcb &utcb, unsigned exit_reason)
void Nova_vcpu::_read_nova_state(Nova::Utcb &utcb, unsigned exit_reason,
uint8_t const &fpu_at_exit)
{
typedef Genode::Vcpu_state::Segment Segment;
typedef Genode::Vcpu_state::Range Range;
@@ -181,10 +185,9 @@ void Nova_vcpu::_read_nova_state(Nova::Utcb &utcb, unsigned exit_reason)
state().exit_reason = exit_reason;
if (utcb.mtd & Nova::Mtd::FPU) {
state().fpu.charge([] (Vcpu_state::Fpu::State &fpu) {
asm volatile ("fxsave %0" : "=m" (fpu) :: "memory");
state().fpu.charge([&] (Vcpu_state::Fpu::State &fpu) {
memcpy(&fpu, &fpu_at_exit, sizeof(fpu));
});
asm volatile ("fxrstor %0" : : "m" (*_fpu_ep) : "memory");
}
if (utcb.mtd & Nova::Mtd::ACDB) {
@@ -314,6 +317,10 @@ void Nova_vcpu::_read_nova_state(Nova::Utcb &utcb, unsigned exit_reason)
state().tsc_offset.charge(utcb.tsc_off);
}
if (utcb.mtd & Nova::Mtd::TSC_AUX) {
state().tsc_aux.charge(utcb.tsc_aux);
}
if (utcb.mtd & Nova::Mtd::EFER) {
state().efer.charge(utcb.read_efer());
}
@@ -506,6 +513,11 @@ void Nova_vcpu::_write_nova_state(Nova::Utcb &utcb)
utcb.tsc_off = state().tsc_offset.value();
}
if (state().tsc_aux.charged()) {
utcb.mtd |= Nova::Mtd::TSC_AUX;
utcb.tsc_aux = state().tsc_aux.value();
}
if (state().efer.charged()) {
utcb.mtd |= Nova::Mtd::EFER;
utcb.write_efer(state().efer.value());
@@ -539,11 +551,8 @@ void Nova_vcpu::_write_nova_state(Nova::Utcb &utcb)
utcb.write_tpr_threshold(state().tpr_threshold.value());
}
if (_use_guest_fpu || state().fpu.charged()) {
asm volatile ("fxsave %0" : "=m" (*_fpu_ep) :: "memory");
}
if (state().fpu.charged()) {
utcb.mtd |= Nova::Mtd::FPU;
state().fpu.with_state([] (Vcpu_state::Fpu::State const &fpu) {
asm volatile ("fxrstor %0" : : "m" (fpu) : "memory");
});
@@ -581,7 +590,7 @@ void Nova_vcpu::run()
* Do not touch the UTCB before _read_nova_state() and after
* _write_nova_state(), particularly not by logging diagnostics.
*/
bool Nova_vcpu::_handle_exit(Nova::Utcb &utcb, uint16_t exit_reason)
bool Nova_vcpu::_handle_exit(Nova::Utcb &utcb, uint16_t exit_reason, uint8_t const &fpu)
{
/* reset blocking state */
bool const previous_blocked = _block;
@@ -595,7 +604,7 @@ bool Nova_vcpu::_handle_exit(Nova::Utcb &utcb, uint16_t exit_reason)
/* transform state from NOVA to Genode */
if (exit_reason != VM_EXIT_RECALL || !previous_blocked)
_read_nova_state(utcb, exit_reason);
_read_nova_state(utcb, exit_reason, fpu);
if (exit_reason == VM_EXIT_RECALL) {
if (previous_blocked)
@@ -653,6 +662,10 @@ bool Nova_vcpu::_handle_exit(Nova::Utcb &utcb, uint16_t exit_reason)
void Nova_vcpu::_exit_entry(addr_t badge)
{
uint8_t _fpu_at_exit[512] __attribute__((aligned(0x10)));
if (Badge(badge).fpu_usage())
asm volatile ("fxsave %0" : "=m" (*_fpu_at_exit) :: "memory");
Thread &myself = *Thread::myself();
Nova::Utcb &utcb = *reinterpret_cast<Nova::Utcb *>(myself.utcb());
@@ -662,7 +675,8 @@ void Nova_vcpu::_exit_entry(addr_t badge)
try {
_vcpu_space().apply<Nova_vcpu>(vcpu_id, [&] (Nova_vcpu &vcpu)
{
bool const block = vcpu._handle_exit(utcb, exit_reason);
bool const block = vcpu._handle_exit(utcb, exit_reason,
*_fpu_at_exit);
if (block) {
Nova::reply(myself.stack_top(), vcpu._sm_sel());
@@ -729,7 +743,7 @@ Signal_context_capability Nova_vcpu::_create_exit_handler(Pd_session &pd,
Native_capability vm_exit_cap =
native_pd.alloc_rpc_cap(thread_cap, (addr_t)Nova_vcpu::_exit_entry, mtd.value());
Badge const badge { vcpu_id, exit_reason };
Badge const badge { vcpu_id, exit_reason, !!(mtd.value() & Nova::Mtd::FPU) };
native_pd.imprint_rpc_cap(vm_exit_cap, badge.value());
return reinterpret_cap_cast<Signal_context>(vm_exit_cap);

View File

@@ -1 +1 @@
2021-10-13 c15d5658974ba0ae9980eb6e762431ba55ded1c4
2021-11-29 2edd7e47571313187be2e2087479f9ef3906a1d6

View File

@@ -24,10 +24,8 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
off_t offset, bool use_local_addr,
Region_map::Local_addr, bool, bool)
{
using namespace Okl4;
return _ep.apply(ds_cap, [&] (Dataspace_component *ds) -> void * {
auto lambda = [&] (Dataspace_component *ds) -> void *
{
if (!ds)
throw Invalid_dataspace();
@@ -48,21 +46,25 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size,
}
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform().region_alloc().alloc(page_rounded_size, &virt_addr)) {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return nullptr;
}
Range_allocator &virt_alloc = platform().region_alloc();
return virt_alloc.try_alloc(page_rounded_size).convert<void *>(
/* map the dataspace's physical pages to corresponding virtual addresses */
unsigned num_pages = page_rounded_size >> get_page_size_log2();
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages))
return nullptr;
return virt_addr;
};
[&] (void *virt_addr) -> void * {
return _ep.apply(ds_cap, lambda);
/* map the dataspace's physical pages to virtual memory */
unsigned num_pages = page_rounded_size >> get_page_size_log2();
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages))
return nullptr;
return virt_addr;
},
[&] (Range_allocator::Alloc_error) -> void * {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return nullptr;
});
});
}

View File

@@ -138,7 +138,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
if (msi)
throw Service_denied();
if (irq_alloc.alloc_addr(1, _irq_number).error()) {
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable IRQ ", Hex(_irq_number), " requested");
throw Service_denied();
}

View File

@@ -189,52 +189,66 @@ Platform::Platform()
/* core log as ROM module */
{
void * core_local_ptr = nullptr;
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const log_size = pages << get_page_size_log2();
unsigned const align = get_page_size_log2();
ram_alloc().alloc_aligned(log_size, &phys_ptr, get_page_size_log2());
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
ram_alloc().alloc_aligned(log_size, align).with_result(
/* let one page free after the log buffer */
region_alloc().alloc_aligned(log_size, &core_local_ptr, get_page_size_log2());
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
[&] (void *phys) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys);
map_local(phys_addr, core_local_addr, pages);
memset(core_local_ptr, 0, log_size);
region_alloc().alloc_aligned(log_size, align). with_result(
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
"core_log"));
[&] (void *ptr) {
init_core_log(Core_log_range { core_local_addr, log_size } );
map_local(phys_addr, (addr_t)ptr, pages);
memset(ptr, 0, log_size);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, log_size, "core_log"));
init_core_log(Core_log_range { (addr_t)ptr, log_size } );
},
[&] (Range_allocator::Alloc_error) { }
);
},
[&] (Range_allocator::Alloc_error) { }
);
}
/* export platform specific infos */
{
void * core_local_ptr = nullptr;
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const size = pages << get_page_size_log2();
if (ram_alloc().alloc_aligned(size, &phys_ptr, get_page_size_log2()).ok()) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result(
/* let one page free after the log buffer */
region_alloc().alloc_aligned(size, &core_local_ptr, get_page_size_log2());
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
[&] (void *phys_ptr) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
if (map_local(phys_addr, core_local_addr, pages)) {
/* let one page free after the log buffer */
region_alloc().alloc_aligned(size, get_page_size_log2()).with_result(
Genode::Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
size, "platform_info", [&] () {
xml.node("kernel", [&] () { xml.attribute("name", "okl4"); });
});
[&] (void *core_local_ptr) {
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"platform_info"));
}
}
if (map_local(phys_addr, core_local_addr, pages)) {
Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
size, "platform_info", [&] () {
xml.node("kernel", [&] () { xml.attribute("name", "okl4"); });
});
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"platform_info"));
}
},
[&] (Range_allocator::Alloc_error) { }
);
},
[&] (Range_allocator::Alloc_error) { }
);
}
}

View File

@@ -38,31 +38,41 @@ void Ram_dataspace_factory::_clear_ds (Dataspace_component &ds)
{
size_t page_rounded_size = (ds.size() + get_page_size() - 1) & get_page_mask();
struct Guard
{
Range_allocator &virt_alloc;
struct { void *virt_ptr = nullptr; };
Guard(Range_allocator &virt_alloc) : virt_alloc(virt_alloc) { }
~Guard() { if (virt_ptr) virt_alloc.free(virt_ptr); }
} guard(platform().region_alloc());
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform().region_alloc().alloc(page_rounded_size, &virt_addr)) {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
platform().region_alloc().try_alloc(page_rounded_size).with_result(
[&] (void *ptr) { guard.virt_ptr = ptr; },
[&] (Range_allocator::Alloc_error e) {
error("could not allocate virtual address range in core of size ",
page_rounded_size, ", error=", e); });
if (!guard.virt_ptr)
return;
}
/* map the dataspace's physical pages to corresponding virtual addresses */
size_t num_pages = page_rounded_size >> get_page_size_log2();
if (!map_local(ds.phys_addr(), (addr_t)virt_addr, num_pages)) {
error("core-local memory mapping failed, error=", Okl4::L4_ErrorCode());
if (!map_local(ds.phys_addr(), (addr_t)guard.virt_ptr, num_pages)) {
error("core-local memory mapping failed");
return;
}
/* clear dataspace */
size_t num_longwords = page_rounded_size/sizeof(long);
for (long *dst = (long *)virt_addr; num_longwords--;)
for (long *dst = (long *)guard.virt_ptr; num_longwords--;)
*dst++ = 0;
/* unmap dataspace from core */
if (!unmap_local((addr_t)virt_addr, num_pages))
error("could not unmap core-local address range at ", virt_addr, ", "
if (!unmap_local((addr_t)guard.virt_ptr, num_pages))
error("could not unmap core-local address range at ", guard.virt_ptr, ", "
"error=", Okl4::L4_ErrorCode());
/* free core's virtual address space */
platform().region_alloc().free(virt_addr, page_rounded_size);
}

View File

@@ -1 +1 @@
2021-10-13 2b72c9c5d111051ff6e274a9231c096fb7d70fed
2021-11-29 c35c9e382e0e54a0fb975e26b88ed0de3d7a027e

View File

@@ -60,28 +60,30 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size)
{
using namespace Pistachio;
addr_t local_base;
auto alloc_virt_range = [&] ()
{
/* special case for the null page */
if (is_conventional_memory(base))
return base;
/* align large I/O dataspaces on a super-page boundary within core */
size_t alignment = (size >= get_super_page_size()) ? get_super_page_size_log2()
: get_page_size_log2();
/* align large I/O dataspaces on a super-page boundary within core */
size_t const align = (size >= get_super_page_size())
? get_super_page_size_log2()
: get_page_size_log2();
/* special case for the null page */
if (is_conventional_memory(base))
local_base = base;
return platform().region_alloc().alloc_aligned(size, align).convert<addr_t>(
[&] (void *ptr) { return (addr_t)ptr; },
[&] (Range_allocator::Alloc_error) -> addr_t {
error(__func__, ": alloc_aligned failed!");
return 0; });
};
else {
addr_t const local_base = (addr_t)alloc_virt_range();
/* find appropriate region for mapping */
void *result = 0;
if (platform().region_alloc().alloc_aligned(size, &result, alignment).error())
error(__func__, ": alloc_aligned failed!");
if (!local_base)
return 0;
local_base = (addr_t)result;
}
unsigned offset = 0;
while (size) {
for (unsigned offset = 0; size; ) {
size_t page_size = get_page_size();
if (can_use_super_page(base + offset, size))

View File

@@ -133,7 +133,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
if (msi)
throw Service_denied();
if (irq_alloc.alloc_addr(1, _irq_number).error()) {
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable IRQ ", Hex(_irq_number), " requested");
throw Service_denied();
}

View File

@@ -605,51 +605,42 @@ Platform::Platform()
core_pd().bind_thread(core_thread);
/* core log as ROM module */
auto export_page_as_rom_module = [&] (auto rom_name, auto content_fn)
{
void * phys_ptr = nullptr;
unsigned const pages = 1;
size_t const log_size = pages << get_page_size_log2();
size_t const size = 1 << get_page_size_log2();
ram_alloc().alloc_aligned(size, get_page_size_log2()).with_result(
ram_alloc().alloc_aligned(log_size, &phys_ptr, get_page_size_log2());
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
[&] (void *phys_ptr) {
void * const core_local_ptr = phys_ptr;
addr_t const core_local_addr = phys_addr;
/* core-local memory is one-to-one mapped physical RAM */
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
void * const core_local_ptr = phys_ptr;
/* let one page free after the log buffer */
region_alloc().remove_range(core_local_addr, log_size + get_page_size());
region_alloc().remove_range((addr_t)core_local_ptr, size);
memset(core_local_ptr, 0, size);
content_fn(core_local_ptr, size);
memset(core_local_ptr, 0, log_size);
_rom_fs.insert(new (core_mem_alloc())
Rom_module(phys_addr, size, rom_name));
},
[&] (Range_allocator::Alloc_error) {
warning("failed to export ", rom_name, " as ROM module"); }
);
};
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
"core_log"));
init_core_log(Core_log_range { core_local_addr, log_size } );
}
/* core log as ROM module */
export_page_as_rom_module("core_log",
[&] (void *core_local_ptr, size_t size) {
init_core_log(Core_log_range { (addr_t)core_local_ptr, size } ); });
/* export platform specific infos */
{
void * phys_ptr = nullptr;
size_t const size = 1 << get_page_size_log2();
if (ram_alloc().alloc_aligned(size, &phys_ptr,
get_page_size_log2()).ok()) {
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
addr_t const core_local_addr = phys_addr;
region_alloc().remove_range(core_local_addr, size);
Genode::Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
size, "platform_info", [&] () {
xml.node("kernel", [&] () { xml.attribute("name", "pistachio"); });
});
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
"platform_info"));
}
}
export_page_as_rom_module("platform_info",
[&] (void *core_local_ptr, size_t size) {
Xml_generator xml(reinterpret_cast<char *>(core_local_ptr),
size, "platform_info",
[&] () {
xml.node("kernel", [&] () {
xml.attribute("name", "pistachio"); }); }); });
}

View File

@@ -1 +1 @@
2021-10-13 e6d9b433aacab2435854c06b6be6e460e5bc0dba
2021-11-29 38db6c16cb9a86e9586cb4c6744de1d3253c187e

View File

@@ -1 +1 @@
2021-10-13 47f688dc1a3cf0cdd01d50c78200f6c673bbd8a7
2021-11-29 312d15c5cc7ba2ad3fc672b22a875f56c48e4665

View File

@@ -1 +1 @@
2021-10-13 8156c9f37aebd3f73047484d66d1a85a669f871d
2021-11-29 5fd017a250665ddaff280b47a32fe0255d141c44

View File

@@ -26,7 +26,8 @@ Region_map::Local_addr
Core_region_map::attach(Dataspace_capability ds_cap, size_t size, off_t offset,
bool use_local_addr, Region_map::Local_addr, bool, bool)
{
auto lambda = [&] (Dataspace_component *ds) -> Local_addr {
return _ep.apply(ds_cap, [&] (Dataspace_component *ds) -> Local_addr {
if (!ds)
throw Invalid_dataspace();
@@ -46,21 +47,22 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size, off_t offset,
}
/* allocate range in core's virtual address space */
void *virt_addr;
if (!platform().region_alloc().alloc(page_rounded_size, &virt_addr)) {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return nullptr;
}
return platform().region_alloc().try_alloc(page_rounded_size).convert<Local_addr>(
[&] (void *virt_ptr) {
/* map the dataspace's physical pages to core-local virtual addresses */
size_t num_pages = page_rounded_size >> get_page_size_log2();
map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages);
/* map the dataspace's physical pages to core-local virtual addresses */
size_t num_pages = page_rounded_size >> get_page_size_log2();
map_local(ds->phys_addr(), (addr_t)virt_ptr, num_pages);
return virt_addr;
};
return _ep.apply(ds_cap, lambda);
return virt_ptr;
},
[&] (Range_allocator::Alloc_error) -> Local_addr {
error("could not allocate virtual address range in core of size ",
page_rounded_size);
return nullptr;
}
);
});
}

View File

@@ -51,21 +51,17 @@ class Genode::Static_allocator : public Allocator
class Alloc_failed { };
bool alloc(size_t size, void **out_addr) override
Alloc_result try_alloc(size_t size) override
{
*out_addr = nullptr;
if (size > sizeof(Elem_space)) {
error("unexpected allocation size of ", size);
return false;
return Alloc_error::DENIED;
}
try {
*out_addr = &_elements[_used.alloc()]; }
return &_elements[_used.alloc()]; }
catch (typename Bit_allocator<MAX>::Out_of_indices) {
return false; }
return true;
return Alloc_error::DENIED; }
}
size_t overhead(size_t) const override { return 0; }

View File

@@ -33,17 +33,17 @@ struct Genode::Untyped_memory
static inline addr_t alloc_pages(Range_allocator &phys_alloc, size_t num_pages)
{
void *out_ptr = nullptr;
Range_allocator::Alloc_return alloc_ret =
phys_alloc.alloc_aligned(num_pages*get_page_size(), &out_ptr,
get_page_size_log2());
size_t const size = num_pages*get_page_size();
unsigned const align = get_page_size_log2();
if (alloc_ret.error()) {
error(__PRETTY_FUNCTION__, ": allocation of untyped memory failed");
throw Phys_alloc_failed();
}
return phys_alloc.alloc_aligned(size, align).convert<addr_t>(
return (addr_t)out_ptr;
[&] (void *ptr) {
return (addr_t)ptr; },
[&] (Range_allocator::Alloc_error) -> addr_t {
error(__PRETTY_FUNCTION__, ": allocation of untyped memory failed");
throw Phys_alloc_failed(); });
}

View File

@@ -109,7 +109,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
if (msi)
throw Service_denied();
if (irq_alloc.alloc_addr(1, _irq_number).error()) {
if (irq_alloc.alloc_addr(1, _irq_number).failed()) {
error("unavailable IRQ ", _irq_number, " requested");
throw Service_denied();
}

Some files were not shown because too many files have changed in this diff Show More