mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-22 13:02:56 +01:00
Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cf7aaad65 | ||
|
|
25a8ef3b7c | ||
|
|
b18a56c2c4 | ||
|
|
9d42e3f69b | ||
|
|
11ef8e1ff2 | ||
|
|
1deab4a67f | ||
|
|
f23c70e068 | ||
|
|
f7c818d303 | ||
|
|
7996cf06ab | ||
|
|
4800bcf5a0 | ||
|
|
4c74f4792c | ||
|
|
57d080d4f8 | ||
|
|
2778debc29 | ||
|
|
7182c10c90 | ||
|
|
7309bcf4b5 | ||
|
|
309bc2083e | ||
|
|
6e098a9d17 | ||
|
|
573b6d3345 | ||
|
|
077fa355ce | ||
|
|
e76ce05844 | ||
|
|
4622ddb46f | ||
|
|
972e1893c9 | ||
|
|
af29dcf557 | ||
|
|
f82714f341 | ||
|
|
02d68fdb97 | ||
|
|
065b9fdb46 | ||
|
|
18dbd75860 | ||
|
|
3ac970ac1d | ||
|
|
3aaed7188f | ||
|
|
ee64e29e77 | ||
|
|
cfba429c15 | ||
|
|
25aa25c6a0 | ||
|
|
2afc02051c | ||
|
|
ce1b813105 | ||
|
|
7ed1d7f11d | ||
|
|
6ccd65bd8e | ||
|
|
18b621c2fe | ||
|
|
cb61a28362 | ||
|
|
4d7d208940 | ||
|
|
f7509a5b78 | ||
|
|
a54c04d247 | ||
|
|
e70c04ef86 | ||
|
|
6410e88698 | ||
|
|
a3cb9d9897 | ||
|
|
b2a7ac2996 | ||
|
|
5f350adb57 | ||
|
|
1485cd9d24 | ||
|
|
65d72fb07a | ||
|
|
4871c7bba0 | ||
|
|
97e2968986 | ||
|
|
eb9a9bf23d | ||
|
|
c51b4b5742 | ||
|
|
9b7915facb | ||
|
|
f0de187bbb | ||
|
|
539110c0b1 | ||
|
|
d7b1a89087 | ||
|
|
c50252fb35 | ||
|
|
54002e6e6b | ||
|
|
16994d637b | ||
|
|
b541a0d448 | ||
|
|
d4e0d2f578 | ||
|
|
fab2fc874f | ||
|
|
54643d6878 | ||
|
|
2653fad0c4 | ||
|
|
b752d22a77 | ||
|
|
ad12b42d1c | ||
|
|
c845a2d943 | ||
|
|
b7e06a0b5b | ||
|
|
417dd59b22 | ||
|
|
3024720656 | ||
|
|
f23eab735b | ||
|
|
112c32eb54 | ||
|
|
3103ce1fa8 | ||
|
|
db18fc42fe | ||
|
|
d28fe9e938 | ||
|
|
31a035a907 | ||
|
|
91412c6c52 | ||
|
|
068324536c | ||
|
|
bb6eb0f6ea | ||
|
|
c1012e6a45 | ||
|
|
23d21d77e9 | ||
|
|
8c44b17e86 | ||
|
|
636e0f6444 | ||
|
|
fafa409cf9 | ||
|
|
dbecceec09 | ||
|
|
60f390ddf8 | ||
|
|
c79ebc93a2 | ||
|
|
55ab694d79 | ||
|
|
f5c5479faa | ||
|
|
ba9b612c4f | ||
|
|
7b0771659e | ||
|
|
e9762ee25f | ||
|
|
7549189f88 | ||
|
|
a5bc031cca | ||
|
|
5cd684997a | ||
|
|
93d3a0848a | ||
|
|
f1b1dd26cf | ||
|
|
cd5e906bd0 | ||
|
|
c589660182 | ||
|
|
8a8aa85726 | ||
|
|
105b2c9b7a | ||
|
|
f6435d91fc | ||
|
|
3e3fb63863 | ||
|
|
4007cee852 | ||
|
|
b622a5a788 | ||
|
|
ec9e40695d | ||
|
|
0ad0153626 | ||
|
|
cd37bff514 | ||
|
|
27c2a66bbd | ||
|
|
58247737fd | ||
|
|
ebcca179ed | ||
|
|
60d37f690c | ||
|
|
0ed5655086 | ||
|
|
87a6368ba1 | ||
|
|
1cbd77c806 | ||
|
|
e3f82b09d7 | ||
|
|
d4a3db22bd | ||
|
|
43f28e0451 | ||
|
|
d516515c7a | ||
|
|
7ac32ea60c | ||
|
|
07a40d028a | ||
|
|
a47adecdcd | ||
|
|
355d94f5df | ||
|
|
c0789a6c0e | ||
|
|
530144b040 | ||
|
|
c85bc38802 | ||
|
|
a8dd7dd2fa | ||
|
|
6e86d6d699 | ||
|
|
2954abb58a | ||
|
|
5bb366513b | ||
|
|
4bcc75365c | ||
|
|
288f79270d | ||
|
|
3c62a33a25 | ||
|
|
80a84bef26 | ||
|
|
022fac0d37 | ||
|
|
5ab1505d43 | ||
|
|
1297a8fb57 | ||
|
|
732215a83f | ||
|
|
e11addec7d | ||
|
|
2166a4b17f | ||
|
|
291587f545 | ||
|
|
97df705e53 | ||
|
|
e281174dae | ||
|
|
ed73feddc5 | ||
|
|
c5706e8f4a | ||
|
|
1782c6be79 | ||
|
|
cccfd0719d | ||
|
|
edc9545229 | ||
|
|
cc611834c9 | ||
|
|
bbd27a54d3 | ||
|
|
5a06751242 | ||
|
|
6df8b44616 | ||
|
|
e0af9c2d8b | ||
|
|
11a7ac0536 | ||
|
|
5c25e0bdb0 | ||
|
|
222f214341 | ||
|
|
eefe91ee41 | ||
|
|
979d823d85 | ||
|
|
76438a3f85 | ||
|
|
b0271ae5e1 | ||
|
|
6a063364da | ||
|
|
99b632f86c | ||
|
|
180f9e6384 | ||
|
|
94b63924ed | ||
|
|
d0bf6d2b52 | ||
|
|
9a82bbb54d | ||
|
|
400039e1b6 | ||
|
|
2e5166efd7 | ||
|
|
2ec3aaf639 | ||
|
|
ab5187d673 | ||
|
|
697d496093 | ||
|
|
a17c5e30b7 | ||
|
|
8d6285927b | ||
|
|
90a91f3536 | ||
|
|
c8b7710e5d | ||
|
|
59c60b8031 | ||
|
|
9500e8b6e1 | ||
|
|
e0ee56275e | ||
|
|
418ac4c560 | ||
|
|
5f5d709c07 | ||
|
|
89a38723bd | ||
|
|
648bcd1505 | ||
|
|
bf92232698 | ||
|
|
aec1178ab1 | ||
|
|
efe7f5172d | ||
|
|
0aedabd245 | ||
|
|
4a7b0e99a6 | ||
|
|
614f7fa56a | ||
|
|
6d230134cb | ||
|
|
d953030c0e | ||
|
|
6fe80c3cc7 | ||
|
|
afa0e26a6a | ||
|
|
1d3bbde70a | ||
|
|
6f0c6501f2 | ||
|
|
e448022f23 | ||
|
|
664d858e63 | ||
|
|
ede009edf9 | ||
|
|
08aa7d310a | ||
|
|
19bf0fdeb8 | ||
|
|
36111a2edf | ||
|
|
ab017607a2 |
@@ -16,17 +16,6 @@ research projects on Genode.
|
||||
Applications and library infrastructure
|
||||
#######################################
|
||||
|
||||
:GNU Privacy Guard:
|
||||
|
||||
The [https://gnupg.org/ - GNU Privacy Guard] (GNUPG) is the most widely
|
||||
used Free-Software implementation of the OpenGPG standard. It comprises a
|
||||
rich set of tools for encryption and key management. For many forthcoming
|
||||
application scenarios of Genode such as package management and email
|
||||
communication, GNUPG is crucial. Hence, it should be ported to Genode. Such
|
||||
a port may leverage Genode's fine-grained component architecture to strongly
|
||||
separate network-exposed functionality, the storage of key material, and the
|
||||
cryptographic functions.
|
||||
|
||||
:VNC server implementing Genode's framebuffer session interface:
|
||||
|
||||
With 'Input' and 'Framebuffer', Genode provides two low-level interfaces
|
||||
@@ -50,24 +39,6 @@ Applications and library infrastructure
|
||||
integrated in the operating system, i.e., in the form of Genode components
|
||||
or a set of Genode VFS plugins.
|
||||
|
||||
:Tiled window manager:
|
||||
|
||||
At Genode Labs, we pursue the goal to shape Genode into an general-purpose
|
||||
operating system suitable for productive work. The feature set needed to
|
||||
achieve this goal largely depends on the tools and applications daily used by
|
||||
the Genode engineers. As one particularly important tool for being highly
|
||||
productive, we identified a tiled user interface. Currently, all developers
|
||||
at Genode Labs embrace either the Ion3 window manager or the tiled Terminator
|
||||
terminal emulator. Hence, we desire to have a similar mode of user
|
||||
interaction on Genode as well. The goal of this challenge is to identify the
|
||||
most important usage patters and the implementation of a tiled GUI that
|
||||
multiplexes the framebuffer into a set of tiled and tabbed virtual
|
||||
framebuffers.
|
||||
|
||||
Related to this work, the low-level 'Framebuffer' and 'Input' interfaces
|
||||
should be subject to a revision, for example for enabling the flexible change
|
||||
of framebuffer sizes as needed by a tiled user interface.
|
||||
|
||||
:Interactive sound switchbox based on Genode's Audio_out session interface:
|
||||
|
||||
Since version 10.05, Genode features a highly flexible configuration concept
|
||||
@@ -116,6 +87,11 @@ Applications and library infrastructure
|
||||
of communicating threads as captured on the running system. The tool should
|
||||
work on a selected kernel that provides a facility for tracing IPC messages.
|
||||
|
||||
The underlying light-weight tracing infrastructure is
|
||||
[https://genode.org/documentation/release-notes/19.08#Tracinghttps://genode.org/documentation/release-notes/19.08#Tracing - already in place].
|
||||
The Qt-based tracing tools would complement this infrastructure with
|
||||
an interactive front end.
|
||||
|
||||
:Ports of popular software:
|
||||
|
||||
Genode features a ports mechanism to cleanly integrate 3rd-party software.
|
||||
@@ -127,6 +103,18 @@ Applications and library infrastructure
|
||||
have available on Genode is available at
|
||||
[http://usr.sysret.de/jws/genode/porting_wishlist.html].
|
||||
|
||||
:Native Open-Street-Maps (OSM) client:
|
||||
|
||||
When using Sculpt OS, we regularly need to spawn a fully fledged web
|
||||
browser in a virtual machine for using OSM or Google maps. The goal
|
||||
of this project would be a native component that makes maps functionality
|
||||
directly available on Genode, alleviating the urge to reach for a SaaS
|
||||
product. The work would include a review of existing OSM clients regarding
|
||||
their feature sets and the feasibility of porting them to Genode.
|
||||
Depending on the outcome of this review, an existing application could
|
||||
be ported or a new component could be developed, e.g., leveraging Genode's
|
||||
Qt support.
|
||||
|
||||
|
||||
Application frameworks and runtime environments
|
||||
###############################################
|
||||
@@ -135,18 +123,18 @@ Application frameworks and runtime environments
|
||||
|
||||
[http://openjdk.java.net/ - OpenJDK] is the reference implementation of the
|
||||
Java programming language and hosts an enormous ecosystem of application
|
||||
software. The goal of this line of work is the ability to run this
|
||||
software directly on Genode. The centerpiece of OpenJDK is Hotspot - the
|
||||
Java virtual machine implementation, which must be ported to Genode.
|
||||
The initial port should suffice to execute simple example programs that
|
||||
operate on textual input. Since Genode has the FreeBSD libc readily
|
||||
available, OpenJDK's existing POSIX backends can be reused. The next step
|
||||
is the creation of Genode-specific native classes that bridge the gap
|
||||
between the Java world and Genode, in particular the glue code to
|
||||
run graphical applications as clients of Genode's GUI server. Since
|
||||
OpenJDK has been ported to numerous platforms (such as Haiku), there
|
||||
exists a comforting number of implementations that can be taken as
|
||||
reference.
|
||||
software.
|
||||
|
||||
Since
|
||||
[https://genode.org/documentation/release-notes/19.02#Showcase_of_a_Java-based_network_appliance - version 19.02],
|
||||
Genode features a port of OpenJDK that allows the use of Java for networking
|
||||
applications.
|
||||
|
||||
The next step would be the creation of Genode-specific native classes that
|
||||
bridge the gap between the Java world and Genode, in particular the glue
|
||||
code to run graphical applications as clients of Genode's GUI server. Since
|
||||
OpenJDK has been ported to numerous platforms (such as Haiku), there exists
|
||||
a comforting number of implementations that can be taken as reference.
|
||||
|
||||
:Android's ART VM natively on Genode:
|
||||
|
||||
@@ -155,22 +143,6 @@ Application frameworks and runtime environments
|
||||
removed from the trusted computing base of Android, facilitating the use of
|
||||
this mobile OS in high-assurance settings.
|
||||
|
||||
:Rust bindings for the Genode API:
|
||||
|
||||
Rust is a low-level systems programming language that ensures memory
|
||||
safety without employing a garbage collector. It thereby challenges C++
|
||||
as the go-to programming language for high-performance and low-level code.
|
||||
Since
|
||||
[http://genode.org/documentation/release-notes/16.05#New_support_for_the_Rust_programming_language - version 16.05],
|
||||
Genode supports the use of the Rust programming language within
|
||||
components. However, to unleash the potential of this combination,
|
||||
Genode's API must become available to native Rust code. The intermediate goal
|
||||
of this project is the implementation of an example server, e.g., a
|
||||
component that provides a terminal-session interface. Thereby, we
|
||||
will encounter the problems of bootstrapping and configuration of the
|
||||
component, the provisioning of signal handlers and session objects, and
|
||||
memory management.
|
||||
|
||||
:Go language runtime:
|
||||
|
||||
Go is a popular language in particular for web applications. In the past,
|
||||
@@ -222,6 +194,33 @@ Application frameworks and runtime environments
|
||||
development is [http://halvm.org - HalVM] - a light-weight OS runtime for
|
||||
Xen that is based on Haskell.
|
||||
|
||||
:Xlib compatibility:
|
||||
|
||||
Developments like Wayland notwithstanding, most application software on
|
||||
GNU/Linux systems is built on top of the Xlib programming interface.
|
||||
However, only a few parts of this wide interface are actually used today.
|
||||
I.e., modern applications generally deal with pixel buffers instead of
|
||||
relying on graphical drawing primitives of the X protocol. Hence, it seems
|
||||
feasible to reimplement the most important parts of the Xlib interface to
|
||||
target Genode's native GUI interfaces (nitpicker) directly. This would
|
||||
allow us to port popular application software to Sculpt OS without
|
||||
changing the application code.
|
||||
|
||||
:Bump-in-the-wire components for visualizing session interfaces:
|
||||
|
||||
Genode's session interfaces bear the potential for monitoring and
|
||||
visualizing their use by plugging a graphical application
|
||||
in-between any two components. For example, by intercepting block
|
||||
requests issued by a block-session client to a block-device driver,
|
||||
such a bump-in-the-wire component could visualize
|
||||
the access patterns of a block device. Similar ideas could be pursued for
|
||||
other session interfaces, like the audio-out (sound visualization) or NIC
|
||||
session (live visualization of network communication).
|
||||
|
||||
The visualization of system behavior would offer valuable insights,
|
||||
e.g., new opportunities for optimization. But more importantly, they
|
||||
would be extremely fun to play with.
|
||||
|
||||
|
||||
Virtualization
|
||||
##############
|
||||
@@ -237,21 +236,6 @@ Virtualization
|
||||
is normally not possible. Also, complex Genode scenarios (like Turmvilla)
|
||||
could be prototyped on GNU/Linux.
|
||||
|
||||
:VirtualBox on top of seL4:
|
||||
|
||||
The [https://sel4.systems - seL4 microkernel] is a modern microkernel that
|
||||
undergoes formal verification to prove the absence of bugs. Since version
|
||||
4.0, the kernel supports virtualization support on x86-based hardware.
|
||||
Genode has experimental support for seL4 that allows almost all Genode
|
||||
components to be used on top of this kernel. VirtualBox is an exception
|
||||
because it closely interacts with the underlying kernel (like NOVA) to
|
||||
attain good performance. We have shown that VirtualBox can be executed
|
||||
within a protection domain of the NOVA microhypervisor. The goal of this
|
||||
project is the application of this approach to the virtualization
|
||||
interface of seL4. The result will be a VM hosting environment that
|
||||
ensures the separation of virtual machines via the formally verified
|
||||
seL4 kernel.
|
||||
|
||||
:Xen as kernel for Genode:
|
||||
|
||||
Using Xen as kernel for Genode would clear the way to remove the
|
||||
@@ -294,22 +278,25 @@ Virtualization
|
||||
the project bears the opportunity to explore the provisioning of the
|
||||
KVM interface based on Genode's VFS plugin concept.
|
||||
|
||||
:Hardware-accelerated graphics for virtual machines:
|
||||
|
||||
In
|
||||
[https://genode.org/documentation/release-notes/17.08#Hardware-accelerated_graphics_for_Intel_Gen-8_GPUs - Genode 17.08],
|
||||
we introduced a GPU multiplexer for Intel Broadwell along with support
|
||||
for Mesa-based 3D-accelerated applications.
|
||||
While designing Genode's GPU-session interface, we also aimed at supporting
|
||||
the hardware-accelerated graphics for Genode's virtual machine monitors like
|
||||
VirtualBox or Seoul, but until now, we did not took the practical steps of
|
||||
implementing a virtual GPU device model.
|
||||
|
||||
The goal of this project is the offering of a virtual GPU to a Linux guest
|
||||
OS running on top of Genode's existing virtualization and driver
|
||||
infrastructure.
|
||||
|
||||
|
||||
Device drivers
|
||||
##############
|
||||
|
||||
:Isochronous USB devices:
|
||||
|
||||
Genode's USB driver supports bulk and interrupt endpoints. Thereby, most
|
||||
USB devices like USB storage, user input, printers, and networking devices
|
||||
can be used. However, multi-media devices such as cameras or audio
|
||||
equipment use isochronous endpoints, which are not supported. The goal
|
||||
of this line of work is the support of these devices in Genode. The topic
|
||||
touches the USB driver, the USB session interface, an example implementation
|
||||
of a USB client driver (using the session interface) for a device of choice,
|
||||
and - potentially - the enhancement of Genode's USB-pass-through mechanism
|
||||
for VirtualBox.
|
||||
|
||||
:Sound on the Raspberry Pi:
|
||||
|
||||
The goal of this project is a component that uses the Raspberry Pi's
|
||||
@@ -318,18 +305,6 @@ Device drivers
|
||||
backend, the new driver will make the sound of all SDL-based games
|
||||
available on the Raspberry Pi.
|
||||
|
||||
:Framebuffer for UEFI and Coreboot:
|
||||
|
||||
By moving away from the legacy BIOS boot mechanism, it is time to
|
||||
reconsider closely related traditional approaches such as the use of
|
||||
the VESA BIOS extensions for accessing the frame buffer. On UEFI or
|
||||
Coreboot systems, there exist alternative ways to initialize and
|
||||
access the framebuffer in a hardware-independent way. On the course of
|
||||
this project, we will explore the available options and create dedicated
|
||||
Genode driver components that use the modern mechanisms.
|
||||
For reference, the current state of Genode's UEFI support is documented
|
||||
in [https://github.com/genodelabs/genode/issues/2242 - Issue 2242].
|
||||
|
||||
:Data Plane Development Kit (DPDK):
|
||||
|
||||
Genode utilizes the network device drivers of the iPXE project, which
|
||||
@@ -357,8 +332,22 @@ Platforms
|
||||
Genode functionality such as its native GUI, lwIP, and Noux, many protocol
|
||||
stacks can effectively be removed from the Linux kernel.
|
||||
|
||||
The goal of this project is to evaluate how small the Linux kernel can get
|
||||
when used as a microkernel.
|
||||
In 2018, Johannes Kliemann pursued this topic to a state where Genode
|
||||
could be used as init process atop a customized Linux kernel.
|
||||
[https://lists.genode.org/pipermail/users/2018-May/006066.html - His work]
|
||||
included the execution of Genode's regular device drivers for VESA and
|
||||
PS/2 as regular Genode components so that Genode's interactive demo
|
||||
scenario ran happily on a laptop. At this time, however, only parts of
|
||||
his results were merged into Genode's mainline.
|
||||
|
||||
The goal of this project is to follow up on Johannes' work, bring the
|
||||
[https://github.com/genodelabs/genode/pull/2829 - remaining parts] into
|
||||
shape for the inclusion into Genode, and address outstanding topics, in
|
||||
particular the handling of DMA by user-level device drivers. Further down
|
||||
the road, it would be tempting to explore the use of
|
||||
[https://en.wikipedia.org/wiki/Seccomp - seccomp] as sandboxing mechanism
|
||||
for Genode on Linux and the improvement of the Linux-specific implementation
|
||||
of Genode's object-capability model.
|
||||
|
||||
:Support for the HelenOS/SPARTAN kernel:
|
||||
|
||||
@@ -381,34 +370,46 @@ Platforms
|
||||
kernel is used for Mac OS X, it could represent an industry-strength
|
||||
base platform for Genode supporting all CPU features as used by Mac OS X.
|
||||
|
||||
:Linux process containers for supporting Genode`s resource trading:
|
||||
:Genode on the Librem5 phone hardware:
|
||||
|
||||
Even though the Linux version of Genode is primarily meant as a development
|
||||
platform, there exist interesting opportunities to explore when combining
|
||||
Genode with Linux, in particular Linux' process containers.
|
||||
Linux process containers provide a mechanism to partition physical resources,
|
||||
foremost CPU time, between Linux processes. This raises the interesting
|
||||
question of whether this mechanism could be used for a proper implementation
|
||||
of Genode's resource trading on Linux.
|
||||
[http://lwn.net/Articles/236038/ - Process containers introduction...]
|
||||
Even though there exists a great variety of ARM-based SoCs, Genode
|
||||
primarily focuses on the NXP i.MX family because it is - in contrast
|
||||
to most SoCs in the consumer space - very liberal in terms of
|
||||
good-quality public documentation and reference code, and it scales
|
||||
from industrial to end-user-facing use cases (multi-media).
|
||||
|
||||
The [https://puri.sm/products/librem-5/ - Librem5] project - with its
|
||||
mission to build a trustworthy mobile phone - has chosen the i.MX family as
|
||||
the basis for their product for likely the same reasons that attract us.
|
||||
|
||||
To goal of this work is bringing Genode to the Librem5 hardware.
|
||||
For the Librem5 project, Genode could pave the ground towards new use cases
|
||||
like high-security markets where a regular Linux-based OS would not be
|
||||
accepted. For the Genode community, the Librem5 hardware could become an
|
||||
attractive mobile platform for everyday use, similar to how we developers
|
||||
use our Genode-based [https://genode.org/download/sculpt - Sculpt OS] on our
|
||||
laptops.
|
||||
|
||||
|
||||
System management
|
||||
#################
|
||||
|
||||
:Remote management of Sculpt OS via Puppet:
|
||||
|
||||
[https://en.wikipedia.org/wiki/Puppet_(company)#Puppet - Puppet] is a
|
||||
software-configuration management tool for administering a large amount
|
||||
of machines from one central place. Genode's
|
||||
[https://genode.org/download/sculpt - Sculpt OS] lends itself to such
|
||||
an approach of remote configuration management by the means of the
|
||||
"config" file system (for configuring components and deployments) and
|
||||
the "report" file system (for obtaining the runtime state of components).
|
||||
The project would explore the application of the Puppet approach and tools
|
||||
to Sculpt OS.
|
||||
|
||||
|
||||
Optimizations
|
||||
#############
|
||||
|
||||
:Low-latency audio streaming:
|
||||
|
||||
Genode comes with an audio streaming interface called 'Audio_out' session.
|
||||
It is based on a shared-memory packet stream accompanied with asynchronous
|
||||
data-flow signals. For real-time audio processing involving chains of Genode
|
||||
components, streams of audio data must be carried at low latency, imposing
|
||||
constraints to buffer sizes and the modes of operation of the audio mixer and
|
||||
audio drivers. The goal of this project is to create a holistic design of the
|
||||
whole chain of audio processing, taking thread-scheduling into account. A
|
||||
particular challenge is the mixed output of real-time (small buffer, low
|
||||
latency) and non-real-time (larger buffer to compensate jitter, higher
|
||||
latency) audio sources.
|
||||
|
||||
:De-privileging the VESA graphics driver:
|
||||
|
||||
The VESA graphics driver executes the graphics initialization code provided
|
||||
|
||||
48
doc/news.txt
48
doc/news.txt
@@ -3,6 +3,54 @@
|
||||
Genode News
|
||||
===========
|
||||
|
||||
Genode OS Framework release 19.11 | 2019-11-28
|
||||
##############################################
|
||||
|
||||
| Following this year's theme of "bridging worlds", Genode 19.11 adds the
|
||||
| ability to use popular build tools like CMake for application development,
|
||||
| introduces a new virtual-machine monitor for 64-bit ARM, and enhances
|
||||
| POSIX compatibility. As another highlight, it features the first version
|
||||
| of our custom block-device encrypter.
|
||||
|
||||
Block-device encryption is a feature often requested by users of our Sculpt OS.
|
||||
Until now, we deliberately left this topic unaddressed because we felt that a
|
||||
profound answer was beyond our expertise. However, during the past year, we
|
||||
dived deep into it. The result is the prototype for a new block encrypter that
|
||||
encrypts data but also protects integrity and freshness. For us, the
|
||||
implementation of the encrypter is especially intriguing because - with about
|
||||
7000 lines of code - it is Genode's first non-trivial component written in the
|
||||
[https://en.wikipedia.org/wiki/SPARK_(programming_language) - SPARK]
|
||||
programming language.
|
||||
|
||||
The second major addition is a new virtual machine monitor (VMM) for 64-bit
|
||||
ARM platforms such as the NXP i.MX8. It leverages the
|
||||
[https://genode.org/documentation/articles/arm_virtualization - proof of concept]
|
||||
we developed in 2015 for ARMv7, which we pursued as a technology exploration.
|
||||
In contrast, our aspiration with the new VMM is a product-quality solution.
|
||||
|
||||
In our [https://genode.org/about/road-map - road map] for 2019, we stated
|
||||
the "bridging of worlds" as our overall theme for this year. On that account,
|
||||
the current release moves the project forward on two levels. First, by
|
||||
successively increasing the scope of POSIX compatibility, we reduce the
|
||||
friction when porting existing application software to Genode. We managed
|
||||
to bridge several gaps in our POSIX support that we considered as impossible
|
||||
to cover some years ago. In particular, we identified ways to emulate certain
|
||||
POSIX signals, ioctl calls, and fork/execve semantics. This way, popular
|
||||
software such as bash, coreutils, or Vim can now be executed as regular
|
||||
Genode components with no additional runtime environment (like Noux or a VMM)
|
||||
required.
|
||||
|
||||
At a higher level, the current release introduces new tooling especially
|
||||
geared at the development and porting of application software. Compared to
|
||||
Genode's regular development tools, which were designed for whole-system
|
||||
development, the new tool called Goa relieves the developer from the
|
||||
complexity of Genode's custom build system and instead promotes the use of
|
||||
popular commodity solutions like CMake.
|
||||
|
||||
These and more topics are described in the
|
||||
[https:/documentation/release-notes/19.11 - release documentation of version 19.11...]
|
||||
|
||||
|
||||
Genode OS Framework release 19.08 | 2019-08-28
|
||||
##############################################
|
||||
|
||||
|
||||
@@ -143,8 +143,8 @@ corresponds to Shift, '<mod2>' to Control, '<mod3>' to AltGr, and '<mod4>' to
|
||||
Caps Lock.
|
||||
|
||||
! <mod1> <key name="KEY_LEFTSHIFT"/> <key name="KEY_RIGHTSHIFT"/> </mod1>
|
||||
! <mod2> <key name="KEY_LEFTCTRL"/> <key name="KEY_RIGHTCTRL"/> </mod4>
|
||||
! <mod3> <key name="KEY_RIGHTALT"/> </mod4> <!-- AltGr -->
|
||||
! <mod2> <key name="KEY_LEFTCTRL"/> <key name="KEY_RIGHTCTRL"/> </mod2>
|
||||
! <mod3> <key name="KEY_RIGHTALT"/> </mod3> <!-- AltGr -->
|
||||
! <mod4> <rom name="capslock"/> </mod4>
|
||||
|
||||
As outlined above, the '<key>' nodes generated by xkb2ifcfg always use the
|
||||
|
||||
815
doc/release_notes-19-11.txt
Normal file
815
doc/release_notes-19-11.txt
Normal file
@@ -0,0 +1,815 @@
|
||||
|
||||
|
||||
===============================================
|
||||
Release notes for the Genode OS Framework 19.11
|
||||
===============================================
|
||||
|
||||
Genode Labs
|
||||
|
||||
|
||||
|
||||
On our [https://genode.org/about/road-map - road map] for this year, we stated
|
||||
"bridging worlds" as our guiding theme of 2019. The current release pays
|
||||
tribute to this ambition on several accounts.
|
||||
|
||||
First, acknowledging the role of POSIX in the real world outside the heavens
|
||||
of Genode, the release vastly improves our (optional) C runtime with respect
|
||||
to the emulation of POSIX signals, execve, and ioctl calls. With the line of
|
||||
work described in Section [C runtime with improved POSIX compatibility], we
|
||||
hope to greatly reduce the friction when porting and hosting existing
|
||||
application software directly on Genode.
|
||||
|
||||
Second, we identified the process of porting or developing application
|
||||
software worth improving. Our existing tools were primarily geared to
|
||||
operating-system development, not application development. Application
|
||||
developers demand different work flows and tools, including the freedom to use
|
||||
a build system of their choice.
|
||||
Section [New tooling for bridging existing build systems with Genode]
|
||||
introduces our new take on this productivity issue.
|
||||
|
||||
Third, in cases where the porting of software to Genode is considered
|
||||
infeasible, virtualization comes to the rescue. With the current release, a
|
||||
new virtual machine monitor for the 64-bit ARM architecture enters the
|
||||
framework. It is presented in Section [Virtualization of 64-bit ARM platforms].
|
||||
|
||||
As another goal for 2019, we envisioned a solution for block-level device
|
||||
encryption, which is a highly anticipated feature among Genode users. We are
|
||||
proud to present the preliminary result of our year-long development in
|
||||
Section [Preliminary block-device encrypter].
|
||||
|
||||
|
||||
Preliminary block-device encrypter
|
||||
##################################
|
||||
|
||||
Over the past year, we worked on implementing a block-device encryption
|
||||
component that makes use of the
|
||||
[https://en.wikipedia.org/wiki/SPARK_(programming_language) - SPARK]
|
||||
programming language for its core logic. In contrast to common
|
||||
block-device encryption techniques where normally is little done besides
|
||||
the encryption of the on-disk blocks, the _consistent block encrypter (CBE)_
|
||||
aims for more. It combines multiple techniques to ensure integrity -
|
||||
the detection of unauthorized modifications of the block-device -
|
||||
and robustness against data loss. Robustness is achieved by keeping snapshots
|
||||
of old states of the device that remain unaffected by the further operation of
|
||||
the device. A copy-on-write mechanism (only the differential changes to the
|
||||
last snapshot are stored) is employed to maintain this snapshot history with
|
||||
low overhead. To be able to access all states of the device in the same manner,
|
||||
some kind of translation from virtual blocks to blocks on the device is needed.
|
||||
Hash-trees, where each node contains the hash of its sub-nodes, combine the
|
||||
aspect of translating blocks and ensuring their integrity in an elegant way.
|
||||
During the tree traversal, the computed hash of each node can be easily checked
|
||||
against the hash stored in the parent node.
|
||||
|
||||
The CBE does not perform any cryptography by itself but delegates
|
||||
cryptographic operations to another entity. It neither knows nor cares about
|
||||
the used algorithm. Of all the nodes in the virtual block device (VBD), only
|
||||
the leaf nodes, which contain the data, are encrypted. All other nodes, which
|
||||
only contain meta-data, are stored unencrypted.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
As depicted in Figure [cbe_trees], all information describing the various
|
||||
parts of the CBE is stored in the superblock. The referenced VBD is a set of
|
||||
several hash trees, each representing a certain device state including the
|
||||
current working state. Only the tree of the current working state is used to
|
||||
write data to the block device. All other trees represent snapshots of older
|
||||
states and are immutable. Each stored device state has a generation number
|
||||
that provides the chronological order of the states.
|
||||
|
||||
As you can see, in the depicted situation, there exist four device states - the
|
||||
snapshot with generation 3 is the oldest, followed by two newer snapshots and
|
||||
generation 6 that marks the working state of the virtual device. The tree with
|
||||
generation 6 is the current working tree. Each tree contains all changes done
|
||||
to the VBD since the previous generation (for generation 6 the red nodes). All
|
||||
parts of a tree that didn't change since the previous generation are references
|
||||
into older trees (for generation 6 the gray nodes). Note that in the picture,
|
||||
nodes that are not relevant for generation 6 are omitted to keep it manageable.
|
||||
The actual data blocks of the virtual device are the leaf nodes of the trees,
|
||||
shown as squares.
|
||||
|
||||
[image cbe_trees]
|
||||
|
||||
Whenever a block request from the client would override data blocks in
|
||||
generation 6 that are still referenced from an older generation, new blocks for
|
||||
storing the changes are needed. Here is where the so-called _Free Tree_ enters
|
||||
the picture. This tree contains and manages the spare blocks. Spare blocks are
|
||||
a certain amount of blocks that the CBE has in addition to the number of blocks
|
||||
needed for initializing the virtual device. So, after having initialized a
|
||||
virtual device, they remain unused and are only referenced by the Free Tree.
|
||||
Therefore, in case the VBD needs new blocks, it consults the Free Tree (red
|
||||
arrow).
|
||||
|
||||
In the depicted situation, writing the first data block (red square) would
|
||||
require allocating 4 new blocks as all nodes in the branch leading to the
|
||||
corresponding leaf node - including the leaf node itself - have to be written.
|
||||
In contrast, writing the second data block would require allocating only one
|
||||
new block as the inner nodes (red circles) now already exist. Subsequent write
|
||||
requests affecting only the new blocks will not trigger further block
|
||||
allocations because they still belong to the current generation and will be
|
||||
changed in-place. To make them immutable we have to create a new snapshot.
|
||||
|
||||
The blocks in generation 5 that were replaced by the change to generation 6
|
||||
(blue nodes) are not needed for the working state of the virtual device
|
||||
anymore. They are therefore, in exchange for the allocated blocks, added to
|
||||
the Free Tree. But don't be fooled by the name, they are not free for
|
||||
allocation yet, but marked as "reserved" only. This means, they are
|
||||
potentially still part of a snapshot (as is the case in our example) but the
|
||||
Free Tree shall keep checking, because once all snapshots that referenced the
|
||||
blue blocks have disappeared, they become free blocks and can be allocated
|
||||
again.
|
||||
|
||||
To create a new snapshot, we first have to make all changes done to the VBDs
|
||||
working state as well as the Free Tree persistent by writing all corresponding
|
||||
blocks to the block-device. After that, the new superblock state is written to
|
||||
the block-device. To safeguard this operation, the CBE always maintains several
|
||||
older states of the superblock on the block device. In case writing the new
|
||||
state of the superblock fails, the CBE could fall back to the last state that,
|
||||
in our example, would contain only generations 3, 4, and 5. Finally, the
|
||||
current generation of the superblock in RAM is incremented by one (in the
|
||||
example to generation 7). Thereby, generation 6 becomes immutable.
|
||||
|
||||
A question that remains is when to create snapshots. Triggering a snapshot
|
||||
according to some heuristics inside the CBE might result in unnecessary
|
||||
overhead. For instance, the inner nodes of the tree change frequently during a
|
||||
sequential operation. We might not want them to be re-allocated all the time.
|
||||
Therefore, the creation of a snapshot must be triggered explicitly from the
|
||||
outside world. This way, we can accommodate different strategies, for
|
||||
instance, client-triggered, time-based, or based on the amount of data
|
||||
written.
|
||||
|
||||
When creating a snapshot, it can be specified whether it shall be disposable
|
||||
or persistent. A disposable snapshot will be removed automatically by the CBE
|
||||
in two situations, either
|
||||
|
||||
* When there are not enough usable nodes in the Free Tree left to
|
||||
satisfy a write request, or
|
||||
* When creating a new snapshot and all slots in the superblock that might
|
||||
reference snapshots are already occupied.
|
||||
|
||||
A persistent snapshot, or quarantine snapshot, on the other hand will never be
|
||||
removed automatically. Its removal must be requested explicitly.
|
||||
|
||||
During initialization, the CBE selects the most recent superblock and reads the
|
||||
last generation value from it. The current generation (or working state
|
||||
generation) is then set to the value incremented by one. Since all old blocks,
|
||||
that are still referenced by a snapshot, are never changed again, overall
|
||||
consistency is guaranteed for every generation whose superblock was stored
|
||||
safely on disk.
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
Although we aimed for a SPARK implementation of the CBE, we saw several
|
||||
obstacles with developing it in SPARK right from the beginning. These obstacles
|
||||
mainly came from the fact that none of us was experienced in designing
|
||||
complex software in SPARK. So we started by conducting a rapid design-space
|
||||
exploration using our mother tongue (C++) while using only language features
|
||||
that can be mapped 1:1 to SPARK concepts. Additionally, we applied a clear
|
||||
design methodology that allowed us to keep implementation-to-test cycles
|
||||
small and perform a seamless and gradual translation into SPARK:
|
||||
|
||||
* _Control flow_
|
||||
|
||||
The core logic of the CBE is a big state machine that doesn't block. On each
|
||||
external event, the state machine gets poked to update itself accordingly.
|
||||
C++ can call SPARK but SPARK never calls C++. The SPARK code therefore
|
||||
evolves as self-contained library.
|
||||
|
||||
* _Modularity_
|
||||
|
||||
The complex state machine of the CBE as a whole is split-up into smaller
|
||||
manageable sub-state-machines, working independently from each other. These
|
||||
modules don't call each other directly. Instead, an additional superior
|
||||
module handles the interplay. This is done by constantly iterating over all
|
||||
modules with the following procedure until no further progress can be made:
|
||||
|
||||
# Try to enter requests of other modules into the current one
|
||||
# Poke the state machine of the current module
|
||||
# The current module may have generated requests - Try to enter them into
|
||||
the targeted modules
|
||||
# The current module may have finished requests - Acknowledge them at the
|
||||
modules they came from
|
||||
|
||||
Each module is represented through a class (C++) respectively a package with
|
||||
a private state record (SPARK).
|
||||
|
||||
* _No global state_
|
||||
|
||||
There are no static (C++) or package (SPARK) variables. All state is kept in
|
||||
members of objects (C++) respectively records (SPARK). All packages are pure
|
||||
and sub-programs have no side-effects. Therefore, memory management and
|
||||
communication with other components is left to OS glue-code outside the
|
||||
core logic.
|
||||
|
||||
This approach worked out well. Module by module, we were able to translate the
|
||||
C++ prototype to SPARK without long untested phases, rendering all regression
|
||||
bugs manageable. In Genode, the CBE library is currently integrated through
|
||||
the CBE-VFS plugin. Figure [cbe_modules] depicts its current structure and the
|
||||
integration via VFS plugin.
|
||||
|
||||
[image cbe_modules]
|
||||
|
||||
The green and blue boxes each represent an Ada/SPARK package. The translation
|
||||
to SPARK started at the bottom of the picture moving up to the more abstract
|
||||
levels until it reached the Library module. This is the module that handles
|
||||
the interplay of all other modules. Its interface is the front end of the CBE
|
||||
library. So, all green packages are now completely written in SPARK and
|
||||
together form the CBE library. Positioned above, the CXX library in blue is
|
||||
brought in by a separate library and exports the CBE interface to C++. This
|
||||
way, the CBE can also be used in other environments including pure SPARK
|
||||
programs. The CXX Library package is not written in SPARK but Ada and performs
|
||||
all the conversions and checks required to meet the preconditions set by the
|
||||
SPARK packages below.
|
||||
|
||||
At the C++ side, we have the VFS plugin. Even at this level, the already
|
||||
mentioned procedure applies: The plugin continuously tries to enter requests
|
||||
coming from the VFS client (above) into the CBE (below), pokes the CBE state
|
||||
machine, and puts thereby generated block/crypto requests of the CBE into the
|
||||
corresponding back-ends (left). This process is repeated until there is no
|
||||
further progress without waiting for an external event.
|
||||
|
||||
Current state
|
||||
-------------
|
||||
|
||||
In its current state, the CBE library is still pretty much in flux and is not
|
||||
meant for productive use.
|
||||
|
||||
As the Free Tree does not employ copy-on-write semantics for its meta-data, a
|
||||
crash, software- or hardware-wise, will corrupt the tree structure and renders
|
||||
the CBE unusable on the next start.
|
||||
|
||||
This issue is subject to ongoing work. That being said, there are
|
||||
components that, besides being used for testing, show how the interface of the
|
||||
CBE library lends itself to be integrated in components in different ways. At
|
||||
the moment, there are two components making use of the CBE library as
|
||||
block-device provider.
|
||||
|
||||
The first one is the aforementioned CBE-VFS plugin. Besides r/w access to the
|
||||
working tree and r/o access to all persistent snapshots, it also provides a
|
||||
management interface where persistent snapshots can be created or discarded.
|
||||
Its current layout is illustrated by Figure [cbe_vfs]. The VFS plugin
|
||||
generates three top directories in its root directory. The first one is the
|
||||
_control_ directory. It contains several pseudo files for managing the CBE:
|
||||
|
||||
[image cbe_vfs]
|
||||
|
||||
:'key': set a key by writing a string into the file.
|
||||
:'create_snapshot': writing 'true' to this file will attempt to create
|
||||
a new snapshot. (Eventually the snapshot will
|
||||
appear in the 'snapshots' directory if it could be
|
||||
created successfully.)
|
||||
:'discard_snapshot': writing a snapshot ID into this file will discard
|
||||
the snapshot
|
||||
|
||||
The second is the 'current' directory. It gives access to the current
|
||||
working tree of the CBE and contains the following file:
|
||||
|
||||
:'data': this file represents the virtual block device and gives
|
||||
read and write access to the data stored by the CBE.
|
||||
|
||||
The third and last is the 'snapshots' directory. For each persistent snapshot,
|
||||
there is a sub-directory named after the ID of the snapshot. This directory,
|
||||
like the 'current' directory, contains a 'data' file. This file, however,
|
||||
gives only read access to the data belonging to the snapshot.
|
||||
|
||||
The CBE-VFS plugin itself uses the VFS to access the underlying block device.
|
||||
It utilizes the file specified in its configuration. Here is a '<vfs>'
|
||||
snippet that shows a configured CBE-VFS plugin where the block device is
|
||||
provided by the block VFS plugin.
|
||||
|
||||
! <vfs>
|
||||
! <dir name="dev">
|
||||
! <block name="block"/>
|
||||
! <cbe name="cbe" block="/dev/block"/>
|
||||
! </dir>
|
||||
! </vfs>
|
||||
|
||||
An exemplary ready-to-use run script can be found in the CBE repository
|
||||
at _run/cbe_vfs_snaps.run_. This run script uses a bash script to
|
||||
automatically perform a few operations on the CBE using the VFS plugin.
|
||||
Afterwards it will drop the user into a shell where further operations
|
||||
can be performed manually, e.g.:
|
||||
|
||||
! dd if=/dev/zero of=/dev/cbe/current/data bs=4K
|
||||
|
||||
The second component is the CBE server. In contrast to the CBE-VFS plugin,
|
||||
it is just a simple block-session proxy component that uses a block connection
|
||||
as back end to access a block-device. It provides a front-end block session to
|
||||
its client, creates disposable snapshots every few seconds, and uses the
|
||||
'External_Crypto' library to encrypt the data blocks using AES-CBC-ESSIV. The
|
||||
used key is a plain passphrase. The following snippet illustrates its
|
||||
configuration:
|
||||
|
||||
! <start name="cbe">
|
||||
! <resource name="RAM" quantum="4M"/>
|
||||
! <provides><service name="Block"/></provides>
|
||||
! <config sync_interval="5" passphrase="All your base are belong to us"/>
|
||||
! </start>
|
||||
|
||||
The _run/cbe.run_ run script in the CBE repository showcases the use of the
|
||||
CBE server.
|
||||
|
||||
Both run scripts will create the initial CBE state in a RAM-backed
|
||||
block device that is then accessed by the CBE server or the CBE-VFS
|
||||
plugin.
|
||||
|
||||
The run-script and the code itself can be found on the
|
||||
[https://github.com/cnuke/cbe/tree/cbe_19.11 - cbe/cbe_19.11] branch on
|
||||
GitHub. If you intend to try it out, you have to checkout
|
||||
the corresponding
|
||||
[https://github.com/cnuke/genode/tree/cbe_19.11 - genode/cbe_19.11]
|
||||
branch in the Genode repository as well.
|
||||
|
||||
Future plans
|
||||
------------
|
||||
|
||||
Besides addressing the current shortcomings and getting the CBE library
|
||||
production-ready so that it can be used in Sculpt, there are still
|
||||
a few features that are currently unimplemented. For one we would like
|
||||
to add support for making it possible to resize the VBD as well as the
|
||||
Free Tree. For now the geometry is fixed at initialization time and cannot
|
||||
be changed afterwards. Furthermore, we would like to enable re-keying,
|
||||
i.e., changing the used cryptographic key and re-encrypting the tree
|
||||
set of the VBD afterwards. In addition to implementing those features, the
|
||||
overall tooling for the CBE needs to be improved. E.g., there is currently
|
||||
no proper initialization component. For now, we rely on a component
|
||||
that was built merely as a test vehicle to generate the initial trees.
|
||||
|
||||
|
||||
Virtualization of 64-bit ARM platforms
|
||||
######################################
|
||||
|
||||
Genode has a long history regarding support of all kinds of
|
||||
virtualization-related techniques including
|
||||
[https://genode.org/documentation/release-notes/9.11#Paravirtualized_Linux_on_Genode_OKL4 - para-virtualization],
|
||||
[https://genode.org/documentation/articles/trustzone - TrustZone],
|
||||
hardware-assisted virtualization on
|
||||
[https://genode.org/documentation/articles/arm_virtualization - ARM],
|
||||
[https://genode.org/documentation/release-notes/13.02#Full_virtualization_on_NOVA_x86 - x86],
|
||||
up to the full virtualization stack of
|
||||
[https://genode.org/documentation/release-notes/14.02#VirtualBox_on_top_of_the_NOVA_microhypervisor - VirtualBox].
|
||||
|
||||
We regard those techniques as welcome stop-gap solutions for using non-trivial
|
||||
existing software stacks on top of Genode's clean-slate OS architecture. The
|
||||
[https://genode.org/documentation/release-notes/19.05#Kernel-agnostic_virtual-machine_monitors - recent]
|
||||
introduction of a kernel-agnostic interface to control virtual machines (VM)
|
||||
ushered a new level for the construction respectively porting of
|
||||
virtual-machine monitors (VMM). By introducing a new ARMv8-compliant VMM
|
||||
developed from scratch, we continue this line of work.
|
||||
|
||||
The new VMM builds upon our existing proof-of-concept (PoC) implementation for
|
||||
ARMv7 as introduced in release
|
||||
[https://genode.org/documentation/release-notes/15.02#Virtualization_on_ARM - 15.02].
|
||||
In contrast to the former PoC implementation, however, it aims to be complete
|
||||
to a greater extent. Currently, it comprises device models for the following
|
||||
virtual hardware:
|
||||
|
||||
* RAM
|
||||
* System Bus
|
||||
* CPU
|
||||
* Generic Interrupt Controller v2 and v3
|
||||
* Generic Timer
|
||||
* PL011 UART (limited)
|
||||
* Pass-through devices
|
||||
|
||||
The VMM is able to load diverse 64-bit Linux kernels including
|
||||
Device-Tree-Binary (DTB) and Initramfs. Currently, the implementation uses a
|
||||
fixed memory layout for the guest-physical memory view, which needs to be
|
||||
reflected by the DTB used by the guest OS. An example device-tree source file
|
||||
can be found at _repos/os/src/server/vmm/spec/arm_v8/virt.dts_. The actual VMM
|
||||
is located in the same directory.
|
||||
|
||||
Although support for multi-core VMs is already considered internally, it is
|
||||
not yet finished. Further outstanding features that are already in development
|
||||
are Virtio device model support for networking and console. As the first - and
|
||||
by now only - back end, we tied the VMM to the ARMv8 broadened Kernel-agnostic
|
||||
VM-session interface as implemented by Genode's custom base-hw kernel. As a
|
||||
side effect of this work, we consolidated the generic VM session interface
|
||||
slightly. The RPC call to create a new virtual-CPU now returns an identifier
|
||||
for identification.
|
||||
|
||||
The VMM has a strict dependency on ARM's hardware virtualization support
|
||||
(EL2), which comprises extensions for the ARMv8-A CPU, ARM's generic timer,
|
||||
and ARM's GIC. This rules out the Raspberry Pi 3 board as a base platform
|
||||
because it does not include a GIC but a custom interrupt-controller without
|
||||
hardware-assisted virtualization of interrupts. To give the new VMM a try, we
|
||||
recommend using the run script _repos/os/run/vmm_arm.run_ as a starting point
|
||||
for executing the VMM on top of the i.MX8 Evaluation Kit board.
|
||||
|
||||
|
||||
New tooling for bridging existing build systems with Genode
|
||||
###########################################################
|
||||
|
||||
Genode's development tools are powerful and intimidating at the same time.
|
||||
Being designed from the perspective of a whole-systems developer, they put
|
||||
emphasis on the modularity of the code base (separating concerns like
|
||||
different kernels or system abstraction levels), transitive dependency
|
||||
tracking between libraries, scripting of a wide variety of system-integration
|
||||
tasks, and the continuous integration of complete Genode-based
|
||||
operating-system scenarios. Those tools are a two-edged sword though.
|
||||
|
||||
On the one hand, the tools are key for the productivity of seasoned Genode
|
||||
developers once the potential of the tools is fully understood and leveraged.
|
||||
For example, during the development of Sculpt OS, we are able to
|
||||
change an arbitrary line of code in any system component and can test-drive
|
||||
the resulting Sculpt system on real hardware within a couple of seconds.
|
||||
As another example, the almost seamless switching from one OS kernel to
|
||||
another has become a daily routine that we just take for granted without
|
||||
even thinking about it.
|
||||
|
||||
On the other hand, the sophistication of the tools stands in the way of
|
||||
application developers who are focused on a particular component instead
|
||||
of the holistic Genode system. In this case, the powerful system-integration
|
||||
features remain unused but the complexity of the tools and the build system
|
||||
prevails. Speaking of build systems, this topic is ripe of emotions
|
||||
anyway. _Developers use to hate build systems._ Forcing Genode's build
|
||||
system down the throats of application developers is probably not the best
|
||||
idea to make Genode popular.
|
||||
|
||||
This line of thoughts prompted us to re-approach the tooling for Genode from
|
||||
the perspective of an application developer. The intermediate result is a new
|
||||
tool called Goa:
|
||||
|
||||
:Goa project at GitHub:
|
||||
|
||||
[https://github.com/nfeske/goa]
|
||||
|
||||
Unlike Genode's regular tools, Goa's work flow is project-centered. A project
|
||||
is a directory that may contain source code, data, instructions how to
|
||||
download source codes from a 3rd party, descriptions of system scenarios, or
|
||||
combinations thereof. Goa is independent from Genode's regular build system.
|
||||
It combines Genode's package management (depot) with commodity build systems
|
||||
such a CMake. In addition to building and test-driving application software
|
||||
directly on a Linux-based development system, Goa is able to aid the process
|
||||
of exporting and packaging the software in the format expected by Genode
|
||||
systems like Sculpt OS.
|
||||
|
||||
At the current stage, Goa should be considered as work in progress. It's a new
|
||||
approach and its success is anything but proven. That said, if you are
|
||||
interested in developing or porting application software for Genode, your
|
||||
feedback would be especially valuable. As a starting point, you may find the
|
||||
following introductory article helpful:
|
||||
|
||||
:Goa - streamlining the development of Genode applications:
|
||||
|
||||
[https://genodians.org/nfeske/2019-11-25-goa]
|
||||
|
||||
|
||||
Base framework and OS-level infrastructure
|
||||
##########################################
|
||||
|
||||
File-system session
|
||||
===================
|
||||
|
||||
The file-system session interface received a much anticipated update.
|
||||
|
||||
Writing modification times
|
||||
--------------------------
|
||||
|
||||
The new operation WRITE_TIMESTAMP allows a client to update the modification
|
||||
time of a file-system node. The time is defined by the client to keep
|
||||
file-system servers free from time-related concerns. The VFS server implements
|
||||
the operation by forwarding it to the VFS plugin interface. At present, this
|
||||
new interface is implemented by the rump VFS plugin to store modification
|
||||
times on EXT2 file systems.
|
||||
|
||||
|
||||
Enhanced file-status info
|
||||
-------------------------
|
||||
|
||||
The status of a file-system node as returned by the 'File_system::Status'
|
||||
operation has been revisited. First, we replaced the fairly opaque "mode" bits -
|
||||
which were an ad-hoc attempt to stay compatible with Unix - with the explicit
|
||||
notion of 'readable', 'writeable', and 'executable' attributes. We completely
|
||||
dropped the notion of users and groups. Second, we added the distinction
|
||||
between *continuous* and *transactional* files to allow for the robust
|
||||
implementation of continuous write operations across component boundaries. A
|
||||
continuous file can be written-to via a sequence of arbitrarily sized chunks
|
||||
of data. For such files, a client can split a large write operation into any
|
||||
number of smaller operations in accordance to the size of the used I/O
|
||||
buffers. In contrast, a write to a transactional file is regarded as a
|
||||
distinct operation. The canonical example of a transactional file is a
|
||||
socket-control pseudo file.
|
||||
|
||||
|
||||
Virtual file-system infrastructure
|
||||
==================================
|
||||
|
||||
First fragments of a front-end API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The VFS is mostly used indirectly via the C runtime. However, it is also
|
||||
useful for a few components that use the Genode API directly without any
|
||||
libc. To accommodate such users of the VFS, we introduced the front-end
|
||||
API at _os/vfs.h_ that covers a variety of current use cases. Currently, those
|
||||
use cases revolve around the watching, reading, and parsing of files and
|
||||
file-system structures - as performed by Sculpt's deployment mechanism.
|
||||
Writing to files is not covered.
|
||||
|
||||
|
||||
Improved file-watching support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All pseudo files that use the VFS-internal 'Readonly_value_file_system'
|
||||
utility have become able to deliver watch notifications. This change enables
|
||||
VFS clients to respond to VFS-plugin events (think of terminal resize)
|
||||
dynamically.
|
||||
|
||||
Speaking of the *terminal VFS plugin*, the current release enhances the plugin
|
||||
in several respects. First, it now delivers status information such as the
|
||||
terminal size via pseudo files. Second, we equipped the VFS terminal file
|
||||
system with the ability to detect user interrupts in the incoming data stream,
|
||||
and propagate this information via the new pseudo file '.terminal/interrupts'.
|
||||
Each time, the user presses control-c in the terminal, the value stored in
|
||||
this pseudo file is increased. Thereby, a VFS client can watch this file to
|
||||
get notified about the occurrences of user interrupts.
|
||||
|
||||
|
||||
VFS plugin for emulating POSIX pipes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We added a new VFS plugin for emulating POSIX pipes. The new plugin creates
|
||||
pipes between pairs of VFS handles. It replaces the deprecated libc_pipe
|
||||
plugin. In contrast to the libc_pipe plugin, which was limited to pipes within
|
||||
one component, the new VFS plugin can also be used to establish pipes between
|
||||
different components by mounting the plugin at a shared VFS server.
|
||||
|
||||
|
||||
C runtime with improved POSIX compatibility
|
||||
===========================================
|
||||
|
||||
Within Genode, we used to think of POSIX as a legacy that is best avoided.
|
||||
In fact, the foundational components of the framework do not depend on a
|
||||
C runtime at all. However, higher up the software stack - at the latest when
|
||||
3rd-party libraries enter the picture - a working C runtime is unavoidable. In
|
||||
this statement, the term "working" is rather muddy though. Since we have never
|
||||
fully embraced POSIX, we were content with cutting corners here and there. For
|
||||
example, given Genode's architecture, supporting 'fork' and 'execve' seemed
|
||||
totally out of question because those mechanisms would go against the grain of
|
||||
Genode.
|
||||
|
||||
However, our growing aspiration to bridge the gap between existing popular
|
||||
applications and Genode made us re-evaluate our stance towards POSIX.
|
||||
All technical criticism aside, POSIX is immensely useful because it is
|
||||
a universally accepted stable interface. To dissolve friction between
|
||||
Genode and popular application software, we have to satisfy the application's
|
||||
expectations. This ignited a series of developments, in particular
|
||||
the added support for 'fork' and 'execve' - of all things - in
|
||||
[https://genode.org/documentation/release-notes/19.08#Consolidation_of_the_C_runtime_and_Noux - Genode 19.08],
|
||||
which was nothing short of surprising, even to us.
|
||||
The current release continues this line of development and brings the
|
||||
following improvements.
|
||||
|
||||
|
||||
Execve
|
||||
------
|
||||
|
||||
The libc's 'execve' implementation got enhanced to evaluate the path of the
|
||||
executable binary according to the information found on the VFS, in particular
|
||||
by traversing directories and following symbolic links. This enables the libc
|
||||
to execute files stored at sub directories of the file system.
|
||||
|
||||
Furthermore, 'execve' received handling for *executing shell scripts* by
|
||||
parsing the shebang marker at the beginning of the executable file. This way,
|
||||
the 'execve' mechanism of the libc reaches parity with the feature set of the
|
||||
Noux runtime that we traditionally used to host Unix software on top of
|
||||
Genode.
|
||||
|
||||
|
||||
Modification-time handling
|
||||
--------------------------
|
||||
|
||||
By default, the libc uses the just added facility for updating the timestamp
|
||||
of file-system nodes when closing a written-to file, which clears the path
|
||||
towards using tools like 'make' that rely on file-modifications times.
|
||||
|
||||
The libc's mechanism can be explicitly disabled by specifying
|
||||
! <libc update_mtime="no"...>
|
||||
This is useful for applications that have no legitimate access to a time
|
||||
source.
|
||||
|
||||
|
||||
Emulation of 'ioctl' operations via pseudo files
|
||||
------------------------------------------------
|
||||
|
||||
With the current release, we introduce a new scheme of handling ioctl
|
||||
operations, which maps 'ioctl' calls to pseudo-file accesses, similar to how
|
||||
the libc already maps socket calls to socket-fs operations.
|
||||
|
||||
A device file can be accompanied with a (hidden) directory that is named after
|
||||
the device file and hosts pseudo files for triggering the various device
|
||||
operations. For example, for accessing a terminal, the directory structure
|
||||
looks like this:
|
||||
|
||||
! /dev/terminal
|
||||
! /dev/.terminal/info
|
||||
! /dev/.terminal/rows
|
||||
! /dev/.terminal/columns
|
||||
! /dev/.terminal/interrupts
|
||||
|
||||
The 'info' file contains device information in XML format. The type of the XML
|
||||
node corresponds to the device type. Whenever the libc receives a TIOCGWINSZ
|
||||
ioctl for _/dev/terminal_, it reads the content of _/dev/.terminal/info_ to
|
||||
obtain the terminal-size information. In this case, the _info_ file looks as
|
||||
follows:
|
||||
|
||||
! <terminal rows="25" columns="80/>
|
||||
|
||||
Following this scheme, VFS plugins can support ioctl operations by providing
|
||||
an ioctl directory in addition to the actual device file.
|
||||
|
||||
|
||||
Emulation of POSIX signals
|
||||
--------------------------
|
||||
|
||||
Even though there is no notion of POSIX signals at the Genode level, we
|
||||
can reasonably emulate certain POSIX signals at the libc level. The current
|
||||
release introduces the first bunch of such emulated signals:
|
||||
|
||||
:SIGWINCH: If 'stdout' is connected to a terminal, the libc watches the
|
||||
terminal's ioctl pseudo file _.terminal/info_. Whenever the terminal
|
||||
size changes, the POSIX signal SIGWINCH is delivered to the application.
|
||||
With this improvement, Vim becomes able to dynamically adjust itself
|
||||
to changed window dimensions when started as a native Genode component
|
||||
(w/o the Noux runtime environment).
|
||||
|
||||
:SIGINT: If 'stdin' is connected to a terminal, the libc watches the
|
||||
terminal's pseudo file _.terminal/interrupts_. Since, the terminal VFS
|
||||
plugin modifies the file for each occurred user interrupt (control-c),
|
||||
the libc is able to reflect such an event as SIGINT signal to the
|
||||
application.
|
||||
|
||||
:Process-local signal delivery: The libc's implementation of 'kill' got
|
||||
enhanced with the ability to submit signals to the local process.
|
||||
|
||||
|
||||
Support for arbitrarily large write operations
|
||||
----------------------------------------------
|
||||
|
||||
The number of bytes written by a single 'write' call used to be constrained by
|
||||
the file's underlying I/O buffer size. Even though our libc correctly returned
|
||||
this information to the application, we found that real-world applications
|
||||
rarely check the return value of 'write' because partial writes do usually not
|
||||
occur on popular POSIX systems. Thanks to the added distinction between
|
||||
continuous and transactional files as described in Section
|
||||
[File-system session], we became able to improve the libc's write operation to
|
||||
iterate on partial writes to continuous files until the original write count
|
||||
is reached. The split of large write operations into small partial writes as
|
||||
dictated by the VFS infrastructure becomes invisible to the libc-using
|
||||
application.
|
||||
|
||||
|
||||
Input-event handling
|
||||
====================
|
||||
|
||||
In Genode 19.08, we undertook a comprehensive rework of our keyboard-event
|
||||
handling in the light of localization and also promised to tie up remaining
|
||||
loose ends soon.
|
||||
|
||||
First, we again dived into our character generators for a thorough check of
|
||||
our stack of keyboards and fixed remaining inconsistencies in French and
|
||||
German layouts. En passant, we also increased the default RAM quotas for
|
||||
the input filter to 1280K in our recipes to cope with the increased
|
||||
layout-configuration sizes in corner cases.
|
||||
|
||||
Next - and more importantly - we subdued the monsters lurking in our Qt5
|
||||
keyboard back end and enabled transparent support for system-wide keyboard
|
||||
layout configuration for Qt5 components. One important change during this work
|
||||
was to move the handling of control key sequences into the clients. For
|
||||
example, the graphical terminal and Qt5 interpret key events in combination
|
||||
with the CTRL modifier based on characters and, thus, support CTRL-A with
|
||||
AZERTY and QWERTY layouts correctly. As a result we removed all CTRL modifier
|
||||
(mod2) configurations from our character-generator configurations.
|
||||
|
||||
Finally we'd like to point out one important change of our rework that
|
||||
repeatedly led to surprises: For keys without character mappings the reworked
|
||||
character-generator mechanism emits invalid codepoints in contrast to
|
||||
codepoints with value 0. For that reason, components interpreting character
|
||||
events should check 'Codepoint::valid()' to prevent the processing of invalid
|
||||
characters (and not the frequent pattern of 'codepoint.value != 0').
|
||||
|
||||
|
||||
NIC router
|
||||
==========
|
||||
|
||||
The NIC router has received the ability to report the link state of its NIC
|
||||
interfaces (downlinks and uplinks). To control this mechanism, there are two
|
||||
new boolean attributes 'link_state' and 'link_state_triggers' in the <report>
|
||||
tag of the NIC router configuration. If the former is set to "true", the report
|
||||
will contain the current link state for each interface:
|
||||
|
||||
! <domain name="domain1">
|
||||
! <interface label="uplink1" link_state="false"/>
|
||||
! <interface label="downlink1" link_state="true"/>
|
||||
! </domain>
|
||||
! <domain name="domain2">
|
||||
! <interface label="downlink2" link_state="true"/>
|
||||
! </domain>
|
||||
|
||||
The second attribute decides whether to trigger a report update each time the
|
||||
link state of an interface changes. By default, both attributes are set to
|
||||
"false".
|
||||
|
||||
|
||||
Device drivers
|
||||
==============
|
||||
|
||||
Platform driver on x86
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
During our enablement of Genode on a
|
||||
[https://genodians.org/chelmuth/2019-10-21-sculpt-elitebook - recent notebook],
|
||||
we spotted some PC platform shortcomings, we address with this release. Most
|
||||
prominently we added support for
|
||||
[https://en.wikipedia.org/wiki/PCI_configuration_space#Bus_enumeration - 64-bit PCI base address registers]
|
||||
to the x86 platform driver. This allows the use of PCI devices that are
|
||||
assigned to physical I/O-memory regions beyond 4 GiB by the boot firmware.
|
||||
|
||||
|
||||
Wireless driver
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
We added the firmware images for the 5000 and 9000 series of Intel wireless
|
||||
devices to the firmware white-list in the _wifi_drv_ component. Such devices
|
||||
as 5100AGN, 5300AGN and 5350AGN as well as 9461, 9462 and 9560 should now be
|
||||
usable on Genode.
|
||||
|
||||
|
||||
Libraries and applications
|
||||
##########################
|
||||
|
||||
VirtualBox improvements
|
||||
=======================
|
||||
|
||||
The GUI handling of our VirtualBox port got improved to react on window-size
|
||||
changes more instantly. The effect is that an interactive adjustment of the
|
||||
window size, e.g., on Sculpt, becomes quickly visible to the user. Still, the
|
||||
VM may take some time to adjust to the resolution change, which ultimately
|
||||
depends on the behavior of the driver of the VirtualBox guest additions.
|
||||
|
||||
|
||||
Updated 3rd-party software
|
||||
==========================
|
||||
|
||||
With the addition of the 64-bit ARM architecture (AARCH64) with the
|
||||
[https://genode.org/documentation/release-notes/19.05#Broadened_CPU_architecture_support_and_updated_tool_chain - 19.05]
|
||||
release, it became necessary to update the libraries the Genode tool chain
|
||||
(gcc) depends on in order to support AARCH64 properly. This concerns the GNU
|
||||
multi precision arithmetic library (gmp), which has been updated from version
|
||||
4.3.2 to 6.1.2, as well as the libraries that depend on it: Multi precision
|
||||
floating point (mpfr) and multi precision complex arithmetic (mpc). All those
|
||||
old versions did not offer support for the AARCH64 architecture, which is a
|
||||
requirement to make Genode self hosting. Targets for building binutils and GCC
|
||||
within Genode for AARCH64 are in place, GNU make is in place, and even code
|
||||
coverage (gcov) has been added. This work puts AARCH64 in line with other
|
||||
supported CPU architectures and emphasizes our interest in the ARM 64-bit
|
||||
architecture.
|
||||
|
||||
|
||||
Platforms
|
||||
#########
|
||||
|
||||
Execution on bare hardware (base-hw)
|
||||
====================================
|
||||
|
||||
With the previous release, Genode's base-hw kernel got extended to support the
|
||||
ARMv8-A architecture in principle. The first hardware supported was the
|
||||
Raspberry Pi 3 as well as the i.MX8 evaluation kit (EVK). But only a single
|
||||
CPU-core was usable at that time. Now, we lifted this limitation. On both
|
||||
boards, all four CPU-cores are available henceforth.
|
||||
|
||||
|
||||
Removed components
|
||||
##################
|
||||
|
||||
The current release removes the following components:
|
||||
|
||||
:gems/src/app/launcher:
|
||||
|
||||
The graphical launcher remained unused for a few years now. It is not
|
||||
suitable for systems as flexible as Sculpt OS.
|
||||
|
||||
:os/src/app/cli_monitor:
|
||||
|
||||
CLI monitor was a runtime environment with a custom command-line interface
|
||||
to start and stop subsystems. It was part of the user interface of our
|
||||
first take on a Genode-based desktop OS called
|
||||
[https://genode.org/documentation/release-notes/15.11#Genode_as_desktop_OS - Turmvilla].
|
||||
|
||||
Nowadays, we use standard command-line tools like Vim to edit init
|
||||
configurations dynamically, which is more flexible and - at the same time -
|
||||
alleviates the need for a custom CLI. The CLI-monitor component was too
|
||||
limited for use cases like Sculpt anyway.
|
||||
|
||||
Along with the CLI monitor, we removed the ancient (and untested for long
|
||||
time) _terminal_mux.run_ script, which was the only remaining user of the CLI
|
||||
monitor.
|
||||
|
||||
:fatfs_fs, rump_fs, and libc_fatfs plugin:
|
||||
|
||||
The stand-alone file-system servers fatfs_fs and rump_fs as well as the
|
||||
fatfs libc plugin have been superseded by the fatfs and rump VFS plugins.
|
||||
The stand-alone servers can be replaced by using the VFS server plus the
|
||||
corresponding VFS plugin as a drop-in replacement.
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 87228cf07e72e871410818fa83bdeef44c9f5ef8
|
||||
2019-11-25 c7e2a3eca5820b2304b4520d0fc831ede73691f2
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 5b6cf80fc675be3f7432434e48f4f1548f55ef41
|
||||
2019-11-25 9a459c4fd8a907810d91041751affcf3e119fcb1
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 a867f84460323da4f69d8159ff21200e50a9a2fd
|
||||
2019-11-25 d8ff4913b8aa117aef77a7918bc82808e38a4ee7
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 e8b6d91bf19df090192d689a46f34570b43bc1bc
|
||||
2019-11-25 a750c8988106d5c26e46dcceb1f76bfd7bfa1457
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 07b6913f38716e380057df3212da94054a359bc8
|
||||
2019-11-25 0c0a26b6ddb0ee5261f0be30f229e9ce04b61eda
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 2f2313ed4479d13b9f3964db6f7ceaaf2c12320a
|
||||
2019-11-25 bce6f0a8f1f46f8edf62ef2180dbfc949123432d
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 b248520f85bcf3d1dbe68e23ca949f447cd78dbb
|
||||
2019-11-25 307d01e531dbbcd672463a4ea090f40bb399cae8
|
||||
|
||||
@@ -108,7 +108,7 @@ class Genode::Vm_session_component
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override;
|
||||
void attach_pic(addr_t) override { }
|
||||
void detach(addr_t, size_t) override;
|
||||
void _create_vcpu(Thread_capability);
|
||||
Vcpu_id _create_vcpu(Thread_capability);
|
||||
};
|
||||
|
||||
#endif /* _CORE__VM_SESSION_COMPONENT_H_ */
|
||||
|
||||
@@ -107,10 +107,12 @@ Vcpu::~Vcpu()
|
||||
_ram_alloc.free(_ds_cap);
|
||||
}
|
||||
|
||||
void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||
Vm_session::Vcpu_id Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||
{
|
||||
Vcpu_id ret;
|
||||
|
||||
if (!cap.valid())
|
||||
return;
|
||||
return ret;
|
||||
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread)
|
||||
@@ -146,10 +148,11 @@ void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||
}
|
||||
|
||||
_vcpus.insert(vcpu);
|
||||
_id_alloc++;
|
||||
ret.id = _id_alloc++;
|
||||
};
|
||||
|
||||
_ep.apply(cap, lambda);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Dataspace_capability Vm_session_component::_cpu_state(Vcpu_id const vcpu_id)
|
||||
|
||||
@@ -50,7 +50,6 @@ static bool svm_np() { return svm_features() & (1U << 0); }
|
||||
struct Vcpu;
|
||||
|
||||
static Genode::Registry<Genode::Registered<Vcpu> > vcpus;
|
||||
static unsigned vcpu_id = 0;
|
||||
|
||||
struct Vcpu : Genode::Thread
|
||||
{
|
||||
@@ -202,7 +201,7 @@ struct Vcpu : Genode::Thread
|
||||
Semaphore _wake_up { 0 };
|
||||
Semaphore &_handler_ready;
|
||||
Allocator &_alloc;
|
||||
Vm_session_client::Vcpu_id _id;
|
||||
Vm_session_client::Vcpu_id _id { Vm_session_client::Vcpu_id::INVALID };
|
||||
addr_t _state { 0 };
|
||||
addr_t _task { 0 };
|
||||
enum Virt const _vm_type;
|
||||
@@ -1184,20 +1183,20 @@ struct Vcpu : Genode::Thread
|
||||
public:
|
||||
|
||||
Vcpu(Env &env, Signal_context_capability &cap,
|
||||
Semaphore &handler_ready,
|
||||
Vm_session_client::Vcpu_id &id, enum Virt type,
|
||||
Semaphore &handler_ready, enum Virt type,
|
||||
Allocator &alloc, Affinity::Location location)
|
||||
:
|
||||
Thread(env, "vcpu_thread", STACK_SIZE, location, Weight(), env.cpu()),
|
||||
_signal(cap), _handler_ready(handler_ready), _alloc(alloc),
|
||||
_id(id), _vm_type(type)
|
||||
_vm_type(type)
|
||||
{ }
|
||||
|
||||
Allocator &allocator() const { return _alloc; }
|
||||
|
||||
bool match(Vm_session_client::Vcpu_id id) { return id.id == _id.id; }
|
||||
|
||||
Genode::Vm_session_client::Vcpu_id id() const { return _id; }
|
||||
Genode::Vm_session_client::Vcpu_id id() const { return _id; }
|
||||
void id(Genode::Vm_session_client::Vcpu_id id) { _id = id; }
|
||||
|
||||
void assign_ds_state(Region_map &rm, Dataspace_capability cap)
|
||||
{
|
||||
@@ -1266,12 +1265,10 @@ Vm_session_client::Vcpu_id
|
||||
Vm_session_client::create_vcpu(Allocator &alloc, Env &env,
|
||||
Vm_handler_base &handler)
|
||||
{
|
||||
Vm_session_client::Vcpu_id id = { vcpu_id };
|
||||
|
||||
enum Virt vm_type = virt_type(env);
|
||||
if (vm_type == Virt::UNKNOWN) {
|
||||
Genode::error("unsupported hardware virtualisation");
|
||||
return id;
|
||||
return Vm_session::Vcpu_id();
|
||||
}
|
||||
|
||||
Thread * ep = reinterpret_cast<Thread *>(&handler._rpc_ep);
|
||||
@@ -1279,17 +1276,17 @@ Vm_session_client::create_vcpu(Allocator &alloc, Env &env,
|
||||
|
||||
/* create thread that switches modes between thread/cpu */
|
||||
Vcpu * vcpu = new (alloc) Registered<Vcpu>(vcpus, env, handler._cap,
|
||||
handler._done, id, vm_type,
|
||||
handler._done, vm_type,
|
||||
alloc, location);
|
||||
|
||||
try {
|
||||
/* now it gets actually valid - vcpu->cap() becomes valid */
|
||||
vcpu->start();
|
||||
|
||||
call<Rpc_exception_handler>(handler._cap, vcpu->id());
|
||||
|
||||
/* instruct core to let it become a vCPU */
|
||||
call<Rpc_create_vcpu>(vcpu->cap());
|
||||
vcpu->id(call<Rpc_create_vcpu>(vcpu->cap()));
|
||||
|
||||
call<Rpc_exception_handler>(handler._cap, vcpu->id());
|
||||
|
||||
vcpu->assign_ds_state(env.rm(), call<Rpc_cpu_state>(vcpu->id()));
|
||||
} catch (...) {
|
||||
@@ -1299,9 +1296,7 @@ Vm_session_client::create_vcpu(Allocator &alloc, Env &env,
|
||||
destroy(alloc, vcpu);
|
||||
throw;
|
||||
}
|
||||
|
||||
vcpu_id ++;
|
||||
return id;
|
||||
return vcpu->id();
|
||||
}
|
||||
|
||||
void Vm_session_client::run(Vcpu_id vcpu_id)
|
||||
|
||||
109
repos/base-hw/include/spec/arm_64/cpu/vm_state_virtualization.h
Normal file
109
repos/base-hw/include/spec/arm_64/cpu/vm_state_virtualization.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* \brief CPU, PIC, and timer context of a virtual machine
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-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 _INCLUDE__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_
|
||||
#define _INCLUDE__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU context of a virtual machine
|
||||
*/
|
||||
struct Vm_state;
|
||||
|
||||
using uint128_t = __uint128_t;
|
||||
}
|
||||
|
||||
struct Genode::Vm_state : Genode::Cpu_state
|
||||
{
|
||||
Genode::uint64_t pstate { 0 };
|
||||
Genode::uint64_t exception_type { 0 };
|
||||
Genode::uint64_t esr_el2 { 0 };
|
||||
|
||||
/** Fpu registers **/
|
||||
Genode::uint128_t q[32] { 0 };
|
||||
Genode::uint32_t fpcr { 0 };
|
||||
Genode::uint32_t fpsr { 0 };
|
||||
|
||||
Genode::uint64_t elr_el1 { 0 };
|
||||
Genode::uint64_t sp_el1 { 0 };
|
||||
Genode::uint32_t spsr_el1 { 0 };
|
||||
Genode::uint32_t esr_el1 { 0 };
|
||||
|
||||
Genode::uint64_t sctlr_el1 { 0 };
|
||||
Genode::uint64_t actlr_el1 { 0 };
|
||||
Genode::uint64_t vbar_el1 { 0 };
|
||||
Genode::uint32_t cpacr_el1 { 0 };
|
||||
Genode::uint32_t afsr0_el1 { 0 };
|
||||
Genode::uint32_t afsr1_el1 { 0 };
|
||||
Genode::uint32_t contextidr_el1 { 0 };
|
||||
|
||||
Genode::uint64_t ttbr0_el1 { 0 };
|
||||
Genode::uint64_t ttbr1_el1 { 0 };
|
||||
Genode::uint64_t tcr_el1 { 0 };
|
||||
Genode::uint64_t mair_el1 { 0 };
|
||||
Genode::uint64_t amair_el1 { 0 };
|
||||
Genode::uint64_t far_el1 { 0 };
|
||||
Genode::uint64_t par_el1 { 0 };
|
||||
|
||||
Genode::uint64_t tpidrro_el0 { 0 };
|
||||
Genode::uint64_t tpidr_el0 { 0 };
|
||||
Genode::uint64_t tpidr_el1 { 0 };
|
||||
|
||||
Genode::uint64_t vmpidr_el2 { 0 };
|
||||
|
||||
Genode::uint64_t far_el2 { 0 };
|
||||
Genode::uint64_t hpfar_el2 { 0 };
|
||||
|
||||
/**
|
||||
* Timer related registers
|
||||
*/
|
||||
struct Timer {
|
||||
Genode::uint64_t offset { 0 };
|
||||
Genode::uint64_t compare { 0 };
|
||||
Genode::uint32_t control { 0 };
|
||||
Genode::uint32_t kcontrol { 0 };
|
||||
bool irq { false };
|
||||
} timer {};
|
||||
|
||||
/**
|
||||
* Interrupt related values
|
||||
*/
|
||||
struct Pic
|
||||
{
|
||||
unsigned last_irq { 1023 };
|
||||
unsigned virtual_irq { 1023 };
|
||||
} irqs {};
|
||||
|
||||
/**************************
|
||||
** Platform information **
|
||||
**************************/
|
||||
|
||||
Genode::uint64_t id_aa64isar0_el1 { 0 };
|
||||
Genode::uint64_t id_aa64isar1_el1 { 0 };
|
||||
Genode::uint64_t id_aa64mmfr0_el1 { 0 };
|
||||
Genode::uint64_t id_aa64mmfr1_el1 { 0 };
|
||||
Genode::uint64_t id_aa64mmfr2_el1 { 0 };
|
||||
Genode::uint64_t id_aa64pfr0_el1 { 0 };
|
||||
Genode::uint64_t id_aa64pfr1_el1 { 0 };
|
||||
Genode::uint64_t id_aa64zfr0_el1 { 0 };
|
||||
|
||||
Genode::uint32_t ccsidr_inst_el1[7] { 0 };
|
||||
Genode::uint32_t ccsidr_data_el1[7] { 0 };
|
||||
Genode::uint64_t clidr_el1 { 0 };
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__SPEC__ARM_64__CPU__VM_STATE_VIRTUALIZATION_H_ */
|
||||
@@ -17,6 +17,7 @@ SRC_CC += lib/base/heap.cc
|
||||
SRC_CC += lib/base/registry.cc
|
||||
SRC_CC += lib/base/log.cc
|
||||
SRC_CC += lib/base/output.cc
|
||||
SRC_CC += lib/base/raw_output.cc
|
||||
SRC_CC += lib/base/slab.cc
|
||||
SRC_CC += lib/base/sleep.cc
|
||||
SRC_CC += lib/base/sliced_heap.cc
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arndale
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v7/virtualization
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/vm_thread_on.cc
|
||||
SRC_CC += spec/arm/gicv2.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/platform_services.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.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_v7/virtualization/exception_vector.s
|
||||
|
||||
@@ -5,7 +5,8 @@ SRC_CC += kernel/vm_thread_on.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/platform_services.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.cc
|
||||
SRC_CC += vm_session_common.cc
|
||||
SRC_CC += vm_session_component.cc
|
||||
|
||||
SRC_S += spec/arm_v7/trustzone/exception_vector.s
|
||||
|
||||
|
||||
@@ -6,17 +6,18 @@
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/imx7d_sabre
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v7/virtualization
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/vm_thread_on.cc
|
||||
SRC_CC += spec/arm/generic_timer.cc
|
||||
SRC_CC += spec/arm/gicv2.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/platform_services.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.cc
|
||||
SRC_CC += spec/arm/virtualization/gicv2.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_v7/virtualization/exception_vector.s
|
||||
|
||||
@@ -17,7 +17,8 @@ SRC_CC += spec/arm/imx_tzic.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/platform_services.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.cc
|
||||
SRC_CC += vm_session_common.cc
|
||||
SRC_CC += vm_session_component.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm_v7/trustzone/exception_vector.s
|
||||
|
||||
@@ -7,6 +7,8 @@ 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 $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
||||
|
||||
@@ -8,4 +8,6 @@ SRC_S += bootstrap/spec/arm_64/crt0.s
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
NR_OF_CPUS = 4
|
||||
|
||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
||||
|
||||
@@ -1,24 +1,32 @@
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/imx8q_evk
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v8
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm/virtualization
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/cpu_up.cc
|
||||
SRC_CC += kernel/lock.cc
|
||||
SRC_CC += kernel/vm_thread_off.cc
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
SRC_CC += kernel/vm_thread_on.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
SRC_CC += spec/arm/generic_timer.cc
|
||||
SRC_CC += spec/arm/gicv3.cc
|
||||
SRC_CC += spec/arm/kernel/lock.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
SRC_CC += spec/arm_v8/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/thread.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/exception_vector.s
|
||||
SRC_S += spec/arm_v8/crt0.s
|
||||
SRC_S += spec/arm_v8/virtualization/exception_vector.s
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
NR_OF_CPUS = 4
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core-hw.inc
|
||||
|
||||
@@ -2,17 +2,17 @@ INC_DIR += $(REP_DIR)/src/core/spec/rpi3
|
||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v8
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += kernel/cpu_mp.cc
|
||||
SRC_CC += kernel/vm_thread_off.cc
|
||||
SRC_CC += kernel/cpu_up.cc
|
||||
SRC_CC += kernel/lock.cc
|
||||
SRC_CC += spec/arm_v8/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/thread.cc
|
||||
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
SRC_CC += spec/arm/bcm2837_pic.cc
|
||||
SRC_CC += spec/arm/generic_timer.cc
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
SRC_CC += spec/arm/kernel/lock.cc
|
||||
SRC_CC += spec/arm/platform_support.cc
|
||||
SRC_CC += spec/arm_v8/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
||||
SRC_CC += spec/arm_v8/kernel/thread.cc
|
||||
|
||||
#add assembly sources
|
||||
SRC_S += spec/arm_v8/exception_vector.s
|
||||
@@ -20,5 +20,7 @@ SRC_S += spec/arm_v8/crt0.s
|
||||
|
||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||
|
||||
NR_OF_CPUS = 4
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core-hw.inc
|
||||
|
||||
@@ -35,7 +35,10 @@ SRC_CC += spec/x86_64/muen/platform_services.cc
|
||||
SRC_CC += spec/x86_64/muen/platform_support.cc
|
||||
SRC_CC += spec/x86_64/muen/sinfo_instance.cc
|
||||
SRC_CC += spec/x86_64/muen/timer.cc
|
||||
SRC_CC += spec/x86_64/muen/vm_session_component.cc
|
||||
SRC_CC += spec/x86_64/platform_support_common.cc
|
||||
SRC_CC += vm_session_common.cc
|
||||
SRC_CC += vm_session_component.cc
|
||||
|
||||
SRC_CC += spec/64bit/memory_map.cc
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-07-08 abc6d82ca4a240319850c788f29cde2655eab1d1
|
||||
2019-11-25 6593319a4dec74af9dc15554139e4343ef4312a9
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 d4178964debbd47e4c0d37a127f51662054cd237
|
||||
2019-11-25 c60d834ce54a46a946c36249784e734e06274d97
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 5b6d3f57e76de132294eca0418ae63ff18a4d921
|
||||
2019-11-25 e9232754efd81c14aa65d4852d276852f591f3e5
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 51d44f6fef88b6cdeba9cfdbab1b170250ed28ad
|
||||
2019-11-25 2ab0250606cee0da4f08ac08f7f33c743f32c88c
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 559fcb46116ad7f3234892968271b268295b9296
|
||||
2019-11-25 7780e0570ac0277d678dee76a579a9d9f9a1a776
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 f2b8b089ac104f6ac25cbdf7a522f83e761bca86
|
||||
2019-11-25 2dee497b7892f706236fdbfabae53bbd4e62463b
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 c4b95a617529b279fb7a681b55cf6861a1cbb8ba
|
||||
2019-11-25 efd164d66086a998484d7413c5416e3aa128e560
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 e70d7f749ced55e96ce5486859123db5e9ee596d
|
||||
2019-11-25 25f54b8744778f0860ac2a93c11ee6b1cd16d0c9
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 c39e790ba567b102afabd0ae34d2fb4bffebb531
|
||||
2019-11-25 ceeaef3ad58fc5b88cf4686aa42f50fd254063e3
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 16dc7287252a28981c894d15465c3ab34a88b91e
|
||||
2019-11-25 aee36abdef456d2d1c6bba023f16cbca08eceabe
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 7bf52d5fec332b0d453e2193c32c6c912467f9fa
|
||||
2019-11-25 ede7ce464c3f4b8486fd93413088a1b83fbf796a
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 a9ed26560e2da949fd5e54bcba12eee6fdef15e5
|
||||
2019-11-25 2bea4132b9ab877e802cfb81ad3c62bda0c2bc50
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 40de2c240789026faa255646fb1063042cb96b0d
|
||||
2019-11-25 807893480c51457cad7e00e1275eff9749c91c68
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 d7ae8cddd46c47b43f7f162c07d19e3a6879d0e0
|
||||
2019-11-25 6a3f12cd6429f5d5bcf617cdd3ea9d345e8614ad
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 9eda2e18c925c75f60be5267e02c65a96d9d4583
|
||||
2019-11-25 a318db7d985930e3f58ce3bccce290bc13aaedab
|
||||
|
||||
@@ -1 +1 @@
|
||||
2019-08-27 1f55a4206dfd96f36c2bb68598a77b2b1b69d663
|
||||
2019-11-25 75f1b89ea50fdfd0a69c33dee4ba1e120d49fad5
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
/* base-internal includes */
|
||||
#include <base/internal/globals.h>
|
||||
#include <base/internal/output.h>
|
||||
#include <base/internal/raw_write_string.h>
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
|
||||
#include <board.h>
|
||||
@@ -57,3 +58,5 @@ struct Buffer
|
||||
Genode::Log &Genode::Log::log() {
|
||||
return unmanaged_singleton<Buffer>()->log; }
|
||||
|
||||
|
||||
void Genode::raw_write_string(char const *str) { log(str); }
|
||||
|
||||
@@ -47,7 +47,6 @@ class Bootstrap::Platform
|
||||
Mmio_space const core_mmio;
|
||||
unsigned cpus { NR_OF_CPUS };
|
||||
::Board::Boot_info info { };
|
||||
::Board::Pic pic { };
|
||||
|
||||
Board();
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
::Board::Pic pic { };
|
||||
::Board::Cpu::Sctlr::init();
|
||||
::Board::Cpu::enable_mmu_and_caches((addr_t)core_pd->table_base);
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
Actlr::disable_smp();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
board.pic.init_cpu_local();
|
||||
::Board::Pic pic { };
|
||||
|
||||
Cpu::invalidate_data_cache();
|
||||
data_cache_invalidated.inc();
|
||||
|
||||
@@ -13,8 +13,41 @@
|
||||
|
||||
#include <board.h>
|
||||
|
||||
void Board::Pic::init_cpu_local()
|
||||
Hw::Gicv2::Gicv2()
|
||||
: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
|
||||
_cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE),
|
||||
_last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)),
|
||||
_max_irq(_distr.max_irq())
|
||||
{
|
||||
static bool distributor_initialized = false;
|
||||
|
||||
if (!distributor_initialized) {
|
||||
distributor_initialized = true;
|
||||
|
||||
/* disable device */
|
||||
_distr.write<Distributor::Ctlr>(0);
|
||||
|
||||
/* configure every shared peripheral interrupt */
|
||||
for (unsigned i = min_spi; i <= _max_irq; i++) {
|
||||
if (Board::NON_SECURE) {
|
||||
_distr.write<Distributor::Igroupr::Group_status>(1, i);
|
||||
}
|
||||
_distr.write<Distributor::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distributor::Ipriorityr::Priority>(0, i);
|
||||
_distr.write<Distributor::Icenabler::Clear_enable>(1, i);
|
||||
}
|
||||
|
||||
/* enable device */
|
||||
Distributor::Ctlr::access_t v = 0;
|
||||
if (Board::NON_SECURE) {
|
||||
Distributor::Ctlr::Enable_grp0::set(v, 1);
|
||||
Distributor::Ctlr::Enable_grp1::set(v, 1);
|
||||
} else {
|
||||
Distributor::Ctlr::Enable::set(v, 1);
|
||||
}
|
||||
_distr.write<Distributor::Ctlr>(v);
|
||||
}
|
||||
|
||||
if (Board::NON_SECURE) {
|
||||
_cpui.write<Cpu_interface::Ctlr>(0);
|
||||
|
||||
@@ -40,34 +73,3 @@ void Board::Pic::init_cpu_local()
|
||||
}
|
||||
_cpui.write<Cpu_interface::Ctlr>(v);
|
||||
}
|
||||
|
||||
|
||||
Hw::Gicv2::Gicv2()
|
||||
: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
|
||||
_cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE),
|
||||
_last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)),
|
||||
_max_irq(_distr.max_irq())
|
||||
{
|
||||
/* disable device */
|
||||
_distr.write<Distributor::Ctlr>(0);
|
||||
|
||||
/* configure every shared peripheral interrupt */
|
||||
for (unsigned i = min_spi; i <= _max_irq; i++) {
|
||||
if (Board::NON_SECURE) {
|
||||
_distr.write<Distributor::Igroupr::Group_status>(1, i);
|
||||
}
|
||||
_distr.write<Distributor::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distributor::Ipriorityr::Priority>(0, i);
|
||||
_distr.write<Distributor::Icenabler::Clear_enable>(1, i);
|
||||
}
|
||||
|
||||
/* enable device */
|
||||
Distributor::Ctlr::access_t v = 0;
|
||||
if (Board::NON_SECURE) {
|
||||
Distributor::Ctlr::Enable_grp0::set(v, 1);
|
||||
Distributor::Ctlr::Enable_grp1::set(v, 1);
|
||||
} else {
|
||||
Distributor::Ctlr::Enable::set(v, 1);
|
||||
}
|
||||
_distr.write<Distributor::Ctlr>(v);
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* \brief Interrupt controller definitions for ARM
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2017-02-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__ARM__GICV2_H_
|
||||
#define _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_
|
||||
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board { struct Pic; }
|
||||
|
||||
struct Board::Pic : Hw::Gicv2
|
||||
{
|
||||
void init_cpu_local();
|
||||
};
|
||||
|
||||
#endif /* _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_ */
|
||||
@@ -11,10 +11,12 @@
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <hw/spec/arm_64/memory_map.h>
|
||||
#include <platform.h>
|
||||
|
||||
using Board::Cpu;
|
||||
|
||||
extern "C" void * _crt0_enable_fpu;
|
||||
|
||||
static inline void prepare_non_secure_world()
|
||||
{
|
||||
@@ -56,11 +58,54 @@ static inline void prepare_non_secure_world()
|
||||
}
|
||||
|
||||
|
||||
static inline void prepare_hypervisor()
|
||||
static inline void prepare_hypervisor(Cpu::Ttbr::access_t const ttbr)
|
||||
{
|
||||
Cpu::Hcr::access_t scr = Cpu::Hcr::read();
|
||||
Cpu::Hcr::Rw::set(scr, 1); /* exec in aarch64 */
|
||||
Cpu::Hcr::write(scr);
|
||||
using namespace Hw::Mm;
|
||||
|
||||
/* forbid trace access */
|
||||
Cpu::Cptr_el2::access_t cptr = Cpu::Cptr_el2::read();
|
||||
Cpu::Cptr_el2::Tta::set(cptr, 1);
|
||||
Cpu::Cptr_el2::write(cptr);
|
||||
|
||||
/* allow physical counter/timer access without trapping */
|
||||
Cpu::Cnthctl_el2::write(0b111);
|
||||
|
||||
/* forbid any 32bit access to coprocessor/sysregs */
|
||||
Cpu::Hstr_el2::write(0xffff);
|
||||
|
||||
Cpu::Hcr_el2::access_t hcr = Cpu::Hcr_el2::read();
|
||||
Cpu::Hcr_el2::Rw::set(hcr, 1); /* exec in aarch64 */
|
||||
Cpu::Hcr_el2::write(hcr);
|
||||
|
||||
/* set hypervisor exception vector */
|
||||
Cpu::Vbar_el2::write(el2_addr(hypervisor_exception_vector().base));
|
||||
Genode::addr_t const stack_el2 = el2_addr(hypervisor_stack().base +
|
||||
hypervisor_stack().size);
|
||||
|
||||
/* set hypervisor's translation table */
|
||||
Cpu::Ttbr0_el2::write(ttbr);
|
||||
|
||||
Cpu::Tcr_el2::access_t tcr_el2 = 0;
|
||||
Cpu::Tcr_el2::T0sz::set(tcr_el2, 25);
|
||||
Cpu::Tcr_el2::Irgn0::set(tcr_el2, 1);
|
||||
Cpu::Tcr_el2::Orgn0::set(tcr_el2, 1);
|
||||
Cpu::Tcr_el2::Sh0::set(tcr_el2, 0b10);
|
||||
|
||||
/* prepare MMU usage by hypervisor code */
|
||||
Cpu::Tcr_el2::write(tcr_el2);
|
||||
|
||||
/* set memory attributes in indirection register */
|
||||
Cpu::Mair::access_t mair = 0;
|
||||
Cpu::Mair::Attr0::set(mair, Cpu::Mair::NORMAL_MEMORY_UNCACHED);
|
||||
Cpu::Mair::Attr1::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair::Attr2::set(mair, Cpu::Mair::NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair::Attr3::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair_el2::write(mair);
|
||||
|
||||
Cpu::Vtcr_el2::access_t vtcr = 0;
|
||||
Cpu::Vtcr_el2::T0sz::set(vtcr, 25);
|
||||
Cpu::Vtcr_el2::Sl0::set(vtcr, 1); /* set to starting level 1 */
|
||||
Cpu::Vtcr_el2::write(vtcr);
|
||||
|
||||
Cpu::Spsr::access_t pstate = 0;
|
||||
Cpu::Spsr::Sp::set(pstate, 1); /* select non-el0 stack pointer */
|
||||
@@ -71,27 +116,52 @@ static inline void prepare_hypervisor()
|
||||
Cpu::Spsr::D::set(pstate, 1);
|
||||
Cpu::Spsr_el2::write(pstate);
|
||||
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr_el2::read();
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::A::set(sctlr, 0);
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::Sa::set(sctlr, 0);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::Wxn::set(sctlr, 0);
|
||||
Cpu::Sctlr_el2::write(sctlr);
|
||||
|
||||
asm volatile("mov x0, sp \n"
|
||||
"msr sp_el1, x0 \n"
|
||||
"adr x0, 1f \n"
|
||||
"msr elr_el2, x0 \n"
|
||||
"mov sp, %0 \n"
|
||||
"eret \n"
|
||||
"1:");
|
||||
"1:": : "r"(stack_el2): "x0");
|
||||
}
|
||||
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
static volatile bool primary_cpu = true;
|
||||
bool primary = primary_cpu;
|
||||
if (primary) primary_cpu = false;
|
||||
|
||||
Cpu::Ttbr::access_t ttbr =
|
||||
Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base);
|
||||
|
||||
while (Cpu::current_privilege_level() > Cpu::Current_el::EL1) {
|
||||
if (Cpu::current_privilege_level() == Cpu::Current_el::EL3)
|
||||
if (Cpu::current_privilege_level() == Cpu::Current_el::EL3) {
|
||||
prepare_non_secure_world();
|
||||
else
|
||||
prepare_hypervisor();
|
||||
} else {
|
||||
::Board::Pic pic __attribute__((unused)) {};
|
||||
prepare_hypervisor(ttbr);
|
||||
}
|
||||
}
|
||||
|
||||
/* primary cpu wakes up all others */
|
||||
if (primary && NR_OF_CPUS > 1) Cpu::wake_up_all_cpus(&_crt0_enable_fpu);
|
||||
|
||||
/* enable performance counter for user-land */
|
||||
Cpu::Pmuserenr_el0::write(0b1111);
|
||||
|
||||
/* enable user-level access of physical/virtual counter */
|
||||
Cpu::Cntkctl_el1::write(0b11);
|
||||
|
||||
Cpu::Vbar_el1::write(Hw::Mm::supervisor_exception_vector().base);
|
||||
|
||||
/* set memory attributes in indirection register */
|
||||
@@ -100,9 +170,8 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
Cpu::Mair::Attr1::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair::Attr2::set(mair, Cpu::Mair::NORMAL_MEMORY_CACHED);
|
||||
Cpu::Mair::Attr3::set(mair, Cpu::Mair::DEVICE_MEMORY);
|
||||
Cpu::Mair::write(mair);
|
||||
Cpu::Mair_el1::write(mair);
|
||||
|
||||
Cpu::Ttbr::access_t ttbr = Cpu::Ttbr::Baddr::masked((Genode::addr_t)core_pd->table_base);
|
||||
Cpu::Ttbr0_el1::write(ttbr);
|
||||
Cpu::Ttbr1_el1::write(ttbr);
|
||||
|
||||
@@ -119,13 +188,14 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
Cpu::Tcr_el1::As::set(tcr, 1);
|
||||
Cpu::Tcr_el1::write(tcr);
|
||||
|
||||
Cpu::Sctlr_el1::access_t sctlr = Cpu::Sctlr_el1::read();
|
||||
Cpu::Sctlr_el1::C::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::I::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::A::set(sctlr, 0);
|
||||
Cpu::Sctlr_el1::M::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::Sa0::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::Sa::set(sctlr, 0);
|
||||
Cpu::Sctlr::access_t sctlr = Cpu::Sctlr_el1::read();
|
||||
Cpu::Sctlr::C::set(sctlr, 1);
|
||||
Cpu::Sctlr::I::set(sctlr, 1);
|
||||
Cpu::Sctlr::A::set(sctlr, 0);
|
||||
Cpu::Sctlr::M::set(sctlr, 1);
|
||||
Cpu::Sctlr::Sa0::set(sctlr, 1);
|
||||
Cpu::Sctlr::Sa::set(sctlr, 0);
|
||||
Cpu::Sctlr::Uct::set(sctlr, 1);
|
||||
Cpu::Sctlr_el1::write(sctlr);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -23,8 +23,19 @@
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #0b11111111
|
||||
cbz x0, _crt0_fill_bss_zero
|
||||
|
||||
/**
|
||||
* Hack for Qemu, which starts all cpus at once
|
||||
*/
|
||||
1:
|
||||
ldr x1, =_crt0_qemu_start_secondary_cpus
|
||||
ldr w1, [x1]
|
||||
cbnz w1, _crt0_enable_fpu
|
||||
wfe
|
||||
b _start
|
||||
b 1b
|
||||
.global _crt0_qemu_start_secondary_cpus
|
||||
_crt0_qemu_start_secondary_cpus:
|
||||
.long 0
|
||||
|
||||
|
||||
/***************************
|
||||
@@ -32,12 +43,12 @@
|
||||
***************************/
|
||||
|
||||
_crt0_fill_bss_zero:
|
||||
ldr x0, =_bss_start
|
||||
ldr x1, =_bss_end
|
||||
ldr x1, =_bss_start
|
||||
ldr x2, =_bss_end
|
||||
1:
|
||||
cmp x1, x0
|
||||
cmp x2, x1
|
||||
b.eq _crt0_enable_fpu
|
||||
str xzr, [x0], #8
|
||||
str xzr, [x1], #8
|
||||
b 1b
|
||||
|
||||
|
||||
@@ -45,20 +56,30 @@
|
||||
** Enable FPU **
|
||||
****************/
|
||||
|
||||
.global _crt0_enable_fpu
|
||||
_crt0_enable_fpu:
|
||||
mov x0, #0b11
|
||||
lsl x0, x0, #20
|
||||
msr cpacr_el1, x0
|
||||
mov x1, #0b11
|
||||
lsl x1, x1, #20
|
||||
msr cpacr_el1, x1
|
||||
|
||||
|
||||
/**********************
|
||||
** Initialize stack **
|
||||
**********************/
|
||||
|
||||
ldr x0, =_crt0_start_stack
|
||||
mov sp, x0
|
||||
.set STACK_SIZE, 0x2000
|
||||
|
||||
ldr x1, =_crt0_start_stack
|
||||
ldr x2, [x1]
|
||||
mul x0, x0, x2
|
||||
add x1, x1, x0
|
||||
mov sp, x1
|
||||
bl init
|
||||
|
||||
.p2align 4
|
||||
.space 0x4000
|
||||
.rept NR_OF_CPUS
|
||||
.space STACK_SIZE
|
||||
.endr
|
||||
_crt0_start_stack:
|
||||
.long STACK_SIZE
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <hw/spec/arm/arndale_board.h>
|
||||
#include <hw/spec/arm/lpae.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Arndale_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
static constexpr bool NON_SECURE = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,9 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
using namespace ::Board;
|
||||
|
||||
static volatile bool primary_cpu = true;
|
||||
board.pic.init_cpu_local();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
::Board::Pic pic { };
|
||||
|
||||
prepare_nonsecure_world();
|
||||
prepare_hypervisor((addr_t)core_pd->table_base);
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Imx6q_sabrelite_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
struct L2_cache;
|
||||
|
||||
static constexpr bool NON_SECURE = false;
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <hw/spec/arm/imx7d_sabre_board.h>
|
||||
#include <hw/spec/arm/lpae.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Imx7d_sabre_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
static constexpr bool NON_SECURE = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -287,7 +287,9 @@ unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
static volatile bool primary_cpu = true;
|
||||
static unsigned long timer_freq = Cpu::Cntfrq::read();
|
||||
board.pic.init_cpu_local();
|
||||
|
||||
/* locally initialize interrupt controller */
|
||||
::Board::Pic pic { };
|
||||
|
||||
prepare_nonsecure_world(timer_freq);
|
||||
prepare_hypervisor((addr_t)core_pd->table_base);
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Imx8q_evk_board;
|
||||
using Cpu = Hw::Arm_64_cpu;
|
||||
|
||||
struct Cpu : Hw::Arm_64_cpu
|
||||
{
|
||||
static void wake_up_all_cpus(void*);
|
||||
};
|
||||
|
||||
using Hw::Pic;
|
||||
};
|
||||
|
||||
|
||||
@@ -24,4 +24,269 @@ Bootstrap::Platform::Board::Board()
|
||||
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::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE })
|
||||
{
|
||||
::Board::Pic pic {};
|
||||
|
||||
static volatile unsigned long initial_values[][2] {
|
||||
// GPC values
|
||||
{ 0x303A0004, 0x5050424 },
|
||||
{ 0x303A0030, 0xEB22DE22 },
|
||||
{ 0x303A0034, 0xFFFFF1C7 },
|
||||
{ 0x303A0038, 0x7BFFBC00 },
|
||||
{ 0x303A003C, 0xFA3BF12A },
|
||||
{ 0x303A004C, 0xFFFFDFFF },
|
||||
{ 0x303A01B4, 0x3980 },
|
||||
{ 0x303A01CC, 0xFFFFBFFF },
|
||||
{ 0x303A01D4, 0xFFFF7FFF },
|
||||
{ 0x303A01DC, 0xFFFF7FFF },
|
||||
{ 0x303A01FC, 0x107FF9F },
|
||||
{ 0x303A080C, 0x1 },
|
||||
{ 0x303A0840, 0x1 },
|
||||
{ 0x303A084C, 0x1 },
|
||||
{ 0x303A0880, 0x1 },
|
||||
{ 0x303A088C, 0x1 },
|
||||
{ 0x303A08C0, 0x1 },
|
||||
{ 0x303A08CC, 0x1 },
|
||||
{ 0x303A0C8C, 0x1 },
|
||||
{ 0x303A0DCC, 0x1 },
|
||||
{ 0x303A0E0C, 0x1 },
|
||||
{ 0x303A0ECC, 0x1 },
|
||||
{ 0x303A0F00, 0x1 },
|
||||
{ 0x303A0F0C, 0x1 },
|
||||
|
||||
// CCM values
|
||||
{ 0x303840B0, 0x2 },
|
||||
{ 0x303840B4, 0x2 },
|
||||
{ 0x303840B8, 0x2 },
|
||||
{ 0x303840BC, 0x2 },
|
||||
{ 0x303840C0, 0x2 },
|
||||
{ 0x303840C4, 0x2 },
|
||||
{ 0x303840C8, 0x2 },
|
||||
{ 0x303840CC, 0x2 },
|
||||
{ 0x303840D0, 0x2 },
|
||||
{ 0x303840D4, 0x2 },
|
||||
{ 0x303840D8, 0x2 },
|
||||
{ 0x303840DC, 0x2 },
|
||||
{ 0x303840E0, 0x2 },
|
||||
{ 0x303840E4, 0x2 },
|
||||
{ 0x303840E8, 0x2 },
|
||||
{ 0x303840EC, 0x2 },
|
||||
{ 0x303840F0, 0x2 },
|
||||
{ 0x303840F4, 0x2 },
|
||||
{ 0x303840F8, 0x2 },
|
||||
{ 0x303840FC, 0x2 },
|
||||
{ 0x30384250, 0x3 },
|
||||
{ 0x30384254, 0x3 },
|
||||
{ 0x30384258, 0x3 },
|
||||
{ 0x3038425C, 0x3 },
|
||||
{ 0x303843A0, 0x3 },
|
||||
{ 0x303843A4, 0x3 },
|
||||
{ 0x303843A8, 0x3 },
|
||||
{ 0x303843AC, 0x3 },
|
||||
{ 0x303844D0, 0x3 },
|
||||
{ 0x303844D4, 0x3 },
|
||||
{ 0x303844D8, 0x3 },
|
||||
{ 0x303844DC, 0x3 },
|
||||
{ 0x303844F0, 0x3 },
|
||||
{ 0x303844F4, 0x3 },
|
||||
{ 0x303844F8, 0x3 },
|
||||
{ 0x303844FC, 0x3 },
|
||||
{ 0x30384560, 0x0 },
|
||||
{ 0x30384564, 0x0 },
|
||||
{ 0x30384568, 0x0 },
|
||||
{ 0x3038456C, 0x0 },
|
||||
{ 0x303845D0, 0x3 },
|
||||
{ 0x303845D4, 0x3 },
|
||||
{ 0x303845D8, 0x3 },
|
||||
{ 0x303845DC, 0x3 },
|
||||
{ 0x30388010, 0x0 },
|
||||
{ 0x30388014, 0x0 },
|
||||
{ 0x30388018, 0x0 },
|
||||
{ 0x3038801C, 0x0 },
|
||||
{ 0x30388020, 0x0 },
|
||||
{ 0x30388024, 0x0 },
|
||||
{ 0x30388028, 0x0 },
|
||||
{ 0x3038802C, 0x0 },
|
||||
{ 0x30388030, 0x11000400 },
|
||||
{ 0x30388034, 0x11000400 },
|
||||
{ 0x30388038, 0x11000400 },
|
||||
{ 0x3038803C, 0x11000400 },
|
||||
{ 0x30388080, 0x11000000 },
|
||||
{ 0x30388084, 0x11000000 },
|
||||
{ 0x30388088, 0x11000000 },
|
||||
{ 0x3038808C, 0x11000000 },
|
||||
{ 0x30388090, 0x0 },
|
||||
{ 0x30388094, 0x0 },
|
||||
{ 0x30388098, 0x0 },
|
||||
{ 0x3038809C, 0x0 },
|
||||
{ 0x303880B0, 0x1100 },
|
||||
{ 0x303880B4, 0x1100 },
|
||||
{ 0x303880B8, 0x1100 },
|
||||
{ 0x303880BC, 0x1100 },
|
||||
{ 0x30388110, 0x0 },
|
||||
{ 0x30388114, 0x0 },
|
||||
{ 0x30388118, 0x0 },
|
||||
{ 0x3038811C, 0x0 },
|
||||
{ 0x30388180, 0x1000000 },
|
||||
{ 0x30388184, 0x1000000 },
|
||||
{ 0x30388188, 0x1000000 },
|
||||
{ 0x3038818C, 0x1000000 },
|
||||
{ 0x303881A0, 0x10000000 },
|
||||
{ 0x303881A4, 0x10000000 },
|
||||
{ 0x303881A8, 0x10000000 },
|
||||
{ 0x303881AC, 0x10000000 },
|
||||
{ 0x303881B0, 0x1000100 },
|
||||
{ 0x303881B4, 0x1000100 },
|
||||
{ 0x303881B8, 0x1000100 },
|
||||
{ 0x303881BC, 0x1000100 },
|
||||
{ 0x30388200, 0x1000000 },
|
||||
{ 0x30388204, 0x1000000 },
|
||||
{ 0x30388208, 0x1000000 },
|
||||
{ 0x3038820C, 0x1000000 },
|
||||
{ 0x30388220, 0x10000000 },
|
||||
{ 0x30388224, 0x10000000 },
|
||||
{ 0x30388228, 0x10000000 },
|
||||
{ 0x3038822C, 0x10000000 },
|
||||
{ 0x30388230, 0x1000100 },
|
||||
{ 0x30388234, 0x1000100 },
|
||||
{ 0x30388238, 0x1000100 },
|
||||
{ 0x3038823C, 0x1000100 },
|
||||
|
||||
// CCMA values
|
||||
{ 0x30360000, 0x88080 },
|
||||
{ 0x30360004, 0x292A2FA6 },
|
||||
{ 0x30360004, 0x292A2FA6 },
|
||||
{ 0x30360008, 0x88080 },
|
||||
{ 0x30360008, 0x88080 },
|
||||
{ 0x3036000C, 0x10385BA3 },
|
||||
{ 0x3036000C, 0x10385BA3 },
|
||||
{ 0x30360010, 0x98080 },
|
||||
{ 0x30360010, 0x98080 },
|
||||
{ 0x30360014, 0x3FFFFF1A },
|
||||
{ 0x30360014, 0x3FFFFF1A },
|
||||
{ 0x30360018, 0x88081 },
|
||||
{ 0x30360054, 0x2B9 },
|
||||
|
||||
// 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 },
|
||||
{ 0x30330220, 0x10 },
|
||||
{ 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 },
|
||||
{ 0x3033033C, 0x9F },
|
||||
{ 0x30330340, 0xDF },
|
||||
{ 0x30330344, 0xDF },
|
||||
{ 0x30330348, 0xDF },
|
||||
{ 0x3033034C, 0xDF },
|
||||
{ 0x30330350, 0xDF },
|
||||
{ 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 },
|
||||
{ 0x30330464, 0x49 },
|
||||
{ 0x30330468, 0x49 },
|
||||
{ 0x3033046C, 0x16 },
|
||||
{ 0x30330484, 0x67 },
|
||||
{ 0x30330488, 0x67 },
|
||||
{ 0x3033048C, 0x67 },
|
||||
{ 0x30330490, 0x67 },
|
||||
{ 0x30330494, 0x76 },
|
||||
{ 0x30330498, 0x76 },
|
||||
{ 0x303304AC, 0x49 },
|
||||
{ 0x303304B0, 0x49 },
|
||||
{ 0x303304C8, 0x1 },
|
||||
{ 0x303304CC, 0x4 },
|
||||
{ 0x30330500, 0x1 },
|
||||
{ 0x30330504, 0x2 },
|
||||
{ 0x30340038, 0x49409600 },
|
||||
{ 0x30340040, 0x49409200 }
|
||||
};
|
||||
|
||||
unsigned num_values = sizeof(initial_values) / (2*sizeof(unsigned long));
|
||||
for (unsigned i = 0; i < num_values; i++)
|
||||
*((volatile Genode::uint32_t*)initial_values[i][0]) = (Genode::uint32_t)initial_values[i][1];
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Nit6_solox_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
struct L2_cache;
|
||||
|
||||
static constexpr bool NON_SECURE = false;
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
#include <hw/spec/arm/odroid_xu_board.h>
|
||||
#include <hw/spec/arm/lpae.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Odroid_xu_board;
|
||||
using Pic = Hw::Gicv2;
|
||||
static constexpr bool NON_SECURE = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ Bootstrap::Platform::Board::Board()
|
||||
|
||||
unsigned Bootstrap::Platform::enable_mmu()
|
||||
{
|
||||
board.pic.init_cpu_local();
|
||||
/* locally initialize interrupt controller */
|
||||
::Board::Pic pic { };
|
||||
|
||||
Cpu::Sctlr::init();
|
||||
Cpu::Cpsr::init();
|
||||
Cpu::invalidate_data_cache();
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <hw/spec/arm/panda_board.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Panda_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
static constexpr bool NON_SECURE = false;
|
||||
|
||||
class L2_cache;
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Pbxa9_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
|
||||
static constexpr bool NON_SECURE = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
#include <hw/spec/riscv/board.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Riscv_board;
|
||||
struct Pic {};
|
||||
}
|
||||
namespace Board { using namespace Hw::Riscv_board; }
|
||||
|
||||
template <typename E, unsigned B, unsigned S>
|
||||
void Sv39::Level_x_translation_table<E, B, S>::_translation_added(addr_t, size_t)
|
||||
|
||||
@@ -18,11 +18,7 @@
|
||||
#include <hw/spec/arm/page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Rpi_board;
|
||||
|
||||
struct Pic {};
|
||||
}
|
||||
namespace Board { using namespace Hw::Rpi_board; }
|
||||
|
||||
|
||||
constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {
|
||||
|
||||
@@ -20,8 +20,13 @@
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Rpi3_board;
|
||||
using Cpu = Hw::Arm_64_cpu;
|
||||
struct Pic {};
|
||||
|
||||
struct Cpu : Hw::Arm_64_cpu
|
||||
{
|
||||
static void wake_up_all_cpus(void*);
|
||||
};
|
||||
|
||||
struct Pic { }; /* dummy object */
|
||||
};
|
||||
|
||||
#endif /* _BOOTSTRAP__SPEC__RPI3__BOARD_H_ */
|
||||
|
||||
@@ -26,3 +26,12 @@ Bootstrap::Platform::Board::Board()
|
||||
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
||||
Memory_region { ::Board::IRQ_CONTROLLER_BASE,
|
||||
::Board::IRQ_CONTROLLER_SIZE }) {}
|
||||
|
||||
|
||||
extern unsigned int _crt0_qemu_start_secondary_cpus;
|
||||
|
||||
void Board::Cpu::wake_up_all_cpus(void *)
|
||||
{
|
||||
_crt0_qemu_start_secondary_cpus = 1;
|
||||
asm volatile("dsb #0; sev");
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ Bootstrap::Platform::Board::Board()
|
||||
Aipstz aipstz_1(AIPS_1_MMIO_BASE);
|
||||
Aipstz aipstz_2(AIPS_2_MMIO_BASE);
|
||||
|
||||
Pic pic {};
|
||||
|
||||
/* set monitor mode exception vector entry */
|
||||
Cpu::Mvbar::write(Hw::Mm::system_exception_vector().base);
|
||||
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
using namespace Hw::Wand_quad_board;
|
||||
|
||||
using Pic = Hw::Gicv2;
|
||||
|
||||
struct L2_cache;
|
||||
|
||||
static constexpr bool NON_SECURE = false;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
namespace Board {
|
||||
using namespace Hw::Pc_board;
|
||||
using Cpu = Hw::X86_64_cpu;
|
||||
struct Pic {};
|
||||
}
|
||||
|
||||
#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ */
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <spec/arm/gicv2.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;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
/* core includes */
|
||||
#include <kernel/irq.h>
|
||||
#include <irq_root.h>
|
||||
#include <irq_args.h>
|
||||
#include <core_env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
@@ -35,10 +34,7 @@ unsigned Irq_session_component::_find_irq_number(const char * const args)
|
||||
|
||||
void Irq_session_component::ack_irq()
|
||||
{
|
||||
using Kernel::User_irq;
|
||||
if (!_sig_cap.valid()) { return; }
|
||||
User_irq * const kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||
Kernel::ack_irq(kirq);
|
||||
if (_kobj.constructed()) Kernel::ack_irq(*_kobj);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,8 +47,8 @@ void Irq_session_component::sigh(Signal_context_capability cap)
|
||||
|
||||
_sig_cap = cap;
|
||||
|
||||
if (Kernel::new_irq((addr_t)&_kernel_object, _irq_number,
|
||||
Capability_space::capid(_sig_cap)))
|
||||
if (!_kobj.create(_irq_number, _irq_args.trigger(), _irq_args.polarity(),
|
||||
Capability_space::capid(_sig_cap)))
|
||||
warning("invalid signal handler for IRQ ", _irq_number);
|
||||
}
|
||||
|
||||
@@ -61,18 +57,16 @@ Irq_session_component::~Irq_session_component()
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
User_irq * kirq = reinterpret_cast<User_irq*>(&_kernel_object);
|
||||
_irq_alloc.free((void *)(addr_t)_irq_number);
|
||||
if (_sig_cap.valid())
|
||||
Kernel::delete_irq(kirq);
|
||||
}
|
||||
|
||||
|
||||
Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
const char * const args)
|
||||
:
|
||||
_irq_number(Platform::irq(_find_irq_number(args))), _irq_alloc(irq_alloc),
|
||||
_is_msi(false), _address(0), _value(0)
|
||||
: _irq_args(args),
|
||||
_irq_number(Platform::irq(_irq_args.irq_number())),
|
||||
_irq_alloc(irq_alloc),
|
||||
_kobj(), _is_msi(false), _address(0), _value(0)
|
||||
{
|
||||
const long mmconf =
|
||||
Arg_string::find_arg(args, "device_config_phys").long_value(0);
|
||||
@@ -89,8 +83,4 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
|
||||
error("unavailable interrupt ", _irq_number, " requested");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
Irq_args const irq_args(args);
|
||||
|
||||
Kernel::irq_mode(_irq_number, irq_args.trigger(), irq_args.polarity());
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <util/list.h>
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
#include <irq_args.h>
|
||||
#include <object.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
namespace Genode { class Irq_session_component; }
|
||||
@@ -31,13 +33,13 @@ class Genode::Irq_session_component : public Rpc_object<Irq_session>,
|
||||
|
||||
friend class List<Irq_session_component>;
|
||||
|
||||
unsigned _irq_number;
|
||||
Range_allocator &_irq_alloc;
|
||||
Genode::uint8_t _kernel_object[sizeof(Kernel::User_irq)];
|
||||
bool _is_msi;
|
||||
addr_t _address, _value;
|
||||
|
||||
Signal_context_capability _sig_cap { };
|
||||
Irq_args const _irq_args;
|
||||
unsigned _irq_number;
|
||||
Range_allocator & _irq_alloc;
|
||||
Kernel_object<Kernel::User_irq> _kobj;
|
||||
bool _is_msi;
|
||||
addr_t _address, _value;
|
||||
Signal_context_capability _sig_cap { };
|
||||
|
||||
unsigned _find_irq_number(const char * const args);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Kernel
|
||||
class Vm;
|
||||
class User_irq;
|
||||
using Native_utcb = Genode::Native_utcb;
|
||||
template <typename T> class Core_object_identity;
|
||||
|
||||
/**
|
||||
* Kernel names of the kernel calls
|
||||
@@ -60,15 +61,14 @@ namespace Kernel
|
||||
constexpr Call_arg call_id_delete_obj() { return 122; }
|
||||
constexpr Call_arg call_id_cancel_thread_blocking() { return 123; }
|
||||
constexpr Call_arg call_id_new_core_thread() { return 124; }
|
||||
constexpr Call_arg call_id_irq_mode() { return 125; }
|
||||
|
||||
/**
|
||||
* Invalidate TLB entries for the `pd` in region `addr`, `sz`
|
||||
*/
|
||||
inline void invalidate_tlb(Pd * const pd, addr_t const addr,
|
||||
inline void invalidate_tlb(Pd & pd, addr_t const addr,
|
||||
size_t const sz)
|
||||
{
|
||||
call(call_id_invalidate_tlb(), (Call_arg)pd, (Call_arg)addr,
|
||||
call(call_id_invalidate_tlb(), (Call_arg)&pd, (Call_arg)addr,
|
||||
(Call_arg)sz);
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ namespace Kernel
|
||||
* \param thread kernel object of the targeted thread
|
||||
* \param quota new CPU quota value
|
||||
*/
|
||||
inline void thread_quota(Kernel::Thread * const thread, size_t const quota)
|
||||
inline void thread_quota(Kernel::Thread & thread, size_t const quota)
|
||||
{
|
||||
call(call_id_thread_quota(), (Call_arg)thread, (Call_arg)quota);
|
||||
call(call_id_thread_quota(), (Call_arg)&thread, (Call_arg)quota);
|
||||
}
|
||||
|
||||
|
||||
@@ -104,9 +104,9 @@ namespace Kernel
|
||||
* continue the execution of a thread no matter what state the thread is
|
||||
* in.
|
||||
*/
|
||||
inline void pause_thread(Thread * const thread)
|
||||
inline void pause_thread(Thread & thread)
|
||||
{
|
||||
call(call_id_pause_thread(), (Call_arg)thread);
|
||||
call(call_id_pause_thread(), (Call_arg)&thread);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,9 +115,9 @@ namespace Kernel
|
||||
*
|
||||
* \param thread pointer to thread kernel object
|
||||
*/
|
||||
inline void resume_thread(Thread * const thread)
|
||||
inline void resume_thread(Thread & thread)
|
||||
{
|
||||
call(call_id_resume_thread(), (Call_arg)thread);
|
||||
call(call_id_resume_thread(), (Call_arg)&thread);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,11 +132,11 @@ namespace Kernel
|
||||
* \retval 0 suceeded
|
||||
* \retval !=0 failed
|
||||
*/
|
||||
inline int start_thread(Thread * const thread, unsigned const cpu_id,
|
||||
Pd * const pd, Native_utcb * const utcb)
|
||||
inline int start_thread(Thread & thread, unsigned const cpu_id,
|
||||
Pd & pd, Native_utcb & utcb)
|
||||
{
|
||||
return call(call_id_start_thread(), (Call_arg)thread, cpu_id,
|
||||
(Call_arg)pd, (Call_arg)utcb);
|
||||
return call(call_id_start_thread(), (Call_arg)&thread, cpu_id,
|
||||
(Call_arg)&pd, (Call_arg)&utcb);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,9 +155,9 @@ namespace Kernel
|
||||
* limit the time a parent waits for a server when closing a session
|
||||
* of one of its children.
|
||||
*/
|
||||
inline void cancel_thread_blocking(Thread * const thread)
|
||||
inline void cancel_thread_blocking(Thread & thread)
|
||||
{
|
||||
call(call_id_cancel_thread_blocking(), (Call_arg)thread);
|
||||
call(call_id_cancel_thread_blocking(), (Call_arg)&thread);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,10 +167,10 @@ namespace Kernel
|
||||
* \param thread pointer to thread kernel object
|
||||
* \param signal_context_id capability id of the page-fault handler
|
||||
*/
|
||||
inline void thread_pager(Thread * const thread,
|
||||
capid_t const signal_context_id)
|
||||
inline void thread_pager(Thread & thread,
|
||||
capid_t const signal_context_id)
|
||||
{
|
||||
call(call_id_thread_pager(), (Call_arg)thread, signal_context_id);
|
||||
call(call_id_thread_pager(), (Call_arg)&thread, signal_context_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -179,9 +179,9 @@ namespace Kernel
|
||||
*
|
||||
* \param vm pointer to vm kernel object
|
||||
*/
|
||||
inline void run_vm(Vm * const vm)
|
||||
inline void run_vm(Vm & vm)
|
||||
{
|
||||
call(call_id_run_vm(), (Call_arg) vm);
|
||||
call(call_id_run_vm(), (Call_arg) &vm);
|
||||
}
|
||||
|
||||
|
||||
@@ -190,33 +190,9 @@ namespace Kernel
|
||||
*
|
||||
* \param vm pointer to vm kernel object
|
||||
*/
|
||||
inline void pause_vm(Vm * const vm)
|
||||
inline void pause_vm(Vm & vm)
|
||||
{
|
||||
call(call_id_pause_vm(), (Call_arg) vm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an interrupt object
|
||||
*
|
||||
* \param p memory donation for the irq object
|
||||
* \param irq_nr interrupt number
|
||||
* \param signal_context_id capability id of the signal context
|
||||
*/
|
||||
inline int new_irq(addr_t const p, unsigned irq_nr,
|
||||
capid_t signal_context_id)
|
||||
{
|
||||
return call(call_id_new_irq(), (Call_arg) p, irq_nr, signal_context_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set trigger/polaruty of IRQ
|
||||
* \param irq_nr interrupt number
|
||||
* \param trigger low or edge
|
||||
* \param polarity low or high
|
||||
*/
|
||||
inline void irq_mode(unsigned irq_nr, unsigned trigger, unsigned polarity)
|
||||
{
|
||||
call(call_id_irq_mode(), irq_nr, trigger, polarity);
|
||||
call(call_id_pause_vm(), (Call_arg) &vm);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,40 +200,9 @@ namespace Kernel
|
||||
*
|
||||
* \param irq pointer to interrupt kernel object
|
||||
*/
|
||||
inline void ack_irq(User_irq * const irq)
|
||||
inline void ack_irq(User_irq & irq)
|
||||
{
|
||||
call(call_id_ack_irq(), (Call_arg) irq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruct an interrupt object
|
||||
*
|
||||
* \param irq pointer to interrupt kernel object
|
||||
*/
|
||||
inline void delete_irq(User_irq * const irq)
|
||||
{
|
||||
call(call_id_delete_irq(), (Call_arg) irq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new object identity for a thread
|
||||
*
|
||||
* \param dst memory donation for the new object
|
||||
* \param cap capability id of the targeted thread
|
||||
*/
|
||||
inline capid_t new_obj(void * const dst, capid_t const cap)
|
||||
{
|
||||
return call(call_id_new_obj(), (Call_arg)dst, (Call_arg)cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an object identity
|
||||
*
|
||||
* \param dst pointer to the object identity object
|
||||
*/
|
||||
inline void delete_obj(void * const dst)
|
||||
{
|
||||
call(call_id_delete_obj(), (Call_arg)dst);
|
||||
call(call_id_ack_irq(), (Call_arg) &irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,10 +157,10 @@ addr_t Cpu::stack_start() {
|
||||
return (addr_t)&kernel_stack + KERNEL_STACK_SIZE * (_id+1); }
|
||||
|
||||
|
||||
Cpu::Cpu(unsigned const id, Board::Pic & pic,
|
||||
Cpu::Cpu(unsigned const id,
|
||||
Inter_processor_work_list & global_work_list)
|
||||
:
|
||||
_id(id), _pic(pic), _timer(*this),
|
||||
_id(id), _timer(*this),
|
||||
_scheduler(&_idle, _quota(), _fill()), _idle(*this),
|
||||
_ipi_irq(*this),
|
||||
_global_work_list(global_work_list)
|
||||
@@ -174,7 +174,7 @@ Cpu::Cpu(unsigned const id, Board::Pic & pic,
|
||||
bool Cpu_pool::initialize()
|
||||
{
|
||||
unsigned id = Cpu::executing_id();
|
||||
_cpus[id].construct(id, _pic, _global_work_list);
|
||||
_cpus[id].construct(id, _global_work_list);
|
||||
return --_initialized == 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
|
||||
|
||||
unsigned const _id;
|
||||
Board::Pic &_pic;
|
||||
Board::Pic _pic {};
|
||||
Timer _timer;
|
||||
Cpu_scheduler _scheduler;
|
||||
Idle_thread _idle;
|
||||
@@ -132,7 +132,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
|
||||
/**
|
||||
* Construct object for CPU 'id'
|
||||
*/
|
||||
Cpu(unsigned const id, Board::Pic & pic,
|
||||
Cpu(unsigned const id,
|
||||
Inter_processor_work_list & global_work_list);
|
||||
|
||||
static inline unsigned primary_id() { return 0; }
|
||||
@@ -191,7 +191,6 @@ class Kernel::Cpu_pool
|
||||
{
|
||||
private:
|
||||
|
||||
Board::Pic _pic {};
|
||||
Inter_processor_work_list _global_work_list {};
|
||||
unsigned _count;
|
||||
unsigned _initialized { _count };
|
||||
|
||||
@@ -46,4 +46,6 @@ void Cpu::trigger_ip_interrupt()
|
||||
}
|
||||
|
||||
|
||||
Cpu::Ipi::Ipi(Cpu & cpu) : Irq(Board::Pic::IPI, cpu), cpu(cpu) { }
|
||||
Cpu::Ipi::Ipi(Cpu & cpu)
|
||||
: Irq(Board::Pic::IPI, cpu), cpu(cpu) {
|
||||
cpu.pic().unmask(Board::Pic::IPI, cpu.id()); }
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
#ifndef _CORE__KERNEL__IPC_NODE_H_
|
||||
#define _CORE__KERNEL__IPC_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/construct_at.h>
|
||||
|
||||
/* base-local includes */
|
||||
#include <base/internal/native_utcb.h>
|
||||
|
||||
|
||||
@@ -30,3 +30,14 @@ Kernel::Irq::Pool &Kernel::User_irq::_pool()
|
||||
static Irq::Pool p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
Kernel::User_irq::User_irq(unsigned const irq,
|
||||
Genode::Irq_session::Trigger trigger,
|
||||
Genode::Irq_session::Polarity polarity,
|
||||
Signal_context & context)
|
||||
: Irq(irq, _pool()), _context(context)
|
||||
{
|
||||
disable();
|
||||
cpu_pool().executing_cpu().pic().irq_mode(_irq_nr, trigger, polarity);
|
||||
}
|
||||
|
||||
@@ -135,8 +135,10 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
|
||||
/**
|
||||
* Construct object that signals interrupt 'irq' via signal 'context'
|
||||
*/
|
||||
User_irq(unsigned const irq, Signal_context &context)
|
||||
: Irq(irq, _pool()), _context(context) { disable(); }
|
||||
User_irq(unsigned const irq,
|
||||
Genode::Irq_session::Trigger trigger,
|
||||
Genode::Irq_session::Polarity polarity,
|
||||
Signal_context & context);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@@ -157,6 +159,33 @@ class Kernel::User_irq : public Kernel::Irq, public Kernel::Object
|
||||
*/
|
||||
static User_irq * object(unsigned const irq) {
|
||||
return dynamic_cast<User_irq*>(_pool().object(irq)); }
|
||||
|
||||
/**
|
||||
* Syscall to create user irq object
|
||||
*
|
||||
* \param irq reference to constructible object
|
||||
* \param nr interrupt number
|
||||
* \param trigger level or edge
|
||||
* \param polarity low or high
|
||||
* \param sig capability of signal context
|
||||
*/
|
||||
static capid_t syscall_create(Genode::Kernel_object<User_irq> & irq,
|
||||
unsigned nr,
|
||||
Genode::Irq_session::Trigger trigger,
|
||||
Genode::Irq_session::Polarity polarity,
|
||||
capid_t sig)
|
||||
{
|
||||
return call(call_id_new_irq(), (Call_arg)&irq, nr,
|
||||
(trigger << 2) | polarity, sig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syscall to delete user irq object
|
||||
*
|
||||
* \param irq reference to constructible object
|
||||
*/
|
||||
static void syscall_destroy(Genode::Kernel_object<User_irq> &irq) {
|
||||
call(call_id_delete_irq(), (Call_arg) &irq); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__KERNEL__IRQ_H_ */
|
||||
|
||||
@@ -31,7 +31,7 @@ class Kernel::Lock
|
||||
|
||||
enum State { UNLOCKED, LOCKED };
|
||||
|
||||
State volatile _locked { UNLOCKED };
|
||||
int volatile _locked { UNLOCKED };
|
||||
unsigned volatile _current_cpu { INVALID };
|
||||
|
||||
public:
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
#include <util/avl_tree.h>
|
||||
#include <util/bit_allocator.h>
|
||||
#include <util/list.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/core_interface.h>
|
||||
#include <kernel/interface.h>
|
||||
#include <kernel/kernel.h>
|
||||
|
||||
@@ -192,6 +194,13 @@ class Kernel::Core_object_identity : public Object_identity,
|
||||
Object_identity_reference(this, core_pd()) { }
|
||||
|
||||
capid_t core_capid() { return capid(); }
|
||||
|
||||
static capid_t syscall_create(Genode::Constructible<Core_object_identity<T>> & t,
|
||||
capid_t const cap) {
|
||||
return call(call_id_new_obj(), (Call_arg)&t, (Call_arg)cap); }
|
||||
|
||||
static void syscall_destroy(Genode::Constructible<Core_object_identity<T>> & t) {
|
||||
call(call_id_delete_obj(), (Call_arg)&t); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
#include <hw/assert.h>
|
||||
#include <cpu.h>
|
||||
#include <kernel/core_interface.h>
|
||||
#include <kernel/object.h>
|
||||
#include <object.h>
|
||||
#include <translation_table.h>
|
||||
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
namespace Genode {
|
||||
class Platform_pd;
|
||||
}
|
||||
@@ -51,6 +53,7 @@ class Kernel::Pd : public Kernel::Object
|
||||
Genode::Platform_pd &_platform_pd;
|
||||
Capid_allocator _capid_alloc { };
|
||||
Object_identity_reference_tree _cap_tree { };
|
||||
bool _core_pd { false };
|
||||
|
||||
public:
|
||||
|
||||
@@ -69,6 +72,12 @@ class Kernel::Pd : public Kernel::Object
|
||||
{
|
||||
capid_t invalid = _capid_alloc.alloc();
|
||||
assert(invalid == cap_id_invalid());
|
||||
|
||||
static bool first_pd = true;
|
||||
if (first_pd) {
|
||||
_core_pd = true;
|
||||
first_pd = false;
|
||||
}
|
||||
}
|
||||
|
||||
~Pd()
|
||||
@@ -77,16 +86,16 @@ class Kernel::Pd : public Kernel::Object
|
||||
oir->~Object_identity_reference();
|
||||
}
|
||||
|
||||
static capid_t syscall_create(void * const dst,
|
||||
Hw::Page_table &tt,
|
||||
Genode::Platform_pd &pd)
|
||||
static capid_t syscall_create(Genode::Kernel_object<Pd> & p,
|
||||
Hw::Page_table & tt,
|
||||
Genode::Platform_pd & pd)
|
||||
{
|
||||
return call(call_id_new_pd(), (Call_arg)dst,
|
||||
return call(call_id_new_pd(), (Call_arg)&p,
|
||||
(Call_arg)&tt, (Call_arg)&pd);
|
||||
}
|
||||
|
||||
static void syscall_destroy(Pd * const pd) {
|
||||
call(call_id_delete_pd(), (Call_arg)pd); }
|
||||
static void syscall_destroy(Genode::Kernel_object<Pd> & p) {
|
||||
call(call_id_delete_pd(), (Call_arg)&p); }
|
||||
|
||||
/**
|
||||
* Check whether the given 'cpu' needs to do some maintainance
|
||||
@@ -103,6 +112,13 @@ class Kernel::Pd : public Kernel::Object
|
||||
Hw::Page_table &translation_table() { return _table; }
|
||||
Capid_allocator &capid_alloc() { return _capid_alloc; }
|
||||
Object_identity_reference_tree &cap_tree() { return _cap_tree; }
|
||||
bool core_pd() const { return _core_pd; }
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
inline Kernel::Core_object_identity<Kernel::Pd>::Core_object_identity(Kernel::Pd & pd)
|
||||
: Object_identity(pd),
|
||||
Object_identity_reference(this, pd.core_pd() ? pd : core_pd()) { }
|
||||
|
||||
#endif /* _CORE__KERNEL__PD_H_ */
|
||||
|
||||
@@ -55,7 +55,7 @@ Signal_context_killer::~Signal_context_killer() { cancel_waiting(); }
|
||||
|
||||
void Signal_context::_deliverable()
|
||||
{
|
||||
if (_submits) { _receiver->_add_deliverable(this); }
|
||||
if (_submits) { _receiver._add_deliverable(this); }
|
||||
}
|
||||
|
||||
|
||||
@@ -118,16 +118,15 @@ int Signal_context::kill(Signal_context_killer * const k)
|
||||
Signal_context::~Signal_context()
|
||||
{
|
||||
if (_killer) { _killer->_signal_context_kill_failed(); }
|
||||
_receiver->_context_destructed(this);
|
||||
_receiver._context_destructed(this);
|
||||
}
|
||||
|
||||
|
||||
Signal_context::Signal_context(Signal_receiver * const r, addr_t const imprint)
|
||||
:
|
||||
_receiver(r),
|
||||
_imprint(imprint)
|
||||
Signal_context::Signal_context(Signal_receiver & r, addr_t const imprint)
|
||||
: _receiver(r),
|
||||
_imprint(imprint)
|
||||
{
|
||||
r->_add_context(this);
|
||||
r._add_context(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +163,7 @@ void Signal_receiver::_listen()
|
||||
/* communicate signal data to handler */
|
||||
_handlers.dequeue([&] (Signal_handler::Fifo_element &elem) {
|
||||
auto const handler = &elem.object();
|
||||
handler->_receiver = 0;
|
||||
handler->_receiver = nullptr;
|
||||
handler->_receive_signal(&data, sizeof(data));
|
||||
});
|
||||
context->_delivered();
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/signal.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
#include <kernel/core_interface.h>
|
||||
#include <kernel/object.h>
|
||||
#include <object.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -160,7 +161,7 @@ class Kernel::Signal_context : public Kernel::Object
|
||||
|
||||
Fifo_element _deliver_fe { *this };
|
||||
Fifo_element _contexts_fe { *this };
|
||||
Signal_receiver * const _receiver;
|
||||
Signal_receiver & _receiver;
|
||||
addr_t const _imprint;
|
||||
Signal_context_killer * _killer { nullptr };
|
||||
unsigned _submits { 0 };
|
||||
@@ -197,7 +198,7 @@ class Kernel::Signal_context : public Kernel::Object
|
||||
*
|
||||
* \throw Assign_to_receiver_failed
|
||||
*/
|
||||
Signal_context(Signal_receiver * const r, addr_t const imprint);
|
||||
Signal_context(Signal_receiver & r, addr_t const imprint);
|
||||
|
||||
/**
|
||||
* Submit the signal
|
||||
@@ -233,12 +234,12 @@ class Kernel::Signal_context : public Kernel::Object
|
||||
*
|
||||
* \retval capability id of the new kernel object
|
||||
*/
|
||||
static capid_t syscall_create(void * p,
|
||||
Signal_receiver * const receiver,
|
||||
static capid_t syscall_create(Genode::Kernel_object<Signal_context> &c,
|
||||
Signal_receiver & receiver,
|
||||
addr_t const imprint)
|
||||
{
|
||||
return call(call_id_new_signal_context(), (Call_arg)p,
|
||||
(Call_arg)receiver, (Call_arg)imprint);
|
||||
return call(call_id_new_signal_context(), (Call_arg)&c,
|
||||
(Call_arg)&receiver, (Call_arg)imprint);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,8 +247,8 @@ class Kernel::Signal_context : public Kernel::Object
|
||||
*
|
||||
* \param context pointer to signal context kernel object
|
||||
*/
|
||||
static void syscall_destroy(Signal_context * const context) {
|
||||
call(call_id_delete_signal_context(), (Call_arg)context); }
|
||||
static void syscall_destroy(Genode::Kernel_object<Signal_context> &c) {
|
||||
call(call_id_delete_signal_context(), (Call_arg)&c); }
|
||||
};
|
||||
|
||||
class Kernel::Signal_receiver : public Kernel::Object
|
||||
@@ -311,16 +312,16 @@ class Kernel::Signal_receiver : public Kernel::Object
|
||||
*
|
||||
* \retval capability id of the new kernel object
|
||||
*/
|
||||
static capid_t syscall_create(void * p) {
|
||||
return call(call_id_new_signal_receiver(), (Call_arg)p); }
|
||||
static capid_t syscall_create(Genode::Kernel_object<Signal_receiver> &r) {
|
||||
return call(call_id_new_signal_receiver(), (Call_arg)&r); }
|
||||
|
||||
/**
|
||||
* Syscall to destruct a signal receiver
|
||||
*
|
||||
* \param receiver pointer to signal receiver kernel object
|
||||
*/
|
||||
static void syscall_destroy(Signal_receiver * const receiver) {
|
||||
call(call_id_delete_signal_receiver(), (Call_arg)receiver); }
|
||||
static void syscall_destroy(Genode::Kernel_object<Signal_receiver> &r) {
|
||||
call(call_id_delete_signal_receiver(), (Call_arg)&r); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__KERNEL__SIGNAL_RECEIVER_H_ */
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
/* Genode includes */
|
||||
#include <base/thread_state.h>
|
||||
#include <cpu_session/cpu_session.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/unmanaged_singleton.h>
|
||||
@@ -47,17 +46,17 @@ Thread::Tlb_invalidation::Tlb_invalidation(Thread & caller, Pd & pd,
|
||||
}
|
||||
|
||||
|
||||
Thread::Destroy::Destroy(Thread & caller, Thread & to_delete)
|
||||
Thread::Destroy::Destroy(Thread & caller, Genode::Kernel_object<Thread> & to_delete)
|
||||
: caller(caller), thread_to_destroy(to_delete)
|
||||
{
|
||||
thread_to_destroy._cpu->work_list().insert(&_le);
|
||||
thread_to_destroy->_cpu->work_list().insert(&_le);
|
||||
caller._become_inactive(AWAITS_RESTART);
|
||||
}
|
||||
|
||||
|
||||
void Thread::Destroy::execute()
|
||||
{
|
||||
thread_to_destroy.~Thread();
|
||||
thread_to_destroy.destruct();
|
||||
cpu_pool().executing_cpu().work_list().remove(&_le);
|
||||
caller._restart();
|
||||
}
|
||||
@@ -193,28 +192,6 @@ size_t Thread::_core_to_kernel_quota(size_t const quota) const
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_new_thread()
|
||||
{
|
||||
void * const p = (void *)user_arg_1();
|
||||
unsigned const priority = user_arg_2();
|
||||
unsigned const quota = _core_to_kernel_quota(user_arg_3());
|
||||
char const * const label = (char *)user_arg_4();
|
||||
Core_object<Thread> * co =
|
||||
Genode::construct_at<Core_object<Thread> >(p, priority, quota, label);
|
||||
user_arg_0(co->core_capid());
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_new_core_thread()
|
||||
{
|
||||
void * const p = (void *)user_arg_1();
|
||||
char const * const label = (char *)user_arg_2();
|
||||
Core_object<Thread> * co =
|
||||
Genode::construct_at<Core_object<Thread> >(p, label);
|
||||
user_arg_0(co->core_capid());
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_thread_quota()
|
||||
{
|
||||
Thread * const thread = (Thread *)user_arg_1();
|
||||
@@ -227,7 +204,7 @@ void Thread::_call_start_thread()
|
||||
/* lookup CPU */
|
||||
Cpu & cpu = cpu_pool().cpu(user_arg_2());
|
||||
user_arg_0(0);
|
||||
Thread &thread = *(Thread *)user_arg_1();
|
||||
Thread &thread = *(Thread*)user_arg_1();
|
||||
|
||||
assert(thread._state == AWAITS_START);
|
||||
|
||||
@@ -338,7 +315,8 @@ void Thread::_call_yield_thread()
|
||||
|
||||
void Thread::_call_delete_thread()
|
||||
{
|
||||
Thread * to_delete = reinterpret_cast<Thread*>(user_arg_1());
|
||||
Genode::Kernel_object<Thread> & to_delete =
|
||||
*(Genode::Kernel_object<Thread>*)user_arg_1();
|
||||
|
||||
/**
|
||||
* Delete a thread immediately if it has no cpu assigned yet,
|
||||
@@ -346,7 +324,7 @@ void Thread::_call_delete_thread()
|
||||
*/
|
||||
if (!to_delete->_cpu ||
|
||||
(to_delete->_cpu->id() == Cpu::executing_id() ||
|
||||
&to_delete->_cpu->scheduled_job() != to_delete)) {
|
||||
&to_delete->_cpu->scheduled_job() != &*to_delete)) {
|
||||
_call_delete<Thread>();
|
||||
return;
|
||||
}
|
||||
@@ -354,7 +332,7 @@ void Thread::_call_delete_thread()
|
||||
/**
|
||||
* Construct a cross-cpu work item and send an IPI
|
||||
*/
|
||||
_destroy.construct(*this, *to_delete);
|
||||
_destroy.construct(*this, to_delete);
|
||||
to_delete->_cpu->trigger_ip_interrupt();
|
||||
}
|
||||
|
||||
@@ -566,21 +544,19 @@ void Thread::_call_kill_signal_context()
|
||||
|
||||
void Thread::_call_new_irq()
|
||||
{
|
||||
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_3());
|
||||
Signal_context * const c = pd().cap_tree().find<Signal_context>(user_arg_4());
|
||||
if (!c) {
|
||||
Genode::raw(*this, ": invalid signal context for interrupt");
|
||||
user_arg_0(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
new ((void *)user_arg_1()) User_irq(user_arg_2(), *c);
|
||||
user_arg_0(0);
|
||||
}
|
||||
Genode::Irq_session::Trigger trigger =
|
||||
(Genode::Irq_session::Trigger) (user_arg_3() & 0b1100);
|
||||
Genode::Irq_session::Polarity polarity =
|
||||
(Genode::Irq_session::Polarity) (user_arg_3() & 0b11);
|
||||
|
||||
void Thread::_call_irq_mode()
|
||||
{
|
||||
cpu_pool().executing_cpu().pic().irq_mode(user_arg_1(), user_arg_2(),
|
||||
user_arg_3());
|
||||
_call_new<User_irq>((unsigned)user_arg_2(), trigger, polarity, *c);
|
||||
}
|
||||
|
||||
|
||||
@@ -601,17 +577,18 @@ void Thread::_call_new_obj()
|
||||
return;
|
||||
}
|
||||
|
||||
using Thread_identity = Core_object_identity<Thread>;
|
||||
Thread_identity * coi =
|
||||
Genode::construct_at<Thread_identity>((void *)user_arg_1(), *thread);
|
||||
using Thread_identity = Genode::Constructible<Core_object_identity<Thread>>;
|
||||
Thread_identity & coi = *(Thread_identity*)user_arg_1();
|
||||
coi.construct(*thread);
|
||||
user_arg_0(coi->core_capid());
|
||||
}
|
||||
|
||||
|
||||
void Thread::_call_delete_obj()
|
||||
{
|
||||
using Object = Core_object_identity<Thread>;
|
||||
reinterpret_cast<Object*>(user_arg_1())->~Object();
|
||||
using Thread_identity = Genode::Constructible<Core_object_identity<Thread>>;
|
||||
Thread_identity & coi = *(Thread_identity*)user_arg_1();
|
||||
coi.destruct();
|
||||
}
|
||||
|
||||
|
||||
@@ -686,8 +663,14 @@ void Thread::_call()
|
||||
}
|
||||
/* switch over kernel calls that are restricted to core */
|
||||
switch (call_id) {
|
||||
case call_id_new_thread(): _call_new_thread(); return;
|
||||
case call_id_new_core_thread(): _call_new_core_thread(); return;
|
||||
case call_id_new_thread():
|
||||
_call_new<Thread>((unsigned) user_arg_2(),
|
||||
(unsigned) _core_to_kernel_quota(user_arg_3()),
|
||||
(char const *) user_arg_4());
|
||||
return;
|
||||
case call_id_new_core_thread():
|
||||
_call_new<Thread>((char const *) user_arg_2());
|
||||
return;
|
||||
case call_id_thread_quota(): _call_thread_quota(); return;
|
||||
case call_id_delete_thread(): _call_delete_thread(); return;
|
||||
case call_id_start_thread(): _call_start_thread(); return;
|
||||
@@ -702,7 +685,7 @@ void Thread::_call()
|
||||
case call_id_delete_pd(): _call_delete<Pd>(); return;
|
||||
case call_id_new_signal_receiver(): _call_new<Signal_receiver>(); return;
|
||||
case call_id_new_signal_context():
|
||||
_call_new<Signal_context>((Signal_receiver*) user_arg_2(), user_arg_3());
|
||||
_call_new<Signal_context>(*(Signal_receiver*) user_arg_2(), user_arg_3());
|
||||
return;
|
||||
case call_id_delete_signal_context(): _call_delete<Signal_context>(); return;
|
||||
case call_id_delete_signal_receiver(): _call_delete<Signal_receiver>(); return;
|
||||
@@ -712,8 +695,7 @@ void Thread::_call()
|
||||
case call_id_pause_vm(): _call_pause_vm(); return;
|
||||
case call_id_pause_thread(): _call_pause_thread(); return;
|
||||
case call_id_new_irq(): _call_new_irq(); return;
|
||||
case call_id_irq_mode(): _call_irq_mode(); return;
|
||||
case call_id_delete_irq(): _call_delete<Irq>(); return;
|
||||
case call_id_delete_irq(): _call_delete<User_irq>(); return;
|
||||
case call_id_ack_irq(): _call_ack_irq(); return;
|
||||
case call_id_new_obj(): _call_new_obj(); return;
|
||||
case call_id_delete_obj(): _call_delete_obj(); return;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <kernel/inter_processor_work.h>
|
||||
#include <kernel/signal_receiver.h>
|
||||
#include <kernel/ipc_node.h>
|
||||
#include <kernel/object.h>
|
||||
#include <object.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@@ -89,10 +89,12 @@ class Kernel::Thread
|
||||
*/
|
||||
struct Destroy : Inter_processor_work
|
||||
{
|
||||
Thread & caller; /* the caller gets blocked till the end */
|
||||
Thread & thread_to_destroy; /* thread to be destroyed */
|
||||
using Kthread = Genode::Kernel_object<Thread>;
|
||||
|
||||
Destroy(Thread & caller, Thread & to_destroy);
|
||||
Thread & caller; /* the caller gets blocked till the end */
|
||||
Kthread & thread_to_destroy; /* thread to be destroyed */
|
||||
|
||||
Destroy(Thread & caller, Kthread & to_destroy);
|
||||
|
||||
/************************************
|
||||
** Inter_processor_work interface **
|
||||
@@ -241,18 +243,19 @@ class Kernel::Thread
|
||||
template <typename T, typename... ARGS>
|
||||
void _call_new(ARGS &&... args)
|
||||
{
|
||||
using Object = Core_object<T>;
|
||||
void * dst = (void *)user_arg_1();
|
||||
Object * o = Genode::construct_at<Object>(dst, args...);
|
||||
user_arg_0(o->core_capid());
|
||||
Genode::Kernel_object<T> & kobj =
|
||||
*(Genode::Kernel_object<T>*)user_arg_1();
|
||||
kobj.construct(args...);
|
||||
user_arg_0(kobj->core_capid());
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void _call_delete()
|
||||
{
|
||||
using Object = Core_object<T>;
|
||||
reinterpret_cast<Object*>(user_arg_1())->~Object();
|
||||
Genode::Kernel_object<T> & kobj =
|
||||
*(Genode::Kernel_object<T>*)user_arg_1();
|
||||
kobj.destruct();
|
||||
}
|
||||
|
||||
|
||||
@@ -317,12 +320,14 @@ class Kernel::Thread
|
||||
void user_arg_2(Kernel::Call_arg const arg);
|
||||
void user_arg_3(Kernel::Call_arg const arg);
|
||||
void user_arg_4(Kernel::Call_arg const arg);
|
||||
void user_arg_5(Kernel::Call_arg const arg);
|
||||
|
||||
Kernel::Call_arg user_arg_0() const;
|
||||
Kernel::Call_arg user_arg_1() const;
|
||||
Kernel::Call_arg user_arg_2() const;
|
||||
Kernel::Call_arg user_arg_3() const;
|
||||
Kernel::Call_arg user_arg_4() const;
|
||||
Kernel::Call_arg user_arg_5() const;
|
||||
|
||||
/**
|
||||
* Syscall to create a thread
|
||||
@@ -334,11 +339,12 @@ class Kernel::Thread
|
||||
*
|
||||
* \retval capability id of the new kernel object
|
||||
*/
|
||||
static capid_t syscall_create(void * const p, unsigned const priority,
|
||||
size_t const quota,
|
||||
char const * const label)
|
||||
static capid_t syscall_create(Genode::Kernel_object<Thread> & t,
|
||||
unsigned const priority,
|
||||
size_t const quota,
|
||||
char const * const label)
|
||||
{
|
||||
return call(call_id_new_thread(), (Call_arg)p, (Call_arg)priority,
|
||||
return call(call_id_new_thread(), (Call_arg)&t, (Call_arg)priority,
|
||||
(Call_arg)quota, (Call_arg)label);
|
||||
}
|
||||
|
||||
@@ -350,9 +356,10 @@ class Kernel::Thread
|
||||
*
|
||||
* \retval capability id of the new kernel object
|
||||
*/
|
||||
static capid_t syscall_create(void * const p, char const * const label)
|
||||
static capid_t syscall_create(Genode::Kernel_object<Thread> & t,
|
||||
char const * const label)
|
||||
{
|
||||
return call(call_id_new_core_thread(), (Call_arg)p,
|
||||
return call(call_id_new_core_thread(), (Call_arg)&t,
|
||||
(Call_arg)label);
|
||||
}
|
||||
|
||||
@@ -361,8 +368,8 @@ class Kernel::Thread
|
||||
*
|
||||
* \param thread pointer to thread kernel object
|
||||
*/
|
||||
static void syscall_destroy(Thread * thread) {
|
||||
call(call_id_delete_thread(), (Call_arg)thread); }
|
||||
static void syscall_destroy(Genode::Kernel_object<Thread> & t) {
|
||||
call(call_id_delete_thread(), (Call_arg)&t); }
|
||||
|
||||
void print(Genode::Output &out) const;
|
||||
|
||||
|
||||
@@ -105,8 +105,6 @@ class Kernel::Timer
|
||||
|
||||
unsigned interrupt_id() const;
|
||||
|
||||
static void init_cpu_local();
|
||||
|
||||
time_t time() const { return _time + _duration(); }
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace Genode { class Vm_state; }
|
||||
#include <kernel/pd.h>
|
||||
#include <kernel/signal_receiver.h>
|
||||
|
||||
#include <board.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
@@ -36,19 +38,22 @@ class Kernel::Vm : public Cpu_job,
|
||||
{
|
||||
private:
|
||||
|
||||
using State = Board::Vm_state;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Vm(Vm const &);
|
||||
Vm &operator = (Vm const &);
|
||||
|
||||
enum State { ACTIVE, INACTIVE };
|
||||
enum Scheduler_state { ACTIVE, INACTIVE };
|
||||
|
||||
unsigned _id = 0;
|
||||
Genode::Vm_state * const _state;
|
||||
Signal_context * const _context;
|
||||
void * const _table;
|
||||
State _scheduled = INACTIVE;
|
||||
unsigned _id = 0;
|
||||
State & _state;
|
||||
Signal_context & _context;
|
||||
void * const _table;
|
||||
Scheduler_state _scheduled = INACTIVE;
|
||||
Board::Vcpu_context _vcpu_context;
|
||||
|
||||
public:
|
||||
|
||||
@@ -59,9 +64,10 @@ class Kernel::Vm : public Cpu_job,
|
||||
* \param context signal for VM exceptions other than interrupts
|
||||
* \param table translation table for guest to host physical memory
|
||||
*/
|
||||
Vm(void * const state,
|
||||
Signal_context * const context,
|
||||
void * const table);
|
||||
Vm(unsigned cpu,
|
||||
State & state,
|
||||
Signal_context & context,
|
||||
void * const table);
|
||||
|
||||
~Vm();
|
||||
|
||||
@@ -84,12 +90,14 @@ class Kernel::Vm : public Cpu_job,
|
||||
*
|
||||
* \retval cap id when successful, otherwise invalid cap id
|
||||
*/
|
||||
static capid_t syscall_create(void * const dst, void * const state,
|
||||
capid_t const signal_context_id,
|
||||
void * const table)
|
||||
static capid_t syscall_create(Genode::Kernel_object<Vm> & vm,
|
||||
unsigned cpu,
|
||||
void * const state,
|
||||
capid_t const signal_context_id,
|
||||
void * const table)
|
||||
{
|
||||
return call(call_id_new_vm(), (Call_arg)dst, (Call_arg)state,
|
||||
(Call_arg)table, signal_context_id);
|
||||
return call(call_id_new_vm(), (Call_arg)&vm, (Call_arg)cpu,
|
||||
(Call_arg)state, (Call_arg)table, signal_context_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,8 +107,8 @@ class Kernel::Vm : public Cpu_job,
|
||||
*
|
||||
* \retval 0 when successful, otherwise !=0
|
||||
*/
|
||||
static void syscall_destroy(Vm * const vm) {
|
||||
call(call_id_delete_vm(), (Call_arg) vm); }
|
||||
static void syscall_destroy(Genode::Kernel_object<Vm> & vm) {
|
||||
call(call_id_delete_vm(), (Call_arg) &vm); }
|
||||
|
||||
|
||||
/****************
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
void Kernel::Thread::_call_new_vm()
|
||||
{
|
||||
Signal_context * context =
|
||||
pd().cap_tree().find<Signal_context>(user_arg_4());
|
||||
pd().cap_tree().find<Signal_context>(user_arg_5());
|
||||
if (!context) {
|
||||
user_arg_0(cap_id_invalid());
|
||||
return;
|
||||
}
|
||||
|
||||
_call_new<Vm>((void*)user_arg_2(), context, (void*)user_arg_3());
|
||||
_call_new<Vm>((unsigned)user_arg_2(), *(Board::Vm_state*)user_arg_3(),
|
||||
*context, (void*)user_arg_4());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define _CORE__OBJECT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/construct_at.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/capability_space.h>
|
||||
@@ -35,13 +35,8 @@ namespace Genode {
|
||||
|
||||
|
||||
template <typename T>
|
||||
class Genode::Kernel_object
|
||||
class Genode::Kernel_object : public Genode::Constructible<Kernel::Core_object<T>>
|
||||
{
|
||||
private:
|
||||
|
||||
uint8_t _data[sizeof(Kernel::Core_object<T>)]
|
||||
__attribute__((aligned(sizeof(addr_t))));
|
||||
|
||||
protected:
|
||||
|
||||
Untyped_capability _cap { };
|
||||
@@ -55,15 +50,17 @@ class Genode::Kernel_object
|
||||
*/
|
||||
template <typename... ARGS>
|
||||
Kernel_object(bool syscall, ARGS &&... args)
|
||||
: _cap(Capability_space::import(syscall ? T::syscall_create(&_data, args...)
|
||||
: _cap(Capability_space::import(syscall ? T::syscall_create(*this, args...)
|
||||
: Kernel::cap_id_invalid()))
|
||||
{
|
||||
if (!syscall) construct_at<T>(&_data, args...);
|
||||
if (!syscall) Genode::Constructible<Kernel::Core_object<T>>::construct(args...);
|
||||
}
|
||||
|
||||
~Kernel_object() { T::syscall_destroy(kernel_object()); }
|
||||
|
||||
T * kernel_object() { return reinterpret_cast<T*>(_data); }
|
||||
~Kernel_object()
|
||||
{
|
||||
if (Genode::Constructible<Kernel::Core_object<T>>::constructed())
|
||||
T::syscall_destroy(*this);
|
||||
}
|
||||
|
||||
Untyped_capability cap() { return _cap; }
|
||||
|
||||
@@ -73,8 +70,10 @@ class Genode::Kernel_object
|
||||
template <typename... ARGS>
|
||||
bool create(ARGS &&... args)
|
||||
{
|
||||
if (_cap.valid()) return false;
|
||||
_cap = Capability_space::import(T::syscall_create(&_data, args...));
|
||||
if (Genode::Constructible<Kernel::Core_object<T>>::constructed())
|
||||
return false;
|
||||
|
||||
_cap = Capability_space::import(T::syscall_create(*this, args...));
|
||||
return _cap.valid();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,12 +53,12 @@ void Pager_object::wake_up()
|
||||
if (pt) pt->restart();
|
||||
}
|
||||
|
||||
void Pager_object::start_paging(Kernel::Signal_receiver * receiver)
|
||||
void Pager_object::start_paging(Kernel_object<Kernel::Signal_receiver> & receiver)
|
||||
{
|
||||
using Object = Kernel_object<Kernel::Signal_context>;
|
||||
using Entry = Object_pool<Pager_object>::Entry;
|
||||
|
||||
create(receiver, (unsigned long)this);
|
||||
create(*receiver, (unsigned long)this);
|
||||
Entry::cap(Object::_cap);
|
||||
}
|
||||
|
||||
@@ -103,13 +103,13 @@ void Pager_entrypoint::dissolve(Pager_object &o)
|
||||
|
||||
Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &)
|
||||
: Thread_deprecated<PAGER_EP_STACK_SIZE>("pager_ep"),
|
||||
Kernel_object<Kernel::Signal_receiver>(true)
|
||||
_kobj(true)
|
||||
{ start(); }
|
||||
|
||||
|
||||
Pager_capability Pager_entrypoint::manage(Pager_object &o)
|
||||
{
|
||||
o.start_paging(kernel_object());
|
||||
o.start_paging(_kobj);
|
||||
insert(&o);
|
||||
return reinterpret_cap_cast<Pager_object>(o.cap());
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ class Genode::Pager_object : private Object_pool<Pager_object>::Entry,
|
||||
*
|
||||
* \param receiver signal receiver that receives the page faults
|
||||
*/
|
||||
void start_paging(Kernel::Signal_receiver * receiver);
|
||||
void start_paging(Kernel_object<Kernel::Signal_receiver> & receiver);
|
||||
|
||||
/**
|
||||
* Called when a page-fault finally could not be resolved
|
||||
@@ -195,9 +195,12 @@ class Genode::Pager_object : private Object_pool<Pager_object>::Entry,
|
||||
|
||||
class Genode::Pager_entrypoint : public Object_pool<Pager_object>,
|
||||
public Thread_deprecated<PAGER_EP_STACK_SIZE>,
|
||||
private Kernel_object<Kernel::Signal_receiver>,
|
||||
private Ipc_pager
|
||||
{
|
||||
private:
|
||||
|
||||
Kernel_object<Kernel::Signal_receiver> _kobj;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
||||
@@ -69,26 +69,29 @@ void Hw::Address_space::flush(addr_t virt, size_t size, Core_local_addr)
|
||||
|
||||
try {
|
||||
_tt.remove_translation(virt, size, _tt_alloc);
|
||||
Kernel::invalidate_tlb(&_kernel_pd, virt, size);
|
||||
Kernel::invalidate_tlb(*_kobj, virt, size);
|
||||
} catch(...) {
|
||||
error("tried to remove invalid region!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Hw::Address_space::Address_space(Kernel::Pd & pd, Page_table & tt,
|
||||
Page_table::Allocator & tt_alloc)
|
||||
: _tt(tt), _tt_phys(Platform::core_page_table()),
|
||||
_tt_alloc(tt_alloc), _kernel_pd(pd) { }
|
||||
Hw::Address_space::Address_space(Page_table & tt,
|
||||
Page_table::Allocator & tt_alloc,
|
||||
Platform_pd & pd)
|
||||
: _tt(tt),
|
||||
_tt_phys(Platform::core_page_table()),
|
||||
_tt_alloc(tt_alloc),
|
||||
_kobj(false, *(Page_table*)translation_table_phys(), pd) {}
|
||||
|
||||
|
||||
Hw::Address_space::Address_space(Kernel::Pd & pd)
|
||||
Hw::Address_space::Address_space(Platform_pd & pd)
|
||||
: _tt(*construct_at<Page_table>(_table_alloc(), *((Page_table*)Hw::Mm::core_page_tables().base))),
|
||||
_tt_phys((addr_t)_cma().phys_addr(&_tt)),
|
||||
_tt_array(new (_cma()) Array([this] (void * virt) {
|
||||
return (addr_t)_cma().phys_addr(virt);})),
|
||||
_tt_alloc(_tt_array->alloc()),
|
||||
_kernel_pd(pd) { }
|
||||
_kobj(true, *(Page_table*)translation_table_phys(), pd) { }
|
||||
|
||||
|
||||
Hw::Address_space::~Address_space()
|
||||
@@ -142,20 +145,13 @@ void Platform_pd::assign_parent(Native_capability parent)
|
||||
|
||||
Platform_pd::Platform_pd(Page_table & tt,
|
||||
Page_table::Allocator & alloc)
|
||||
:
|
||||
Hw::Address_space(*kernel_object(), tt, alloc),
|
||||
Kernel_object<Kernel::Pd>(false, *(Page_table*)translation_table_phys(), *this),
|
||||
_label("core")
|
||||
{ }
|
||||
: Hw::Address_space(tt, alloc, *this), _label("core") { }
|
||||
|
||||
|
||||
Platform_pd::Platform_pd(Allocator &, char const *label)
|
||||
:
|
||||
Hw::Address_space(*kernel_object()),
|
||||
Kernel_object<Kernel::Pd>(true, *(Page_table*)translation_table_phys(), *this),
|
||||
_label(label)
|
||||
: Hw::Address_space(*this), _label(label)
|
||||
{
|
||||
if (!_cap.valid()) {
|
||||
if (!_kobj.cap().valid()) {
|
||||
error("failed to create kernel object");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
@@ -72,12 +72,11 @@ class Hw::Address_space : public Genode::Address_space
|
||||
using Table = Hw::Page_table;
|
||||
using Array = Table::Allocator::Array<DEFAULT_TRANSLATION_TABLE_MAX>;
|
||||
|
||||
Genode::Lock _lock { }; /* table lock */
|
||||
Table & _tt; /* table virt addr */
|
||||
Genode::addr_t _tt_phys; /* table phys addr */
|
||||
Array * _tt_array = nullptr;
|
||||
Table::Allocator & _tt_alloc; /* table allocator */
|
||||
Kernel::Pd & _kernel_pd;
|
||||
Genode::Lock _lock { }; /* table lock */
|
||||
Table & _tt; /* table virt addr */
|
||||
Genode::addr_t _tt_phys; /* table phys addr */
|
||||
Array * _tt_array = nullptr;
|
||||
Table::Allocator & _tt_alloc; /* table allocator */
|
||||
|
||||
static inline Genode::Core_mem_allocator &_cma();
|
||||
|
||||
@@ -85,25 +84,27 @@ class Hw::Address_space : public Genode::Address_space
|
||||
|
||||
protected:
|
||||
|
||||
Kernel_object<Kernel::Pd> _kobj;
|
||||
|
||||
/**
|
||||
* Core-specific constructor
|
||||
*
|
||||
* \param pd pointer to kernel's pd object
|
||||
* \param tt pointer to translation table
|
||||
* \param tt_alloc pointer to translation table allocator
|
||||
* \param tt reference to translation table
|
||||
* \param tt_alloc reference to translation table allocator
|
||||
* \param pd reference to platform pd object
|
||||
*/
|
||||
Address_space(Kernel::Pd & pd,
|
||||
Hw::Page_table & tt,
|
||||
Hw::Page_table::Allocator & tt_alloc);
|
||||
Address_space(Hw::Page_table & tt,
|
||||
Hw::Page_table::Allocator & tt_alloc,
|
||||
Platform_pd & pd);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param pd pointer to kernel's pd object
|
||||
* \param pd reference to platform pd object
|
||||
*/
|
||||
Address_space(Kernel::Pd & pd);
|
||||
Address_space(Platform_pd & pd);
|
||||
|
||||
~Address_space();
|
||||
|
||||
@@ -132,9 +133,9 @@ class Hw::Address_space : public Genode::Address_space
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
Kernel::Pd & kernel_pd() { return _kernel_pd; }
|
||||
Hw::Page_table & translation_table() { return _tt; }
|
||||
Genode::addr_t translation_table_phys() { return _tt_phys; }
|
||||
Kernel::Pd & kernel_pd() { return *_kobj; }
|
||||
Hw::Page_table & translation_table() { return _tt; }
|
||||
Genode::addr_t translation_table_phys() { return _tt_phys; }
|
||||
};
|
||||
|
||||
|
||||
@@ -161,8 +162,7 @@ class Genode::Cap_space
|
||||
|
||||
|
||||
class Genode::Platform_pd : public Hw::Address_space,
|
||||
private Cap_space,
|
||||
private Kernel_object<Kernel::Pd>
|
||||
private Cap_space
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ Platform_thread::~Platform_thread()
|
||||
void Platform_thread::quota(size_t const quota)
|
||||
{
|
||||
_quota = quota;
|
||||
Kernel::thread_quota(_kobj.kernel_object(), quota);
|
||||
Kernel::thread_quota(*_kobj, quota);
|
||||
}
|
||||
|
||||
|
||||
@@ -158,8 +158,8 @@ int Platform_thread::start(void * const ip, void * const sp)
|
||||
}
|
||||
|
||||
/* initialize thread registers */
|
||||
_kobj.kernel_object()->regs->ip = reinterpret_cast<addr_t>(ip);
|
||||
_kobj.kernel_object()->regs->sp = reinterpret_cast<addr_t>(sp);
|
||||
_kobj->regs->ip = reinterpret_cast<addr_t>(ip);
|
||||
_kobj->regs->sp = reinterpret_cast<addr_t>(sp);
|
||||
|
||||
/* start executing new thread */
|
||||
if (!_pd) {
|
||||
@@ -179,8 +179,7 @@ int Platform_thread::start(void * const ip, void * const sp)
|
||||
utcb.cap_add(Capability_space::capid(_pd->parent()));
|
||||
utcb.cap_add(Capability_space::capid(_utcb));
|
||||
}
|
||||
Kernel::start_thread(_kobj.kernel_object(), cpu, &_pd->kernel_pd(),
|
||||
_utcb_core_addr);
|
||||
Kernel::start_thread(*_kobj, cpu, _pd->kernel_pd(), *_utcb_core_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -189,7 +188,7 @@ void Platform_thread::pager(Pager_object &pager)
|
||||
{
|
||||
using namespace Kernel;
|
||||
|
||||
thread_pager(_kobj.kernel_object(), Capability_space::capid(pager.cap()));
|
||||
thread_pager(*_kobj, Capability_space::capid(pager.cap()));
|
||||
_pager = &pager;
|
||||
}
|
||||
|
||||
@@ -205,14 +204,14 @@ Genode::Pager_object &Platform_thread::pager()
|
||||
|
||||
Thread_state Platform_thread::state()
|
||||
{
|
||||
Thread_state bstate(*_kobj.kernel_object()->regs);
|
||||
Thread_state bstate(*_kobj->regs);
|
||||
return Thread_state(bstate);
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::state(Thread_state thread_state)
|
||||
{
|
||||
Cpu_state * cstate = static_cast<Cpu_state *>(&*_kobj.kernel_object()->regs);
|
||||
Cpu_state * cstate = static_cast<Cpu_state *>(&*_kobj->regs);
|
||||
*cstate = static_cast<Cpu_state>(thread_state);
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Genode {
|
||||
/**
|
||||
* Return information about current fault
|
||||
*/
|
||||
Kernel::Thread_fault fault_info() { return _kobj.kernel_object()->fault(); }
|
||||
Kernel::Thread_fault fault_info() { return _kobj->fault(); }
|
||||
|
||||
/**
|
||||
* Join a protection domain
|
||||
@@ -150,7 +150,7 @@ namespace Genode {
|
||||
/**
|
||||
* Pause this thread
|
||||
*/
|
||||
void pause() { Kernel::pause_thread(_kobj.kernel_object()); }
|
||||
void pause() { Kernel::pause_thread(*_kobj); }
|
||||
|
||||
/**
|
||||
* Enable/disable single stepping
|
||||
@@ -160,13 +160,13 @@ namespace Genode {
|
||||
/**
|
||||
* Resume this thread
|
||||
*/
|
||||
void resume() { Kernel::resume_thread(_kobj.kernel_object()); }
|
||||
void resume() { Kernel::resume_thread(*_kobj); }
|
||||
|
||||
/**
|
||||
* Cancel currently blocking operation
|
||||
*/
|
||||
void cancel_blocking() {
|
||||
Kernel::cancel_thread_blocking(_kobj.kernel_object()); }
|
||||
Kernel::cancel_thread_blocking(*_kobj); }
|
||||
|
||||
/**
|
||||
* Set CPU quota of the thread to 'quota'
|
||||
|
||||
@@ -36,7 +36,7 @@ void Pager_entrypoint::entry()
|
||||
if (cap.valid()) Kernel::ack_signal(Capability_space::capid(cap));
|
||||
|
||||
/* receive fault */
|
||||
if (Kernel::await_signal(Capability_space::capid(_cap))) continue;
|
||||
if (Kernel::await_signal(Capability_space::capid(_kobj.cap()))) continue;
|
||||
|
||||
Pager_object *po = *(Pager_object**)Thread::myself()->utcb()->data();
|
||||
cap = po->cap();
|
||||
|
||||
@@ -39,14 +39,18 @@ class Genode::Rpc_cap_factory
|
||||
/**
|
||||
* Kernel object placeholder held in a list
|
||||
*/
|
||||
struct Kobject : List<Kobject>::Element
|
||||
struct Kobject
|
||||
: List<Kobject>::Element
|
||||
{
|
||||
using Identity = Kernel::Core_object_identity<Kernel::Thread>;
|
||||
using O = Kernel::Core_object_identity<Kernel::Thread>;
|
||||
|
||||
Native_capability cap { };
|
||||
Constructible<O> kobj {};
|
||||
Native_capability cap;
|
||||
|
||||
uint8_t data[sizeof(Identity)]
|
||||
__attribute__((aligned(sizeof(addr_t))));
|
||||
Kobject(Native_capability ep)
|
||||
: cap(Capability_space::import(O::syscall_create(kobj, Capability_space::capid(ep)))) {}
|
||||
|
||||
void destruct() { O::syscall_destroy(kobj); }
|
||||
};
|
||||
|
||||
using Slab = Tslab<Kobject, get_page_size()>;
|
||||
@@ -68,7 +72,6 @@ class Genode::Rpc_cap_factory
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
while (Kobject * obj = _list.first()) {
|
||||
Kernel::delete_obj(obj->data);
|
||||
_list.remove(obj);
|
||||
destroy(&_slab, obj);
|
||||
}
|
||||
@@ -87,11 +90,8 @@ class Genode::Rpc_cap_factory
|
||||
Kobject * obj;
|
||||
if (!_slab.alloc(sizeof(Kobject), (void**)&obj))
|
||||
throw Allocator::Out_of_memory();
|
||||
construct_at<Kobject>(obj);
|
||||
construct_at<Kobject>(obj, ep);
|
||||
|
||||
/* create kernel object via syscall */
|
||||
Kernel::capid_t capid = Kernel::new_obj(obj->data, Capability_space::capid(ep));
|
||||
obj->cap = Capability_space::import(capid);
|
||||
if (!obj->cap.valid()) {
|
||||
raw("Invalid entrypoint ", (addr_t)Capability_space::capid(ep),
|
||||
" for allocating a capability!");
|
||||
@@ -110,7 +110,7 @@ class Genode::Rpc_cap_factory
|
||||
|
||||
for (Kobject * obj = _list.first(); obj; obj = obj->next()) {
|
||||
if (obj->cap.data() == cap.data()) {
|
||||
Kernel::delete_obj(obj->data);
|
||||
obj->destruct();
|
||||
_list.remove(obj);
|
||||
destroy(&_slab, obj);
|
||||
return;
|
||||
|
||||
@@ -55,19 +55,21 @@ struct Genode::Signal_source_component : private Kernel_object<Kernel::Signal_re
|
||||
using Signal_source_pool::Entry::cap;
|
||||
|
||||
Signal_source_component()
|
||||
:
|
||||
Kernel_object<Kernel::Signal_receiver>(true),
|
||||
Signal_source_pool::Entry(Kernel_object<Kernel::Signal_receiver>::_cap)
|
||||
: Kernel_object<Kernel::Signal_receiver>(true),
|
||||
Signal_source_pool::Entry(Kernel_object<Kernel::Signal_receiver>::cap())
|
||||
{ }
|
||||
|
||||
void submit(Signal_context_component *, unsigned long) { ASSERT_NEVER_CALLED; }
|
||||
|
||||
Kernel::Signal_receiver & signal_receiver() {
|
||||
return **static_cast<Kernel_object<Kernel::Signal_receiver>*>(this); }
|
||||
};
|
||||
|
||||
|
||||
Genode::Signal_context_component::Signal_context_component(Signal_source_component &s,
|
||||
addr_t const imprint)
|
||||
:
|
||||
Kernel_object<Kernel::Signal_context>(true, s.kernel_object(), imprint),
|
||||
Kernel_object<Kernel::Signal_context>(true, s.signal_receiver(), imprint),
|
||||
Signal_context_pool::Entry(Kernel_object<Kernel::Signal_context>::_cap)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
#include <cpu.h>
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
@@ -21,41 +22,109 @@ Board::Pic::Pic()
|
||||
|
||||
bool Board::Pic::take_request(unsigned & irq)
|
||||
{
|
||||
Core0_irq_source::access_t src = read<Core0_irq_source>();
|
||||
unsigned cpu = Genode::Cpu::executing_id();
|
||||
Core_irq_source<0>::access_t src = 0;
|
||||
switch (cpu) {
|
||||
case 0: src = read<Core_irq_source<0>>(); break;
|
||||
case 1: src = read<Core_irq_source<1>>(); break;
|
||||
case 2: src = read<Core_irq_source<2>>(); break;
|
||||
case 3: src = read<Core_irq_source<3>>(); break;
|
||||
}
|
||||
|
||||
if ((1 << TIMER_IRQ) & src) {
|
||||
irq = TIMER_IRQ;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (0xf0 & src) {
|
||||
irq = IPI;
|
||||
switch (cpu) {
|
||||
case 0: write<Core_mailbox_clear<0>>(1); break;
|
||||
case 1: write<Core_mailbox_clear<1>>(1); break;
|
||||
case 2: write<Core_mailbox_clear<2>>(1); break;
|
||||
case 3: write<Core_mailbox_clear<3>>(1); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::mask() { }
|
||||
void Board::Pic::_timer_irq(unsigned cpu, bool enable)
|
||||
{
|
||||
unsigned v = enable ? 1 : 0;
|
||||
switch (cpu) {
|
||||
case 0:
|
||||
write<Core_timer_irq_control<0>::Cnt_p_ns_irq>(v);
|
||||
return;
|
||||
case 1:
|
||||
write<Core_timer_irq_control<1>::Cnt_p_ns_irq>(v);
|
||||
return;
|
||||
case 2:
|
||||
write<Core_timer_irq_control<2>::Cnt_p_ns_irq>(v);
|
||||
return;
|
||||
case 3:
|
||||
write<Core_timer_irq_control<3>::Cnt_p_ns_irq>(v);
|
||||
return;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::_ipi(unsigned cpu, bool enable)
|
||||
{
|
||||
unsigned v = enable ? 1 : 0;
|
||||
switch (cpu) {
|
||||
case 0:
|
||||
write<Core_mailbox_irq_control<0>>(v);
|
||||
return;
|
||||
case 1:
|
||||
write<Core_mailbox_irq_control<1>>(v);
|
||||
return;
|
||||
case 2:
|
||||
write<Core_mailbox_irq_control<2>>(v);
|
||||
return;
|
||||
case 3:
|
||||
write<Core_mailbox_irq_control<3>>(v);
|
||||
return;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::unmask(unsigned const i, unsigned cpu)
|
||||
{
|
||||
if (cpu > 0)
|
||||
Genode::raw("multi-core irq controller not implemented yet");
|
||||
|
||||
if (i == TIMER_IRQ) {
|
||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(1);
|
||||
return;
|
||||
switch (i) {
|
||||
case TIMER_IRQ: _timer_irq(cpu, true); return;
|
||||
case IPI: _ipi(cpu, true); return;
|
||||
}
|
||||
|
||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
||||
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")");
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::mask(unsigned const i)
|
||||
{
|
||||
if (i == TIMER_IRQ) {
|
||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(0);
|
||||
return;
|
||||
unsigned cpu = Genode::Cpu::executing_id();
|
||||
switch (i) {
|
||||
case TIMER_IRQ: _timer_irq(cpu, false); return;
|
||||
case IPI: _ipi(cpu, false); return;
|
||||
}
|
||||
|
||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
||||
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")");
|
||||
}
|
||||
|
||||
|
||||
void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { }
|
||||
|
||||
|
||||
void Board::Pic::send_ipi(unsigned cpu_target)
|
||||
{
|
||||
switch (cpu_target) {
|
||||
case 0: write<Core_mailbox_set<0>>(1); return;
|
||||
case 1: write<Core_mailbox_set<1>>(1); return;
|
||||
case 2: write<Core_mailbox_set<2>>(1); return;
|
||||
case 3: write<Core_mailbox_set<3>>(1); return;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user