mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-22 13:02:56 +01:00
Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54ef87c979 | ||
|
|
0bbad0f5d4 | ||
|
|
2392700c79 | ||
|
|
e866bf3fa3 | ||
|
|
d68c7d1d10 | ||
|
|
89dbc10334 | ||
|
|
c78efd4428 | ||
|
|
9737b5d966 | ||
|
|
be392b3bf9 | ||
|
|
2b87628b3c | ||
|
|
76d38a8c76 | ||
|
|
c176fc24a1 | ||
|
|
70540e6f8e | ||
|
|
d2b82274db | ||
|
|
8d9561595c | ||
|
|
894974f73b | ||
|
|
818dad72d0 | ||
|
|
85031f1c1a | ||
|
|
c578a455ba | ||
|
|
417199ea64 | ||
|
|
d86380d744 | ||
|
|
e4194b4f44 | ||
|
|
7582396e9c | ||
|
|
07c8d1652e | ||
|
|
e7dad39016 | ||
|
|
1e3c80ff5b | ||
|
|
8e2b4d6f45 | ||
|
|
0836726df2 | ||
|
|
a40932a324 | ||
|
|
c13fbff8c1 | ||
|
|
47b0b9b689 | ||
|
|
422923cc95 | ||
|
|
a594ae703d | ||
|
|
babe1d1026 | ||
|
|
679ae1dd14 | ||
|
|
a31378476d | ||
|
|
0f47ac958b | ||
|
|
6329395026 | ||
|
|
3a40c27c26 | ||
|
|
467eee07a6 | ||
|
|
7617833365 | ||
|
|
2b69310adf | ||
|
|
00167aec14 | ||
|
|
b4a880ca54 | ||
|
|
2e1686558c | ||
|
|
34719c4589 | ||
|
|
8c66a4b1be | ||
|
|
95ff5ba11d | ||
|
|
57c4678aa1 | ||
|
|
322be1b4fb | ||
|
|
21fd2fc582 | ||
|
|
102444b82b | ||
|
|
34f169293f | ||
|
|
4ca1284e0e | ||
|
|
c2c8483293 | ||
|
|
5dea0b40aa | ||
|
|
63f8a38b5a | ||
|
|
cb579ec8d7 | ||
|
|
7cb4d7bf41 | ||
|
|
a3abf74d1e | ||
|
|
4caf12cd16 | ||
|
|
a838b6a657 | ||
|
|
7ecd83373c | ||
|
|
ab0fd6510f | ||
|
|
b69deec067 | ||
|
|
0ac039fad7 | ||
|
|
78e8e04b88 | ||
|
|
863b6fef80 | ||
|
|
0a835e4ce9 | ||
|
|
6d2c697da1 | ||
|
|
8843564850 | ||
|
|
3fd561aab6 | ||
|
|
0c2bdf9edd | ||
|
|
e479b9e8e8 | ||
|
|
1717d11742 | ||
|
|
15a379894a | ||
|
|
b2947d2187 | ||
|
|
671682cb6a | ||
|
|
f68889ea0a | ||
|
|
cb4302d06a | ||
|
|
623bc82e07 | ||
|
|
ff422ccc6e | ||
|
|
db56946ba9 | ||
|
|
86eb3f4a0d | ||
|
|
026b5a66c9 | ||
|
|
55bf0bb294 | ||
|
|
88f62b0988 | ||
|
|
e3c37f43a0 | ||
|
|
ce24547eea | ||
|
|
c706b1c0a7 | ||
|
|
febca1b827 | ||
|
|
a36d0ec83a | ||
|
|
363fd6065d | ||
|
|
a0abb093ed | ||
|
|
e1667e61cc | ||
|
|
e4ac1f99ed | ||
|
|
b5f1af6af0 | ||
|
|
cfea0ea97d | ||
|
|
cbe835f2c8 | ||
|
|
ce15800beb | ||
|
|
9262629a86 | ||
|
|
50950ec248 | ||
|
|
336018b493 | ||
|
|
25eec75ad8 | ||
|
|
988a7962a8 | ||
|
|
ee996d2280 | ||
|
|
e8d1d6e87c | ||
|
|
28112d1ff9 | ||
|
|
df8bdaaf79 | ||
|
|
f99ca9e372 | ||
|
|
6791fd18cc | ||
|
|
4be7b3c3ad | ||
|
|
d58509f446 | ||
|
|
f01472b308 | ||
|
|
2380fc442f | ||
|
|
901bff813d | ||
|
|
0f18ecc142 | ||
|
|
1a26f33469 | ||
|
|
e5b509cabb | ||
|
|
9a4a0448be | ||
|
|
91daf433c5 | ||
|
|
be7d5b4827 | ||
|
|
e63092f1dd | ||
|
|
ba321c20d1 | ||
|
|
6f8f9085f3 | ||
|
|
11a513ac63 | ||
|
|
8842ba2e1c | ||
|
|
1d920fa1b5 | ||
|
|
2cd902f09f | ||
|
|
bfa2ad7d47 | ||
|
|
77410a08a8 | ||
|
|
659f6ff5c8 | ||
|
|
59d26e040e | ||
|
|
5783ba4b1f | ||
|
|
d31492040c | ||
|
|
a59cf9f557 | ||
|
|
6344ab94b2 | ||
|
|
22db466194 | ||
|
|
fa0f7c0d6d | ||
|
|
727ac4bc0c | ||
|
|
d704563453 | ||
|
|
6370b6880a | ||
|
|
6f377ec4c5 | ||
|
|
9c027fd9bd | ||
|
|
cdaf6a502d | ||
|
|
6d02c4c89f | ||
|
|
51489e2f82 | ||
|
|
f36c0f150f | ||
|
|
b557fb13f9 | ||
|
|
4c7a5bb388 | ||
|
|
9ed935ff2a | ||
|
|
183a2c1be6 | ||
|
|
b4f41aecad | ||
|
|
3367fd27e4 | ||
|
|
68abf0616a | ||
|
|
cf358b5db1 | ||
|
|
513be78c05 | ||
|
|
9996acf091 | ||
|
|
36ca0497de | ||
|
|
136d87bd9a | ||
|
|
21154d6866 | ||
|
|
a9a6e8df89 | ||
|
|
726c32e5f6 | ||
|
|
6d391aae10 | ||
|
|
f970e4a71b | ||
|
|
f9422b241f | ||
|
|
9c0ced0a85 |
@@ -21,12 +21,16 @@ Quick start to build Genode for Linux
|
||||
The best starting point for exploring Genode is to run it on Linux. Make sure
|
||||
that your system satisfies the following requirements:
|
||||
|
||||
* GNU 'Make' version 3.81 or newer
|
||||
* GNU Make version 3.81 or newer
|
||||
* 'libSDL-dev'
|
||||
* 'tclsh' and 'expect'
|
||||
* 'byacc' (only needed for the L4/Fiasco kernel)
|
||||
* 'qemu' and 'genisoimage' (for testing non-Linux platforms via Qemu)
|
||||
|
||||
For using the entire collection of ported 3rd-party software, the following
|
||||
packages should be installed additionally: 'autoconf2.64', 'autogen', 'bison',
|
||||
'flex', 'g++', 'git', 'gperf', 'libxml2-utils', 'subversion', and 'xsltproc'.
|
||||
|
||||
Furthermore, you will need to install the official Genode toolchain, which
|
||||
you can download at [http://genode.org/download/tool-chain].
|
||||
|
||||
|
||||
81
doc/news.txt
81
doc/news.txt
@@ -4,6 +4,87 @@
|
||||
===========
|
||||
|
||||
|
||||
Genode OS Framework release 15.02 | 2015-01-27
|
||||
##############################################
|
||||
|
||||
| Version 15.02 extends the base-hw kernel with ARM-virtualization support,
|
||||
| introduces a highly modularized tool kit for automated testing, adds
|
||||
| support for the USB Armory platform, and improves the performance and
|
||||
| stability of VirtualBox on Genode/NOVA.
|
||||
|
||||
Most of the previous releases were motivated by our desire for features that
|
||||
we deemed as fundamentally important to use Genode as a general-purpose
|
||||
system. Now that we have reached most of the feature set that we longed after,
|
||||
the project adjusts its focus. According to our recently published
|
||||
[http://genode.org/about/road-map - roadmap], the underlying theme of the
|
||||
current development shifted towards the cultivation of the existing feature
|
||||
set rather than the introduction of new functionality. The current release
|
||||
perfectly reflects this change. It introduces a highly modular tool kit for
|
||||
scaling up the project's automated testing efforts and comes with stability
|
||||
and performance improvements all over the place. In particular, we are happy
|
||||
to report substantial performance gains of our version of VirtualBox running
|
||||
on NOVA.
|
||||
|
||||
As a second focus of the version 15.02, our custom base-hw kernel platform
|
||||
received a lot of attention. The most prominent news is the added support
|
||||
for virtualization on ARM. This line of work has been conducted and refined over
|
||||
the time span of more than a year and took much of our prior experience with
|
||||
the NOVA virtualization architecture and ARM TrustZone into account. This
|
||||
experience resulted in a novel microhypervisor design with an extremely
|
||||
tiny foot print with respect to the added complexity on the account of
|
||||
virtualization support. In fact, less than 1000 lines of code had to be added
|
||||
to the root of the trusted computing base. Besides virtualization
|
||||
support, our kernel's scheduler got refined to take IPC relationships into
|
||||
account while additionally gaining support for the USB Armory hardware platform.
|
||||
|
||||
These and many more improvements are covered in more detail by the
|
||||
[http:/documentation/release-notes/15.02 - release documentation of version 15.02...]
|
||||
|
||||
|
||||
Road Map for 2015 | 2015-01-14
|
||||
##############################
|
||||
|
||||
| After brainstorming Genode's mid-term future on our mailing list,
|
||||
| we finalized our road map for this year.
|
||||
|
||||
The development during the past years was primarily driven by our desire for
|
||||
features. With respect to the feature set, we have eventually reached a state
|
||||
where Genode becomes viable as general-purpose computing platform.
|
||||
|
||||
That said, we are still not there yet, because apart from a list
|
||||
of features, it is important how those features fit together and
|
||||
how easy it is to use them. Therefore, the focus for 2015 will be
|
||||
the consolidation and cultivation of the existing feature set.
|
||||
Still, there will be room for new developments, i.e., the use of
|
||||
Genode on the seL4 kernel.
|
||||
|
||||
The new road map is available at [http://genode.org/about/road-map].
|
||||
|
||||
|
||||
Genode at FOSDEM 2015 | 2015-01-14
|
||||
##################################
|
||||
|
||||
| With three talks, Genode will show a strong presence at this year's FOSDEM.
|
||||
| The talks will cover an introduction of Genode, our line of work
|
||||
| regarding VirtualBox on NOVA, and Genode's evolving GUI architecture.
|
||||
|
||||
Keeping up with our tradition to participate in the worlds largest
|
||||
gathering of the open-source and free-software community, we are happy
|
||||
to announce three talks to be held by Norman Feske at FOSDEM 2015:
|
||||
|
||||
Sunday 12:00 - 12:25 *Genode - OS security by design*
|
||||
_Security devroom (AW1.120)_
|
||||
|
||||
Sunday 14:20 - 15:00 *Transplantation of VirtualBox to the NOVA microhypervisor*
|
||||
_Virtualization devroom (UD2.120)_
|
||||
|
||||
Sunday 15:30 - 16:15 *Introducing a radically componentized GUI architecture*
|
||||
_Microkernel devroom (K.3.201)_
|
||||
|
||||
More information about the talks (including abstracts) are
|
||||
available at the [https://fosdem.org/2015/schedule/speaker/norman_feske/ - FOSDEM website].
|
||||
|
||||
|
||||
Genode OS Framework release 14.11 | 2014-11-28
|
||||
##############################################
|
||||
|
||||
|
||||
899
doc/release_notes-15-02.txt
Normal file
899
doc/release_notes-15-02.txt
Normal file
@@ -0,0 +1,899 @@
|
||||
|
||||
|
||||
===============================================
|
||||
Release notes for the Genode OS Framework 15.02
|
||||
===============================================
|
||||
|
||||
Genode Labs
|
||||
|
||||
|
||||
|
||||
Genode's [http://genode.org/about/road-map - roadmap] for this year puts a
|
||||
strong emphasis on the consolidation and cultivation of the existing feature
|
||||
set. With the first release of the year, version 15.02 pays tribute to this
|
||||
mission by stepping up to extensive and systematic automated testing. As
|
||||
a precondition for scaling up Genode's test infrastructure, the release
|
||||
features a highly modular tool kit for exercising system scenarios on a growing zoo
|
||||
of test machines. Section [Modular tool kit for automated testing] explains
|
||||
the new tools in detail. In the spirit of improving the existing feature
|
||||
set, Genode 15.02 vastly improves the performance and stability of our version of
|
||||
VirtualBox running on the NOVA microhypervisor, solves long-standing shortcomings
|
||||
of memory management on machines with a lot of RAM, addresses NOVA-related
|
||||
scalability limitations, stabilizes our Rump-kernel-based file-system server,
|
||||
and refines the configuration interface of the Intel wireless driver.
|
||||
|
||||
As the most significant new feature, the new version introduces virtualization
|
||||
support for ARM to our custom base-hw kernel. Section [Virtualization on ARM]
|
||||
outlines the design and implementation of this feature, which was greatly
|
||||
inspired by NOVA's virtualization architecture and has been developed over the
|
||||
time span of more than a year.
|
||||
|
||||
With respect to platform support, we are happy to accommodate the upcoming
|
||||
USB-Armory board, which is a computer in the form factor of a USB
|
||||
stick especially geared towards security applications. Section
|
||||
[Support for the USB-Armory board] covers the background and the current
|
||||
state of this line of work.
|
||||
|
||||
|
||||
Virtualization on ARM
|
||||
#####################
|
||||
|
||||
The ARMv7 architecture of recent processors like Cortex-A7, Cortex-A15, or
|
||||
Cortex-A17 CPUs support hardware extensions to facilitate virtualization of
|
||||
guest operating systems. With the current release, we enable the use of these
|
||||
virtualization extensions in our custom base-hw kernel when running on the
|
||||
Cortex-A15-based Arndale board.
|
||||
|
||||
While integrating ARM's virtualization extension, we aimed to strictly follow
|
||||
microkernel-construction principles. The primary design is inspired by the
|
||||
[http://hypervisor.org/ - NOVA OS Virtualization Architecture]. It is based on a
|
||||
microhypervisor that provides essential microkernel mechanisms along with
|
||||
basic primitives to switch between virtual machines (VMs). On top of the
|
||||
microhypervisor, classical OS services are implemented as
|
||||
ordinary, unprivileged user-level components. Those services can be used by other
|
||||
applications. Services may be shared between applications or instantiated
|
||||
separately, according to security and safety needs. Correspondingly,
|
||||
following the NOVA principles, each VM has its own associated virtual-machine
|
||||
monitor (VMM) that runs as an unprivileged user-level component. VMM implementations
|
||||
can range from simple ones that just emulate primary device requirements to highly
|
||||
complex monitors including sophisticated device models, like VirtualBox. The
|
||||
NOVA approach allows to decouple the TCB complexity of one VM with respect to
|
||||
another, as well as with respect to all components not related to
|
||||
virtualization at all.
|
||||
|
||||
Along those lines, we extended the base-hw kernel/core conglomerate with API
|
||||
extensions that enable user-level VMM components to create and control virtual
|
||||
machines.
|
||||
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
The ARM virtualization extensions are based on the so-called security
|
||||
extensions, commonly known as
|
||||
[http://genode.org/documentation/articles/trustzone - TrustZone].
|
||||
The ARM designers did not follow the
|
||||
Intel approach to split the CPU into a "root" and a "guest" world while having all prior
|
||||
existing CPU modes available in both worlds. Instead, ARM added a new privilege level
|
||||
to the non-secure side of TrustZone that sits underneath the ordinary kernel
|
||||
and userland privilege levels. It is subjected to a hypervisor-like kernel. All
|
||||
instructions used to prepare a VM's environment have to be executed in this so
|
||||
called "hyp" mode. In hyp mode, some instructions
|
||||
differ from their regular behaviour on the kernel-privilege level.
|
||||
For this reason, prior-existing kernel code cannot simply be reused in
|
||||
hyp mode without modifications.
|
||||
|
||||
The base-hw kernel is meant to execute Genode's core component on bare hardware.
|
||||
Core, which is an ordinary user-level component, is
|
||||
linked together with a slim kernel library that is executed in privileged kernel
|
||||
mode. To enable ARM hardware virtualization, we pushed this approach
|
||||
even further by executing core in three different privilege levels. Thereby,
|
||||
core shares the same view on hardware resources and virtual memory across all
|
||||
levels. A code path is executed on a higher privilege level only if the code
|
||||
would fail to execute on a lower privilege level.
|
||||
Following this approach, we were able to keep most of the existing kernel code
|
||||
with no modifications.
|
||||
|
||||
[image avirt_overview]
|
||||
Genode's ARM kernel (core) runs across all privilege levels
|
||||
|
||||
The hypervisor part of core is solely responsible to switch between VMs and the
|
||||
host system. Therefore, it needs to load/store additional CPU state that
|
||||
normally remains untouched during context switches of ordinary tasks. It also needs to
|
||||
configure the VM's guest-physical to host-physical memory translations. Moreover, the
|
||||
virtualization extensions of the ARMv7 architecture are not related to the CPU
|
||||
cores only. The interrupt controller and the CPU-local timers are also
|
||||
virtualization-aware. Therefore, the hypervisor has to load/store state specific
|
||||
to those devices, too. Nevertheless, the hypervisor merely reloads those
|
||||
devices. It does not interpret their state.
|
||||
|
||||
In contrast to the low-complexity hypervisor, a user-level VMM can be complex
|
||||
without putting the system's security at risk. It contains potentially complex
|
||||
device-emulation code and assigns hardware resources such as memory and
|
||||
interrupts to the VM. The VMM is an ordinary user-level component running
|
||||
unprivileged. Of course, as a plain user-level component, it is not able to
|
||||
directly access hardware resources. Hence an interface between VMMs and the
|
||||
kernel is needed to share the state of a virtual machine. In the past, we faced a similar
|
||||
problem when building a VMM for our former TrustZone experiments. It was natural
|
||||
to build upon the available solution and to extend it where necessary. Core
|
||||
provides a so-called VM service. Each VM corresponds to a session of this
|
||||
service. The session provides the following extended interface:
|
||||
|
||||
:CPU state:
|
||||
The CPU-state function returns a dataspace containing the virtual machine's
|
||||
state. The state is initialized by the VMM before bootstrapping the VM, gets updated
|
||||
by the hypervisor whenever it switches away from the VM, and can be used by
|
||||
the VMM to interpret the behavior of the guest OS. Moreover, the CPU state can be
|
||||
updated after the virtual machine monitor emulated instructions
|
||||
for the VM.
|
||||
|
||||
:Exception handler:
|
||||
The second function is used to register a signal handler that gets informed
|
||||
whenever the VM produces a virtualization fault.
|
||||
|
||||
:Run:
|
||||
The run function starts or resumes the execution of the VM.
|
||||
|
||||
:Pause:
|
||||
The pause function removes the VM from the kernel's scheduler.
|
||||
|
||||
:Attach:
|
||||
This function attaches a given RAM dataspace to a designated area of the
|
||||
guest-physical address space.
|
||||
|
||||
:Detach:
|
||||
The detach function invalidates a designated area of the guest-physical
|
||||
address space.
|
||||
|
||||
:Attach_pic: Tells the hypervisor to attach the CPU's virtual interface of the
|
||||
virtualization-aware interrupt controller to a designated area of the
|
||||
guest-physical address space.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
By strictly following the micro-kernel construction principles when integrating the
|
||||
hypervisor into the base-hw kernel, we reached a minimally invasive solution. In
|
||||
doing so, we took the time to separate TrustZone-specific code that was formerly
|
||||
an inherent part of the kernel on ARMv7 platforms. Now, TrustZone- and
|
||||
virtualization-specific aspects are incorporated into the kernel only if
|
||||
actually used. The change in complexity of the whole core component expressed in
|
||||
lines of code is shown in the table below. As can be seen, the additional code in
|
||||
the root of the trusted computing base when using virtualization is about 700-800
|
||||
LOC.
|
||||
|
||||
Platform | with TrustZone, no VT | TrustZone/VT optional
|
||||
-----------------------------------------------------------------
|
||||
hw_arndale | 17970 LOC | 18730 LOC
|
||||
----------------------------------------------------------------
|
||||
hw_imx53_qsb | 17900 LOC | 17760 LOC
|
||||
----------------------------------------------------------------
|
||||
hw_imx53_qsb_tz | 18260 LOC | 18320 LOC
|
||||
----------------------------------------------------------------
|
||||
hw_rpi | 17500 LOC | 17430 LOC
|
||||
----------------------------------------------------------------
|
||||
hw_panda | 18040 LOC | 17880 LOC
|
||||
----------------------------------------------------------------
|
||||
hw_odroid_xu | 17980 LOC | 18050 LOC
|
||||
|
||||
Besides the VM world switch, we enabled support for the so-called "large
|
||||
physical address extension" (LPAE), which is obligatory when using
|
||||
virtualization. It allows for addressing a 40-bit instead of only 32-bit physical
|
||||
address space. Moreover, to execute in hypervisor mode, the bootstrap code of
|
||||
the kernel had to be set up properly. Hence, when booting on the Arndale board,
|
||||
the kernel now prepares the non-secure TrustZone world first, and finally leaves the
|
||||
secure world forever.
|
||||
|
||||
To test and showcase the ARM virtualization features integrated in base-hw, we
|
||||
implemented a minimal, exemplary VMM. It can be found in
|
||||
_repos/os/src/server/vmm_. The VMM emulates a simplified variant of ARM's
|
||||
Versatile Express Cortex-A15 development platform. Currently, it only comprises
|
||||
support for the CPU, the timer, the interrupt controller, and a UART device. It is
|
||||
written in 1100 lines of C++ in addition to the base Genode libraries. The VMM
|
||||
is able to boot a vanilla Linux kernel compiled with a slightly modified
|
||||
standard configuration (no-SMP), and a device tree description stripped down to
|
||||
the devices provided by the VMM. This release includes an automated run test that
|
||||
executes the Linux kernel on top of the VMM on Genode. It can be started via:
|
||||
|
||||
! make run/vmm
|
||||
|
||||
[image avirt_screen]
|
||||
Three Linux serial consoles running in parallel on top of Genode
|
||||
|
||||
|
||||
Modular tool kit for automated testing
|
||||
######################################
|
||||
|
||||
In
|
||||
[http://genode.org/documentation/release-notes/13.05#Automated_quality-assurance_testing - Genode version 13.05],
|
||||
we already introduced comprehensive support for the automated testing of
|
||||
Genode scenarios. Since then, Genode Labs has significantly widened the scope
|
||||
of its internal test infrastructure, both in terms of the coverage of the test
|
||||
scenarios as well as the variety of the used hardware platforms.
|
||||
|
||||
The centerpiece of our test infrastructure is the so-called run tool. Steered
|
||||
by a script (run script), it performs all the steps necessary to test drive
|
||||
a Genode system scenario. Those steps are:
|
||||
|
||||
# *Building* the components of a scenario
|
||||
# *Configuration* of the init component
|
||||
# Assembly of the *boot directory*
|
||||
# Creation of the *boot image*
|
||||
# *Powering-on* the test machine
|
||||
# *Loading* of the boot image
|
||||
# Capturing the *LOG output*
|
||||
# *Validation* of the scenario behavior
|
||||
# *Powering-off* the test machine
|
||||
|
||||
Each of those steps depends on various parameters such as the
|
||||
used kernel, the hardware platform used to run the scenario, the
|
||||
way the test hardware is connected to the test infrastructure
|
||||
(e.g., UART, AMT, JTAG, network), the way the test hardware is powered or
|
||||
reseted, or the way of how the scenario is loaded into the test hardware.
|
||||
Naturally, to accommodate the growing variety of combinations of those
|
||||
parameters, the complexity of the run tool increased over time.
|
||||
This growth of complexity prompted us to eventually turn the run tool into a
|
||||
highly modular and extensible tool kit.
|
||||
|
||||
Originally, the run tool consisted of built-in rules that could be
|
||||
extended and tweaked by a kernel-specific supplement called run environment.
|
||||
The execution of a run script used to depend on the policies built into
|
||||
the run tool, the used run environment, and optional configuration
|
||||
parameters (run opts).
|
||||
|
||||
The new run tool kit replaces most of the formerly built-in policies by the
|
||||
ability to select and configure different modules for the various steps.
|
||||
The selection and configuration of the modules is expressed in the run-tool
|
||||
configuration. There exist the following types of modules:
|
||||
|
||||
:boot-dir modules:
|
||||
These modules contain the functionality to populate the boot directory
|
||||
and are specific to each kernel. It is mandatory to always include the
|
||||
module corresponding to the used kernel.
|
||||
|
||||
_(the available modules are: linux, hw, okl4, fiasco, pistachio, nova,_
|
||||
_codezero, foc)_
|
||||
|
||||
:image modules:
|
||||
These modules are used to wrap up all components used by the run script
|
||||
in a specific format and thereby prepare them for execution.
|
||||
Depending on the used kernel, different formats can be used. With these
|
||||
modules, the creation of ISO and disk images is also handled.
|
||||
|
||||
_(the available modules are: uboot, disk, iso)_
|
||||
|
||||
:load modules:
|
||||
These modules handle the way the components are transfered to the
|
||||
target system. Depending on the used kernel there are various options
|
||||
to pass on the components. For example, loading from TFTP or via JTAG is handled
|
||||
by the modules of this category.
|
||||
|
||||
_(the available modules are: tftp, jtag, fastboot)_
|
||||
|
||||
:log modules:
|
||||
These modules handle how the output of a currently executed run script
|
||||
is captured.
|
||||
|
||||
_(the available modules are: qemu, linux, serial, amt)_
|
||||
|
||||
:power_on modules:
|
||||
These modules are used for bringing the target system into a defined
|
||||
state, e.g., by starting or rebooting the system.
|
||||
|
||||
_(the available modules are: qemu, linux, softreset, powerplug, amt)_
|
||||
|
||||
:power_off modules:
|
||||
These modules are used for turning the target system off after the
|
||||
execution of a run script.
|
||||
|
||||
_(the available modules are: powerplug)_
|
||||
|
||||
When executing a run script, only one module of each category must be used.
|
||||
|
||||
Each module has the form of a script snippet located under the
|
||||
_tool/run/<step>/_
|
||||
directory where _<step>_ is a subdirectory named after the module type.
|
||||
Further instructions about the use of each module (e.g., additional
|
||||
configuration arguments) can be found in the form of comments inside the
|
||||
respective script snippets.
|
||||
Thanks to this modular structure,
|
||||
the extension of the tool kit comes down to adding a file at the corresponding
|
||||
module-type subdirectory. This way, custom work flows (such as tunneling JTAG
|
||||
over SSH) can be accommodated fairly easily.
|
||||
|
||||
|
||||
Usage examples
|
||||
==============
|
||||
|
||||
To execute a run script, a combination of modules may be used. The combination
|
||||
is controlled via the RUN_OPT variable used by the build framework. Here are a
|
||||
few common exemplary combinations:
|
||||
|
||||
Executing NOVA in Qemu:
|
||||
|
||||
!RUN_OPT = --include boot_dir/nova \
|
||||
! --include power_on/qemu --include log/qemu --include image/iso
|
||||
|
||||
Executing NOVA on a real x86 machine using AMT for resetting the target system
|
||||
and for capturing the serial output while loading the files via TFTP:
|
||||
|
||||
!RUN_OPT = --include boot_dir/nova \
|
||||
! --include power_on/amt --power-on-amt-host 10.23.42.13 \
|
||||
! --power-on-amt-password 'foo!' \
|
||||
! --include load/tftp --load-tftp-base-dir /var/lib/tftpboot \
|
||||
! --load-tftp-offset-dir /x86 \
|
||||
! --include log/amt --log-amt-host 10.23.42.13 \
|
||||
! --log-amt-password 'foo!'
|
||||
|
||||
Executing Fiasco.OC on a real x86 machine using AMT for resetting, USB serial
|
||||
for output while loading the files via TFTP:
|
||||
|
||||
!RUN_OPT = --include boot_dir/foc \
|
||||
! --include power_on/amt --amt-host 10.23.42.13 --amt-password 'foo!' \
|
||||
! --include load/tftp --tftp-base-dir /var/lib/tftpboot \
|
||||
! --tftp-offset-dir /x86 \
|
||||
! --include log/serial --log-serial-cmd 'picocom -b 115200 /dev/ttyUSB0'
|
||||
|
||||
Executing base-hw on a Raspberry Pi using powerplug to reset the hardware,
|
||||
JTAG to load the image and USB serial to capture the output:
|
||||
|
||||
!RUN_OPT = --include boot_dir/hw \
|
||||
! --include power_on/powerplug --power-on-powerplug-ip 10.23.42.5 \
|
||||
! --power-on-powerplug-user admin \
|
||||
! --power-on-powerplug-password secret \
|
||||
! --power-on-powerplug-port 1
|
||||
! --include power_off/powerplug --power-off-powerplug-ip 10.23.42.5 \
|
||||
! --power-off-powerplug-user admin \
|
||||
! --power-off-powerplug-password secret \
|
||||
! --power-off-powerplug-port 1
|
||||
! --include load/jtag \
|
||||
! --load-jtag-debugger /usr/share/openocd/scripts/interface/flyswatter2.cfg \
|
||||
! --load-jtag-board /usr/share/openocd/scripts/interface/raspberrypi.cfg \
|
||||
! --include log/serial --log-serial-cmd 'picocom -b 115200 /dev/ttyUSB0'
|
||||
|
||||
After the run script was executed successfully, the run tool will print the
|
||||
string 'Run script execution successful.". This message can be used to check
|
||||
for the successful completion of the run script when doing automated testing.
|
||||
|
||||
|
||||
Meaningful default behaviour
|
||||
============================
|
||||
|
||||
To maintain the ease of use of creating and using a build directory, the
|
||||
'create_builddir' tool equips a freshly created build directory with a meaningful
|
||||
default configuration that depends on the selected platform. For example, if
|
||||
creating a build directory for the Linux base platform, RUN_OPT
|
||||
is initially defined as
|
||||
|
||||
! RUN_OPT = --include boot_dir/linux \
|
||||
! --include power_on/linux --include log/linux
|
||||
|
||||
|
||||
Low-level OS infrastructure
|
||||
###########################
|
||||
|
||||
Improved management of physical memory
|
||||
======================================
|
||||
|
||||
On machines with a lot of memory, there exist constraints with regard to
|
||||
the physical address ranges of memory:
|
||||
|
||||
* On platforms with a non-uniform memory architecture, subsystems should
|
||||
preferably use memory that is local to the CPU cores the subsystem is using.
|
||||
Otherwise the performance is impeded by costly memory accesses to
|
||||
the memory of remote computing nodes.
|
||||
|
||||
* Unless an IOMMU is used, device drivers program physical addresses
|
||||
into device registers to perform DMA operations. Legacy devices such as
|
||||
USB UHCI controllers expect a 32-bit address. Consequently, the memory
|
||||
used as DMA buffers for those devices must not be allocated above 4 GiB.
|
||||
|
||||
* When using an IOMMU on NOVA, Genode represents the address space
|
||||
accessible by devices (by the means of DMA) using a so-called device PD
|
||||
([http://genode.org/documentation/release-notes/13.02#DMA_protection_via_IOMMU]).
|
||||
DMA transactions originating from PCI devices are subjected to the virtual
|
||||
address space of the device PD.
|
||||
All DMA buffers are identity-mapped with their physical addresses within
|
||||
the device PD. On 32-bit systems with more than 3 GiB of memory, this
|
||||
creates a problem. Because the device PD is a regular user-level component, the
|
||||
upper 1 GiB of its virtual address space is preserved for the kernel. Since
|
||||
no user-level memory objects can be attached to this
|
||||
area, the physical address range to be used for DMA buffers is limited
|
||||
to the lower 3 GiB.
|
||||
|
||||
Up to now, Genode components had no way to influence the allocation of
|
||||
memory with respect to physical address ranges. To solve the problems outlined
|
||||
above, we extended core's RAM services to take allocation constraints
|
||||
as session arguments when a RAM session is created. All dataspaces created
|
||||
from such a session are subjected to the specified constraints. In particular,
|
||||
this change enables the AHCI/PCI driver to allocate DMA buffers at suitable
|
||||
physical address ranges.
|
||||
|
||||
This innocent looking feature to constrain RAM allocations raises a problem
|
||||
though: If any component is able to constrain RAM allocations in
|
||||
arbitrary ways, it would become able to scan the physical address space for
|
||||
allocated memory by successively opening RAM sessions with the constraints set
|
||||
to an individual page and observe whether an allocation succeeds or not. Two
|
||||
conspiring components could use this information to construct a covert storage
|
||||
channel.
|
||||
|
||||
To prevent such an abuse, the init component filters out allocations
|
||||
constrains from RAM-session requests unless explicitly permitted. The
|
||||
permission is granted by supplementing the RAM resource assignment of
|
||||
a component with a new 'constrain_phys' attribute. For example:
|
||||
|
||||
! <resource name="RAM" quantum="3M" constrain_phys="yes"/>
|
||||
|
||||
|
||||
Init component
|
||||
==============
|
||||
|
||||
Most of Genode's example scenarios in the form of run scripts support
|
||||
different platforms. However, as the platform details vary, the run scripts
|
||||
have to tweak the configuration of the init component according to the
|
||||
features of the platform.
|
||||
For example, when declaring an explicit route to a framebuffer driver named
|
||||
"fb_drv", the run script won't work on Linux because on this platform, the
|
||||
framebuffer driver is called "fb_sdl".
|
||||
Another example is the role of the USB driver. Depending on the platform, the
|
||||
USB driver is an input driver, a block driver, a networking driver, or a
|
||||
combination of those.
|
||||
Consequently, run scripts with support
|
||||
for a great variety of platforms tend to become convoluted with
|
||||
platform-specific conditionals.
|
||||
|
||||
To counter this problem, we enhanced init to support aliases for component
|
||||
names. By defining the following aliases in the init configuration
|
||||
! <alias name="nic_drv" child="usb_drv"/>
|
||||
! <alias name="input_drv" child="usb_drv"/>
|
||||
! <alias name="block_drv" child="usb_drv"/>
|
||||
the USB driver becomes reachable for session requests routed to either "usb_drv",
|
||||
"nic_drv", "input_drv", and "block_drv". Consequently, the routing
|
||||
configuration of components that use either of those drivers does no longer
|
||||
depend on any platform-intrinsic knowledge.
|
||||
|
||||
|
||||
RTC session interface
|
||||
=====================
|
||||
|
||||
Until now, the RTC session interface used an integer to return the current
|
||||
time. Although this is preferable when performing time-related
|
||||
calculations, a structured representation is more convenient to use, i.e., if
|
||||
the whole purpose is showing the current time. This interface change is only
|
||||
visible to components that use the RTC session directly.
|
||||
|
||||
Since the current OS API of Genode lacks time-related functions, most users
|
||||
end up using the libc, which already converts the structured time stamp
|
||||
internally, or provide their own time related functions.
|
||||
|
||||
|
||||
Update of rump-kernel-based file systems
|
||||
========================================
|
||||
|
||||
We updated the rump-kernel support to a newer rump-kernel version (as of mid of
|
||||
January 2015). This way, Genode is able to benefit from upstream stability
|
||||
improvements related to the memory management. Furthermore, we revised the
|
||||
Genode backend to allow the rump_fs server to cope well with a large amount of
|
||||
memory assigned to it. The latter is useful to utilize the block cache of the
|
||||
NetBSD kernel.
|
||||
|
||||
|
||||
Libraries and applications
|
||||
##########################
|
||||
|
||||
As a stepping stone in the
|
||||
[https://github.com/genodelabs/genode/issues/1399 - forthcoming community effort]
|
||||
to bring the Nix package manager to Genode, ports of libbz2 and sqlite have
|
||||
been added to the _repos/libports/_ repository.
|
||||
|
||||
|
||||
Runtime environments
|
||||
####################
|
||||
|
||||
VirtualBox on NOVA
|
||||
==================
|
||||
|
||||
Whereas our previous efforts to run VirtualBox on Genode/NOVA were mostly
|
||||
concerned with enabling principal functionality and with the addition of
|
||||
features, we took the release cycle of Genode 15.02 as a chance to focus
|
||||
on performance and stability improvements.
|
||||
|
||||
|
||||
:Performance:
|
||||
|
||||
Our goal with VirtualBox on NOVA is to achieve a user experience
|
||||
comparable to running VirtualBox on Linux. Our initial port of VirtualBox used
|
||||
to cut a lot of corners with regards to performance and timing accuracy
|
||||
because we had to concentrate on more fundamental issues of the porting
|
||||
work first. Now, with the feature set settled, it was time to revisit
|
||||
and solidify our interim solutions.
|
||||
|
||||
The first category of performance improvements is the handling of timing,
|
||||
and virtual guest time in particular. In our original version,
|
||||
we could observe a substantial drift of the guest time compared to the host time.
|
||||
The drift is not merely inconvenient but may even irritate the guest OS
|
||||
because it violates its assumptions about the behaviour of certain virtual devices.
|
||||
The drift was caused by basing the timing on a simple jiffies counter
|
||||
that was incremented by a thread after sleeping for a fixed period. Even
|
||||
though the thread almost never executes, there is still a chance that it gets
|
||||
preempted by the kernel and resumed only after the time slices of
|
||||
concurrently running threads have elapsed. This can take tens of milliseconds.
|
||||
During this time, the jiffies counter remains unchanged. We could
|
||||
significantly reduce the drift by basing the timing on absolute time values
|
||||
requested from the timer driver. Depending on the used guest OS, however,
|
||||
there is still a residual inaccuracy left, which is subject to ongoing
|
||||
investigations.
|
||||
|
||||
The second type of improvements is related to the handling of virtual
|
||||
interrupts. In its original habitat, VirtualBox relies on so-called
|
||||
external-interrupt virtualization events. If a host interrupt occurs while the
|
||||
virtual machine is active, the virtualization event is forwarded by the
|
||||
VirtualBox hypervisor to the virtual machine monitor (VMM).
|
||||
On NOVA, however, the kernel does not propagate this
|
||||
condition to the user-level VMM because the occurrence of host interrupts should
|
||||
be of no matter to the VMM. In the event of a host interrupt, NOVA takes
|
||||
a normal scheduling decision (eventually activating the user-level device driver
|
||||
the interrupt belongs to) and leaves the virtual CPU (vCPU) in a runnable
|
||||
state - to be rescheduled later. Once the interrupt is handled, the vCPU gets
|
||||
resumed. The VMM remains out of the loop. Because the update of the VirtualBox
|
||||
device models ultimately relies on the delivery of external-interrupt
|
||||
virtualization events, the lack of this kind of event introduced huge delays
|
||||
with respect to the update of device models and the injection of virtual
|
||||
interrupts. We solved this problem by exploiting a VirtualBox-internal
|
||||
mechanism called POKE. By setting the so-called POKE flag, an I/O thread is
|
||||
able to express its wish to force the virtual machine into the VMM. We only
|
||||
needed to find the right spots to set the POKE flag.
|
||||
|
||||
Another performance-related optimization is the caching of RTC time
|
||||
information inside VirtualBox. The original version of the gettimeofday
|
||||
function used by VirtualBox contacted the RTC server for obtaining the
|
||||
wall-clock time on each call. After the update to VirtualBox 4.3, the rate of those
|
||||
calls increased significantly. To reduce the costs of these calls, our
|
||||
new version of gettimeofday combines infrequent calls to the RTC driver
|
||||
with a component-local time source based on the jiffies mechanism mentioned above.
|
||||
|
||||
With these optimizations in place,
|
||||
simple benchmarks like measuring the boot time of Window 7 or the time of
|
||||
compiling Genode within a Debian VM suggest that our version of VirtualBox
|
||||
has reached a performance that is roughly on par with the Linux version.
|
||||
|
||||
|
||||
:Stability:
|
||||
|
||||
Since the upgrade to VirtualBox 4.3.16 in release 14.11, we fixed several
|
||||
regression issues caused by the upgrade. Beside that, we completed the
|
||||
support to route serial output of guests to Genode, lifted the restriction
|
||||
to use just one fixed VESA mode, and enabled support for 32-bit Windows 8
|
||||
guests on 64-bit Genode/NOVA. The 64-bit host restriction stems from
|
||||
the fact that Windows 8 requires support for the non-executable bit (NX)
|
||||
feature of page tables. The 32-bit version of the NOVA kernel does not leverage
|
||||
the physical address extension (PAE) feature, which is a pre-requisite for
|
||||
using NX on 32-bit.
|
||||
|
||||
In the course of the adaptation, our port of VirtualBox now evaluates the
|
||||
PAE and HardwareVirtExUX XML tags of .vbox files:
|
||||
|
||||
!<VirtualBox xmlns=...>
|
||||
! <Machine uuid=...>
|
||||
! <Hardware ..>
|
||||
! <CPU ...>
|
||||
! <HardwareVirtExUX enabled="true"/>
|
||||
! <PAE enabled="true"/>
|
||||
! ...
|
||||
|
||||
The PAE tag specifies whether to report PAE capabilities to the guest
|
||||
or not. The HardwareVirtExUx tag is used by our port to decide whether to stay
|
||||
for non-paged x86 modes in Virtualbox's recompiler (REM) or not. Until now, we used REM
|
||||
to emulate execution when the guest was running in real mode and protected mode
|
||||
with paging disabled. However, newer Intel machines support the unrestricted guest
|
||||
feature, which makes the usage of REM in non-paged modes not strictly
|
||||
necessary anymore. Setting the HardwareVirtExUx tag to false accommodates
|
||||
older machines with no support for the unrestricted-guest feature.
|
||||
|
||||
|
||||
Device drivers
|
||||
##############
|
||||
|
||||
iPXE-based network drivers
|
||||
==========================
|
||||
|
||||
We enabled and tested the driver with Intel I218-LM and I218-V PCI devices.
|
||||
|
||||
|
||||
Intel wireless stack
|
||||
====================
|
||||
|
||||
In this release, several small issues regarding the wireless stack are fixed.
|
||||
From now on, the driver only probes devices on the PCI bus that correspond to
|
||||
the PCI_CLASS_NETWORK_OTHER device class. Prior to that, the driver probed all
|
||||
devices attached to the bus resulting in problems with other devices, e.g.
|
||||
the GPU, when accessing their extended PCI config space.
|
||||
Since the driver uses cooperative scheduling internally, it must never block
|
||||
or, in case it blocks, must schedule another task. Various sleep functions
|
||||
lacked this scheduling call and are now fixed. Furthermore, a bug in the timer
|
||||
implementation has been corrected, which caused the scheduling of wrong timeouts.
|
||||
In addition to these fixes, patches for enabling the support for
|
||||
Intel 7260 cards were incorporated.
|
||||
|
||||
Up to now, the configuration of the wireless driver was rather inconvenient because
|
||||
it did not export any information to the system. The driver now creates two
|
||||
distinct reports to communicate its state and information about the wireless
|
||||
infrastructure to other components. The first one is a list of all available
|
||||
access points. The following exemplary report shows its structure:
|
||||
|
||||
!<wlan_accesspoints>
|
||||
! <accesspoint ssid="skynet" bssid="00:01:02:03:04:05" quality="40"/>
|
||||
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:06" quality="70" protection="WPA-PSK"/>
|
||||
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:07" quality="10" protection="WPA-PSK"/>
|
||||
!</wlan_accesspoints>
|
||||
|
||||
Each '<accesspoint>' node has attributes that contain the SSID and the BSSID
|
||||
of the access point as well as the link quality (signal strength). These
|
||||
attributes are mandatory. If the network is protected, the node will also
|
||||
have an attribute describing the type of protection in addition.
|
||||
|
||||
The second report provides information about the state of the connection
|
||||
with the currently associated access point:
|
||||
|
||||
!<wlan_state>
|
||||
! <accesspoint ssid="foobar" bssid="01:02:03:04:05:06" quality="70"
|
||||
! protection="WPA-PSK" state="connected"/>
|
||||
!</wlan_state>
|
||||
|
||||
Valid state values are 'connected', 'disconnected', 'connecting' and
|
||||
'disconnecting'.
|
||||
|
||||
The driver obtains its configuration via a ROM module. This ROM
|
||||
module contains the selected access point and can be updated during runtime.
|
||||
To connect to an access point, a configuration like the following is used:
|
||||
|
||||
!<selected_accesspoint ssid="foobar" bssid="01:02:03:04:05:06"
|
||||
! protection="WPA-PSK" psk="foobar123!"/>
|
||||
|
||||
To disconnect from an access point, an empty configuration can be set:
|
||||
|
||||
!<selected_accesspoint/>
|
||||
|
||||
For now, the prevalent WPA/WPA2 protection using a pre-shared key is supported.
|
||||
|
||||
|
||||
Improved UART driver for Exynos5
|
||||
================================
|
||||
|
||||
The UART driver for the Exynos5 SoC has been enhanced by enabling the RX
|
||||
channel. This improvement was motivated by automated tests, where a run script
|
||||
needs to interact with some component via a terminal connection.
|
||||
|
||||
|
||||
Touchscreen support
|
||||
===================
|
||||
|
||||
We enabled support of Wacom USB touchscreen devices via dde_linux - a port of
|
||||
Linux USB driver to Genode. In order to make touchscreen coordinates
|
||||
usable by Genode's input services, they must be calibrated
|
||||
to screen-absolute coordinates. The screen resolution is not determined
|
||||
automatically by the USB driver. It can, however, be configured as a sub
|
||||
node of the '<hid>' XML tag of the USB driver's configuration:
|
||||
|
||||
!<start name="usb_drv">
|
||||
! ...
|
||||
! <config uhci=... ohci=... xhci=...>
|
||||
! <hid>
|
||||
! <screen width="1024" height="768"/>
|
||||
! </hid>
|
||||
! ...
|
||||
|
||||
|
||||
USB session interface
|
||||
=====================
|
||||
|
||||
We enhanced our USB driver with the support of remote USB sessions. This
|
||||
feature makes it possible to implement USB-device drivers outside the USB
|
||||
server using a native Genode API. The new USB session can be found under
|
||||
_repos/os/include/usb_session_ and can be used to communicate with the USB
|
||||
server, which merely acts as a host controller and HUB driver in this scenario.
|
||||
Under _repos/os/include/usb_, there are a number of convenience
|
||||
and wrapper functions that operate directly on top of a USB session. These
|
||||
functions are meant to ease the task of USB-device-driver programming by hiding
|
||||
most of the USB session management, like packet-stream handling.
|
||||
|
||||
We also added a USB terminal server, which exposes a Genode terminal session to
|
||||
its clients and drives the popular PL2303 USB to UART adapters using the new
|
||||
USB-session interface.
|
||||
A practical use case for this component is the transmission of logging data on
|
||||
systems where neither UART, AMT, nor JTAG are available. A run script
|
||||
showcasing this feature can be found at _repos/dde_linux/run/usb_terminal.run_.
|
||||
|
||||
|
||||
RTC proxy driver for Linux
|
||||
==========================
|
||||
|
||||
There are a handful of run scripts that depend on the RTC service. So far,
|
||||
it was not possible to run these tests on Linux due to the lack of an RTC
|
||||
driver on this platform. To address this problem, we created a proxy driver
|
||||
that uses the time() system call to provide a
|
||||
reasonable base period on Linux.
|
||||
|
||||
|
||||
Platforms
|
||||
#########
|
||||
|
||||
Execution on bare hardware (base-hw)
|
||||
====================================
|
||||
|
||||
Support for the USB-Armory board
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
With [https://www.crowdsupply.com/inverse-path/usb-armory - USB Armory],
|
||||
there is an intriguing hardware platform for Genode on the horizon.
|
||||
In short, USB Armory is a computer in the form factor of a USB
|
||||
stick. It is meant for security applications such as VPNs,
|
||||
authentication tokens, and encrypted storage. It is based on the
|
||||
FreeScale i.MX53 SoC, which is well supported by Genode, i.e.,
|
||||
Genode can be used as secure-world OS besides Linux running in the
|
||||
normal world.
|
||||
Apart from introducing a novel form factor, this project is
|
||||
interesting because it strives to be an 100% open platform, which
|
||||
includes hardware, software, and firmware. This motivated us to
|
||||
bring Genode to this platform.
|
||||
|
||||
The underlying idea is to facilitate
|
||||
[http://genode.org/documentation/articles/trustzone - ARM TrustZone] to
|
||||
use Genode as a companion to a Linux-based OS on the platform.
|
||||
Whereas Linux would run in the normal world of TrustZone, Genode runs
|
||||
in the secure world. With Linux, the normal world will control the
|
||||
communication over USB and provide a familiar environment to implement
|
||||
USB-Armory applications. However, security-critical functions and data like
|
||||
cryptographic keys will reside exclusively in the secure world. Even in
|
||||
the event that Linux gets compromised, the credentials of the user
|
||||
will stay protected.
|
||||
|
||||
The support of the USB Armory platform was added in two steps:
|
||||
First, we enabled our base-hw kernel to run as TrustZone monitor with
|
||||
Genode on the "secure side". Since the USB Armory is based on the
|
||||
FreeScale i.MX53 SoC, which Genode already supported, this step went
|
||||
relatively straight-forward.
|
||||
|
||||
Second, we enabled a recent version of the Linux kernel (3.18) to run in the
|
||||
normal world. The normal world is supervised by a user-level Genode component
|
||||
called tz_vmm (TrustZone Virtual Machine Monitor). The tz_vmm is, among
|
||||
others, responsible for providing startup and hardware information to the
|
||||
non-secure guest. The Linux kernel version we used previously as TrustZone
|
||||
guest on i.MX53 boards expected this information to be communicated via
|
||||
so-called ATAGs. The new version, however, expects this to be done via a
|
||||
device tree blob. As a consequence, the tz_vmm had to be adapted to properly
|
||||
load this blob into the non-secure RAM. The original USB-Armory device tree
|
||||
was modified to blind out the RAM regions that get protected by the TrustZone
|
||||
hardware. This way, Linux won't attempt to access them. Furthermore,
|
||||
to keep basic user interaction simple, our device tree tells Linux to use the
|
||||
same non-secure UART as Genode for console I/O.
|
||||
|
||||
The kernel itself received some modifications, for two reasons. First,
|
||||
we don't want Linux to rely on resources that are protected to keep
|
||||
the secure world secure. This is why the driver for the interrupt controller
|
||||
that originally made use of the TrustZone interrupt configuration, had to be
|
||||
adapted. Second, to prevent Linux from disturbing Genode activities, we
|
||||
disabled most of the dynamic clock and power management as it may sporadically
|
||||
gear down or even disable hardware that Genode relies on. Furthermore, we
|
||||
disabled the Linux drivers for I2C interfaces and the GPIO configuration as
|
||||
these are reserved for Genode.
|
||||
|
||||
|
||||
IPC helping
|
||||
~~~~~~~~~~~
|
||||
|
||||
In traditional L4 microkernels, scheduling parameters (like time-slice
|
||||
length and priority) used to be bound to threads. Usually, those parameters
|
||||
are defined at thread creation time. The initial version
|
||||
of base-hw followed this traditional approach. However, it has a few problems:
|
||||
|
||||
* For most threads, the proper *choice of scheduling parameters* is very
|
||||
difficult if not impossible. For example, the CPU-time demands of a
|
||||
server thread may depend on the usage patterns of its clients. Most
|
||||
theoretical work in the domain of scheduling presumes the knowledge of
|
||||
job lengths in advance of computing a schedule. But in practice and in
|
||||
particular in general-purpose computing, job lengths are hardly known a priori.
|
||||
As a consequence, in most scenarios, scheduling parameters are
|
||||
set to default values.
|
||||
|
||||
* With each thread being represented as an independent schedulable entity,
|
||||
the kernel has to take a scheduling decision each time a thread performs an
|
||||
IPC call because the calling thread gets blocked and the called thread
|
||||
may get unblocked. In a microkernel-based system, those events occur at a
|
||||
much higher rate than the duration of typical time slices, which puts the
|
||||
scheduler in a *performance-critical* position.
|
||||
|
||||
* Regarding IPC calls, a synchronous flow of control along IPC call chains is
|
||||
desired. Ideally, an IPC call should have the same characteristics as
|
||||
a function call with respect to scheduling. When a client thread performs an
|
||||
IPC call, it expects the server to immediately become active to
|
||||
handle the request. But if the kernel treats each thread independently,
|
||||
it may pick any other thread and thereby introduce *high latencies* into
|
||||
IPC operations.
|
||||
|
||||
To counter those problems, the NOVA microhypervisor introduced a new approach
|
||||
that decouples scheduling parameters from threads. Instead of selecting
|
||||
threads for execution, the scheduler selects so-called scheduling contexts.
|
||||
For a selected scheduling context, the kernel dynamically determines a
|
||||
thread to execute by taking IPC relationships into account. When a thread
|
||||
performs an IPC, the thread's scheduling context will be used to execute
|
||||
the called server. In principle, a server does not need CPU time on its own
|
||||
but always works with CPU resources provided by clients.
|
||||
|
||||
The new version of the base-hw kernel adapts NOVA's approach with slight
|
||||
modifications. Each thread owns exactly one scheduling context for its entire
|
||||
lifetime. However, by the means of "helping" during an IPC call, the caller
|
||||
lends its scheduling context to the callee. Even if the callee is still busy
|
||||
and cannot handle the IPC request right away, the caller helps because it
|
||||
wants the callee to become available for its request as soon as
|
||||
possible. Consequently, a thread has potentially many scheduling contexts at
|
||||
its disposal, its own scheduling context plus all scheduling contexts
|
||||
provisioned by helpers. This works transitively.
|
||||
|
||||
|
||||
Purged outdated platforms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We removed the support for two stale platforms that remained unused for
|
||||
more than a year, namely FreeScale i.MX31 and the TrustZone variant
|
||||
of the Coretile Versatile Express board.
|
||||
|
||||
|
||||
NOVA
|
||||
====
|
||||
|
||||
On Genode/NOVA, we used to employ one pager thread in core for each thread
|
||||
in the system. We were forced to do so because not every page
|
||||
fault can be resolved immediately. In some situations, core asynchronously
|
||||
propagates the fault to an external component for the resolution.
|
||||
In the meantime, the
|
||||
pager thread leaves the page fault unanswered. Unfortunately, the kernel
|
||||
provides no mechanism to support this scenario besides just blocking the
|
||||
pager thread using a semaphore. This, in turn, means that the pager thread is not
|
||||
available for other page-fault requests. Ultimately, we had to setup a
|
||||
dedicated pager per thread.
|
||||
|
||||
This implementation has the downside of "wasting" memory for a lot of
|
||||
pager threads. Moreover, it becomes a denial-of-service vector as soon as more
|
||||
threads get created than core can accommodate. The number of threads is
|
||||
limited per address space - also for core - by the size of Genode's context
|
||||
area, which typically means 256 threads.
|
||||
|
||||
To avoid the downsides mentioned, we extended the NOVA IPC reply syscall to
|
||||
specify an optional semaphore capability. The NOVA kernel validates the
|
||||
capability and blocks the faulting thread in the semaphore. The faulted thread
|
||||
remains blocked even after the pager has replied to the fault message. But
|
||||
the pager immediately becomes available for other
|
||||
page-fault requests. With this change, it suffices to maintain only one pager
|
||||
thread per CPU for all client threads.
|
||||
|
||||
The benefits are manifold. First, the base-nova implementation converges more
|
||||
closely to other Genode base platforms. Second, core can not run out of threads
|
||||
anymore as the number of threads in core is fixed for a given setup. And the
|
||||
third benefit is that the helping mechanism of NOVA can be leveraged for
|
||||
concurrently faulting threads.
|
||||
|
||||
|
||||
Build system and tools
|
||||
######################
|
||||
|
||||
Tools for convenient handling of port contrib directories
|
||||
=========================================================
|
||||
|
||||
We supplemented our tools for the ports mechanism with two convenient
|
||||
scripts:
|
||||
|
||||
:_tool/ports/shortcut_:
|
||||
|
||||
Creates a symbolic link from _contrib/<port-name>-<hash>_ to
|
||||
_contrib/<port-name>_. This is useful when working on the third-party
|
||||
code contained in the _contrib_ directory.
|
||||
|
||||
:_tool/ports/current_:
|
||||
|
||||
Prints the current contrib directory of a port. When switching
|
||||
branches back and forth, the hash of the used port might change.
|
||||
The script provides a shortcut to looking up the hash file for a
|
||||
specific port within the repositories and printing its content.
|
||||
|
||||
191
doc/road_map.txt
191
doc/road_map.txt
@@ -14,138 +14,95 @@ The road map is not fixed. If there is commercial interest of pushing the
|
||||
Genode technology to a certain direction, we are willing to revisit our plans.
|
||||
|
||||
|
||||
Review of the past year
|
||||
#######################
|
||||
Review of 2014
|
||||
##############
|
||||
|
||||
In 2013, we worked on four construction sites: Framework infrastructure,
|
||||
self-hosting, tooling and optimization, and hardware support. When
|
||||
reviewing the road map for 2013, it is great to see that we largely
|
||||
lived up to our planning.
|
||||
Most of the progress in 2014 was motivated by our goal to use
|
||||
Genode as general-purpose OS on x86-based platforms. To highlight a
|
||||
few achievements, we started to use [http://rumpkernel.org/ - Rump kernels]
|
||||
as file-system providers, enabled VirtualBox on NOVA, pulled off the
|
||||
engineering feat to run the Intel Wireless stack natively on microkernels, and
|
||||
came up with a new GUI architecture. We regard these features as the
|
||||
groundwork to make Genode a feasible platform for day-to-day computing.
|
||||
|
||||
The framework infrastructure was enhanced with concepts for managing
|
||||
CPUs on multi-processor systems and for dynamically balancing memory
|
||||
resources, it received new audio and file-system capabilities, and, with
|
||||
the addition of Qt5 and the lxIP stack, we could enable highly
|
||||
sophisticated workloads natively on Genode.
|
||||
|
||||
On our endeavour of self-hosting Genode on Genode, we could eliminate
|
||||
long-standing show stoppers for several base platforms. We were able to
|
||||
improve them to the point where we can routinely execute Genode's tool
|
||||
chain across several base platforms such as NOVA and Fiasco.OC as part
|
||||
of our nightly automated tests. On the user-facing side, a new
|
||||
command-line interface has seen the light of the day.
|
||||
|
||||
Two highlights when it comes to tooling were the new event tracing
|
||||
facilities, and profound support for automated testing. Thanks to the
|
||||
latter, we expose Genode to over 500 test runs including automated
|
||||
performance benchmarks. By executing those tests each night, we have
|
||||
become able to resolve regressions before they enter the master branch.
|
||||
So the master branch remains always in a good shape.
|
||||
|
||||
As expected for an operating-system project, most of our work was spent
|
||||
on hardware support. On x86, we added IOMMU support, and the
|
||||
virtualization capabilities on NOVA have seen a major upgrade. On ARM,
|
||||
we enabled or vastly enhanced the device drivers for Samsung Exynos 5,
|
||||
Freescale i.MX, and Raspberry Pi. We also explored the possibilities of
|
||||
combining Genode with ARM TrustZone.
|
||||
|
||||
Only two topics, namely Intel wireless and a new user interface concept
|
||||
had been deferred. We decided to postpone the Intel wireless topic to
|
||||
address gigabit networking instead. Even though the new user-interface
|
||||
concept served as a strong motivation behind many improvements of the
|
||||
base system such as dynamic reconfiguration and dynamic resource
|
||||
balancing, the work on those fundamentals left little room to bring
|
||||
forward the actual UI concept. Now that those pieces are in place, we
|
||||
can go full steam ahead.
|
||||
|
||||
The most surprising topic that was not clearly laid out in our last
|
||||
year's road map is the advancement of the base-hw platform. Started as a
|
||||
mere experiment, it received so much love and attention that it
|
||||
unexpectedly became able to host the whole universe of Genode's software
|
||||
stack.
|
||||
That said, even though we are proud about the progress, we are still not there
|
||||
yet. So what keeps us back? The answer is actually not technical. Most
|
||||
developments over the past years were concerned with individual features or
|
||||
technical challenges. But the integration of sophisticated system scenarios
|
||||
was a rare occurrence. For the most part, such integration activities were
|
||||
solely triggered by a particular project or by a presentation. In order to
|
||||
make Genode fit for regular use, we need to make the composing of advanced
|
||||
systems a habit for most of the regular developers.
|
||||
|
||||
|
||||
2014
|
||||
####
|
||||
Big picture for 2015
|
||||
####################
|
||||
|
||||
In 2014, we will put the emphasis on the base-hw kernel, 3rd-party software,
|
||||
storage, and the user-facing side of Genode.
|
||||
On the account of this realization, the overall theme of 2015 will be the
|
||||
consolidation and cultivation of the existing feature set rather than the
|
||||
conquering of new grounds. This implies the following topics:
|
||||
|
||||
The experience with base-hw in 2013 ignited our ambitions to develop this
|
||||
kernel not just into a complete base platform for Genode, but also
|
||||
to explore new grounds. To fully accommodate Genode, we will complement
|
||||
base-hw with multi-processor support, kernel-protected capability-based
|
||||
security, and real-time scheduling. Beyond supporting Genode's software
|
||||
stack, we will explore the use of ARM's virtualization extensions
|
||||
to turn base-hw into a microhypervisor, similar to NOVA but focusing on ARM.
|
||||
* Advancing our automated test and integration infrastructure towards
|
||||
the continuous integration of real-world system scenarios,
|
||||
* Fostering good-quality documentation,
|
||||
* Optimization of performance and stability,
|
||||
* Improvement of our tooling
|
||||
|
||||
With Genode becoming more and more flexible, the role of 3rd-party software in
|
||||
both source-code and binary form grows. Even though Genode offers a pretty
|
||||
convenient mechanism to automatically download and integrate 3rd-party source
|
||||
codes, the burden to resolve inter-dependencies between such source packages is
|
||||
still left to the user of the framework. Many new users stumble over
|
||||
the installation of 3rd-party code as it is not obvious to see which packages
|
||||
are required for a particular system scenario. To make Genode better
|
||||
approachable and more convenient to use, we plan to consolidate the current
|
||||
mechanisms into a solid source-code package management solution.
|
||||
Furthermore, we have to address outstanding limitations of the most
|
||||
commonly used base platforms, namely base-hw and NOVA. I.e., only
|
||||
with kernel-protected capabilities, base-hw can be considered as a viable
|
||||
base platform for security-critical systems, and only with proper
|
||||
kernel-resource management, NOVA can be recommended as a kernel for
|
||||
general-purpose computing.
|
||||
|
||||
The improved 3rd-party software support will hopefully allow us to realize
|
||||
sophisticated and popular usage scenarios more easily. As security is one of
|
||||
Genode's major benefits compared to commodity operating systems, we consider
|
||||
supporting TOR, either as server, or client side, or even both. One
|
||||
possibility would be to provide a ready-to-use live image containing a TOR
|
||||
client and a configured browser, which would enable users to browse
|
||||
anonymously.
|
||||
|
||||
Besides the use of ported 3rd-party software on top of Genode, we see clear
|
||||
demand for hosting 3rd-party binary software, particularly virtualized OSes.
|
||||
The Seoul VMM (on NOVA) and L4Linux (on Fiasco.OC) already allow for the use
|
||||
of Linux guest OSes as Genode sub systems. However, both solutions fall short
|
||||
in different ways. Whereas L4Linux requires the maintenance of a patched Linux
|
||||
kernel, Seoul can execute unpatched Linux kernels but requires a fine-tuned
|
||||
kernel configuration. Because we long for a product-quality virtualization
|
||||
solution that works just out of the box with most existing guest OSes, we will
|
||||
make VirtualBox available on Genode/NOVA.
|
||||
|
||||
The move to employing Genode for day-to-day computing requires reliable,
|
||||
secure, and fast storage. Hence, we will build and optimize components that
|
||||
operate on file-system and block level. This includes work on device drivers,
|
||||
file-system stacks, caching mechanisms, block-level encryption, as well as
|
||||
improved per-process virtual file systems.
|
||||
|
||||
Finally, we plan to complement Genode with an entirely capability-based user
|
||||
interface, which will present the user with a unique model of how to interact
|
||||
with the system. With user interface, we actually refer to three different
|
||||
things: System configuration (the user interface a system integrator has
|
||||
to deal with), text-based user interface, and a graphical desktop environment.
|
||||
We hope to cover those with one single holistic concept.
|
||||
Besides the cultivation of the existing feature set, there will still be room
|
||||
for new things. We are particularly excited about the prospect of combining
|
||||
Genode with the [http://sel4.systems - seL4 kernel] and
|
||||
the [http://nixos.org/nix/ - Nix package manager]. Furthermore, we desire to
|
||||
continue the work on our new GUI architecture towards a capability-based
|
||||
desktop environment.
|
||||
|
||||
|
||||
Milestones
|
||||
==========
|
||||
Milestones for 2015
|
||||
###################
|
||||
|
||||
In the following, there is a rough schedule of the planned work. As usual,
|
||||
In the following, we present a rough schedule of the planned work. As usual,
|
||||
it is not set in stone. If you are interested in a particular line of work,
|
||||
please get in touch.
|
||||
|
||||
:February - Release 14.02:
|
||||
* First version of VirtualBox on NOVA
|
||||
* Base-hw: multi-processor support
|
||||
* Block cache
|
||||
* Component composition tool kit
|
||||
|
||||
:May - Release 14.05:
|
||||
* Base-hw: real-time scheduling
|
||||
* 3rd-party source-code package management
|
||||
* Block-level encryption
|
||||
February - Release 15.02
|
||||
========================
|
||||
|
||||
:August - Release 14.08:
|
||||
* Desktop environment
|
||||
* Base-hw: kernel-protected capability-based security
|
||||
* TOR on Genode
|
||||
* ARM virtualization on top of the base-hw kernel
|
||||
* Modularized tooling for automated tests
|
||||
|
||||
|
||||
May - Release 15.05
|
||||
===================
|
||||
|
||||
* Comprehensive documentation of the Genode foundations
|
||||
* Kernel-protected capabilities for the base-hw kernel
|
||||
* seL4 microkernel as base platform
|
||||
* Refined platform-driver architecture (support for MSIs, assignment of
|
||||
I/O resources to drivers, standardized configuration)
|
||||
|
||||
|
||||
August - Release 15.08
|
||||
======================
|
||||
|
||||
* Capability-based desktop environment allowing the interactive installation
|
||||
and management of Genode subsystems and the interaction with files
|
||||
* Accommodation of typical desktop-computing tasks (e.g., email)
|
||||
* Interactive tools for observing the system behavior
|
||||
* NOVA kernel-resource management
|
||||
|
||||
|
||||
November - Release 15.11
|
||||
========================
|
||||
|
||||
* Achieving cross-kernel binary compatibility
|
||||
* Package management
|
||||
* Modern web browser
|
||||
|
||||
:November - Release 14.11:
|
||||
* Base-hw: virtualization on ARM, support for Cortex-A7
|
||||
* Intel wireless
|
||||
* NOVA kernel resource management
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ SECTIONS
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
_dtors_end = .;
|
||||
} : ro = 0x90909090
|
||||
} : ro = 0x0
|
||||
|
||||
/* Linux: exception section for uaccess mechanism */
|
||||
__ex_table : { *(__ex_table) }
|
||||
|
||||
@@ -1 +1 @@
|
||||
fa0ea19bd94fb109dac558e37996b60243eef785
|
||||
ac9483f591c9b8dd4ed22b28e3a7e7ee382011bd
|
||||
|
||||
@@ -1,201 +0,0 @@
|
||||
#
|
||||
# \brief Fiasco-specific test-environment supplements
|
||||
# \author Norman Feske
|
||||
# \author Christian Helmuth
|
||||
# \date 2010-08-26
|
||||
#
|
||||
# This file is meant to be used as '--include' argument for 'tool/run'.
|
||||
#
|
||||
|
||||
|
||||
##
|
||||
# Install files needed to boot via PXE
|
||||
#
|
||||
proc install_pxe_bootloader_to_run_dir { } {
|
||||
exec cp [genode_dir]/tool/boot/pulsar [run_dir]/boot/pulsar
|
||||
exec cp [genode_dir]/tool/boot/bender [run_dir]/boot/bender
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Read the location of the Fiasco user directory from 'etc/fiasco.conf'
|
||||
#
|
||||
proc l4_dir { } {
|
||||
global _l4_dir
|
||||
|
||||
if {![info exists _l4_dir]} {
|
||||
if {[file exists etc/fiasco.conf]} {
|
||||
set _l4_dir [exec sed -n "/^L4_BUILD_DIR/s/^.*=\\s*//p" etc/fiasco.conf]
|
||||
if {[file exists $_l4_dir]} { return $_l4_dir }
|
||||
}
|
||||
|
||||
set _l4_dir "[pwd]/l4"
|
||||
if {![file exists $_l4_dir]} {
|
||||
puts -nonewline stderr "Error: Could neither find the L4 build directory "
|
||||
puts -nonewline stderr "within '<genode-build-dir>/l4' nor at a location "
|
||||
puts -nonewline stderr "specified via 'L4_BUILD_DIR = <l4v2-build-dir>' "
|
||||
puts stderr "in <genode-build-dir>/etc/fiasco.conf'."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
return $_l4_dir
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return whether the l4-buid-directory is provided from the outside
|
||||
#
|
||||
proc l4_dir_external { } {
|
||||
if {[l4_dir] == "[pwd]/l4"} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return the location of the Fiasco kernel
|
||||
#
|
||||
proc fiasco { } {
|
||||
return [kernel_location_from_config_file etc/fiasco.conf [pwd]/kernel/fiasco/fiasco]
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
# Return whether fiasco kernel is provided from the outside
|
||||
#
|
||||
proc fiasco_external { } {
|
||||
if {[fiasco] == "[pwd]/kernel/fiasco/fiasco"} { return 0 }
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
##################################
|
||||
## Test framework API functions ##
|
||||
##################################
|
||||
|
||||
proc create_boot_directory { } {
|
||||
exec rm -rf [run_dir]
|
||||
exec mkdir -p [run_dir]/genode
|
||||
exec mkdir -p [run_dir]/fiasco
|
||||
}
|
||||
|
||||
proc bin_dir { } {
|
||||
if {[have_spec x86_32]} { return "[l4_dir]/bin/x86_586" }
|
||||
|
||||
puts stderr "Error: Cannot determine bin directory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set fiasco_serial_esc_arg "-serial_esc "
|
||||
|
||||
proc build_boot_image {binaries} {
|
||||
|
||||
global fiasco_serial_esc_arg
|
||||
|
||||
#
|
||||
# Collect contents of the ISO image
|
||||
#
|
||||
copy_and_strip_genode_binaries_to_run_dir $binaries
|
||||
|
||||
if {![fiasco_external]} { build { kernel } }
|
||||
if {![l4_dir_external]} { build { bootstrap sigma0 } }
|
||||
|
||||
# assert existence of the L4 build directory
|
||||
l4_dir
|
||||
|
||||
puts "using fiasco kernel [fiasco]"
|
||||
exec cp [fiasco] [run_dir]/fiasco/fiasco
|
||||
puts "using sigma0/bootstrap at [l4_dir]"
|
||||
exec cp [bin_dir]/l4v2/sigma0 [run_dir]/fiasco
|
||||
exec cp [bin_dir]/bootstrap [run_dir]/fiasco
|
||||
|
||||
install_iso_bootloader_to_run_dir
|
||||
|
||||
#
|
||||
# Generate grub config file
|
||||
#
|
||||
# The core binary is part of the 'binaries' list but it must
|
||||
# appear right after 'sigma0' as boot module. Hence the special case.
|
||||
#
|
||||
set fh [open "[run_dir]/boot/grub/menu.lst" "WRONLY CREAT TRUNC"]
|
||||
puts $fh "timeout 0"
|
||||
puts $fh "default 0"
|
||||
puts $fh "\ntitle Genode on L4/Fiasco"
|
||||
puts $fh " kernel /boot/bender"
|
||||
puts $fh " module /fiasco/bootstrap -serial -modaddr=0x02000000"
|
||||
puts $fh " module /fiasco/fiasco -serial -jdb_cmd=JH $fiasco_serial_esc_arg"
|
||||
puts $fh " module /fiasco/sigma0"
|
||||
puts $fh " module /genode/core"
|
||||
puts $fh " module /genode/config"
|
||||
foreach binary $binaries {
|
||||
if {$binary != "core"} {
|
||||
puts $fh " module /genode/$binary" } }
|
||||
puts $fh " vbeset 0x117 506070"
|
||||
close $fh
|
||||
|
||||
#
|
||||
# Install PXE bootloader pulsar
|
||||
#
|
||||
install_pxe_bootloader_to_run_dir
|
||||
|
||||
create_iso_image_from_run_dir
|
||||
create_disk_image_from_run_dir
|
||||
|
||||
#
|
||||
# Generate pulsar config file
|
||||
#
|
||||
set fh [open "[run_dir]/config-52-54-00-12-34-56" "WRONLY CREAT TRUNC"]
|
||||
puts $fh " exec /boot/bender"
|
||||
puts $fh " load /fiasco/bootstrap -serial -modaddr=0x02000000"
|
||||
puts $fh " load /fiasco/fiasco -serial -serial_esc -jdb_cmd=JH"
|
||||
puts $fh " load /fiasco/sigma0"
|
||||
puts $fh " load /genode/core"
|
||||
puts $fh " load /genode/config"
|
||||
foreach binary $binaries {
|
||||
if {$binary != "core"} {
|
||||
puts $fh " load /genode/$binary" } }
|
||||
close $fh
|
||||
|
||||
#
|
||||
# Generate pulsar config file pointing to the config file above.
|
||||
#
|
||||
if {[info exists ::env(PXE_TFTP_DIR_BASE)] && [info exists ::env(PXE_TFTP_DIR_OFFSET)]} {
|
||||
exec ln -nfs "[pwd]" "$::env(PXE_TFTP_DIR_BASE)$::env(PXE_TFTP_DIR_OFFSET)"
|
||||
|
||||
set tftp_base ""
|
||||
if {[get_cmd_switch --tftp-absolute]} {
|
||||
set tftp_base $::env(PXE_TFTP_DIR_BASE)
|
||||
}
|
||||
|
||||
set fh [open "$::env(PXE_TFTP_DIR_BASE)$::env(PXE_TFTP_DIR_OFFSET)/config-00-00-00-00-00-00" "WRONLY CREAT TRUNC"]
|
||||
puts $fh " root $tftp_base$::env(PXE_TFTP_DIR_OFFSET)/[run_dir]"
|
||||
puts $fh " config config-52-54-00-12-34-56"
|
||||
close $fh
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc run_genode_until {{wait_for_re forever} {timeout_value 0} {running_spawn_id -1}} {
|
||||
#
|
||||
# If a running_spawn_id is specified, wait for the expected output
|
||||
#
|
||||
if {$running_spawn_id != -1} {
|
||||
wait_for_output $wait_for_re $timeout_value $running_spawn_id
|
||||
return
|
||||
}
|
||||
|
||||
#
|
||||
# Try to use one of the supported backends for running the scripts
|
||||
#
|
||||
if {[is_amt_available]} {
|
||||
spawn_amt $wait_for_re $timeout_value
|
||||
return
|
||||
}
|
||||
if {[is_qemu_available]} {
|
||||
spawn_qemu $wait_for_re $timeout_value
|
||||
return
|
||||
}
|
||||
|
||||
global run_target
|
||||
puts stderr "Error: Can't execute automatically on target '$run_target'"
|
||||
exit -1
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
SPECS += foc_arm platform_imx53
|
||||
|
||||
REP_INC_DIR += include/platform/imx53_qsb
|
||||
|
||||
include $(call select_from_repositories,mk/spec-platform_imx53.mk)
|
||||
include $(call select_from_repositories,mk/spec-foc_arm.mk)
|
||||
|
||||
@@ -1 +1 @@
|
||||
3456a52b6603b16c9f157c9b3e2045e0984028c0
|
||||
3e7716b7918d12d3c2a545a36c949e97c3bb705c
|
||||
|
||||
@@ -2,5 +2,5 @@ LICENSE := GPLv2
|
||||
VERSION := git
|
||||
DOWNLOADS := foc.git
|
||||
URL(foc) := http://github.com/ssumpf/foc.git
|
||||
REV(foc) := 7cd187003db06c842b11c9f46f0a0753ed677203
|
||||
REV(foc) := 1acdeeb38185afb3ec19d2c15c458d5bc0fe4d4c
|
||||
DIR(foc) := src/kernel/foc
|
||||
|
||||
@@ -16,10 +16,7 @@ For further target specific informations, have a look at
|
||||
'<GENODE_DIR>/repos/base-hw/doc/<TARGET>.txt' where '<TARGET>'
|
||||
is one of the following:
|
||||
|
||||
'pbxa9' - Realview PBXA9
|
||||
'vea9x4' - Versatile Express A9X4
|
||||
'imx31' - Freescale i.MX31
|
||||
'panda' - PandaBoard A2
|
||||
'panda' - PandaBoard A2
|
||||
|
||||
|
||||
Prerequisites
|
||||
@@ -61,10 +58,14 @@ build directory you want to create, and the hardware target to run Genode on.
|
||||
Where '<TARGET>' is one of the following, depending on the hardware system
|
||||
you aim at:
|
||||
|
||||
'pbxa9' - Realview PBXA9
|
||||
'vea9x4' - Versatile Express A9X4
|
||||
'imx31' - Freescale i.MX31
|
||||
'panda' - PandaBoard A2
|
||||
'arndale' - Arndale (Exynos5) board
|
||||
'imx53' - i.MX53 based board
|
||||
'imx53_tz' - i.MX53 based board using TrustZone
|
||||
'odroid_xu' - Odroid XU (Exynos5) board
|
||||
'panda' - PandaBoard A2
|
||||
'pbxa9' - Realview PBXA9
|
||||
'rpi' - Raspberry PI
|
||||
'vea9x4' - Versatile Express A9X4
|
||||
|
||||
Please notice that not all of these targets might be emulateable with Qemu.
|
||||
To be on the safe side use 'pbxa9'. For informations about how to boot
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
==================================================
|
||||
Getting started with 'base-hw' on Freescale i.MX31
|
||||
==================================================
|
||||
|
||||
|
||||
Martin Stein
|
||||
|
||||
Abstract
|
||||
########
|
||||
|
||||
This is a short tutorial that depicts a handy way to get a Genode ELF-image,
|
||||
build with 'base-hw', started on the Freescale i.MX31. For informations
|
||||
about how to build Genode images with 'base-hw', have a look at
|
||||
'<GENODE_DIR>/repos/base-hw/doc/hw.txt'. This tutorial is dedicated to common
|
||||
Linux systems, but all examples originate from a Ubuntu 11.10.
|
||||
|
||||
|
||||
Tutorial
|
||||
########
|
||||
|
||||
Connect the i.MX31 to your local Ethernet through its RJ45 connector.
|
||||
Additionally connect the i.MX31 to your machine through its COM port.
|
||||
We use the bootloader that is installed on the board by the manufacturer, it's
|
||||
the LogicLoader by Logic Product Development, Version 2.3.5-IMX31_10 0001.
|
||||
Now install the following packages to communicate with the i.MX31:
|
||||
|
||||
! apt-get install tftp-hpa minicom
|
||||
|
||||
Open '/etc/default/tftpd-hpa' with a text editor and ensure that it has
|
||||
the following content:
|
||||
|
||||
! TFTP_USERNAME="tftp"
|
||||
! TFTP_DIRECTORY="/var/lib/tftpboot"
|
||||
! TFTP_ADDRESS="0.0.0.0:69"
|
||||
! TFTP_OPTIONS="-l"
|
||||
|
||||
Tell TFTP wich image to provide:
|
||||
|
||||
! cd /var/lib/tftpboot/
|
||||
! ln -s <GENODE_BOOT_ELF> image.elf
|
||||
|
||||
Where '<GENODE_BOOT_ELF>' is the absolute path of the targeted ELF image.
|
||||
Start TFTP to enable the upload of the image:
|
||||
|
||||
! service tftp-hpa restart
|
||||
|
||||
Precautionary determine the inet address of your TFTP machine:
|
||||
|
||||
! ifconfig
|
||||
|
||||
Start Minicom in configuration mode:
|
||||
|
||||
! minicom -s
|
||||
|
||||
Go to 'Serial port setting' and ensure that the device is set to the
|
||||
TTY of the COM port you've conntected the i.MX31 with. In my case it was
|
||||
'/dev/ttyS0'. Configure the other settings for a baud rate of '115200',
|
||||
8 bit char length, no parity and 1 stop bit. Quit Minicom and start
|
||||
it once more in a dedicated terminal:
|
||||
|
||||
! minicom
|
||||
|
||||
Plug in the i.MX31 power connector or push the 'S1' button if the i.MX31 is
|
||||
already powered. Minicom should now show the following message below some
|
||||
bootloader info:
|
||||
|
||||
! losh>
|
||||
|
||||
We have to start DHCP first, so in the Minicom console type:
|
||||
|
||||
! ifconfig sm0 dhcp
|
||||
|
||||
Wait until DHCP is started:
|
||||
|
||||
! Starting DHCP on sm0 ...
|
||||
! losh>
|
||||
|
||||
Then load the Genode image:
|
||||
|
||||
! load elf /tftp/<INET_ADDR>:/var/lib/tftpboot/image.elf
|
||||
|
||||
Where '<INET_ADDR>' is the inet address of your TFTP machine.
|
||||
To execute the loaded image type:
|
||||
|
||||
! exec start
|
||||
|
||||
Now your Genode scenario should start and offer its debug output
|
||||
in Minicom. You can boot other images by redirecting the link
|
||||
'/var/lib/tftpboot/image.elf' accordingly, restarting your i.MX31
|
||||
and instructing LogicLoader again as described above.
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
namespace Genode
|
||||
{
|
||||
class Platform_thread;
|
||||
class Tlb;
|
||||
|
||||
typedef unsigned Native_thread_id;
|
||||
|
||||
@@ -113,7 +112,7 @@ namespace Genode
|
||||
* Thread-context area configuration.
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
return 0xe0000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
||||
Thread_capability _thread_cap;
|
||||
bool _signal_valid;
|
||||
char _signal_buf[sizeof(Signal)];
|
||||
unsigned const _badge;
|
||||
unsigned long const _badge;
|
||||
|
||||
/**
|
||||
* Remember an incoming fault for handling
|
||||
@@ -196,7 +196,7 @@ class Genode::Pager_object : public Object_pool<Pager_object>::Entry,
|
||||
/**
|
||||
* User identification of pager object
|
||||
*/
|
||||
unsigned badge() const { return _badge; }
|
||||
unsigned long badge() const { return _badge; }
|
||||
|
||||
/**
|
||||
* Resume faulter
|
||||
|
||||
@@ -21,12 +21,10 @@ namespace Genode
|
||||
{
|
||||
class Native_utcb;
|
||||
class Platform_pd;
|
||||
class Tlb;
|
||||
}
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
typedef Genode::Tlb Tlb;
|
||||
typedef Genode::addr_t addr_t;
|
||||
typedef Genode::size_t size_t;
|
||||
typedef Genode::Platform_pd Platform_pd;
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Kernel
|
||||
/**
|
||||
* Print an unsigned integer x as hexadecimal value
|
||||
*/
|
||||
Log & operator << (unsigned int const x)
|
||||
Log & operator << (unsigned long const x)
|
||||
{
|
||||
enum {
|
||||
BYTE_WIDTH = 8,
|
||||
@@ -101,7 +101,7 @@ namespace Kernel
|
||||
/**
|
||||
* Print a pointer p as hexadecimal value
|
||||
*/
|
||||
Log & operator << (void * const p) { return *this << (unsigned)p; }
|
||||
Log & operator << (void * const p) { return *this << (unsigned long)p; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
80
repos/base-hw/include/platform/arndale/vm_state.h
Normal file
80
repos/base-hw/include/platform/arndale/vm_state.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* \brief CPU, PIC, and timer context of a virtual machine
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__PLATFORM__ARNDALE__VM_STATE_H_
|
||||
#define _INCLUDE__PLATFORM__ARNDALE__VM_STATE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU context of a virtual machine
|
||||
*/
|
||||
struct Vm_state;
|
||||
}
|
||||
|
||||
struct Genode::Vm_state : Genode::Cpu_state_modes
|
||||
{
|
||||
Genode::uint64_t vttbr;
|
||||
Genode::uint32_t sctrl;
|
||||
Genode::uint32_t hsr;
|
||||
Genode::uint32_t hpfar;
|
||||
Genode::uint32_t hdfar;
|
||||
Genode::uint32_t hifar;
|
||||
Genode::uint32_t ttbcr;
|
||||
Genode::uint32_t ttbr0;
|
||||
Genode::uint32_t ttbr1;
|
||||
Genode::uint32_t prrr;
|
||||
Genode::uint32_t nmrr;
|
||||
Genode::uint32_t dacr;
|
||||
Genode::uint32_t dfsr;
|
||||
Genode::uint32_t ifsr;
|
||||
Genode::uint32_t adfsr;
|
||||
Genode::uint32_t aifsr;
|
||||
Genode::uint32_t dfar;
|
||||
Genode::uint32_t ifar;
|
||||
Genode::uint32_t cidr;
|
||||
Genode::uint32_t tls1;
|
||||
Genode::uint32_t tls2;
|
||||
Genode::uint32_t tls3;
|
||||
Genode::uint32_t cpacr;
|
||||
|
||||
|
||||
/**
|
||||
* Timer related registers
|
||||
*/
|
||||
|
||||
Genode::uint32_t timer_ctrl;
|
||||
Genode::uint32_t timer_val;
|
||||
bool timer_irq;
|
||||
|
||||
|
||||
/**
|
||||
* PIC related registers
|
||||
*/
|
||||
|
||||
enum { NR_IRQ = 4 };
|
||||
|
||||
Genode::uint32_t gic_hcr;
|
||||
Genode::uint32_t gic_vmcr;
|
||||
Genode::uint32_t gic_misr;
|
||||
Genode::uint32_t gic_apr;
|
||||
Genode::uint32_t gic_eisr;
|
||||
Genode::uint32_t gic_elrsr0;
|
||||
Genode::uint32_t gic_lr[4];
|
||||
unsigned gic_irq;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__PLATFORM__ARNDALE__VM_STATE_H_ */
|
||||
@@ -28,8 +28,8 @@ namespace Trustzone
|
||||
*/
|
||||
SECURE_RAM_BASE = Genode::Board_base::RAM0_BASE,
|
||||
SECURE_RAM_SIZE = 256 * 1024 * 1024,
|
||||
NONSECURE_RAM_BASE = Genode::Board_base::RAM1_BASE,
|
||||
NONSECURE_RAM_SIZE = Genode::Board_base::RAM1_SIZE,
|
||||
NONSECURE_RAM_BASE = Genode::Board_base::RAM0_BASE + SECURE_RAM_SIZE,
|
||||
NONSECURE_RAM_SIZE = 256 * 1024 * 1024,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
36
repos/base-hw/include/platform/imx53/vm_state.h
Normal file
36
repos/base-hw/include/platform/imx53/vm_state.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* \brief CPU context of a virtual machine for TrustZone
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2013-10-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__PLATFORM__IMX53__VM_STATE_H_
|
||||
#define _INCLUDE__PLATFORM__IMX53__VM_STATE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* CPU context of a virtual machine
|
||||
*/
|
||||
struct Vm_state;
|
||||
}
|
||||
|
||||
struct Genode::Vm_state : Genode::Cpu_state_modes
|
||||
{
|
||||
Genode::addr_t dfar;
|
||||
Genode::addr_t ttbr[2];
|
||||
Genode::addr_t ttbrc;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__PLATFORM__IMX53__VM_STATE_H_ */
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* \brief TrustZone specific definitions for the Versatile Express board
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-11-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__PLATFORM__VEA9X4__DRIVERS__TRUSTZONE_H_
|
||||
#define _INCLUDE__PLATFORM__VEA9X4__DRIVERS__TRUSTZONE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Trustzone
|
||||
{
|
||||
enum {
|
||||
SECURE_RAM_BASE = Genode::Board_base::RAM_2_BASE,
|
||||
SECURE_RAM_SIZE = Genode::Board_base::RAM_2_SIZE,
|
||||
NONSECURE_RAM_BASE = 0x80000000,
|
||||
NONSECURE_RAM_SIZE = 0x20000000,
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__PLATFORM__VEA9X4__DRIVERS__TRUSTZONE_H_ */
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Genode
|
||||
explicit Vm_session_client(Vm_session_capability session)
|
||||
: Rpc_client<Vm_session>(session) { }
|
||||
|
||||
|
||||
/**************************
|
||||
** Vm_session interface **
|
||||
**************************/
|
||||
@@ -43,6 +44,15 @@ namespace Genode
|
||||
|
||||
void run() { call<Rpc_run>(); }
|
||||
void pause() { call<Rpc_pause>(); }
|
||||
|
||||
void attach(Dataspace_capability ds,addr_t vm_addr) {
|
||||
call<Rpc_attach>(ds, vm_addr); }
|
||||
|
||||
void detach(addr_t vm_addr, size_t size) {
|
||||
call<Rpc_detach>(vm_addr, size); }
|
||||
|
||||
void attach_pic(addr_t vm_addr) {
|
||||
call<Rpc_attach_pic>(vm_addr); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ namespace Genode {
|
||||
{
|
||||
static const char *service_name() { return "VM"; }
|
||||
|
||||
class Invalid_dataspace : Exception { };
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
@@ -51,6 +53,33 @@ namespace Genode {
|
||||
*/
|
||||
virtual void pause(void) {}
|
||||
|
||||
/**
|
||||
* Attach dataspace to the guest-physical memory address space
|
||||
*
|
||||
* \param ds dataspace to be attached
|
||||
* \param vm_addr address in guest-physical memory address space
|
||||
*/
|
||||
virtual void attach(Dataspace_capability ds, addr_t vm_addr) = 0;
|
||||
|
||||
/**
|
||||
* Invalidate region of the guest-physical memory address space
|
||||
*
|
||||
* \param vm_addr address in guest-physical memory address space
|
||||
* \param size size of the region to invalidate
|
||||
*/
|
||||
virtual void detach(addr_t vm_addr, size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Attach cpu-local interrupt-controller's interface to
|
||||
* guest-physical memory address space.
|
||||
*
|
||||
* \param vm_addr address in guest-physical memory address space
|
||||
*
|
||||
* Note: this is currently only support for ARM interrupt-controller
|
||||
* hardware virtualization
|
||||
*/
|
||||
virtual void attach_pic(addr_t vm_addr) = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
@@ -61,8 +90,14 @@ namespace Genode {
|
||||
Signal_context_capability);
|
||||
GENODE_RPC(Rpc_run, void, run);
|
||||
GENODE_RPC(Rpc_pause, void, pause);
|
||||
GENODE_RPC_THROW(Rpc_attach, void, attach,
|
||||
GENODE_TYPE_LIST(Invalid_dataspace),
|
||||
Dataspace_capability, addr_t);
|
||||
GENODE_RPC(Rpc_detach, void, detach, addr_t, size_t);
|
||||
GENODE_RPC(Rpc_attach_pic, void, attach_pic, addr_t);
|
||||
GENODE_RPC_INTERFACE(Rpc_cpu_state, Rpc_exception_handler,
|
||||
Rpc_run, Rpc_pause);
|
||||
Rpc_run, Rpc_pause, Rpc_attach, Rpc_detach,
|
||||
Rpc_attach_pic);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,11 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/kernel/thread_base.cc
|
||||
SRC_CC += spec/arm/kernel/thread.cc
|
||||
SRC_CC += spec/arm/kernel/cpu.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm/crt0.s
|
||||
|
||||
# use dummy boot-modules per default
|
||||
BOOT_MODULES_VPATH = $(REP_DIR)/src/core/spec/arm
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core.inc
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v6
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += cpu.cc
|
||||
SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm_v6/mode_transition.s
|
||||
|
||||
@@ -50,7 +50,6 @@ SRC_CC += pager.cc
|
||||
SRC_CC += _main.cc
|
||||
SRC_CC += kernel/kernel.cc
|
||||
SRC_CC += kernel/thread.cc
|
||||
SRC_CC += kernel/vm.cc
|
||||
SRC_CC += kernel/signal_receiver.cc
|
||||
SRC_CC += kernel/irq.cc
|
||||
SRC_CC += kernel/pd.cc
|
||||
@@ -62,10 +61,13 @@ SRC_S += boot_modules.s
|
||||
# provide Genode version information
|
||||
include $(BASE_DIR)/src/core/version.inc
|
||||
|
||||
# switch to specific boot-modules if further images shall be available
|
||||
# switch to build-specific boot-modules if further images shall be available
|
||||
ifneq ($(wildcard $(BUILD_BASE_DIR)/boot_modules.s),)
|
||||
BOOT_MODULES_VPATH = $(BUILD_BASE_DIR)
|
||||
INC_DIR += $(BOOT_MODULES_VPATH)
|
||||
else
|
||||
# use dummy boot-modules per default
|
||||
BOOT_MODULES_VPATH = $(REP_DIR)/src/core/
|
||||
endif
|
||||
vpath boot_modules.s $(BOOT_MODULES_VPATH)
|
||||
|
||||
|
||||
12
repos/base-hw/lib/mk/cortex_a15/core.inc
Normal file
12
repos/base-hw/lib/mk/cortex_a15/core.inc
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2014-09-02
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
15
repos/base-hw/lib/mk/cortex_a8/core.inc
Normal file
15
repos/base-hw/lib/mk/cortex_a8/core.inc
Normal file
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2014-09-02
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
18
repos/base-hw/lib/mk/cortex_a9/core.inc
Normal file
18
repos/base-hw/lib/mk/cortex_a9/core.inc
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2014-09-02
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arm/cpu.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
@@ -6,12 +6,10 @@
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/exynos5
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/corelink_gic400
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += spec/exynos5/platform_support.cc
|
||||
SRC_CC += spec/exynos5/cpu.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
include $(REP_DIR)/lib/mk/cortex_a15/core.inc
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \author Martin Stein
|
||||
# \date 2012-10-04
|
||||
# \date 2015-02-09
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arndale
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v7/virtualization
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/arndale/platform_support.cc
|
||||
SRC_CC += spec/arndale/cpu.cc
|
||||
SRC_CC += spec/arndale/board.cc
|
||||
SRC_CC += spec/arndale/pic.cc
|
||||
SRC_CC += spec/arndale/platform_services.cc
|
||||
SRC_CC += spec/arm_v7/kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/kernel/cpu_context.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/virtualization/vm_session_component.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm_v7/virtualization/mode_transition.s
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/exynos5/core.inc
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Martin Stein
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx31
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/imx31/platform_support.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v6/core.inc
|
||||
13
repos/base-hw/lib/mk/platform_imx53/core-trustzone.inc
Normal file
13
repos/base-hw/lib/mk/platform_imx53/core-trustzone.inc
Normal file
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \author Martin Stein
|
||||
# \date 2012-10-24
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx53
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/cortex_a8/core.inc
|
||||
@@ -5,14 +5,12 @@
|
||||
# \date 2012-10-24
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx53
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/imx53/platform_support.cc
|
||||
SRC_CC += spec/imx53/pic.cc
|
||||
SRC_CC += platform_services.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/platform_imx53/core-trustzone.inc
|
||||
include $(REP_DIR)/lib/mk/core-trustzone.inc
|
||||
|
||||
@@ -6,15 +6,22 @@
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v7/trustzone
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx53/trustzone
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx53
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/imx53/trustzone/platform_support.cc
|
||||
SRC_CC += spec/imx53/trustzone/platform_services.cc
|
||||
SRC_CC += spec/imx53/trustzone/pic.cc
|
||||
SRC_CC += vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm_v7/vm_session_component.cc
|
||||
SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
|
||||
|
||||
# add assembly sources
|
||||
SRC_S += spec/arm_v7/trustzone/mode_transition.s
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/platform_imx53/core-trustzone.inc
|
||||
include $(REP_DIR)/lib/mk/core-trustzone.inc
|
||||
|
||||
@@ -7,14 +7,3 @@
|
||||
|
||||
# add library dependencies
|
||||
LIBS += core-trustzone
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx53
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/imx
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += cpu.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2013-11-25
|
||||
# \date 2015-02-09
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/odroid_xu
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += spec/odroid_xu/platform_support.cc
|
||||
SRC_CC += cpu.cc
|
||||
SRC_CC += spec/exynos5/board.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += kernel/vm_thread.cc
|
||||
SRC_CC += spec/arm/kernel/cpu_context.cc
|
||||
|
||||
# include less specific library parts
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/exynos5/core.inc
|
||||
|
||||
@@ -7,15 +7,11 @@
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/panda
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/tl16c750
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/panda/platform_support.cc
|
||||
SRC_CC += spec/cortex_a9/pic.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += cpu.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
include $(REP_DIR)/lib/mk/cortex_a9/core.inc
|
||||
|
||||
@@ -7,15 +7,11 @@
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/pbxa9
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/pl011
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/pbxa9/platform_support.cc
|
||||
SRC_CC += spec/cortex_a9/pic.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
SRC_CC += cpu.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
include $(REP_DIR)/lib/mk/cortex_a9/core.inc
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# \brief Build config for parts of core that depend on Trustzone status
|
||||
# \author Stefan Kalkowski
|
||||
# \author Martin Stein
|
||||
# \date 2012-10-24
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/vea9x4
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/vea9x4/platform_support.cc
|
||||
SRC_CC += spec/cortex_a9/pic.cc
|
||||
SRC_CC += spec/arm_gic/pic.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core-trustzone.inc
|
||||
@@ -1,20 +0,0 @@
|
||||
#
|
||||
# \brief Build config for parts of core that depend on Trustzone status
|
||||
# \author Stefan Kalkowski
|
||||
# \author Martin Stein
|
||||
# \date 2012-10-24
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/vea9x4/trustzone
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/vea9x4
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += vm_session_component.cc
|
||||
SRC_CC += spec/vea9x4/trustzone/platform_support.cc
|
||||
SRC_CC += spec/vea9x4/trustzone/pic.cc
|
||||
SRC_CC += spec/vea9x4/trustzone/platform_services.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/core-trustzone.inc
|
||||
@@ -5,16 +5,14 @@
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# add library dependencies
|
||||
LIBS += core-trustzone
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/vea9x4
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9
|
||||
INC_DIR += $(REP_DIR)/src/core/include/spec/pl011
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += cpu.cc
|
||||
SRC_CC += platform_services.cc
|
||||
SRC_CC += spec/vea9x4/platform_support.cc
|
||||
SRC_CC += spec/vea9x4/board.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core.inc
|
||||
include $(REP_DIR)/lib/mk/cortex_a9/core.inc
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#
|
||||
# \brief Build configurations for 'base-hw' on Freescale i.MX31
|
||||
# \author Martin Stein
|
||||
# \date 2011-12-20
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += hw platform_imx31 epit
|
||||
|
||||
# configure multiprocessor mode
|
||||
NR_OF_CPUS = 1
|
||||
|
||||
# set address where to link the text segment at
|
||||
LD_TEXT_ADDR ?= 0x82000000
|
||||
|
||||
# include implied specs
|
||||
include $(call select_from_repositories,mk/spec-hw.mk)
|
||||
include $(call select_from_repositories,mk/spec-platform_imx31.mk)
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += hw platform_imx53 epit
|
||||
SPECS += hw platform_imx53 platform_imx53_qsb epit
|
||||
|
||||
# configure multiprocessor mode
|
||||
NR_OF_CPUS = 1
|
||||
@@ -13,6 +13,9 @@ NR_OF_CPUS = 1
|
||||
# set address where to link the text segment at
|
||||
LD_TEXT_ADDR ?= 0x70010000
|
||||
|
||||
# add repository relative include paths
|
||||
REP_INC_DIR += include/platform/imx53_qsb
|
||||
|
||||
# include implied specs
|
||||
include $(call select_from_repositories,mk/spec-hw.mk)
|
||||
include $(call select_from_repositories,mk/spec-platform_imx53.mk)
|
||||
@@ -5,7 +5,7 @@
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += hw_imx53 trustzone
|
||||
SPECS += hw_imx53_qsb trustzone
|
||||
|
||||
# include implied specs
|
||||
include $(call select_from_repositories,mk/spec-hw_imx53.mk)
|
||||
include $(call select_from_repositories,mk/spec-hw_imx53_qsb.mk)
|
||||
21
repos/base-hw/mk/spec-hw_usb_armory.mk
Normal file
21
repos/base-hw/mk/spec-hw_usb_armory.mk
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# \brief Build configurations for 'base-hw' on USB Armory
|
||||
# \author Martin Stein
|
||||
# \date 2015-02-24
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += hw platform_imx53 platform_usb_armory epit trustzone
|
||||
|
||||
# configure multiprocessor mode
|
||||
NR_OF_CPUS = 1
|
||||
|
||||
# set address where to link the text segment at
|
||||
LD_TEXT_ADDR ?= 0x72000000
|
||||
|
||||
# add repository relative include paths
|
||||
REP_INC_DIR += include/platform/usb_armory
|
||||
|
||||
# include implied specs
|
||||
include $(call select_from_repositories,mk/spec-hw.mk)
|
||||
include $(call select_from_repositories,mk/spec-platform_imx53.mk)
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# \brief Offer build configurations that are specific to base-hw and VEA9X4
|
||||
# \author Martin Stein
|
||||
# \date 2011-12-20
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += hw_vea9x4 trustzone
|
||||
|
||||
# adjust link address of a trustzone text segment
|
||||
LD_TEXT_ADDR = 0x48000000
|
||||
|
||||
# include implied specs
|
||||
include $(call select_from_repositories,mk/spec-hw_vea9x4.mk)
|
||||
@@ -150,7 +150,7 @@ Signal_context_capability Signal_receiver::manage(Signal_context * const c)
|
||||
Signal_connection * const s = signal_connection();
|
||||
while (1) {
|
||||
try {
|
||||
c->_cap = s->alloc_context(_cap, (unsigned)c);
|
||||
c->_cap = s->alloc_context(_cap, (unsigned long)c);
|
||||
c->_receiver = this;
|
||||
_contexts.insert(&c->_receiver_le);
|
||||
return c->_cap;
|
||||
|
||||
@@ -39,12 +39,12 @@ Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
|
||||
|
||||
if (use_local_addr) {
|
||||
PERR("Parameter 'use_local_addr' not supported within core");
|
||||
return 0;
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
if (offset) {
|
||||
PERR("Parameter 'offset' not supported within core");
|
||||
return 0;
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
/* allocate range in core's virtual address space */
|
||||
@@ -63,7 +63,7 @@ Core_rm_session::attach(Dataspace_capability ds_cap, size_t size,
|
||||
ds.object()->cacheability(),
|
||||
ds.object()->is_io_mem());
|
||||
if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages, flags))
|
||||
return 0;
|
||||
return 0UL;
|
||||
|
||||
return virt_addr;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace Kernel
|
||||
unsigned pd_alignment_log2();
|
||||
size_t signal_context_size();
|
||||
size_t signal_receiver_size();
|
||||
size_t vm_size();
|
||||
|
||||
/**
|
||||
* Kernel names of the kernel calls
|
||||
@@ -48,6 +47,7 @@ namespace Kernel
|
||||
constexpr Call_arg call_id_run_vm() { return 28; }
|
||||
constexpr Call_arg call_id_pause_vm() { return 29; }
|
||||
constexpr Call_arg call_id_pause_thread() { return 30; }
|
||||
constexpr Call_arg call_id_bin_vm() { return 31; }
|
||||
|
||||
/**
|
||||
* Create a domain
|
||||
@@ -58,7 +58,7 @@ namespace Kernel
|
||||
* \retval >0 kernel name of the new domain
|
||||
* \retval 0 failed
|
||||
*/
|
||||
inline unsigned new_pd(void * const dst, Platform_pd * const pd)
|
||||
inline unsigned long new_pd(void * const dst, Platform_pd * const pd)
|
||||
{
|
||||
return call(call_id_new_pd(), (Call_arg)dst, (Call_arg)pd);
|
||||
}
|
||||
@@ -141,12 +141,15 @@ namespace Kernel
|
||||
* \param cpu_id kernel name of the targeted CPU
|
||||
* \param pd_id kernel name of the targeted domain
|
||||
* \param utcb core local pointer to userland thread-context
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval !=0 failed
|
||||
*/
|
||||
inline Tlb * start_thread(unsigned const thread_id, unsigned const cpu_id,
|
||||
unsigned const pd_id, Native_utcb * const utcb)
|
||||
inline int start_thread(unsigned const thread_id, unsigned const cpu_id,
|
||||
unsigned const pd_id, Native_utcb * const utcb)
|
||||
{
|
||||
return (Tlb *)call(call_id_start_thread(), thread_id, cpu_id, pd_id,
|
||||
(Call_arg)utcb);
|
||||
return call(call_id_start_thread(), thread_id, cpu_id, pd_id,
|
||||
(Call_arg)utcb);
|
||||
}
|
||||
|
||||
|
||||
@@ -290,6 +293,8 @@ namespace Kernel
|
||||
* \param dst memory donation for the VM object
|
||||
* \param state location of the CPU state of the VM
|
||||
* \param signal_context_id kernel name of the signal context for VM events
|
||||
* \param table guest-physical to host-physical translation
|
||||
* table pointer
|
||||
*
|
||||
* \retval >0 kernel name of the new VM
|
||||
* \retval 0 failed
|
||||
@@ -297,10 +302,11 @@ namespace Kernel
|
||||
* Regaining of the supplied memory is not supported by now.
|
||||
*/
|
||||
inline unsigned new_vm(void * const dst, void * const state,
|
||||
unsigned const signal_context_id)
|
||||
unsigned const signal_context_id,
|
||||
void * const table)
|
||||
{
|
||||
return call(call_id_new_vm(), (Call_arg)dst, (Call_arg)state,
|
||||
signal_context_id);
|
||||
(Call_arg)table, signal_context_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -308,10 +314,27 @@ namespace Kernel
|
||||
* Execute a virtual-machine (again)
|
||||
*
|
||||
* \param vm_id kernel name of the targeted VM
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline void run_vm(unsigned const vm_id)
|
||||
inline int run_vm(unsigned const vm_id)
|
||||
{
|
||||
call(call_id_run_vm(), vm_id);
|
||||
return call(call_id_run_vm(), vm_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destruct a virtual-machine
|
||||
*
|
||||
* \param vm_id kernel name of the targeted VM
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline int bin_vm(unsigned const vm_id)
|
||||
{
|
||||
return call(call_id_bin_vm(), vm_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -319,10 +342,13 @@ namespace Kernel
|
||||
* Stop execution of a virtual-machine
|
||||
*
|
||||
* \param vm_id kernel name of the targeted VM
|
||||
*
|
||||
* \retval 0 suceeded
|
||||
* \retval -1 failed
|
||||
*/
|
||||
inline void pause_vm(unsigned const vm_id)
|
||||
inline int pause_vm(unsigned const vm_id)
|
||||
{
|
||||
call(call_id_pause_vm(), vm_id);
|
||||
return call(call_id_pause_vm(), vm_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,22 @@
|
||||
#define _KERNEL__CPU_H_
|
||||
|
||||
/* core includes */
|
||||
#include <translation_table.h>
|
||||
#include <timer.h>
|
||||
#include <cpu.h>
|
||||
#include <kernel/cpu_scheduler.h>
|
||||
#include <kernel/irq.h>
|
||||
|
||||
/* base includes */
|
||||
#include <unmanaged_singleton.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* CPU context of a kernel stack
|
||||
*/
|
||||
class Cpu_context;
|
||||
|
||||
/**
|
||||
* Context of a job (thread, VM, idle) that shall be executed by a CPU
|
||||
*/
|
||||
@@ -56,6 +63,28 @@ namespace Kernel
|
||||
Cpu_pool * cpu_pool();
|
||||
}
|
||||
|
||||
class Kernel::Cpu_context : Genode::Cpu::Context
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Hook for environment specific initializations
|
||||
*
|
||||
* \param stack_size size of kernel stack
|
||||
* \param table base of transit translation table
|
||||
*/
|
||||
void _init(size_t const stack_size, addr_t const table);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param table mode-transition table
|
||||
*/
|
||||
Cpu_context(Genode::Translation_table * const table);
|
||||
};
|
||||
|
||||
class Kernel::Cpu_domain_update : public Double_list_item
|
||||
{
|
||||
friend class Cpu_domain_update_list;
|
||||
@@ -109,20 +138,25 @@ class Kernel::Cpu_job : public Cpu_share
|
||||
void _interrupt(unsigned const id);
|
||||
|
||||
/**
|
||||
* Insert context into the scheduling of this CPU
|
||||
* Activate our own CPU-share
|
||||
*/
|
||||
void _schedule();
|
||||
void _activate_own_share();
|
||||
|
||||
/**
|
||||
* Remove context from the scheduling of this CPU
|
||||
* Deactivate our own CPU-share
|
||||
*/
|
||||
void _unschedule();
|
||||
void _deactivate_own_share();
|
||||
|
||||
/**
|
||||
* Yield the currently scheduled CPU share of this context
|
||||
*/
|
||||
void _yield();
|
||||
|
||||
/**
|
||||
* Return wether we are allowed to help job 'j' with our CPU-share
|
||||
*/
|
||||
bool _helping_possible(Cpu_job * const j) { return j->_cpu == _cpu; }
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -135,6 +169,11 @@ class Kernel::Cpu_job : public Cpu_share
|
||||
*/
|
||||
virtual void proceed(unsigned const id) = 0;
|
||||
|
||||
/**
|
||||
* Return which job currently uses our CPU-share
|
||||
*/
|
||||
virtual Cpu_job * helping_sink() = 0;
|
||||
|
||||
/**
|
||||
* Construct a job with scheduling priority 'p' and time quota 'q'
|
||||
*/
|
||||
@@ -151,6 +190,11 @@ class Kernel::Cpu_job : public Cpu_share
|
||||
*/
|
||||
void affinity(Cpu * const cpu);
|
||||
|
||||
/**
|
||||
* Return wether our CPU-share is currently active
|
||||
*/
|
||||
bool own_share_active() { return Cpu_share::ready(); }
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
***************/
|
||||
@@ -179,39 +223,61 @@ class Kernel::Cpu_idle : public Genode::Cpu::User_context, public Cpu_job
|
||||
*/
|
||||
Cpu_idle(Cpu * const cpu);
|
||||
|
||||
/**
|
||||
* Handle exception that occured during execution on CPU 'cpu'
|
||||
*/
|
||||
void exception(unsigned const cpu)
|
||||
{
|
||||
switch (cpu_exception) {
|
||||
case INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return;
|
||||
case RESET: return;
|
||||
default: assert(0); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue execution on CPU 'cpu_id'
|
||||
/*
|
||||
* Cpu_job interface
|
||||
*/
|
||||
|
||||
void exception(unsigned const cpu);
|
||||
void proceed(unsigned const cpu_id);
|
||||
Cpu_job * helping_sink() { return this; }
|
||||
};
|
||||
|
||||
class Kernel::Cpu : public Genode::Cpu
|
||||
class Kernel::Cpu : public Genode::Cpu,
|
||||
public Irq::Pool
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Cpu_job Job;
|
||||
|
||||
/**
|
||||
* Inter-processor-interrupt object of the cpu
|
||||
*/
|
||||
struct Ipi : Irq
|
||||
{
|
||||
bool pending = false;
|
||||
|
||||
|
||||
/*********************
|
||||
** Irq interface **
|
||||
*********************/
|
||||
|
||||
void occurred();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param p interrupt pool this irq shall reside in
|
||||
*/
|
||||
Ipi(Irq::Pool &p);
|
||||
|
||||
/**
|
||||
* Trigger the ipi
|
||||
*
|
||||
* \param cpu_id id of the cpu this ipi object is related to
|
||||
*/
|
||||
void trigger(unsigned const cpu_id);
|
||||
};
|
||||
|
||||
unsigned const _id;
|
||||
Cpu_idle _idle;
|
||||
Timer * const _timer;
|
||||
Cpu_scheduler _scheduler;
|
||||
bool _ip_interrupt_pending;
|
||||
Ipi _ipi_irq;
|
||||
Irq _timer_irq; /* timer irq implemented as empty event */
|
||||
|
||||
unsigned _quota() const { return _timer->ms_to_tics(cpu_quota_ms); }
|
||||
unsigned _fill() const { return _timer->ms_to_tics(cpu_fill_ms); }
|
||||
Job * _head() const { return static_cast<Job *>(_scheduler.head()); }
|
||||
unsigned _fill() const { return _timer->ms_to_tics(cpu_fill_ms); }
|
||||
|
||||
public:
|
||||
|
||||
@@ -219,25 +285,29 @@ class Kernel::Cpu : public Genode::Cpu
|
||||
* Construct object for CPU 'id' with scheduling timer 'timer'
|
||||
*/
|
||||
Cpu(unsigned const id, Timer * const timer)
|
||||
:
|
||||
_id(id), _idle(this), _timer(timer),
|
||||
_scheduler(&_idle, _quota(), _fill()),
|
||||
_ip_interrupt_pending(false) { }
|
||||
|
||||
/**
|
||||
* Check if IRQ 'i' was due to a scheduling timeout
|
||||
*/
|
||||
bool timer_irq(unsigned const i) { return _timer->interrupt_id(_id) == i; }
|
||||
|
||||
/**
|
||||
* Notice that the IPI of the CPU isn't pending anymore
|
||||
*/
|
||||
void ip_interrupt_handled() { _ip_interrupt_pending = false; }
|
||||
: _id(id), _idle(this), _timer(timer),
|
||||
_scheduler(&_idle, _quota(), _fill()),
|
||||
_ipi_irq(*this),
|
||||
_timer_irq(_timer->interrupt_id(_id), *this) { }
|
||||
|
||||
/**
|
||||
* Raise the IPI of the CPU
|
||||
*/
|
||||
void trigger_ip_interrupt();
|
||||
void trigger_ip_interrupt() { _ipi_irq.trigger(_id); }
|
||||
|
||||
/**
|
||||
* Deliver interrupt to the CPU
|
||||
*
|
||||
* \param irq_id id of the interrupt that occured
|
||||
* \returns true if the interrupt belongs to this CPU, otherwise false
|
||||
*/
|
||||
bool interrupt(unsigned const irq_id)
|
||||
{
|
||||
Irq * const irq = object(irq_id);
|
||||
if (!irq) return false;
|
||||
irq->occurred();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule 'job' at this CPU
|
||||
@@ -250,7 +320,7 @@ class Kernel::Cpu : public Genode::Cpu
|
||||
void exception()
|
||||
{
|
||||
/* update old job */
|
||||
Job * const old_job = _head();
|
||||
Job * const old_job = scheduled_job();
|
||||
old_job->exception(_id);
|
||||
|
||||
/* update scheduler */
|
||||
@@ -260,7 +330,7 @@ class Kernel::Cpu : public Genode::Cpu
|
||||
_scheduler.update(quota);
|
||||
|
||||
/* get new job */
|
||||
Job * const new_job = _head();
|
||||
Job * const new_job = scheduled_job();
|
||||
quota = _scheduler.head_quota();
|
||||
assert(quota);
|
||||
_timer->start_one_shot(quota, _id);
|
||||
@@ -278,6 +348,12 @@ class Kernel::Cpu : public Genode::Cpu
|
||||
** Accessors **
|
||||
***************/
|
||||
|
||||
/**
|
||||
* Returns the currently active job
|
||||
*/
|
||||
Job * scheduled_job() const {
|
||||
return static_cast<Job *>(_scheduler.head())->helping_sink(); }
|
||||
|
||||
unsigned id() const { return _id; }
|
||||
Cpu_scheduler * scheduler() { return &_scheduler; }
|
||||
};
|
||||
@@ -315,6 +391,11 @@ class Kernel::Cpu_pool
|
||||
*/
|
||||
Cpu * primary_cpu() const { return cpu(Cpu::primary_id()); }
|
||||
|
||||
/**
|
||||
* Return object of current CPU
|
||||
*/
|
||||
Cpu * executing_cpu() const { return cpu(Cpu::executing_id()); }
|
||||
|
||||
/*
|
||||
* Accessors
|
||||
*/
|
||||
|
||||
@@ -99,6 +99,12 @@ class Kernel::Cpu_share : public Cpu_claim, public Cpu_fill
|
||||
*/
|
||||
Cpu_share(signed const p, unsigned const q)
|
||||
: _prio(p), _quota(q), _claim(q), _ready(0) { }
|
||||
|
||||
/*
|
||||
* Accessors
|
||||
*/
|
||||
|
||||
bool ready() const { return _ready; }
|
||||
};
|
||||
|
||||
class Kernel::Cpu_scheduler
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define _KERNEL__EARLY_TRANSLATIONS_H_
|
||||
|
||||
/* core includes */
|
||||
#include <assert.h>
|
||||
#include <page_slab.h>
|
||||
#include <translation_table.h>
|
||||
|
||||
@@ -45,7 +46,7 @@ class Genode::Early_translations_allocator : public Genode::Core_mem_translator
|
||||
Early_translations_allocator() { }
|
||||
int add_range(addr_t base, size_t size) { return -1; }
|
||||
int remove_range(addr_t base, size_t size) { return -1; }
|
||||
Alloc_return alloc_aligned(size_t size, void **out_addr, int align) {
|
||||
Alloc_return alloc_aligned(size_t, void **, int, addr_t, addr_t) {
|
||||
return Alloc_return::RANGE_CONFLICT; }
|
||||
Alloc_return alloc_addr(size_t size, addr_t addr) {
|
||||
return Alloc_return::RANGE_CONFLICT; }
|
||||
|
||||
43
repos/base-hw/src/core/include/kernel/fifo.h
Normal file
43
repos/base-hw/src/core/include/kernel/fifo.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* \brief Queue with first-in first-out semantics
|
||||
* \author Martin Stein
|
||||
* \date 2012-11-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _KERNEL__FIFO_H_
|
||||
#define _KERNEL__FIFO_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/fifo.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
/**
|
||||
* Queue with first-in first-out semantics
|
||||
*
|
||||
* \param T queue element type
|
||||
*/
|
||||
template <typename T>
|
||||
class Fifo : public Genode::Fifo<T>
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Call function 'f' of type 'void (QT *)' for each queue element
|
||||
*/
|
||||
template <typename F> void for_each(F f)
|
||||
{
|
||||
typedef Genode::Fifo<T> B;
|
||||
for (T * e = B::head(); e; e = e->B::Element::next()) { f(e); }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _KERNEL__FIFO_H_ */
|
||||
@@ -14,10 +14,8 @@
|
||||
#ifndef _KERNEL__IPC_NODE_H_
|
||||
#define _KERNEL__IPC_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/fifo.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/fifo.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace Kernel
|
||||
@@ -45,7 +43,7 @@ class Kernel::Ipc_node
|
||||
|
||||
class Message_buf;
|
||||
|
||||
typedef Genode::Fifo<Message_buf> Message_fifo;
|
||||
typedef Kernel::Fifo<Message_buf> Message_fifo;
|
||||
|
||||
/**
|
||||
* Describes the buffer for incoming or outgoing messages
|
||||
@@ -63,6 +61,7 @@ class Kernel::Ipc_node
|
||||
Message_buf _inbuf;
|
||||
Message_buf _outbuf;
|
||||
Ipc_node * _outbuf_dst;
|
||||
bool _outbuf_dst_help;
|
||||
State _state;
|
||||
|
||||
/**
|
||||
@@ -181,6 +180,15 @@ class Kernel::Ipc_node
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wether we are the source of a helping relationship
|
||||
*/
|
||||
bool _helps_outbuf_dst()
|
||||
{
|
||||
return (_state == PREPARE_AND_AWAIT_REPLY ||
|
||||
_state == AWAIT_REPLY) && _outbuf_dst_help;
|
||||
}
|
||||
|
||||
/**
|
||||
* IPC node returned from waiting due to reply receipt
|
||||
*/
|
||||
@@ -229,23 +237,28 @@ class Kernel::Ipc_node
|
||||
* \param buf_base base of receive buffer and request message
|
||||
* \param buf_size size of receive buffer
|
||||
* \param msg_size size of request message
|
||||
* \param help wether the request implies a helping relationship
|
||||
*/
|
||||
void send_request(Ipc_node * const dst, void * const buf_base,
|
||||
size_t const buf_size, size_t const msg_size)
|
||||
size_t const buf_size, size_t const msg_size,
|
||||
bool help)
|
||||
{
|
||||
/* assertions */
|
||||
assert(_state == INACTIVE || _state == PREPARE_REPLY);
|
||||
|
||||
/* prepare transmission of request message */
|
||||
_outbuf.base = buf_base;
|
||||
_outbuf.size = msg_size;
|
||||
_outbuf.src = this;
|
||||
_outbuf_dst = dst;
|
||||
_outbuf.base = buf_base;
|
||||
_outbuf.size = msg_size;
|
||||
_outbuf.src = this;
|
||||
_outbuf_dst = dst;
|
||||
_outbuf_dst_help = 0;
|
||||
|
||||
/* prepare reception of reply message */
|
||||
/*
|
||||
* Prepare reception of reply message but don't clear
|
||||
* '_inbuf.origin' because we might also prepare a reply.
|
||||
*/
|
||||
_inbuf.base = buf_base;
|
||||
_inbuf.size = buf_size;
|
||||
/* don't clear '_inbuf.origin' because we might prepare a reply */
|
||||
|
||||
/* update state */
|
||||
if (_state != PREPARE_REPLY) { _state = AWAIT_REPLY; }
|
||||
@@ -253,6 +266,29 @@ class Kernel::Ipc_node
|
||||
|
||||
/* announce request */
|
||||
dst->_announce_request(&_outbuf);
|
||||
|
||||
/* set help relation after announcement to simplify scheduling */
|
||||
_outbuf_dst_help = help;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return root destination of the helping-relation tree we are in
|
||||
*/
|
||||
Ipc_node * helping_sink() {
|
||||
return _helps_outbuf_dst() ? _outbuf_dst->helping_sink() : this; }
|
||||
|
||||
/**
|
||||
* Call function 'f' of type 'void (Ipc_node *)' for each helper
|
||||
*/
|
||||
template <typename F> void for_each_helper(F f)
|
||||
{
|
||||
/* if we have a helper in the receive buffer, call 'f' for it */
|
||||
if (_state == PREPARE_REPLY || _state == PREPARE_AND_AWAIT_REPLY) {
|
||||
if (_inbuf.src->_outbuf_dst_help) { f(_inbuf.src); } }
|
||||
|
||||
/* call 'f' for each helper in our request queue */
|
||||
_request_queue.for_each([f] (Message_buf * const b) {
|
||||
if (b->src->_outbuf_dst_help) { f(b->src); } });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Kernel back-end and core front-end for user interrupts
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-10-28
|
||||
*/
|
||||
|
||||
@@ -25,9 +26,14 @@
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* Kernel back-end of a user interrupt
|
||||
* Kernel back-end interface of an interrupt
|
||||
*/
|
||||
class Irq;
|
||||
|
||||
/**
|
||||
* Kernel back-end of a user interrupt
|
||||
*/
|
||||
class User_irq;
|
||||
}
|
||||
|
||||
namespace Genode
|
||||
@@ -38,43 +44,75 @@ namespace Genode
|
||||
class Irq;
|
||||
}
|
||||
|
||||
class Kernel::Irq
|
||||
:
|
||||
public Object_pool<Irq>::Item,
|
||||
public Signal_receiver,
|
||||
public Signal_context,
|
||||
public Signal_ack_handler
|
||||
|
||||
class Kernel::Irq : public Object_pool<Irq>::Item
|
||||
{
|
||||
friend class Genode::Irq;
|
||||
|
||||
private:
|
||||
|
||||
typedef Object_pool<Irq> Pool;
|
||||
|
||||
/**
|
||||
* Get map that provides all user interrupts by their kernel names
|
||||
*/
|
||||
static Pool * _pool()
|
||||
{
|
||||
static Pool p;
|
||||
return &p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent interrupt from occurring
|
||||
*/
|
||||
void _disable() const;
|
||||
|
||||
/**
|
||||
* Allow interrupt to occur
|
||||
*/
|
||||
void _enable() const;
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt
|
||||
*/
|
||||
unsigned _id() const { return Pool::Item::id(); };
|
||||
|
||||
public:
|
||||
|
||||
using Pool = Object_pool<Irq>;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
*/
|
||||
Irq(unsigned const irq_id)
|
||||
: Pool::Item(irq_id) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
* \param pool pool this interrupt shall belong to
|
||||
*/
|
||||
Irq(unsigned const irq_id, Pool &pool)
|
||||
: Irq(irq_id) { pool.insert(this); }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* By now, there is no use case to destruct interrupts
|
||||
*/
|
||||
virtual ~Irq() { PERR("destruction of interrupts not implemented"); }
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
*/
|
||||
virtual void occurred() { }
|
||||
|
||||
/**
|
||||
* Prevent interrupt from occurring
|
||||
*/
|
||||
void disable() const;
|
||||
|
||||
/**
|
||||
* Allow interrupt to occur
|
||||
*/
|
||||
void enable() const;
|
||||
};
|
||||
|
||||
|
||||
class Kernel::User_irq
|
||||
:
|
||||
public Kernel::Irq,
|
||||
public Signal_receiver,
|
||||
public Signal_context,
|
||||
public Signal_ack_handler
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Get map that provides all user interrupts by their kernel names
|
||||
*/
|
||||
static Irq::Pool * _pool();
|
||||
|
||||
/**
|
||||
* Get kernel name of the interrupt-signal receiver
|
||||
*/
|
||||
@@ -85,49 +123,12 @@ class Kernel::Irq
|
||||
*/
|
||||
unsigned _context_id() const { return Signal_context::Object::id(); }
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
*/
|
||||
void _occurred()
|
||||
{
|
||||
Signal_context::submit(1);
|
||||
_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information that enables a user to handle an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static Genode::Irq_signal _genode_signal(unsigned const irq_id)
|
||||
{
|
||||
typedef Genode::Irq_signal Irq_signal;
|
||||
static Irq_signal const invalid = { 0, 0 };
|
||||
Irq * const irq = _pool()->object(irq_id);
|
||||
if (irq) {
|
||||
Irq_signal s = { irq->_receiver_id(), irq->_context_id() };
|
||||
return s;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* By now, there is no use case to destruct user interrupts
|
||||
*/
|
||||
~Irq()
|
||||
{
|
||||
PERR("destruction of interrupts not implemented");
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
** Signal_ack_handler **
|
||||
************************/
|
||||
|
||||
void _signal_acknowledged() { _enable(); }
|
||||
void _signal_acknowledged() { enable(); }
|
||||
|
||||
public:
|
||||
|
||||
@@ -136,14 +137,39 @@ class Kernel::Irq
|
||||
*
|
||||
* \param irq_id kernel name of the interrupt
|
||||
*/
|
||||
Irq(unsigned const irq_id)
|
||||
:
|
||||
Pool::Item(irq_id),
|
||||
Signal_context(this, 0)
|
||||
User_irq(unsigned const irq_id)
|
||||
: Irq(irq_id), Signal_context(this, 0)
|
||||
{
|
||||
Signal_context::ack_handler(this);
|
||||
_pool()->insert(this);
|
||||
_disable();
|
||||
disable();
|
||||
Signal_context::ack_handler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle occurence of the interrupt
|
||||
*/
|
||||
void occurred()
|
||||
{
|
||||
Signal_context::submit(1);
|
||||
disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information that enables a user to handle an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static Genode::Irq_signal signal(unsigned const irq_id)
|
||||
{
|
||||
typedef Genode::Irq_signal Irq_signal;
|
||||
static Irq_signal const invalid = { 0, 0 };
|
||||
User_irq * const irq =
|
||||
dynamic_cast<User_irq*>(_pool()->object(irq_id));
|
||||
if (irq) {
|
||||
Irq_signal s = { irq->_receiver_id(), irq->_context_id() };
|
||||
return s;
|
||||
}
|
||||
return invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,30 +177,8 @@ class Kernel::Irq
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static void occurred(unsigned const irq_id)
|
||||
{
|
||||
Irq * const irq = _pool()->object(irq_id);
|
||||
if (!irq) {
|
||||
PWRN("unknown interrupt occurred");
|
||||
return;
|
||||
}
|
||||
irq->_occurred();
|
||||
}
|
||||
};
|
||||
|
||||
class Genode::Irq
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Get information that enables a user to handle an interrupt
|
||||
*
|
||||
* \param irq_id kernel name of targeted interrupt
|
||||
*/
|
||||
static Irq_signal signal(unsigned const irq_id)
|
||||
{
|
||||
return Kernel::Irq::_genode_signal(irq_id);
|
||||
}
|
||||
static User_irq * object(unsigned const irq_id) {
|
||||
return dynamic_cast<User_irq*>(_pool()->object(irq_id)); }
|
||||
};
|
||||
|
||||
#endif /* _KERNEL__IRQ_H_ */
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
#ifndef _KERNEL__KERNEL_H_
|
||||
#define _KERNEL__KERNEL_H_
|
||||
|
||||
#include <pic.h>
|
||||
#include <kernel/pd.h>
|
||||
|
||||
namespace Kernel {
|
||||
Pd * core_pd();
|
||||
Mode_transition_control * mtc();
|
||||
Pic * pic();
|
||||
}
|
||||
|
||||
#endif /* _KERNEL__KERNEL_H_ */
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
#include <kernel/configuration.h>
|
||||
#include <kernel/object.h>
|
||||
#include <kernel/cpu.h>
|
||||
#include <translation_table.h>
|
||||
#include <assert.h>
|
||||
#include <page_slab.h>
|
||||
#include <board.h>
|
||||
|
||||
/* structure of the mode transition */
|
||||
extern int _mt_begin;
|
||||
extern int _mt_end;
|
||||
extern int _mt_user_entry_pic;
|
||||
extern int _mt_vm_entry_pic;
|
||||
extern Genode::addr_t _mt_client_context_ptr;
|
||||
extern Genode::addr_t _mt_master_context_begin;
|
||||
extern Genode::addr_t _mt_master_context_end;
|
||||
@@ -76,11 +76,6 @@ class Kernel::Lock
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/**
|
||||
* CPU context of the kernel
|
||||
*/
|
||||
class Cpu_context;
|
||||
|
||||
/**
|
||||
* Controls the mode-transition page
|
||||
*
|
||||
@@ -112,28 +107,6 @@ namespace Kernel
|
||||
Lock & data_lock();
|
||||
}
|
||||
|
||||
class Kernel::Cpu_context : Cpu::Context
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Hook for environment specific initializations
|
||||
*
|
||||
* \param stack_size size of kernel stack
|
||||
* \param table base of transit translation table
|
||||
*/
|
||||
void _init(size_t const stack_size, addr_t const table);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param table mode-transition table
|
||||
*/
|
||||
Cpu_context(Genode::Translation_table * const table);
|
||||
};
|
||||
|
||||
class Kernel::Mode_transition_control
|
||||
{
|
||||
friend class Pd;
|
||||
@@ -143,7 +116,6 @@ class Kernel::Mode_transition_control
|
||||
typedef Early_translations_allocator Allocator;
|
||||
typedef Early_translations_slab Slab;
|
||||
typedef Genode::Translation_table Table;
|
||||
typedef Genode::Cpu_state_modes Cpu_state_modes;
|
||||
typedef Genode::Page_flags Page_flags;
|
||||
|
||||
Allocator _allocator;
|
||||
@@ -176,31 +148,6 @@ class Kernel::Mode_transition_control
|
||||
return VIRT_BASE + (phys - phys_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue execution of client context
|
||||
*
|
||||
* \param context targeted CPU context
|
||||
* \param cpu kernel name of targeted CPU
|
||||
* \param entry_raw raw pointer to assembly entry-code
|
||||
*/
|
||||
void _continue_client(void * const context, unsigned const cpu,
|
||||
addr_t const entry_raw)
|
||||
{
|
||||
/* override client-context pointer of the executing CPU */
|
||||
addr_t const context_ptr_base = (addr_t)&_mt_client_context_ptr;
|
||||
size_t const context_ptr_offset = cpu * sizeof(context);
|
||||
addr_t const context_ptr = context_ptr_base + context_ptr_offset;
|
||||
*(void * *)context_ptr = context;
|
||||
|
||||
/* unlock kernel data */
|
||||
data_lock().unlock();
|
||||
|
||||
/* call assembly code that applies the virtual-machine context */
|
||||
typedef void (* Entry)();
|
||||
Entry __attribute__((noreturn)) const entry = (Entry)entry_raw;
|
||||
entry();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
@@ -236,17 +183,44 @@ class Kernel::Mode_transition_control
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue execution of 'user' at 'cpu'
|
||||
* Continue execution of client context
|
||||
*
|
||||
* \param context targeted CPU context
|
||||
* \param cpu kernel name of targeted CPU
|
||||
* \param entry_raw raw pointer to assembly entry-code
|
||||
* \param context_ptr_base base address of client-context pointer region
|
||||
*/
|
||||
void continue_user(Cpu::Context * const user, unsigned const cpu) {
|
||||
_continue_client(user, cpu, _virt_user_entry()); }
|
||||
void switch_to(Cpu::Context * const context,
|
||||
unsigned const cpu,
|
||||
addr_t const entry_raw,
|
||||
addr_t const context_ptr_base)
|
||||
{
|
||||
/* override client-context pointer of the executing CPU */
|
||||
size_t const context_ptr_offset = cpu * sizeof(context);
|
||||
addr_t const context_ptr = context_ptr_base + context_ptr_offset;
|
||||
*(void * *)context_ptr = context;
|
||||
|
||||
/* unlock kernel data */
|
||||
data_lock().unlock();
|
||||
|
||||
/* call assembly code that applies the virtual-machine context */
|
||||
typedef void (* Entry)();
|
||||
Entry __attribute__((noreturn)) const entry = (Entry)entry_raw;
|
||||
entry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Continue execution of 'vm' at 'cpu'
|
||||
* Continue execution of user context
|
||||
*
|
||||
* \param context targeted CPU context
|
||||
* \param cpu kernel name of targeted CPU
|
||||
*/
|
||||
void continue_vm(Cpu_state_modes * const vm, unsigned const cpu) {
|
||||
_continue_client(vm, cpu, (addr_t)&_mt_vm_entry_pic); }
|
||||
|
||||
void switch_to_user(Cpu::Context * const context,
|
||||
unsigned const cpu)
|
||||
{
|
||||
switch_to(context, cpu, _virt_user_entry(),
|
||||
(addr_t)&_mt_client_context_ptr);
|
||||
}
|
||||
} __attribute__((aligned(Mode_transition_control::ALIGN)));
|
||||
|
||||
class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
||||
@@ -260,10 +234,6 @@ class Kernel::Pd : public Object<Pd, MAX_PDS, Pd_ids, pd_ids, pd_pool>
|
||||
Table * const _table;
|
||||
Platform_pd * const _platform_pd;
|
||||
|
||||
/* keep ready memory for size-aligned extra costs at construction */
|
||||
enum { EXTRA_RAM_SIZE = 2 * Table::MAX_COSTS_PER_TRANSLATION };
|
||||
char _extra_ram[EXTRA_RAM_SIZE];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,8 +44,8 @@ class Kernel::Thread
|
||||
:
|
||||
public Cpu::User_context,
|
||||
public Object<Thread, MAX_THREADS, Thread_ids, thread_ids, thread_pool>,
|
||||
public Cpu_job, public Cpu_domain_update, public Ipc_node,
|
||||
public Signal_context_killer, public Signal_handler, public Thread_base
|
||||
public Cpu_domain_update, public Ipc_node, public Signal_context_killer,
|
||||
public Signal_handler, public Thread_base, public Cpu_job
|
||||
{
|
||||
friend class Thread_event;
|
||||
|
||||
@@ -55,7 +55,7 @@ class Kernel::Thread
|
||||
|
||||
enum State
|
||||
{
|
||||
SCHEDULED = 1,
|
||||
ACTIVE = 1,
|
||||
AWAITS_START = 2,
|
||||
AWAITS_IPC = 3,
|
||||
AWAITS_RESUME = 4,
|
||||
@@ -103,14 +103,24 @@ class Kernel::Thread
|
||||
bool _core() const;
|
||||
|
||||
/**
|
||||
* Resume execution rawly
|
||||
* Switch from an inactive state to the active state
|
||||
*/
|
||||
void _schedule();
|
||||
void _become_active();
|
||||
|
||||
/**
|
||||
* Pause execution rawly
|
||||
* Switch from the active state to the inactive state 's'
|
||||
*/
|
||||
void _unschedule(State const s);
|
||||
void _become_inactive(State const s);
|
||||
|
||||
/**
|
||||
* Activate our CPU-share and those of our helpers
|
||||
*/
|
||||
void _activate_used_shares();
|
||||
|
||||
/**
|
||||
* Deactivate our CPU-share and those of our helpers
|
||||
*/
|
||||
void _deactivate_used_shares();
|
||||
|
||||
/**
|
||||
* Pause execution
|
||||
@@ -225,6 +235,7 @@ class Kernel::Thread
|
||||
void _call_bin_signal_context();
|
||||
void _call_bin_signal_receiver();
|
||||
void _call_new_vm();
|
||||
void _call_bin_vm();
|
||||
void _call_run_vm();
|
||||
void _call_pause_vm();
|
||||
void _call_access_thread_regs();
|
||||
@@ -277,7 +288,7 @@ class Kernel::Thread
|
||||
char const * const label);
|
||||
|
||||
/**
|
||||
* Prepare thread to get scheduled the first time
|
||||
* Prepare thread to get active the first time
|
||||
*
|
||||
* \param cpu targeted CPU
|
||||
* \param pd targeted domain
|
||||
@@ -294,6 +305,7 @@ class Kernel::Thread
|
||||
|
||||
void exception(unsigned const cpu);
|
||||
void proceed(unsigned const cpu);
|
||||
Cpu_job * helping_sink();
|
||||
|
||||
|
||||
/***************
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#ifndef _KERNEL__VM_H_
|
||||
#define _KERNEL__VM_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cpu/cpu_state.h>
|
||||
#include <vm_state.h>
|
||||
|
||||
/* core includes */
|
||||
#include <kernel/kernel.h>
|
||||
@@ -36,18 +35,18 @@ namespace Kernel
|
||||
Vm_pool * vm_pool();
|
||||
}
|
||||
|
||||
|
||||
class Kernel::Vm : public Object<Vm, MAX_VMS, Vm_ids, vm_ids, vm_pool>,
|
||||
public Cpu_job
|
||||
{
|
||||
private:
|
||||
|
||||
struct Vm_state : Genode::Cpu_state_modes
|
||||
{
|
||||
Genode::addr_t dfar;
|
||||
};
|
||||
enum State { ACTIVE, INACTIVE };
|
||||
|
||||
Vm_state * const _state;
|
||||
Signal_context * const _context;
|
||||
Genode::Vm_state * const _state;
|
||||
Signal_context * const _context;
|
||||
void * const _table;
|
||||
State _scheduled = INACTIVE;
|
||||
|
||||
public:
|
||||
|
||||
@@ -56,42 +55,44 @@ class Kernel::Vm : public Object<Vm, MAX_VMS, Vm_ids, vm_ids, vm_pool>,
|
||||
*
|
||||
* \param state initial CPU state
|
||||
* \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)
|
||||
:
|
||||
Cpu_job(Cpu_priority::min, 0), _state((Vm_state * const)state),
|
||||
_context(context)
|
||||
{ affinity(cpu_pool()->primary_cpu()); }
|
||||
Vm(void * const state,
|
||||
Signal_context * const context,
|
||||
void * const table);
|
||||
|
||||
/**
|
||||
* Inject an interrupt to this VM
|
||||
*
|
||||
* \param irq interrupt number to inject
|
||||
*/
|
||||
void inject_irq(unsigned irq);
|
||||
|
||||
|
||||
/****************
|
||||
** Vm_session **
|
||||
****************/
|
||||
|
||||
void run() { Cpu_job::_schedule(); }
|
||||
void pause() { Cpu_job::_unschedule(); }
|
||||
void run()
|
||||
{
|
||||
if (_scheduled != ACTIVE) Cpu_job::_activate_own_share();
|
||||
_scheduled = ACTIVE;
|
||||
}
|
||||
|
||||
void pause()
|
||||
{
|
||||
if (_scheduled != INACTIVE) Cpu_job::_deactivate_own_share();
|
||||
_scheduled = INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
/*************
|
||||
** Cpu_job **
|
||||
*************/
|
||||
|
||||
void exception(unsigned const cpu)
|
||||
{
|
||||
switch(_state->cpu_exception) {
|
||||
case Genode::Cpu_state::INTERRUPT_REQUEST:
|
||||
case Genode::Cpu_state::FAST_INTERRUPT_REQUEST:
|
||||
_interrupt(cpu);
|
||||
return;
|
||||
case Genode::Cpu_state::DATA_ABORT:
|
||||
_state->dfar = Cpu::Dfar::read();
|
||||
default:
|
||||
Cpu_job::_unschedule();
|
||||
_context->submit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void proceed(unsigned const cpu) { mtc()->continue_vm(_state, cpu); }
|
||||
void exception(unsigned const cpu);
|
||||
void proceed(unsigned const cpu);
|
||||
Cpu_job * helping_sink() { return this; }
|
||||
};
|
||||
|
||||
#endif /* _KERNEL__VM_H_ */
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <root/root.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <translation_table.h>
|
||||
@@ -80,7 +81,7 @@ namespace Genode
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
|
||||
_tt = new (tt) Translation_table();
|
||||
_tt = construct_at<Translation_table>(tt);
|
||||
_tt_phys = (Translation_table*) cma->phys_addr(_tt);
|
||||
_pslab = new (cma) Page_slab(cma);
|
||||
Kernel::mtc()->map(_tt, _pslab);
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Genode {
|
||||
/**
|
||||
* Return unique identification of this thread as faulter
|
||||
*/
|
||||
unsigned pager_object_badge() { return (unsigned)this; }
|
||||
unsigned long pager_object_badge() { return (unsigned long)this; }
|
||||
|
||||
/**
|
||||
* Set the executing CPU for this thread
|
||||
|
||||
@@ -221,10 +221,19 @@ class Genode::Arm
|
||||
*/
|
||||
struct Psr : Register<32>
|
||||
{
|
||||
static constexpr access_t usr = 16;
|
||||
static constexpr access_t svc = 19;
|
||||
/**
|
||||
* CPU mode
|
||||
*/
|
||||
struct M : Bitfield<0,5>
|
||||
{
|
||||
enum {
|
||||
USR = 16,
|
||||
SVC = 19,
|
||||
MON = 22,
|
||||
HYP = 26,
|
||||
};
|
||||
};
|
||||
|
||||
struct M : Bitfield<0,5> { }; /* CPU mode */
|
||||
struct F : Bitfield<6,1> { }; /* FIQ disable */
|
||||
struct I : Bitfield<7,1> { }; /* IRQ disable */
|
||||
struct A : Bitfield<8,1> { }; /* async. abort disable */
|
||||
@@ -260,7 +269,7 @@ class Genode::Arm
|
||||
{
|
||||
access_t v = 0;
|
||||
init_common(v);
|
||||
M::set(v, usr);
|
||||
M::set(v, M::USR);
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -271,7 +280,7 @@ class Genode::Arm
|
||||
{
|
||||
access_t v = 0;
|
||||
init_common(v);
|
||||
M::set(v, svc);
|
||||
M::set(v, M::SVC);
|
||||
I::set(v, 1);
|
||||
return v;
|
||||
}
|
||||
@@ -345,6 +354,7 @@ class Genode::Arm
|
||||
addr_t translation_table() const {
|
||||
return Ttbr0::Ba::masked(ttbr0); }
|
||||
|
||||
|
||||
/**
|
||||
* Assign translation-table base 'table'
|
||||
*/
|
||||
@@ -409,37 +419,43 @@ class Genode::Arm
|
||||
{
|
||||
switch (cpu_exception) {
|
||||
|
||||
case PREFETCH_ABORT: {
|
||||
case PREFETCH_ABORT:
|
||||
{
|
||||
/* check if fault was caused by a translation miss */
|
||||
Ifsr::access_t const fs = Ifsr::Fs::get(Ifsr::read());
|
||||
if (fs != Ifsr::section && fs != Ifsr::page)
|
||||
return false;
|
||||
|
||||
/* check if fault was caused by a translation miss */
|
||||
Ifsr::access_t const fs = Ifsr::Fs::get(Ifsr::read());
|
||||
if (fs != Ifsr::section && fs != Ifsr::page) { return 0; }
|
||||
/* fetch fault data */
|
||||
w = 0;
|
||||
va = ip;
|
||||
return true;
|
||||
}
|
||||
case DATA_ABORT:
|
||||
{
|
||||
/* check if fault was caused by translation miss */
|
||||
Dfsr::access_t const fs = Dfsr::Fs::get(Dfsr::read());
|
||||
if (fs != Dfsr::section && fs != Dfsr::page)
|
||||
return false;
|
||||
|
||||
/* fetch fault data */
|
||||
w = 0;
|
||||
va = ip;
|
||||
return 1; }
|
||||
/* fetch fault data */
|
||||
Dfsr::access_t const dfsr = Dfsr::read();
|
||||
w = Dfsr::Wnr::get(dfsr);
|
||||
va = Dfar::read();
|
||||
return true;
|
||||
}
|
||||
|
||||
case DATA_ABORT: {
|
||||
|
||||
/* check if fault was caused by translation miss */
|
||||
Dfsr::access_t const fs = Dfsr::Fs::get(Dfsr::read());
|
||||
if (fs != Dfsr::section && fs != Dfsr::page) { return 0; }
|
||||
|
||||
/* fetch fault data */
|
||||
Dfsr::access_t const dfsr = Dfsr::read();
|
||||
w = Dfsr::Wnr::get(dfsr);
|
||||
va = Dfar::read();
|
||||
return 1; }
|
||||
|
||||
default: return 0; }
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if current execution context is running in user mode
|
||||
*/
|
||||
static bool is_user() { return Psr::M::get(Psr::read()) == Psr::usr; }
|
||||
static bool is_user() { return Psr::M::get(Psr::read()) == Psr::M::USR; }
|
||||
|
||||
/**
|
||||
* Invalidate all entries of all instruction caches
|
||||
|
||||
@@ -53,3 +53,74 @@
|
||||
/* alignment constraints */
|
||||
.set MIN_PAGE_SIZE_LOG2, 12
|
||||
.set DATA_ACCESS_ALIGNM_LOG2, 2
|
||||
|
||||
|
||||
/***************************************************
|
||||
** Constant values that the mode transition uses **
|
||||
***************************************************/
|
||||
|
||||
/* kernel names of exceptions that can interrupt a user */
|
||||
.set RST_TYPE, 1
|
||||
.set UND_TYPE, 2
|
||||
.set SVC_TYPE, 3
|
||||
.set PAB_TYPE, 4
|
||||
.set DAB_TYPE, 5
|
||||
.set IRQ_TYPE, 6
|
||||
.set FIQ_TYPE, 7
|
||||
|
||||
.set RST_PC_ADJUST, 0
|
||||
.set UND_PC_ADJUST, 4
|
||||
.set SVC_PC_ADJUST, 0
|
||||
.set PAB_PC_ADJUST, 4
|
||||
.set DAB_PC_ADJUST, 8
|
||||
.set IRQ_PC_ADJUST, 4
|
||||
.set FIQ_PC_ADJUST, 4
|
||||
|
||||
/* offsets of the member variables in a CPU context */
|
||||
.set R12_OFFSET, 12 * 4
|
||||
.set SP_OFFSET, 13 * 4
|
||||
.set LR_OFFSET, 14 * 4
|
||||
.set PC_OFFSET, 15 * 4
|
||||
.set PSR_OFFSET, 16 * 4
|
||||
.set EXCEPTION_TYPE_OFFSET, 17 * 4
|
||||
.set TRANSIT_TTBR0_OFFSET, 17 * 4
|
||||
.set CIDR_OFFSET, 18 * 4
|
||||
.set TTBR0_OFFSET, 19 * 4
|
||||
.set TTBCR_OFFSET, 20 * 4
|
||||
.set MAIR0_OFFSET, 21 * 4
|
||||
|
||||
/* size of local variables */
|
||||
.set CONTEXT_PTR_SIZE, 1 * 4
|
||||
|
||||
|
||||
/*********************************************************
|
||||
** Local data structures that the mode transition uses **
|
||||
*********************************************************/
|
||||
|
||||
.macro _mt_local_variables
|
||||
|
||||
/* space for a copy of the kernel context */
|
||||
.p2align 2
|
||||
.global _mt_master_context_begin
|
||||
_mt_master_context_begin:
|
||||
.space 32 * 4
|
||||
.global _mt_master_context_end
|
||||
_mt_master_context_end:
|
||||
|
||||
/* space for a client context-pointer per CPU */
|
||||
.p2align 2
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr:
|
||||
.rept NR_OF_CPUS
|
||||
.space CONTEXT_PTR_SIZE
|
||||
.endr
|
||||
|
||||
/* a globally mapped buffer per CPU */
|
||||
.p2align 2
|
||||
.global _mt_buffer
|
||||
_mt_buffer:
|
||||
.rept NR_OF_CPUS
|
||||
.space BUFFER_SIZE
|
||||
.endr
|
||||
|
||||
.endm /* _mt_local_variables */
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* \brief Mode transition definitions used by all ARM architectures
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-06-12
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/***************************************************
|
||||
** Constant values that the mode transition uses **
|
||||
***************************************************/
|
||||
|
||||
/* kernel names of exceptions that can interrupt a user */
|
||||
.set RST_TYPE, 1
|
||||
.set UND_TYPE, 2
|
||||
.set SVC_TYPE, 3
|
||||
.set PAB_TYPE, 4
|
||||
.set DAB_TYPE, 5
|
||||
.set IRQ_TYPE, 6
|
||||
.set FIQ_TYPE, 7
|
||||
|
||||
.set RST_PC_ADJUST, 0
|
||||
.set UND_PC_ADJUST, 4
|
||||
.set SVC_PC_ADJUST, 0
|
||||
.set PAB_PC_ADJUST, 4
|
||||
.set DAB_PC_ADJUST, 8
|
||||
.set IRQ_PC_ADJUST, 4
|
||||
.set FIQ_PC_ADJUST, 4
|
||||
|
||||
/* offsets of the member variables in a CPU context */
|
||||
.set R12_OFFSET, 12 * 4
|
||||
.set SP_OFFSET, 13 * 4
|
||||
.set LR_OFFSET, 14 * 4
|
||||
.set PC_OFFSET, 15 * 4
|
||||
.set PSR_OFFSET, 16 * 4
|
||||
.set EXCEPTION_TYPE_OFFSET, 17 * 4
|
||||
.set TRANSIT_TTBR0_OFFSET, 17 * 4
|
||||
.set CIDR_OFFSET, 18 * 4
|
||||
.set TTBR0_OFFSET, 19 * 4
|
||||
|
||||
/* size of local variables */
|
||||
.set CONTEXT_PTR_SIZE, 1 * 4
|
||||
|
||||
|
||||
/*********************************************************
|
||||
** Local data structures that the mode transition uses **
|
||||
*********************************************************/
|
||||
|
||||
.macro _mt_local_variables
|
||||
|
||||
/* space for a copy of the kernel context */
|
||||
.p2align 2
|
||||
.global _mt_master_context_begin
|
||||
_mt_master_context_begin:
|
||||
.space 32 * 4
|
||||
.global _mt_master_context_end
|
||||
_mt_master_context_end:
|
||||
|
||||
/* space for a client context-pointer per CPU */
|
||||
.p2align 2
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr:
|
||||
.rept NR_OF_CPUS
|
||||
.space CONTEXT_PTR_SIZE
|
||||
.endr
|
||||
|
||||
/* a globally mapped buffer per CPU */
|
||||
.p2align 2
|
||||
.global _mt_buffer
|
||||
_mt_buffer:
|
||||
.rept NR_OF_CPUS
|
||||
.space BUFFER_SIZE
|
||||
.endr
|
||||
|
||||
.endm /* _mt_local_variables */
|
||||
@@ -279,10 +279,9 @@ class Genode::Translation_table
|
||||
public:
|
||||
|
||||
enum {
|
||||
SIZE_LOG2 = 14,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
||||
SIZE_LOG2 = 14,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
MAX_PAGE_SIZE_LOG2 = 20,
|
||||
MIN_PAGE_SIZE_LOG2 = 12,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-10-26
|
||||
*/
|
||||
|
||||
@@ -17,6 +18,9 @@
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
/* core includes */
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
@@ -32,9 +36,12 @@ namespace Genode
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Arm_gic;
|
||||
class Pic;
|
||||
}
|
||||
|
||||
namespace Kernel { using Pic = Genode::Pic; }
|
||||
|
||||
|
||||
class Genode::Arm_gic_distributor : public Mmio
|
||||
{
|
||||
public:
|
||||
@@ -44,8 +51,12 @@ class Genode::Arm_gic_distributor : public Mmio
|
||||
/**
|
||||
* Control register
|
||||
*/
|
||||
struct Ctlr : Register<0x000, 32> {
|
||||
struct Enable : Bitfield<0,1> { }; };
|
||||
struct Ctlr : Register<0x000, 32>
|
||||
{
|
||||
struct Enable : Bitfield<0,1> { };
|
||||
struct Enable_grp0 : Bitfield<0,1> { };
|
||||
struct Enable_grp1 : Bitfield<1,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Controller type register
|
||||
@@ -168,8 +179,12 @@ class Genode::Arm_gic_cpu_interface : public Mmio
|
||||
Arm_gic_cpu_interface(addr_t const base) : Mmio(base) { }
|
||||
};
|
||||
|
||||
class Genode::Arm_gic
|
||||
class Genode::Pic
|
||||
{
|
||||
public:
|
||||
|
||||
enum { IPI = 1 };
|
||||
|
||||
protected:
|
||||
|
||||
typedef Arm_gic_cpu_interface Cpui;
|
||||
@@ -183,11 +198,6 @@ class Genode::Arm_gic
|
||||
unsigned const _max_irq;
|
||||
unsigned _last_request;
|
||||
|
||||
/**
|
||||
* Return inter-processor IRQ of the CPU with kernel name 'cpu_id'
|
||||
*/
|
||||
unsigned _ipi(unsigned const cpu_id) const { return cpu_id + 1; }
|
||||
|
||||
/**
|
||||
* Platform specific initialization
|
||||
*/
|
||||
@@ -205,26 +215,16 @@ class Genode::Arm_gic
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Arm_gic(addr_t const distr_base, addr_t const cpu_base)
|
||||
:
|
||||
_distr(distr_base), _cpui(cpu_base),
|
||||
_max_irq(_distr.max_irq()),
|
||||
_last_request(spurious_id) { _init(); }
|
||||
Pic()
|
||||
: _distr(Board::IRQ_CONTROLLER_DISTR_BASE),
|
||||
_cpui (Board::IRQ_CONTROLLER_CPU_BASE),
|
||||
_max_irq(_distr.max_irq()),
|
||||
_last_request(spurious_id) { _init(); }
|
||||
|
||||
/**
|
||||
* Initialize CPU local interface of the controller
|
||||
*/
|
||||
void init_cpu_local()
|
||||
{
|
||||
/* disable the priority filter */
|
||||
_cpui.write<Cpui::Pmr::Priority>(_distr.min_priority());
|
||||
|
||||
/* disable preemption of IRQ handling by other IRQs */
|
||||
_cpui.write<Cpui::Bpr::Binary_point>(~0);
|
||||
|
||||
/* enable device */
|
||||
_cpui.write<Cpui::Ctlr::Enable>(1);
|
||||
}
|
||||
void init_cpu_local();
|
||||
|
||||
/**
|
||||
* Try to take an IRQ and return wether it was successful
|
||||
@@ -267,15 +267,6 @@ class Genode::Arm_gic
|
||||
void mask(unsigned const irq_id) {
|
||||
_distr.write<Distr::Icenabler::Clear_enable>(1, irq_id); }
|
||||
|
||||
/**
|
||||
* Return wether an IRQ is inter-processor IRQ of a CPU
|
||||
*
|
||||
* \param irq_id kernel name of the IRQ
|
||||
* \param cpu_id kernel name of the CPU
|
||||
*/
|
||||
bool is_ip_interrupt(unsigned const irq_id, unsigned const cpu_id) {
|
||||
return irq_id == _ipi(cpu_id); }
|
||||
|
||||
/**
|
||||
* Raise inter-processor IRQ of the CPU with kernel name 'cpu_id'
|
||||
*/
|
||||
@@ -283,7 +274,7 @@ class Genode::Arm_gic
|
||||
{
|
||||
typedef Distr::Sgir Sgir;
|
||||
Sgir::access_t sgir = 0;
|
||||
Sgir::Sgi_int_id::set(sgir, _ipi(cpu_id));
|
||||
Sgir::Sgi_int_id::set(sgir, IPI);
|
||||
Sgir::Cpu_target_list::set(sgir, 1 << cpu_id);
|
||||
_distr.write<Sgir>(sgir);
|
||||
}
|
||||
@@ -141,14 +141,19 @@ namespace Genode
|
||||
|
||||
class Genode::Arm_v7 : public Arm
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
|
||||
/**
|
||||
* Secure configuration register
|
||||
*/
|
||||
struct Scr : Register<32>
|
||||
{
|
||||
struct Ns : Bitfield<0, 1> { }; /* not secure */
|
||||
struct Ns : Bitfield<0, 1> { }; /* not secure */
|
||||
struct Fw : Bitfield<4, 1> { }; /* F bit writeable */
|
||||
struct Aw : Bitfield<5, 1> { }; /* A bit writeable */
|
||||
struct Scd : Bitfield<7, 1> { }; /* smc call disable */
|
||||
struct Hce : Bitfield<8, 1> { }; /* hyp call enable */
|
||||
struct Sif : Bitfield<9, 1> { }; /* secure instruction fetch */
|
||||
|
||||
/**
|
||||
* Read register value
|
||||
@@ -159,6 +164,15 @@ class Genode::Arm_v7 : public Arm
|
||||
asm volatile ("mrc p15, 0, %[v], c1, c1, 0" : [v]"=r"(v) ::);
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write register value
|
||||
*/
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, %[v], c1, c1, 0 \n"
|
||||
"isb" : : [v] "r" (v));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -168,6 +182,14 @@ class Genode::Arm_v7 : public Arm
|
||||
{
|
||||
struct Cpnsae10 : Bitfield<10, 1> { };
|
||||
struct Cpnsae11 : Bitfield<11, 1> { };
|
||||
|
||||
/**
|
||||
* Write register value
|
||||
*/
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, %[v], c1, c1, 2" : : [v] "r" (v));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -216,7 +238,21 @@ class Genode::Arm_v7 : public Arm
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Memory attribute indirection register 0
|
||||
*/
|
||||
struct Mair0 : Register<32>
|
||||
{
|
||||
struct Attr0 : Bitfield<0, 8> { };
|
||||
struct Attr1 : Bitfield<8, 8> { };
|
||||
struct Attr2 : Bitfield<16, 8> { };
|
||||
struct Attr3 : Bitfield<24, 8> { };
|
||||
|
||||
static void write(access_t v) {
|
||||
asm volatile ("mcr p15, 0, %[v], c10, c2, 0" :: [v]"r"(v) : ); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Invalidate all branch predictions
|
||||
@@ -255,37 +291,6 @@ class Genode::Arm_v7 : public Arm
|
||||
finish_init_phys_kernel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wether we are in secure mode
|
||||
*/
|
||||
static bool secure_mode()
|
||||
{
|
||||
if (!Board::SECURITY_EXTENSION) return 0;
|
||||
return !Scr::Ns::get(Scr::read());
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
** Trustzone specific API **
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* Set exception-vector's address for monitor mode to 'a'
|
||||
*/
|
||||
static void mon_exception_entry_at(addr_t const a) {
|
||||
asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (a)); }
|
||||
|
||||
/**
|
||||
* Enable access of co-processors cp10 and cp11 from non-secure mode.
|
||||
*/
|
||||
static inline void allow_coprocessor_nonsecure()
|
||||
{
|
||||
Nsacr::access_t v = 0;
|
||||
Nsacr::Cpnsae10::set(v, 1);
|
||||
Nsacr::Cpnsae11::set(v, 1);
|
||||
asm volatile ("mcr p15, 0, %[v], c1, c1, 2" : : [v] "r" (v));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish all previous data transfers
|
||||
*/
|
||||
@@ -306,6 +311,37 @@ class Genode::Arm_v7 : public Arm
|
||||
* Wait for the next interrupt as cheap as possible
|
||||
*/
|
||||
static void wait_for_interrupt() { asm volatile ("wfi"); }
|
||||
|
||||
|
||||
/******************************
|
||||
** Trustzone specific API **
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* Wether we are in secure mode
|
||||
*/
|
||||
static bool secure_mode()
|
||||
{
|
||||
if (!Board::SECURITY_EXTENSION) return 0;
|
||||
return !Scr::Ns::get(Scr::read());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set exception-vector's address for monitor mode to 'a'
|
||||
*/
|
||||
static void mon_exception_entry_at(addr_t const a) {
|
||||
asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (a)); }
|
||||
|
||||
|
||||
/***********************************
|
||||
** Virtualization specific API **
|
||||
***********************************/
|
||||
|
||||
/**
|
||||
* Set exception-vector's address for hypervisor mode to 'a'
|
||||
*/
|
||||
static void hyp_exception_entry_at(void * a) {
|
||||
asm volatile ("mcr p15, 4, %[rd], c12, c0, 0" :: [rd] "r" (a)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -332,7 +368,7 @@ void Genode::Arm::invalidate_data_caches()
|
||||
Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone()
|
||||
{
|
||||
access_t v = 0;
|
||||
M::set(v, usr);
|
||||
M::set(v, M::USR);
|
||||
I::set(v, 1);
|
||||
A::set(v, 1);
|
||||
return v;
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* \brief Long descriptor translation table definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-07-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ARM_V7__LONG_TRANSLATION_TABLE_H_
|
||||
#define _ARM_V7__LONG_TRANSLATION_TABLE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/misc_math.h>
|
||||
#include <util/register.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <page_flags.h>
|
||||
#include <page_slab.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
enum {
|
||||
SIZE_LOG2_4KB = 12,
|
||||
SIZE_LOG2_16KB = 14,
|
||||
SIZE_LOG2_2MB = 21,
|
||||
SIZE_LOG2_1GB = 30,
|
||||
SIZE_LOG2_4GB = 32,
|
||||
SIZE_LOG2_256GB = 38,
|
||||
};
|
||||
|
||||
/**
|
||||
* The stage indicates the kind of translation
|
||||
*
|
||||
* STAGE1 denotes the translation of 32-bit virtual addresses
|
||||
* to a 40-bit "intermediate" or actual physical addresses
|
||||
* STAGE2 denotes the translation of intermediate physical
|
||||
* addresses to actual physical addresses
|
||||
*/
|
||||
enum Stage { STAGE1, STAGE2 };
|
||||
|
||||
/**
|
||||
* Translation table base class for long format
|
||||
*
|
||||
* Long translation tables are part of the Large Physical Address Extension
|
||||
* of ARM. They are organized in at most three-level. This class comprises
|
||||
* properties shared between all 3 level of tables.
|
||||
*
|
||||
* \param BLOCK_SIZE_LOG2 virtual address range size in log2
|
||||
* of a single table entry
|
||||
* \param SIZE_LOG2 virtual address range size in log2 of whole table
|
||||
*/
|
||||
template <unsigned BLOCK_SIZE_LOG2, unsigned SIZE_LOG2>
|
||||
class Long_translation_table;
|
||||
|
||||
/**
|
||||
* Translation table third level (leaf in the table tree)
|
||||
*
|
||||
* \param STAGE marks whether it is part of a stage 1 or 2 table
|
||||
*/
|
||||
template <Stage STAGE>
|
||||
class Level_3_translation_table;
|
||||
|
||||
/**
|
||||
* Translation table first and second level
|
||||
*
|
||||
* \param ENTRY type of the table entries
|
||||
* \param STAGE marks whether it is part of a stage 1 or 2 table
|
||||
* \param SIZE_LOG2 virtual address range size in log2 of whole table
|
||||
*/
|
||||
template <typename ENTRY, Stage STAGE, unsigned SIZE_LOG2>
|
||||
class Level_x_translation_table;
|
||||
|
||||
/**
|
||||
* Trait pattern: helper class to carry information about
|
||||
* the type of a block descriptor (and stage)
|
||||
* through the template forest
|
||||
*
|
||||
* \param TABLE carries information about the table type
|
||||
* \param STAGE marks whether it is part of a stage 1 or 2 table
|
||||
*/
|
||||
template <typename TABLE, Stage STAGE> struct Stage_trait;
|
||||
|
||||
template <typename TABLE> struct Stage_trait<TABLE, STAGE1> {
|
||||
using Type = typename TABLE::Block_descriptor_stage1; };
|
||||
template <typename TABLE> struct Stage_trait<TABLE, STAGE2> {
|
||||
using Type = typename TABLE::Block_descriptor_stage2; };
|
||||
|
||||
using Level_3_stage_1_translation_table = Level_3_translation_table<STAGE1>;
|
||||
using Level_2_stage_1_translation_table =
|
||||
Level_x_translation_table<Level_3_stage_1_translation_table,
|
||||
STAGE1, SIZE_LOG2_1GB>;
|
||||
using Level_1_stage_1_translation_table =
|
||||
Level_x_translation_table<Level_2_stage_1_translation_table,
|
||||
STAGE1, SIZE_LOG2_4GB>;
|
||||
|
||||
using Level_3_stage_2_translation_table = Level_3_translation_table<STAGE2>;
|
||||
using Level_2_stage_2_translation_table =
|
||||
Level_x_translation_table<Level_3_stage_2_translation_table,
|
||||
STAGE2, SIZE_LOG2_1GB>;
|
||||
using Level_1_stage_2_translation_table =
|
||||
Level_x_translation_table<Level_2_stage_2_translation_table,
|
||||
STAGE2, SIZE_LOG2_256GB>;
|
||||
|
||||
using Translation_table = Level_1_stage_1_translation_table;
|
||||
}
|
||||
|
||||
|
||||
template <unsigned BLOCK_SIZE_LOG2, unsigned SZ_LOG2>
|
||||
class Genode::Long_translation_table
|
||||
{
|
||||
private:
|
||||
|
||||
inline bool _aligned(addr_t const a, size_t const alignm_log2) {
|
||||
return a == ((a >> alignm_log2) << alignm_log2); }
|
||||
|
||||
public:
|
||||
|
||||
static constexpr size_t SIZE_LOG2 = SZ_LOG2;
|
||||
static constexpr size_t MAX_ENTRIES = 1 << (SIZE_LOG2-BLOCK_SIZE_LOG2);
|
||||
static constexpr size_t BLOCK_SIZE = 1 << BLOCK_SIZE_LOG2;
|
||||
static constexpr size_t BLOCK_MASK = ~((1 << BLOCK_SIZE_LOG2) - 1);
|
||||
static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB;
|
||||
|
||||
class Misaligned {};
|
||||
class Invalid_range {};
|
||||
class Double_insertion {};
|
||||
|
||||
struct Descriptor : Register<64>
|
||||
{
|
||||
enum Type { INVALID, TABLE, BLOCK };
|
||||
|
||||
struct Valid : Bitfield<0, 1> { };
|
||||
struct Table : Bitfield<1, 1> { };
|
||||
|
||||
static Type type(access_t const v)
|
||||
{
|
||||
if (!Valid::get(v)) return INVALID;
|
||||
if (Table::get(v)) return TABLE;
|
||||
return BLOCK;
|
||||
}
|
||||
|
||||
static bool valid(access_t const v) {
|
||||
return Valid::get(v); }
|
||||
};
|
||||
|
||||
|
||||
struct Block_descriptor_base : Descriptor
|
||||
{
|
||||
struct Shareability : Descriptor::template Bitfield<8, 2>
|
||||
{
|
||||
enum { NON_SHAREABLE = 0,
|
||||
OUTER_SHAREABLE = 2,
|
||||
INNER_SHAREABLE = 3 };
|
||||
};
|
||||
|
||||
struct Access_flag : Descriptor::template Bitfield<10,1> { };
|
||||
|
||||
struct Output_address :
|
||||
Descriptor::template Bitfield<BLOCK_SIZE_LOG2,
|
||||
39 - BLOCK_SIZE_LOG2> { };
|
||||
|
||||
/**
|
||||
* Indicates that 16 adjacent entries point to contiguous
|
||||
* memory regions
|
||||
*/
|
||||
struct Continguous_hint : Descriptor::template Bitfield<52,1> { };
|
||||
|
||||
struct Execute_never : Descriptor::template Bitfield<54,1> { };
|
||||
};
|
||||
|
||||
|
||||
struct Table_descriptor : Descriptor
|
||||
{
|
||||
struct Next_table : Descriptor::template Bitfield<12, 27> { };
|
||||
|
||||
static typename Descriptor::access_t create(void * const pa)
|
||||
{
|
||||
typename Descriptor::access_t oa = (addr_t) pa;
|
||||
return Next_table::masked(oa)
|
||||
| Descriptor::Table::bits(1)
|
||||
| Descriptor::Valid::bits(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Block_descriptor_stage1 : Block_descriptor_base
|
||||
{
|
||||
using Base = Block_descriptor_base;
|
||||
|
||||
/**
|
||||
* Indicates memory attribute indirection register MAIR
|
||||
*/
|
||||
struct Attribute_index : Base::template Bitfield<2, 3>
|
||||
{
|
||||
enum {
|
||||
UNCACHED = Cache_attribute::UNCACHED,
|
||||
CACHED = Cache_attribute::CACHED,
|
||||
DEVICE
|
||||
};
|
||||
|
||||
static typename Descriptor::access_t create(Page_flags const &f)
|
||||
{
|
||||
if (f.device) { return Attribute_index::bits(DEVICE); }
|
||||
switch (f.cacheable) {
|
||||
case CACHED: return Attribute_index::bits(CACHED);
|
||||
case WRITE_COMBINED:
|
||||
case UNCACHED: return Attribute_index::bits(UNCACHED);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct Non_secure : Base::template Bitfield<5, 1> { };
|
||||
|
||||
struct Access_permission : Base::template Bitfield<6, 2>
|
||||
{
|
||||
enum { PRIVILEGED_RW, USER_RW, PRIVILEGED_RO, USER_RO };
|
||||
|
||||
static typename Descriptor::access_t create(Page_flags const &f)
|
||||
{
|
||||
bool p = f.privileged;
|
||||
if (f.writeable) {
|
||||
if (p) { return Access_permission::bits(PRIVILEGED_RW); }
|
||||
else { return Access_permission::bits(USER_RW); }
|
||||
} else {
|
||||
if (p) { return Access_permission::bits(PRIVILEGED_RO); }
|
||||
else { return Access_permission::bits(USER_RO); }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Not_global : Base::template Bitfield<11,1> { };
|
||||
|
||||
struct Privileged_execute_never : Base::template Bitfield<53,1> { };
|
||||
|
||||
static typename Descriptor::access_t create(Page_flags const &f,
|
||||
addr_t const pa)
|
||||
{
|
||||
return Access_permission::create(f)
|
||||
| Attribute_index::create(f)
|
||||
| Not_global::bits(!f.global)
|
||||
| Base::Shareability::bits(
|
||||
Base::Shareability::OUTER_SHAREABLE)
|
||||
| Base::Output_address::masked(pa)
|
||||
| Base::Access_flag::bits(1)
|
||||
| Descriptor::Valid::bits(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Block_descriptor_stage2 : Block_descriptor_base
|
||||
{
|
||||
using Base = Block_descriptor_base;
|
||||
|
||||
struct Mem_attr : Block_descriptor_base::template Bitfield<2,4>{};
|
||||
struct Hap : Block_descriptor_base::template Bitfield<6,2>{};
|
||||
|
||||
static typename Descriptor::access_t create(Page_flags const &f,
|
||||
addr_t const pa)
|
||||
{
|
||||
return Base::Shareability::bits(
|
||||
Base::Shareability::NON_SHAREABLE)
|
||||
| Base::Output_address::masked(pa)
|
||||
| Base::Access_flag::bits(1)
|
||||
| Descriptor::Valid::bits(1)
|
||||
| Mem_attr::bits(0xf)
|
||||
| Hap::bits(0x3);
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
typename Descriptor::access_t _entries[MAX_ENTRIES];
|
||||
|
||||
Long_translation_table()
|
||||
{
|
||||
if (!_aligned((addr_t)this, ALIGNM_LOG2))
|
||||
throw Misaligned();
|
||||
|
||||
memset(&_entries, 0, sizeof(_entries));
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func)
|
||||
{
|
||||
for (size_t i = vo >> BLOCK_SIZE_LOG2; size > 0;
|
||||
i = vo >> BLOCK_SIZE_LOG2) {
|
||||
addr_t end = (vo + BLOCK_SIZE) & BLOCK_MASK;
|
||||
size_t sz = min(size, end-vo);
|
||||
|
||||
func(vo, pa, sz, _entries[i]);
|
||||
|
||||
/* check whether we wrap */
|
||||
if (end < vo) return;
|
||||
|
||||
size = size - sz;
|
||||
vo += sz;
|
||||
pa += sz;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool empty()
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_ENTRIES; i++)
|
||||
if (Descriptor::valid(_entries[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
} __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
|
||||
template <Genode::Stage STAGE>
|
||||
class Genode::Level_3_translation_table :
|
||||
public Genode::Long_translation_table<Genode::SIZE_LOG2_4KB,
|
||||
Genode::SIZE_LOG2_2MB>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
size_t const size,
|
||||
Descriptor::access_t &desc)
|
||||
{
|
||||
using Base = Long_translation_table<Genode::SIZE_LOG2_4KB,
|
||||
Genode::SIZE_LOG2_2MB>;
|
||||
using Block_descriptor = typename Stage_trait<Base, STAGE>::Type;
|
||||
|
||||
if ((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) ||
|
||||
size < BLOCK_SIZE)
|
||||
throw Invalid_range();
|
||||
|
||||
Descriptor::access_t blk_desc =
|
||||
Block_descriptor::create(flags, pa)
|
||||
| Descriptor::Table::bits(1);
|
||||
if (Descriptor::valid(desc) && desc != blk_desc)
|
||||
throw Double_insertion();
|
||||
desc = blk_desc;
|
||||
}
|
||||
};
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
size_t const size,
|
||||
Descriptor::access_t &desc) {
|
||||
desc = 0; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
void insert_translation(addr_t vo,
|
||||
addr_t pa,
|
||||
size_t size,
|
||||
Page_flags const & flags,
|
||||
Page_slab * slab) {
|
||||
_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
||||
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab) {
|
||||
_range_op(vo, 0, size, Remove_func(slab)); }
|
||||
};
|
||||
|
||||
|
||||
template <typename ENTRY, Genode::Stage STAGE, unsigned SIZE_LOG2>
|
||||
class Genode::Level_x_translation_table :
|
||||
public Genode::Long_translation_table<ENTRY::SIZE_LOG2, SIZE_LOG2>
|
||||
{
|
||||
private:
|
||||
|
||||
using Base = Long_translation_table<ENTRY::SIZE_LOG2, SIZE_LOG2>;
|
||||
using Descriptor = typename Base::Descriptor;
|
||||
using Table_descriptor = typename Base::Table_descriptor;
|
||||
using Block_descriptor = typename Stage_trait<Base, STAGE>::Type;
|
||||
|
||||
struct Insert_func
|
||||
{
|
||||
Page_flags const & flags;
|
||||
Page_slab * slab;
|
||||
|
||||
Insert_func(Page_flags const & flags,
|
||||
Page_slab * slab) : flags(flags), slab(slab) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
size_t const size,
|
||||
typename Descriptor::access_t &desc)
|
||||
{
|
||||
/* can we insert a whole block? */
|
||||
if (!((vo & ~Base::BLOCK_MASK) || (pa & ~Base::BLOCK_MASK) ||
|
||||
size < Base::BLOCK_SIZE)) {
|
||||
typename Descriptor::access_t blk_desc =
|
||||
Block_descriptor::create(flags, pa);
|
||||
if (Descriptor::valid(desc) && desc != blk_desc)
|
||||
throw typename Base::Double_insertion();
|
||||
desc = blk_desc;
|
||||
return;
|
||||
}
|
||||
|
||||
/* we need to use a next level table */
|
||||
ENTRY *table;
|
||||
switch (Descriptor::type(desc)) {
|
||||
|
||||
case Descriptor::INVALID: /* no entry */
|
||||
{
|
||||
if (!slab) throw Allocator::Out_of_memory();
|
||||
|
||||
/* create and link next level table */
|
||||
table = new (slab) ENTRY();
|
||||
ENTRY * phys_addr = (ENTRY*) slab->phys_addr(table);
|
||||
desc = Table_descriptor::create(phys_addr ?
|
||||
phys_addr : table);
|
||||
}
|
||||
|
||||
case Descriptor::TABLE: /* table already available */
|
||||
{
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Table_descriptor::Next_table::masked(desc);
|
||||
table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
break;
|
||||
}
|
||||
|
||||
case Descriptor::BLOCK: /* there is already a block */
|
||||
{
|
||||
throw typename Base::Double_insertion();
|
||||
}
|
||||
};
|
||||
|
||||
/* insert translation */
|
||||
table->insert_translation(vo - (vo & Base::BLOCK_MASK),
|
||||
pa, size, flags, slab);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Remove_func
|
||||
{
|
||||
Page_slab * slab;
|
||||
|
||||
Remove_func(Page_slab * slab) : slab(slab) { }
|
||||
|
||||
void operator () (addr_t const vo,
|
||||
addr_t const pa,
|
||||
size_t const size,
|
||||
typename Descriptor::access_t &desc)
|
||||
{
|
||||
switch (Descriptor::type(desc)) {
|
||||
case Descriptor::TABLE:
|
||||
{
|
||||
/* use allocator to retrieve virt address of table */
|
||||
ENTRY * phys_addr = (ENTRY*)
|
||||
Table_descriptor::Next_table::masked(desc);
|
||||
ENTRY * table = (ENTRY*) slab->virt_addr(phys_addr);
|
||||
table = table ? table : (ENTRY*)phys_addr;
|
||||
table->remove_translation(vo - (vo & Base::BLOCK_MASK),
|
||||
size, slab);
|
||||
if (!table->empty())
|
||||
break;
|
||||
destroy(slab, table);
|
||||
}
|
||||
case Descriptor::BLOCK:
|
||||
case Descriptor::INVALID:
|
||||
desc = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB;
|
||||
static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_16KB;
|
||||
|
||||
/**
|
||||
* Insert translations into this table
|
||||
*
|
||||
* \param vo offset of the virtual region represented
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
* \param pa base of the physical backing store
|
||||
* \param size size of the translated region
|
||||
* \param flags mapping flags
|
||||
* \param slab second level page slab allocator
|
||||
*/
|
||||
void insert_translation(addr_t vo,
|
||||
addr_t pa,
|
||||
size_t size,
|
||||
Page_flags const & flags,
|
||||
Page_slab * slab) {
|
||||
this->_range_op(vo, pa, size, Insert_func(flags, slab)); }
|
||||
|
||||
/**
|
||||
* Remove translations that overlap with a given virtual region
|
||||
*
|
||||
* \param vo region offset within the tables virtual region
|
||||
* \param size region size
|
||||
* \param slab second level page slab allocator
|
||||
*/
|
||||
void remove_translation(addr_t vo, size_t size, Page_slab * slab) {
|
||||
this->_range_op(vo, 0, size, Remove_func(slab)); }
|
||||
};
|
||||
|
||||
#endif /* _ARM_V7__LONG_TRANSLATION_TABLE_H_ */
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* \brief Macros that are used by multiple assembly files
|
||||
* \author Martin Stein
|
||||
* \date 2014-01-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
.include "spec/arm/macros_support.s"
|
||||
|
||||
/**
|
||||
* Load kernel name of the executing CPU into register 'r'
|
||||
*/
|
||||
.macro _get_cpu_id r
|
||||
|
||||
/* read the multiprocessor affinity register */
|
||||
mrc p15, 0, \r, c0, c0, 5
|
||||
|
||||
/* get the affinity-0 bitfield from the read register value */
|
||||
and \r, \r, #0xff
|
||||
.endm
|
||||
86
repos/base-hw/src/core/include/spec/arm_v7/macros_support.s
Normal file
86
repos/base-hw/src/core/include/spec/arm_v7/macros_support.s
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* \brief Macros that are used by multiple assembly files
|
||||
* \author Martin Stein
|
||||
* \date 2014-01-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
.include "spec/arm/macros_support.s"
|
||||
|
||||
/**
|
||||
* Load kernel name of the executing CPU into register 'r'
|
||||
*/
|
||||
.macro _get_cpu_id r
|
||||
|
||||
/* read the multiprocessor affinity register */
|
||||
mrc p15, 0, \r, c0, c0, 5
|
||||
|
||||
/* get the affinity-0 bitfield from the read register value */
|
||||
and \r, \r, #0xff
|
||||
.endm
|
||||
|
||||
|
||||
/**
|
||||
* Determine the base of the client context of the executing CPU
|
||||
*
|
||||
* \param target_reg register that shall receive the base pointer
|
||||
* \param buf_reg register that can be polluted by the macro
|
||||
* \param client_context_ptr label of the client context pointer base
|
||||
*/
|
||||
.macro _get_client_context_ptr target_reg, buf_reg, client_context_ptr
|
||||
|
||||
/* get kernel name of CPU */
|
||||
_get_cpu_id \buf_reg
|
||||
|
||||
/* multiply CPU name with pointer size to get offset of pointer */
|
||||
mov \target_reg, #CONTEXT_PTR_SIZE
|
||||
mul \buf_reg, \buf_reg, \target_reg
|
||||
|
||||
/* get base of the pointer array */
|
||||
adr \target_reg, \client_context_ptr
|
||||
|
||||
/* add offset and base to get CPU-local pointer */
|
||||
add \target_reg, \target_reg, \buf_reg
|
||||
ldr \target_reg, [\target_reg]
|
||||
.endm
|
||||
|
||||
|
||||
/**
|
||||
* Save sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _save_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
mrs r1, spsr /* store mode-specific spsr */
|
||||
stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */
|
||||
.endm /* _save_bank mode */
|
||||
|
||||
|
||||
/**
|
||||
* Restore sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _restore_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
ldmia r0!, {r1,sp,lr} /* load mode-specific sp, lr, and spsr into r1 */
|
||||
msr spsr_cxfs, r1 /* load mode-specific spsr */
|
||||
.endm
|
||||
|
||||
|
||||
/***************
|
||||
** Constants **
|
||||
***************/
|
||||
|
||||
/* hardware names of CPU modes */
|
||||
.set USR_MODE, 16
|
||||
.set FIQ_MODE, 17
|
||||
.set IRQ_MODE, 18
|
||||
.set SVC_MODE, 19
|
||||
.set ABT_MODE, 23
|
||||
.set UND_MODE, 27
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <vm_session/vm_session.h>
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <dataspace_component.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
namespace Genode {
|
||||
class Vm_session_component;
|
||||
}
|
||||
|
||||
class Genode::Vm_session_component :
|
||||
public Genode::Rpc_object<Genode::Vm_session>
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
unsigned _vm_id;
|
||||
char _vm[sizeof(Kernel::Vm)];
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
addr_t _ds_addr;
|
||||
|
||||
static size_t _ds_size() {
|
||||
return align_addr(sizeof(Cpu_state_modes),
|
||||
get_page_size_log2()); }
|
||||
|
||||
addr_t _alloc_ds(size_t &ram_quota);
|
||||
|
||||
public:
|
||||
|
||||
Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
size_t ram_quota);
|
||||
~Vm_session_component();
|
||||
|
||||
|
||||
/**************************
|
||||
** Vm session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability cpu_state(void) { return _ds_cap; }
|
||||
void exception_handler(Signal_context_capability handler);
|
||||
void run(void);
|
||||
void pause(void);
|
||||
|
||||
void attach(Dataspace_capability ds_cap, addr_t vm_addr) {
|
||||
PWRN("Not implemented for TrustZone case"); }
|
||||
|
||||
void attach_pic(addr_t vm_addr) {
|
||||
PWRN("Not implemented for TrustZone case"); }
|
||||
|
||||
void detach(addr_t vm_addr, size_t size) {
|
||||
PWRN("Not implemented for TrustZone case"); }
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__VM_SESSION_COMPONENT_H_ */
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <vm_session/vm_session.h>
|
||||
#include <dataspace/capability.h>
|
||||
#include <long_translation_table.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <dataspace_component.h>
|
||||
#include <kernel/vm.h>
|
||||
|
||||
namespace Genode {
|
||||
class Vm_session_component;
|
||||
}
|
||||
|
||||
class Genode::Vm_session_component :
|
||||
public Genode::Rpc_object<Genode::Vm_session>
|
||||
{
|
||||
private:
|
||||
|
||||
using Translation_table =
|
||||
Genode::Level_1_stage_2_translation_table;
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
unsigned _vm_id;
|
||||
char _vm[sizeof(Kernel::Vm)];
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
addr_t _ds_addr;
|
||||
Translation_table *_table;
|
||||
Page_slab *_pslab;
|
||||
|
||||
static size_t _ds_size() {
|
||||
return align_addr(sizeof(Cpu_state_modes),
|
||||
get_page_size_log2()); }
|
||||
|
||||
addr_t _alloc_ds(size_t &ram_quota);
|
||||
void _attach(addr_t phys_addr, addr_t vm_addr, size_t size);
|
||||
|
||||
public:
|
||||
|
||||
Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
size_t ram_quota);
|
||||
~Vm_session_component();
|
||||
|
||||
|
||||
/**************************
|
||||
** Vm session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability cpu_state(void) { return _ds_cap; }
|
||||
void exception_handler(Signal_context_capability handler);
|
||||
void run(void);
|
||||
void pause(void);
|
||||
void attach(Dataspace_capability ds_cap, addr_t vm_addr);
|
||||
void attach_pic(addr_t vm_addr);
|
||||
void detach(addr_t vm_addr, size_t size);
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__VM_SESSION_COMPONENT_H_ */
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin stein
|
||||
* \date 2013-01-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIC_H_
|
||||
#define _PIC_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/arm_gic/pic_support.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Pic;
|
||||
}
|
||||
|
||||
class Genode::Pic : public Arm_gic
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
BASE = Board::GIC_CPU_MMIO_BASE,
|
||||
DISTR_BASE = BASE + 0x1000,
|
||||
CPUI_BASE = BASE + 0x2000,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic() : Arm_gic(DISTR_BASE, CPUI_BASE) { }
|
||||
};
|
||||
|
||||
namespace Kernel { class Pic : public Genode::Pic { }; }
|
||||
|
||||
#endif /* _PIC_H_ */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* \brief Board driver definitions common to Cortex A15 SoCs
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SPEC__CORTEX_A15__BOARD_SUPPORT_H_
|
||||
#define _SPEC__CORTEX_A15__BOARD_SUPPORT_H_
|
||||
|
||||
/* core includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Cortex_a15
|
||||
{
|
||||
class Board_base : public Genode::Board_base
|
||||
{
|
||||
private:
|
||||
|
||||
using Base = Genode::Board_base;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
/* interrupt controller */
|
||||
IRQ_CONTROLLER_DISTR_BASE = Base::IRQ_CONTROLLER_BASE + 0x1000,
|
||||
IRQ_CONTROLLER_DISTR_SIZE = 0x1000,
|
||||
IRQ_CONTROLLER_CPU_BASE = Base::IRQ_CONTROLLER_BASE + 0x2000,
|
||||
IRQ_CONTROLLER_CPU_SIZE = 0x2000,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _SPEC__CORTEX_A15__BOARD_SUPPORT_H_ */
|
||||
@@ -36,6 +36,377 @@ class Genode::Cpu : public Arm_v7
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Translation table base control register
|
||||
*/
|
||||
struct Ttbcr : Arm::Ttbcr
|
||||
{
|
||||
struct Irgn0 : Bitfield<8, 2> { };
|
||||
struct Orgn0 : Bitfield<10, 2> { };
|
||||
struct Sh0 : Bitfield<12, 2> { };
|
||||
struct Eae : Bitfield<31, 1> { }; /* extended address enable */
|
||||
|
||||
static access_t init_virt_kernel()
|
||||
{
|
||||
access_t v = 0;
|
||||
Irgn0::set(v, 1);
|
||||
Orgn0::set(v, 1);
|
||||
Sh0::set(v, 0b10);
|
||||
Eae::set(v, 1);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory attribute indirection register 0
|
||||
*/
|
||||
struct Mair0 : Arm_v7::Mair0
|
||||
{
|
||||
enum Attr {
|
||||
DEVICE_MEMORY = 0x04,
|
||||
NORMAL_MEMORY_UNCACHED = 0x44,
|
||||
NORMAL_MEMORY_CACHED = 0xff,
|
||||
};
|
||||
|
||||
static access_t init_virt_kernel()
|
||||
{
|
||||
access_t v = 0;
|
||||
Attr0::set(v, NORMAL_MEMORY_UNCACHED);
|
||||
Attr1::set(v, DEVICE_MEMORY);
|
||||
Attr2::set(v, NORMAL_MEMORY_CACHED);
|
||||
Attr3::set(v, DEVICE_MEMORY);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Non-secure access control register
|
||||
*/
|
||||
struct Nsacr : Arm_v7::Nsacr
|
||||
{
|
||||
struct Ns_smp : Bitfield<18,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Translation table base register 0 (64-bit format)
|
||||
*/
|
||||
struct Ttbr0 : Register<64>
|
||||
{
|
||||
enum Memory_region { NON_CACHEABLE = 0, CACHEABLE = 1 };
|
||||
|
||||
struct Ba : Bitfield<5, 34> { }; /* translation table base */
|
||||
struct Asid : Bitfield<48,8> { };
|
||||
|
||||
static void write(access_t const v)
|
||||
{
|
||||
asm volatile ("mcrr p15, 0, %[v0], %[v1], c2"
|
||||
:: [v0]"r"(v), [v1]"r"(v >> 32) : );
|
||||
}
|
||||
|
||||
static access_t read()
|
||||
{
|
||||
uint32_t v0, v1;
|
||||
asm volatile ("mrrc p15, 0, %[v0], %[v1], c2"
|
||||
: [v0]"=r"(v0), [v1]"=r"(v1) :: );
|
||||
return (access_t) v0 | ((access_t)v1 << 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return initialized value
|
||||
*
|
||||
* \param table base of targeted translation table
|
||||
*/
|
||||
static access_t init(addr_t const table, unsigned const id)
|
||||
{
|
||||
access_t v = Ba::masked((access_t)table);
|
||||
Asid::set(v, id);
|
||||
return v;
|
||||
}
|
||||
|
||||
static Genode::uint32_t init(addr_t const table) {
|
||||
return table; }
|
||||
};
|
||||
|
||||
|
||||
/*********************************
|
||||
** Virtualization extensions **
|
||||
*********************************/
|
||||
|
||||
/**
|
||||
* Hypervisor translation table base register
|
||||
*/
|
||||
struct Httbr : Register<64>
|
||||
{
|
||||
static void translation_table(addr_t const table)
|
||||
{
|
||||
asm volatile ("mcrr p15, 4, %[v0], %[v1], c2"
|
||||
:: [v0]"r"(table), [v1]"r"(0));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor translation control register
|
||||
*/
|
||||
struct Htcr : Register<32>
|
||||
{
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 4, %[v], c2, c0, 2" :: [v] "r" (v)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor coprocessor trap register
|
||||
*/
|
||||
struct Hcptr : Register<32>
|
||||
{
|
||||
/* Coprocessor access trap */
|
||||
template <unsigned COPROC>
|
||||
struct Tcp : Bitfield<COPROC, 1> {};
|
||||
|
||||
struct Tase : Bitfield<15, 1> { };
|
||||
struct Tta : Bitfield<20, 1> { };
|
||||
struct Tcpac : Bitfield<31, 1> { };
|
||||
|
||||
static access_t init()
|
||||
{
|
||||
/* don't trap on cporocessor 10 + 11, but all others */
|
||||
access_t v = 0;
|
||||
Tcp<0>::set(v, 1);
|
||||
Tcp<1>::set(v, 1);
|
||||
Tcp<2>::set(v, 1);
|
||||
Tcp<3>::set(v, 1);
|
||||
Tcp<4>::set(v, 1);
|
||||
Tcp<5>::set(v, 1);
|
||||
Tcp<6>::set(v, 1);
|
||||
Tcp<7>::set(v, 1);
|
||||
Tcp<8>::set(v, 1);
|
||||
Tcp<9>::set(v, 1);
|
||||
Tcp<12>::set(v, 1);
|
||||
Tcp<13>::set(v, 1);
|
||||
Tta::set(v, 1);
|
||||
Tcpac::set(v, 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 4, %[v], c1, c1, 2" :: [v] "r" (v)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor Memory attribute indirection register 0
|
||||
*/
|
||||
struct Hmair0 : Register<32>
|
||||
{
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 4, %[v], c10, c2, 0" :: [v] "r" (v)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor system control register
|
||||
*/
|
||||
struct Hsctlr : Arm_v7::Sctlr
|
||||
{
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 4, %[v], c1, c0, 0" :: [v] "r" (v)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor system trap register
|
||||
*/
|
||||
struct Hstr : Register<32>
|
||||
{
|
||||
/* System coprocessor primary register access trap */
|
||||
template <unsigned R>
|
||||
struct T : Bitfield<R, 1> {};
|
||||
|
||||
static access_t init()
|
||||
{
|
||||
/*
|
||||
* allow cache (7), TLB (8) maintenance, and performance
|
||||
* monitor (9), process/thread ID register (13) and timer (14)
|
||||
* access.
|
||||
*/
|
||||
access_t v = 0;
|
||||
T<0>::set(v, 1);
|
||||
T<1>::set(v, 1);
|
||||
T<2>::set(v, 1);
|
||||
T<3>::set(v, 1);
|
||||
T<5>::set(v, 1);
|
||||
T<6>::set(v, 1);
|
||||
T<10>::set(v, 1);
|
||||
T<11>::set(v, 1);
|
||||
T<12>::set(v, 1);
|
||||
T<15>::set(v, 1);
|
||||
return v;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Hypervisor control register
|
||||
*/
|
||||
struct Hcr : Register<32>
|
||||
{
|
||||
struct Vm : Bitfield<0, 1> {}; /* VT MMU enabled */
|
||||
struct Fmo : Bitfield<3, 1> {}; /* FIQ cannot been masked */
|
||||
struct Imo : Bitfield<4, 1> {}; /* IRQ cannot been masked */
|
||||
struct Amo : Bitfield<5, 1> {}; /* A bit cannot been masked */
|
||||
struct Twi : Bitfield<13, 1> {}; /* trap on WFI instruction */
|
||||
struct Twe : Bitfield<14, 1> {}; /* trap on WFE instruction */
|
||||
struct Tidcp : Bitfield<20, 1> {}; /* trap lockdown */
|
||||
struct Tac : Bitfield<21, 1> {}; /* trap ACTLR accesses */
|
||||
struct Tvm : Bitfield<26, 1> {}; /* trap virtual memory ctrls */
|
||||
|
||||
static access_t init()
|
||||
{
|
||||
access_t v = 0;
|
||||
Vm::set(v, 1);
|
||||
Fmo::set(v, 1);
|
||||
Imo::set(v, 1);
|
||||
Amo::set(v, 1);
|
||||
Twi::set(v, 1);
|
||||
Twe::set(v, 1);
|
||||
Tidcp::set(v, 1);
|
||||
Tac::set(v, 1);
|
||||
Tvm::set(v, 1);
|
||||
return v;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Virtualization translation control register
|
||||
*/
|
||||
struct Vtcr : Ttbcr
|
||||
{
|
||||
struct Sl0 : Bitfield<6,2> {};
|
||||
|
||||
static access_t init()
|
||||
{
|
||||
access_t v = Ttbcr::init_virt_kernel();
|
||||
Sl0::set(v, 1); /* set to starting level 1 */
|
||||
return v;
|
||||
}
|
||||
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 4, %[v], c2, c1, 2" :: [v] "r" (v)); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Extend basic CPU state by members relevant for 'base-hw' only
|
||||
*
|
||||
* Note: this class redefines Genode::Arm::Context
|
||||
*/
|
||||
struct Context : Genode::Cpu_state
|
||||
{
|
||||
Ttbr0::access_t ttbr0 = 0;
|
||||
Sctlr::access_t sctlr = 0;
|
||||
Ttbcr::access_t ttbrc = 0;
|
||||
Mair0::access_t mair0 = 0;
|
||||
|
||||
/**
|
||||
* Return base of assigned translation table
|
||||
*/
|
||||
addr_t translation_table() const {
|
||||
return Ttbr0::Ba::masked(ttbr0); }
|
||||
|
||||
/**
|
||||
* Assign translation-table base 'table'
|
||||
*/
|
||||
void translation_table(addr_t const table) {
|
||||
Ttbr0::Ba::set(ttbr0, (Ttbr0::access_t)(table >> 5)); }
|
||||
|
||||
/**
|
||||
* Assign protection domain
|
||||
*/
|
||||
void protection_domain(unsigned const id) {
|
||||
Ttbr0::Asid::set(ttbr0, id); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* An usermode execution state
|
||||
*
|
||||
* FIXME: this class largely overlaps with Genode::Arm::User_context
|
||||
*/
|
||||
struct User_context : Context
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
User_context() { cpsr = Psr::init_user(); }
|
||||
|
||||
/**
|
||||
* Support for kernel calls
|
||||
*/
|
||||
void user_arg_0(unsigned const arg) { r0 = arg; }
|
||||
void user_arg_1(unsigned const arg) { r1 = arg; }
|
||||
void user_arg_2(unsigned const arg) { r2 = arg; }
|
||||
void user_arg_3(unsigned const arg) { r3 = arg; }
|
||||
void user_arg_4(unsigned const arg) { r4 = arg; }
|
||||
void user_arg_5(unsigned const arg) { r5 = arg; }
|
||||
void user_arg_6(unsigned const arg) { r6 = arg; }
|
||||
void user_arg_7(unsigned const arg) { r7 = arg; }
|
||||
unsigned user_arg_0() const { return r0; }
|
||||
unsigned user_arg_1() const { return r1; }
|
||||
unsigned user_arg_2() const { return r2; }
|
||||
unsigned user_arg_3() const { return r3; }
|
||||
unsigned user_arg_4() const { return r4; }
|
||||
unsigned user_arg_5() const { return r5; }
|
||||
unsigned user_arg_6() const { return r6; }
|
||||
unsigned user_arg_7() const { return r7; }
|
||||
|
||||
/**
|
||||
* Initialize thread context
|
||||
*
|
||||
* \param table physical base of appropriate translation table
|
||||
* \param pd_id kernel name of appropriate protection domain
|
||||
*/
|
||||
void init_thread(addr_t const table, unsigned const pd_id)
|
||||
{
|
||||
protection_domain(pd_id);
|
||||
translation_table(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the context is in a page fault due to translation miss
|
||||
*
|
||||
* \param va holds the virtual fault-address if call returns 1
|
||||
* \param w holds wether it's a write fault if call returns 1
|
||||
*/
|
||||
bool in_fault(addr_t & va, addr_t & w) const
|
||||
{
|
||||
switch (cpu_exception) {
|
||||
|
||||
case PREFETCH_ABORT:
|
||||
{
|
||||
/* check if fault was caused by a translation miss */
|
||||
Ifsr::access_t const fs = Ifsr::Fs::get(Ifsr::read());
|
||||
if ((fs & 0b11100) != 0b100) return false;
|
||||
|
||||
/* fetch fault data */
|
||||
w = 0;
|
||||
va = ip;
|
||||
return true;
|
||||
}
|
||||
|
||||
case DATA_ABORT:
|
||||
{
|
||||
/* check if fault was caused by translation miss */
|
||||
Dfsr::access_t const fs = Dfsr::Fs::get(Dfsr::read());
|
||||
if ((fs & 0b11100) != 0b100) return false;
|
||||
|
||||
/* fetch fault data */
|
||||
Dfsr::access_t const dfsr = Dfsr::read();
|
||||
w = Dfsr::Wnr::get(dfsr);
|
||||
va = Dfar::read();
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return wether to retry an undefined user instruction after this call
|
||||
*/
|
||||
@@ -51,6 +422,24 @@ class Genode::Cpu : public Arm_v7
|
||||
*/
|
||||
static unsigned primary_id();
|
||||
|
||||
/**
|
||||
* Switch to the virtual mode in kernel
|
||||
*
|
||||
* \param table base of targeted translation table
|
||||
* \param process_id process ID of the kernel address-space
|
||||
*/
|
||||
static void
|
||||
init_virt_kernel(addr_t const table, unsigned const process_id)
|
||||
{
|
||||
Mair0::write(Mair0::init_virt_kernel());
|
||||
Cidr::write(process_id);
|
||||
Dacr::write(Dacr::init_virt_kernel());
|
||||
Ttbr0::write(Ttbr0::init(table, 1));
|
||||
Ttbcr::write(Ttbcr::init_virt_kernel());
|
||||
Sctlr::write(Sctlr::init_virt_kernel());
|
||||
inval_branch_predicts();
|
||||
}
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
*************/
|
||||
|
||||
37
repos/base-hw/src/core/include/spec/cortex_a15/macros.s
Normal file
37
repos/base-hw/src/core/include/spec/cortex_a15/macros.s
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* \brief Macros that are used by multiple assembly files
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-01-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
.include "spec/arm_v7/macros_support.s"
|
||||
|
||||
|
||||
/**
|
||||
* Switch to a given protection domain
|
||||
*
|
||||
* There is no atomicity problem when setting the ASID and translation table
|
||||
* base address in the one 64-bit TTBR0 register, like in Armv7 cpus without
|
||||
* LPAE extensions. Therefore, we don't have to use a transition table.
|
||||
*
|
||||
* \param ignored ignored parameter
|
||||
* \param ttbr0_low low word of TTBR0 64-bit register
|
||||
* \param ttbr0_high high word of TTBR0 64-bit register
|
||||
*/
|
||||
.macro _switch_protection_domain ignored, ttbr0_low, ttbr0_high
|
||||
|
||||
/* write translation-table-base register 0 */
|
||||
mcrr p15, 0, \ttbr0_low, \ttbr0_high, c2
|
||||
|
||||
/* instruction and data synchronization barrier */
|
||||
isb
|
||||
dsb
|
||||
.endm
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* \brief Translation table definitions for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-01-30
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#ifndef _TRANSLATION_TABLE_H_
|
||||
#define _TRANSLATION_TABLE_H_
|
||||
|
||||
/* core includes */
|
||||
#include <long_translation_table.h>
|
||||
|
||||
#endif /* _TRANSLATION_TABLE_H_ */
|
||||
31
repos/base-hw/src/core/include/spec/cortex_a8/macros.s
Normal file
31
repos/base-hw/src/core/include/spec/cortex_a8/macros.s
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* \brief Macros that are used by multiple assembly files
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-01-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
.include "spec/arm_v7/macros_support.s"
|
||||
|
||||
/**
|
||||
* Switch to a given protection domain
|
||||
*
|
||||
* \param transit_ttbr0 transitional TTBR0 value, read/write reg
|
||||
* \param new_cidr new CIDR value, read reg
|
||||
* \param new_ttbr0 new TTBR0 value, read/write reg
|
||||
*/
|
||||
.macro _switch_protection_domain transit_ttbr0, new_cidr, new_ttbr0
|
||||
mcr p15, 0, \transit_ttbr0, c2, c0, 0
|
||||
isb
|
||||
mcr p15, 0, \new_cidr, c13, c0, 1
|
||||
isb
|
||||
mcr p15, 0, \new_ttbr0, c2, c0, 0
|
||||
isb
|
||||
.endm
|
||||
@@ -1,22 +1,20 @@
|
||||
/*
|
||||
* \brief Armv7 translation table definitions for core
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-02-22
|
||||
* \brief Translation table definitions for core
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TRANSLATION_TABLE_H_
|
||||
#define _TRANSLATION_TABLE_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/arm/short_translation_table.h>
|
||||
#include <short_translation_table.h>
|
||||
|
||||
constexpr unsigned Genode::Translation::_device_tex() { return 2; }
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* \brief Board driver definitions common to Cortex A9 SoCs
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SPEC__CORTEX_A9__BOARD_H_
|
||||
#define _SPEC__CORTEX_A9__BOARD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Cortex_a9
|
||||
{
|
||||
class Board_base : public Genode::Board_base
|
||||
{
|
||||
private:
|
||||
|
||||
using Base = Genode::Board_base;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
/* interrupt controller */
|
||||
IRQ_CONTROLLER_DISTR_BASE = Base::CORTEX_A9_PRIVATE_MEM_BASE
|
||||
+ 0x1000,
|
||||
IRQ_CONTROLLER_DISTR_SIZE = 0x1000,
|
||||
IRQ_CONTROLLER_CPU_BASE = Base::CORTEX_A9_PRIVATE_MEM_BASE
|
||||
+ 0x100,
|
||||
IRQ_CONTROLLER_CPU_SIZE = 0x100,
|
||||
|
||||
/* timer */
|
||||
PRIVATE_TIMER_MMIO_BASE = Base::CORTEX_A9_PRIVATE_MEM_BASE
|
||||
+ 0x600,
|
||||
PRIVATE_TIMER_MMIO_SIZE = 0x10,
|
||||
PRIVATE_TIMER_IRQ = 29,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _SPEC__CORTEX_A9__BOARD_H_ */
|
||||
@@ -213,22 +213,22 @@ class Genode::Cpu : public Arm_v7
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
/**
|
||||
* Auxiliary Control Register
|
||||
*/
|
||||
struct Actlr : Register<32>
|
||||
{
|
||||
/* common */
|
||||
PERIPH_CLK = Board::CORTEX_A9_CLOCK,
|
||||
struct Smp : Bitfield<6, 1> { };
|
||||
|
||||
/* interrupt controller */
|
||||
PL390_DISTRIBUTOR_MMIO_BASE = Board::CORTEX_A9_PRIVATE_MEM_BASE + 0x1000,
|
||||
PL390_DISTRIBUTOR_MMIO_SIZE = 0x1000,
|
||||
PL390_CPU_MMIO_BASE = Board::CORTEX_A9_PRIVATE_MEM_BASE + 0x100,
|
||||
PL390_CPU_MMIO_SIZE = 0x100,
|
||||
static access_t read()
|
||||
{
|
||||
access_t v;
|
||||
asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (v) :: );
|
||||
return v;
|
||||
}
|
||||
|
||||
/* timer */
|
||||
PRIVATE_TIMER_MMIO_BASE = Board::CORTEX_A9_PRIVATE_MEM_BASE + 0x600,
|
||||
PRIVATE_TIMER_MMIO_SIZE = 0x10,
|
||||
PRIVATE_TIMER_IRQ = 29,
|
||||
PRIVATE_TIMER_CLK = PERIPH_CLK
|
||||
static void write(access_t const v) {
|
||||
asm volatile ("mcr p15, 0, %0, c1, c0, 1" :: "r" (v) : ); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
40
repos/base-hw/src/core/include/spec/cortex_a9/macros.s
Normal file
40
repos/base-hw/src/core/include/spec/cortex_a9/macros.s
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Macros that are used by multiple assembly files
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-01-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
.include "spec/arm_v7/macros_support.s"
|
||||
|
||||
/**
|
||||
* Switch to a given protection domain
|
||||
*
|
||||
* \param transit_ttbr0 transitional TTBR0 value, read/write reg
|
||||
* \param new_cidr new CIDR value, read reg
|
||||
* \param new_ttbr0 new TTBR0 value, read/write reg
|
||||
*/
|
||||
.macro _switch_protection_domain transit_ttbr0, new_cidr, new_ttbr0
|
||||
|
||||
/*
|
||||
* FIXME: Fixes instability problems that were observed on the
|
||||
* PandaBoard only. We neither know why invalidating predictions
|
||||
* at PD switches is a fix nor wether not doing so is the real
|
||||
* cause of this instability.
|
||||
*/
|
||||
mcr p15, 0, r0, c7, c5, 6
|
||||
|
||||
mcr p15, 0, \transit_ttbr0, c2, c0, 0
|
||||
isb
|
||||
mcr p15, 0, \new_cidr, c13, c0, 1
|
||||
isb
|
||||
mcr p15, 0, \new_ttbr0, c2, c0, 0
|
||||
isb
|
||||
.endm
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin stein
|
||||
* \date 2011-10-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIC_H_
|
||||
#define _PIC_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/arm_gic/pic_support.h>
|
||||
#include <cpu.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Pic;
|
||||
}
|
||||
|
||||
class Genode::Pic : public Arm_gic
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic() : Arm_gic(Cpu::PL390_DISTRIBUTOR_MMIO_BASE,
|
||||
Cpu::PL390_CPU_MMIO_BASE) { }
|
||||
|
||||
/**
|
||||
* Mark interrupt 'i' unsecure
|
||||
*/
|
||||
void unsecure(unsigned const i);
|
||||
};
|
||||
|
||||
namespace Kernel { class Pic : public Genode::Pic { }; }
|
||||
|
||||
#endif /* _PIC_H_ */
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <util/mmio.h>
|
||||
|
||||
/* core includes */
|
||||
#include <cpu.h>
|
||||
#include <board.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@@ -27,7 +27,7 @@ namespace Genode
|
||||
*/
|
||||
class Timer : public Mmio
|
||||
{
|
||||
enum { TICS_PER_MS = Cpu::PRIVATE_TIMER_CLK / 1000, };
|
||||
enum { TICS_PER_MS = Board::CORTEX_A9_PRIVATE_TIMER_CLK / 1000 };
|
||||
|
||||
/**
|
||||
* Load value register
|
||||
@@ -61,7 +61,7 @@ namespace Genode
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timer() : Mmio(Cpu::PRIVATE_TIMER_MMIO_BASE)
|
||||
Timer() : Mmio(Board::PRIVATE_TIMER_MMIO_BASE)
|
||||
{
|
||||
write<Control::Timer_enable>(0);
|
||||
}
|
||||
@@ -69,10 +69,8 @@ namespace Genode
|
||||
/**
|
||||
* Return kernel name of timer interrupt
|
||||
*/
|
||||
static unsigned interrupt_id(unsigned)
|
||||
{
|
||||
return Cpu::PRIVATE_TIMER_IRQ;
|
||||
}
|
||||
static unsigned interrupt_id(unsigned) {
|
||||
return Board::PRIVATE_TIMER_IRQ; }
|
||||
|
||||
/**
|
||||
* Start single timeout run
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* \brief Translation table definitions for core
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
#ifndef _TRANSLATION_TABLE_H_
|
||||
#define _TRANSLATION_TABLE_H_
|
||||
|
||||
/* core includes */
|
||||
#include <short_translation_table.h>
|
||||
|
||||
constexpr unsigned Genode::Translation::_device_tex() { return 2; }
|
||||
|
||||
#endif /* _TRANSLATION_TABLE_H_ */
|
||||
@@ -15,17 +15,17 @@
|
||||
#define _BOARD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <drivers/board_base.h>
|
||||
#include <spec/cortex_a15/board_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Board : public Board_base
|
||||
class Board : public Cortex_a15::Board_base
|
||||
{
|
||||
public:
|
||||
|
||||
static void outer_cache_invalidate() { }
|
||||
static void outer_cache_flush() { }
|
||||
static void prepare_kernel() { }
|
||||
static void prepare_kernel();
|
||||
|
||||
/**
|
||||
* Tell secondary CPUs to start execution from instr. pointer 'ip'
|
||||
@@ -18,14 +18,14 @@
|
||||
#include <board.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/uart/imx31_uart_base.h>
|
||||
#include <drivers/uart/imx_uart_base.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Serial output driver for core
|
||||
*/
|
||||
class Serial : public Imx31_uart_base
|
||||
class Serial : public Imx_uart_base
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Genode
|
||||
*
|
||||
* XXX: The 'baud_rate' argument is ignored for now.
|
||||
*/
|
||||
Serial(unsigned) : Imx31_uart_base(Board::UART_1_MMIO_BASE) { }
|
||||
Serial(unsigned) : Imx_uart_base(Board::UART_1_MMIO_BASE) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* \brief Board driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-11-01
|
||||
*/
|
||||
|
||||
#ifndef _BOARD_H_
|
||||
#define _BOARD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* AHB-lite 2v6 to IP bus interface
|
||||
*/
|
||||
class Aips : public Mmio
|
||||
{
|
||||
/**
|
||||
* Configuration of the masters
|
||||
*/
|
||||
struct Mpr { enum { ALL_UNBUFFERED_AND_FULLY_TRUSTED = 0x77777777 }; };
|
||||
struct Mpr1 : Register<0x0, 32>, Mpr { };
|
||||
struct Mpr2 : Register<0x4, 32>, Mpr { };
|
||||
|
||||
/**
|
||||
* Configuration of the platform peripherals
|
||||
*/
|
||||
struct Pacr { enum { ALL_UNBUFFERED_AND_FULLY_UNPROTECTED = 0 }; };
|
||||
struct Pacr1 : Register<0x20, 32>, Pacr { };
|
||||
struct Pacr2 : Register<0x24, 32>, Pacr { };
|
||||
struct Pacr3 : Register<0x28, 32>, Pacr { };
|
||||
struct Pacr4 : Register<0x2c, 32>, Pacr { };
|
||||
|
||||
/**
|
||||
* Configuration of the off-platform peripherals
|
||||
*/
|
||||
struct Opacr1 : Register<0x40, 32>, Pacr { };
|
||||
struct Opacr2 : Register<0x44, 32>, Pacr { };
|
||||
struct Opacr3 : Register<0x48, 32>, Pacr { };
|
||||
struct Opacr4 : Register<0x4c, 32>, Pacr { };
|
||||
struct Opacr5 : Register<0x50, 32>, Pacr { };
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Aips(addr_t const base) : Mmio(base) { }
|
||||
|
||||
/**
|
||||
* Configure this module appropriately for the first kernel run
|
||||
*/
|
||||
void prepare_kernel()
|
||||
{
|
||||
/* avoid AIPS intervention at any memory access */
|
||||
write<Mpr1>(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED);
|
||||
write<Mpr2>(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED);
|
||||
write<Pacr1>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Pacr2>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Pacr3>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Pacr4>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Opacr1>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Opacr2>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Opacr3>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Opacr4>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
write<Opacr5>(Pacr::ALL_UNBUFFERED_AND_FULLY_UNPROTECTED);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Board driver for core
|
||||
*/
|
||||
struct Board : Board_base
|
||||
{
|
||||
/**
|
||||
* Static AIPS 1 instance
|
||||
*/
|
||||
static Aips * aips_1() { static Aips a(AIPS_1_MMIO_BASE); return &a; }
|
||||
|
||||
/**
|
||||
* Static AIPS 2 instance
|
||||
*/
|
||||
static Aips * aips_2() { static Aips a(AIPS_2_MMIO_BASE); return &a; }
|
||||
|
||||
/**
|
||||
* Configure this module appropriately for the first kernel run
|
||||
*/
|
||||
static void prepare_kernel()
|
||||
{
|
||||
aips_1()->prepare_kernel();
|
||||
aips_2()->prepare_kernel();
|
||||
}
|
||||
|
||||
static void outer_cache_invalidate() { }
|
||||
static void outer_cache_flush() { }
|
||||
static bool is_smp() { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _BOARD_H_ */
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIC_H_
|
||||
#define _PIC_H_
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Pic;
|
||||
}
|
||||
|
||||
class Genode::Pic : public Mmio
|
||||
{
|
||||
private:
|
||||
|
||||
struct Intcntl : Register<0x0, 32> { }; /* IRQ control register */
|
||||
struct Nimask : Register<0x4, 32> { }; /* normal IRQ mask reg. */
|
||||
struct Intennum : Register<0x8, 32> { }; /* IRQ enable nr. reg. */
|
||||
struct Intdisnum : Register<0xc, 32> { }; /* IRQ disable nr. reg. */
|
||||
struct Intenableh : Register<0x10, 32> { }; /* IRQ enable register */
|
||||
struct Intenablel : Register<0x14, 32> { }; /* IRQ enable register */
|
||||
struct Inttypeh : Register<0x18, 32> { }; /* IRQ type register */
|
||||
struct Inttypel : Register<0x1c, 32> { }; /* IRQ type register */
|
||||
struct Intsrch : Register<0x48, 32> { }; /* IRQ source register */
|
||||
struct Intsrcl : Register<0x4c, 32> { }; /* IRQ source register */
|
||||
struct Nipndh : Register<0x58, 32> { }; /* normal IRQ pending */
|
||||
struct Nipndl : Register<0x5c, 32> { }; /* normal IRQ pending */
|
||||
|
||||
/**
|
||||
* Normal interrupt priority registers
|
||||
*/
|
||||
struct Nipriority : Register_array<0x20, 32, 8, 32> { };
|
||||
|
||||
/**
|
||||
* Normal interrupt vector and status register
|
||||
*/
|
||||
struct Nivecsr : Register<0x40, 32>
|
||||
{
|
||||
struct Nvector : Bitfield<16, 16> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate request number 'i'
|
||||
*/
|
||||
bool _valid(unsigned const i) const { return i < NR_OF_IRQ; }
|
||||
|
||||
public:
|
||||
|
||||
enum { NR_OF_IRQ = 64 };
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic() : Mmio(Board::AVIC_MMIO_BASE)
|
||||
{
|
||||
write<Intenablel>(0);
|
||||
write<Intenableh>(0);
|
||||
write<Nimask>(~0);
|
||||
write<Intcntl>(0);
|
||||
write<Inttypeh>(0);
|
||||
write<Inttypel>(0);
|
||||
for (unsigned i = 0; i < Nipriority::ITEMS; i++) {
|
||||
write<Nipriority>(0, i); }
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to receive an IRQ in 'i' and return wether it was successful
|
||||
*/
|
||||
bool take_request(unsigned & i)
|
||||
{
|
||||
i = read<Nivecsr::Nvector>();
|
||||
return _valid(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmask IRQ 'i'
|
||||
*/
|
||||
void unmask(unsigned const i, unsigned) {
|
||||
if (_valid(i)) { write<Intennum>(i); } }
|
||||
|
||||
/**
|
||||
* Mask IRQ 'i'
|
||||
*/
|
||||
void mask(unsigned const i) { if (i < NR_OF_IRQ) write<Intdisnum>(i); }
|
||||
|
||||
/**
|
||||
* Return wether IRQ 'irq_id' is inter-processor IRQ of CPU 'cpu_id'
|
||||
*/
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
*************/
|
||||
|
||||
void init_cpu_local() { }
|
||||
void trigger_ip_interrupt(unsigned) { }
|
||||
void finish_request() { /* done by source retraction or masking */ }
|
||||
};
|
||||
|
||||
namespace Kernel { class Pic : public Genode::Pic { }; }
|
||||
|
||||
#endif /* _PIC_H_ */
|
||||
@@ -15,7 +15,7 @@
|
||||
#define _BOARD_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <platform/imx53/drivers/board_base.h>
|
||||
#include <drivers/board_base.h>
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Imx53
|
||||
|
||||
@@ -32,7 +32,14 @@ class Genode::Pic : public Mmio
|
||||
{
|
||||
public:
|
||||
|
||||
enum { NR_OF_IRQ = 109 };
|
||||
enum {
|
||||
/*
|
||||
* FIXME: dummy ipi value on non-SMP platform, should be removed
|
||||
* when SMP is an aspect of CPUs only compiled where necessary
|
||||
*/
|
||||
IPI = 0,
|
||||
NR_OF_IRQ = 109,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
@@ -91,7 +98,7 @@ class Genode::Pic : public Mmio
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic() : Mmio(Board::TZIC_MMIO_BASE)
|
||||
Pic() : Mmio(Board::IRQ_CONTROLLER_BASE)
|
||||
{
|
||||
for (unsigned i = 0; i < NR_OF_IRQ; i++) {
|
||||
write<Intsec::Nonsecure>(1, i);
|
||||
@@ -146,10 +153,6 @@ class Genode::Pic : public Mmio
|
||||
void mask(unsigned const i) {
|
||||
if (valid(i)) { write<Enclear::Clear_enable>(1, i); } }
|
||||
|
||||
/**
|
||||
* Wether an interrupt is inter-processor interrupt of a CPU
|
||||
*/
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
|
||||
/*************
|
||||
** Dummies **
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
|
||||
/* core includes */
|
||||
#include <util/mmio.h>
|
||||
#include <drivers/board_base.h>
|
||||
#include <spec/cortex_a9/board_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
struct Board : Board_base
|
||||
struct Board : Cortex_a9::Board_base
|
||||
{
|
||||
/**
|
||||
* L2 outer cache controller
|
||||
|
||||
34
repos/base-hw/src/core/include/spec/pbxa9/board.h
Normal file
34
repos/base-hw/src/core/include/spec/pbxa9/board.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* \brief Board driver for core
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-02-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SPEC__PBXA9__BOARD_H_
|
||||
#define _SPEC__PBXA9__BOARD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/cortex_a9/board_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Board : public Cortex_a9::Board_base
|
||||
{
|
||||
public:
|
||||
|
||||
static void outer_cache_invalidate() { }
|
||||
static void outer_cache_flush() { }
|
||||
static void prepare_kernel() { }
|
||||
static void secondary_cpus_ip(void * const ip) { }
|
||||
static bool is_smp() { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _SPEC__PBXA9__BOARD_H_ */
|
||||
@@ -135,7 +135,14 @@ class Genode::Pic : Mmio
|
||||
{
|
||||
public:
|
||||
|
||||
enum { NR_OF_IRQ = 64 };
|
||||
enum {
|
||||
/*
|
||||
* FIXME: dummy ipi value on non-SMP platform, should be removed
|
||||
* when SMP is an aspect of CPUs only compiled where necessary
|
||||
*/
|
||||
IPI = 63,
|
||||
NR_OF_IRQ = 64,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -239,7 +246,7 @@ class Genode::Pic : Mmio
|
||||
* Dummies
|
||||
*/
|
||||
|
||||
bool is_ip_interrupt(unsigned, unsigned) { return false; }
|
||||
bool is_ip_interrupt(unsigned) { return false; }
|
||||
void trigger_ip_interrupt(unsigned) { }
|
||||
};
|
||||
|
||||
|
||||
40
repos/base-hw/src/core/include/spec/vea9x4/board.h
Normal file
40
repos/base-hw/src/core/include/spec/vea9x4/board.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* \brief Board driver for core
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _BOARD_H_
|
||||
#define _BOARD_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/cortex_a9/board_support.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Board : public Cortex_a9::Board_base
|
||||
{
|
||||
public:
|
||||
|
||||
static void outer_cache_invalidate() { }
|
||||
static void outer_cache_flush() { }
|
||||
static void prepare_kernel();
|
||||
static void secondary_cpus_ip(void * const ip) { }
|
||||
|
||||
/**
|
||||
* FIXME We return true although base-hw doesn't support SMP
|
||||
* because UP-configurations in the TTBRs and the
|
||||
* translation-table descriptors cause problems.
|
||||
*/
|
||||
static bool is_smp() { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _BOARD_H_ */
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* \brief Programmable interrupt controller for core
|
||||
* \author Martin Stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-04-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PIC_H_
|
||||
#define _PIC_H_
|
||||
|
||||
/* core includes */
|
||||
#include <spec/arm_gic/pic_support.h>
|
||||
#include <cpu.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Programmable interrupt controller for core
|
||||
*/
|
||||
class Pic;
|
||||
}
|
||||
|
||||
class Genode::Pic : public Arm_gic
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Pic() : Arm_gic(Cpu::PL390_DISTRIBUTOR_MMIO_BASE,
|
||||
Cpu::PL390_CPU_MMIO_BASE)
|
||||
{
|
||||
/* configure every shared peripheral interrupt */
|
||||
for (unsigned i = min_spi; i <= _max_interrupt; i++) {
|
||||
_distr.write<Distr::Icfgr::Edge_triggered>(0, i);
|
||||
_distr.write<Distr::Ipriorityr::Priority>(0, i);
|
||||
_distr.write<Distr::Itargetsr::Cpu_targets>(0xff, i);
|
||||
}
|
||||
|
||||
/* disable the priority filter */
|
||||
_cpui.write<Cpui::Pmr::Priority>(0xff);
|
||||
|
||||
/* signal secure IRQ via FIQ interface */
|
||||
Cpui::Ctlr::access_t ctlr = 0;
|
||||
Cpui::Ctlr::Enable_grp0::set(ctlr, 1);
|
||||
Cpui::Ctlr::Enable_grp1::set(ctlr, 1);
|
||||
Cpui::Ctlr::Fiq_en::set(ctlr, 1);
|
||||
_cpui.write<Cpui::Ctlr>(ctlr);
|
||||
|
||||
/* use whole band of prios */
|
||||
_cpui.write<Cpui::Bpr::Binary_point>(~0);
|
||||
|
||||
/* enable device */
|
||||
_distr.write<Distr::Ctlr>(Distr::Ctlr::Enable::bits(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark interrupt 'i' unsecure
|
||||
*/
|
||||
void unsecure(unsigned const i) {
|
||||
_distr.write<Distr::Igroupr::Group_status>(1, i); }
|
||||
};
|
||||
|
||||
|
||||
bool Genode::Arm_gic::_use_security_ext() { return 1; }
|
||||
|
||||
|
||||
namespace Kernel { class Pic : public Genode::Pic { }; }
|
||||
|
||||
#endif /* _PIC_H_ */
|
||||
@@ -14,11 +14,10 @@
|
||||
#ifndef _CORE__INCLUDE__TRUSTZONE_H_
|
||||
#define _CORE__INCLUDE__TRUSTZONE_H_
|
||||
|
||||
/* core includes */
|
||||
#include <pic.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class Pic;
|
||||
|
||||
|
||||
void init_trustzone(Pic * pic);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <vm_session/vm_session.h>
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <dataspace_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Vm_session_component : public Rpc_object<Vm_session>
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
unsigned _vm_id;
|
||||
void *_vm;
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
addr_t _ds_addr;
|
||||
|
||||
static size_t _ds_size() {
|
||||
return align_addr(sizeof(Cpu_state_modes),
|
||||
get_page_size_log2()); }
|
||||
|
||||
addr_t _alloc_ds(size_t &ram_quota);
|
||||
|
||||
public:
|
||||
|
||||
Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
size_t ram_quota);
|
||||
~Vm_session_component();
|
||||
|
||||
|
||||
/**************************
|
||||
** Vm session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability cpu_state(void) { return _ds_cap; }
|
||||
void exception_handler(Signal_context_capability handler);
|
||||
void run(void);
|
||||
void pause(void);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__VM_SESSION_COMPONENT_H_ */
|
||||
@@ -63,6 +63,6 @@ Irq_session_component::Irq_session_component(Cap_session * const cap_session
|
||||
throw Root::Invalid_args();
|
||||
}
|
||||
/* make interrupt accessible */
|
||||
_signal = Irq::signal(irq_number);
|
||||
_signal = Kernel::User_irq::signal(irq_number);
|
||||
_cap = Irq_session_capability(irq_session_ep()->manage(this));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user