Compare commits

...

167 Commits
14.11 ... 15.02

Author SHA1 Message Date
Christian Helmuth
54ef87c979 version: 15.02 2015-02-27 11:57:59 +01:00
Norman Feske
0bbad0f5d4 News item for Genode 15.02 2015-02-27 11:52:17 +01:00
Norman Feske
2392700c79 Release notes for version 15.02 2015-02-27 11:52:17 +01:00
Sebastian Sumpf
e866bf3fa3 l4linux: Adapt netperf run script to new run tool
With the new run tool, we net to use the 'serial_id' when using the 'send'
command.
2015-02-27 11:48:36 +01:00
Alexander Boettcher
d68c7d1d10 usb: rename coordinates to width/height for touch 2015-02-27 11:48:36 +01:00
Sebastian Sumpf
89dbc10334 L4Linux: Update hash and revision (eager FPU)
The corresponding L4Linux fix:

25aa4a5f25
2015-02-27 11:48:36 +01:00
Martin Stein
c78efd4428 odroid_xu: prevent tests with sd/platform/ahci/fb
Drivers like SD-Card, platform, AHCI, and framebuffer are specified as Exynos5
compliant. But they are at least not compliant with Odroid-XU although this is
Exynos5. Thus, prevent tests that rely on such drivers when building for
hw_odoid_xu. Furthermore, make previous Arndale regulator/consts.h,
uart_defs.h, and some Board_base enums available to all Exynos5 builds to
enable at least building the drivers.

Fixes #1419
2015-02-27 11:48:36 +01:00
Martin Stein
9737b5d966 tz_vmm: support USB-Armory board
For the USB-Armory, we use a newer version of Linux (3.18) as for the
i.MX53-QSB. The main difference is, that the newer Linux uses a DTB instead of
ATAGs.

Fixes #1422
2015-02-27 11:48:35 +01:00
Martin Stein
be392b3bf9 hw: support USB-Armory board
The USB Armory is almost the same as the i.MX53-QSB but it uses only
one of the two RAM banks available in i.MX53. Furthermore we use the USB
Armory only with Trustzone enabled.

Ref #1422
2015-02-27 11:48:35 +01:00
Sebastian Sumpf
2b87628b3c base-foc: Update hash/revision for cli patch.
Issue #1420
2015-02-27 11:48:08 +01:00
Sebastian Sumpf
76d38a8c76 L4Linux: Update hash and revision (SMEP patch)
The corresponding L4Linux fix:

  7f2ab08eb6
2015-02-27 11:48:08 +01:00
Stefan Kalkowski
c176fc24a1 tz_vmm: make script success detection more robust 2015-02-27 11:48:08 +01:00
Christian Prochaska
70540e6f8e Improve 'Timed_semaphore' accuracy
Fixes #1421
2015-02-27 11:48:07 +01:00
Martin Stein
d2b82274db run scripts: don't use is_qemu_available anymore
With the new run tool, there is no more is_qemu_available function. However,
some scripts still try to use it because only frequently used scripts were
updated by now. The commit replaces the function calls with the new
'have_include power_on/qemu' check.

Ref #1419
2015-02-27 11:48:07 +01:00
Josef Söntgen
8d9561595c netperf: add wifi test
Enables testing of the wifi_drv with netperf.

Fixes #1415.
2015-02-27 11:48:07 +01:00
Josef Söntgen
894974f73b wifi_drv: copy firmware images to build directory
Always copy the firmware images to the bin directory within the
build directyry when building the wifi_drv binary.

Issue #1415.
2015-02-27 11:48:06 +01:00
Josef Söntgen
818dad72d0 dde_linux: download firmware for iwlwifi driver
Also download firmware images needed by the wifi_drv when preparing
the dde_linux port. The images are placed in 'firmware' directory.

Issue #1415.
2015-02-27 11:48:06 +01:00
Josef Söntgen
85031f1c1a wifi: report wlan networks
The wifi_drv now provides two reports. The first one contains all
accesspoints that were found while scanning the supported frequencies.
The second one reports the state of the driver, i.e., if it is
conntected to an accesspoint or not. In addition to that, the driver
now gets its configuration via a ROM session.

More detailed information are available in 'repos/dde_linux/README'.

Issue #1415.
2015-02-27 11:48:06 +01:00
Alexander Boettcher
c578a455ba vbox: adapt auto run scripts for win8
Issue #1413
2015-02-27 11:48:06 +01:00
Christian Helmuth
417199ea64 vbox: enable support for Windows 8
Fixes #1413
2015-02-27 11:48:05 +01:00
Alexander Boettcher
d86380d744 nova: provide assessors in utcb for efer register
Issue #1413
2015-02-27 11:48:05 +01:00
Sebastian Sumpf
e4194b4f44 base-foc: Remove 'modaddr' from bootstrap
Let bender relocate the boot modules. Skip relocation strep in bootstrap (only
the kernel, sigma0, and roottask will be loaded).
2015-02-27 11:48:05 +01:00
Stefan Kalkowski
7582396e9c hw_arndale: enable ARM virtualization extensions
* enables world-switch using ARM virtualization extensions
* split TrustZone and virtualization extensions hardly from platforms,
  where it is not used
* extend 'Vm_session' interface to enable configuration of guest-physical memory
* introduce VM destruction syscall
* add virtual machine monitor for hw_arndale that emulates a simplified version
  of ARM's Versatile Express Cortex A15 board for a Linux guest OS

Fixes #1405
2015-02-27 11:48:05 +01:00
Stefan Kalkowski
07c8d1652e hw_arndale: setup ARM hypervisor mode
To enable support of hardware virtualization for ARM on the Arndale board,
the cpu needs to be prepared to enter the non-secure mode, as long as it does
not already run in it. Therefore, especially the interrupt controller and
some TrustZone specific system registers need to be prepared. Moreover,
the exception vector for the hypervisor needs to be set up properly, before
booting normally in the supervisor mode of the non-secure world.

Ref #1405
2015-02-27 11:48:05 +01:00
Stefan Kalkowski
e7dad39016 uart_drv: enable RX channel for exynos5 driver
This is useful for automated tests on this platform, where the run script
wants to interact with some component via terminal

Ref #1405
2015-02-27 11:48:05 +01:00
Stefan Kalkowski
1e3c80ff5b arm: enable cpu cortex_a15 compiler flag
To enable the usage of virtualization extension related instructions
there is the need to enable the '-mcpu=cortex_a15' compiler flag on
those cpus. To not conflict with other compiler flags (Ref #810) we've
to disable the '-march=arm_v7a' flag.

Ref #1405
2015-02-27 11:48:04 +01:00
Stefan Kalkowski
8e2b4d6f45 hw: extend kernel interrupt class
The generalization of interrupt objects in the kernel and the use of
C++ polymorphism instead of explicitely checking for special interrupts
within generic code (Cpu_job::_interrupt) enables the registration of
additional interrupts used by the kernel, which are needed for specific
aspects added to the kernel, like ARM hardware virtualization interrupts.

* Introduce generic base class for interrupt objects handled by the kernel
* Derive an interrupt class for those handled by the user-land
* Implement IPI-specific interrupt class
* Implement timer interrupts using the new generic base class

Ref #1405
2015-02-27 11:43:56 +01:00
Stefan Kalkowski
0836726df2 hw: use one IRQ for all cpus to send IPIs
Until now, one distinct software generated IRQ per cpu was used to
send signals between cpus. As ARM's GIC has 16 software generated
IRQs only, and they need to be partitioned between secure/non-secure
TrustZone world as well as virtual and non-virtual worlds, we should
save them.

Ref #1405
2015-02-27 11:43:56 +01:00
Stefan Kalkowski
a40932a324 hw: refactor irq controllers
* name irq controller memory mapped I/O regions consistently
  in board descriptions
* move irq controller and timer memory mapped I/O region descriptions
  from cpu class to board class
* eliminate artificial distinction between flavors of ARM's GIC
* factor cpu local initialization out of ARM's GIC interface description,
  which is needed if the GIC is initialized differently e.g. for TrustZone

Ref #1405
2015-02-27 11:43:56 +01:00
Sebastian Sumpf
c13fbff8c1 rump: Silence build process
The 'dest' target is renamed in the updated rump version  to 'dest.stage'. This
triggered some building steps, even when the targets already existed.

Issue #1409
2015-02-27 11:43:56 +01:00
Sebastian Sumpf
47b0b9b689 rump: Enable single CPU lock semantics
* Compile in single CPU support only
* Fix 'try_enter' semtantic for mutexes
* Unschedule when entering RW locks

Issue #1409
2015-02-27 11:43:56 +01:00
Sebastian Sumpf
422923cc95 rump: Add 'get_random_backend' function
A rump server may now implement its own random number generator, the default
impelementation will not generate random number.

Issue #1409
2015-02-27 11:43:55 +01:00
Alexander Boettcher
a594ae703d base: fix location_of_index affinity calculation
Take care that ypos parameter is smaller than height().
If it is not - wrap around.

Issue #1412.
2015-02-27 11:43:55 +01:00
Alexander Boettcher
babe1d1026 acpi: amend handling MMIO regions for ACPI tables
The handling of MMIO regions now supports more pathological cases with
weird cross references. Also, MMIO regions are releases after the
parsing is done.

Fixes #998
2015-02-27 11:40:59 +01:00
Christian Prochaska
679ae1dd14 vbox: improve virtual time accuracy
Fixes #1411
2015-02-27 11:40:58 +01:00
Alexander Boettcher
a31378476d nova: use in core one pager per CPU
Fixes #1394
2015-02-27 11:40:58 +01:00
Josef Söntgen
0f47ac958b log/serial: handle spurious EOF
While booting up, some devices send garbage over the serial connection.
This can result in an unexpected EOF event within expect(1). A filter
program may be specified with '--log-serial-filter' to circumvent this
problem. Then, the output of the serial program is piped through
the filter, which may sanitize the character stream.

Fixes #1395.
2015-02-17 16:01:37 +01:00
Alexander Boettcher
6329395026 run: remove upgrade messages in mp_server script 2015-02-17 14:18:16 +01:00
Martin Stein
3a40c27c26 hw_vea9x4: quickfix slow RAM access
Setting the ACTLR.SMP bit also without SMP support fastens RAM access
significantly. A proper solution would implement SMP support which must enable
the bit anyway.

Fixes #1353
2015-02-17 14:18:16 +01:00
Alexander Boettcher
467eee07a6 run: increase tcl buffer for run_genode_until
and move it close to run_genode_until implementation.
Somehow the "match_max -d" gets ignored if it is to far away and some
our run scripts fails because the buffer contains not all information
(seen for affinity.run on a 8 core machine)
2015-02-17 14:18:16 +01:00
Josef Söntgen
7617833365 run: capture kernel msg to detect boot errors
Handle boot errors like the old run tool did by checking a kernel
specific string on boot up and start the run script timeout afterwards.

Issue #1395.
2015-02-16 14:01:45 +01:00
Alexander Boettcher
2b69310adf nova: detect overlapping module regions
Detect overlapping regions which should not overlap and print some meaningful
message instead of dying with some mysterious page fault.

Issue #1402
2015-02-16 14:01:45 +01:00
Martin Stein
00167aec14 hw: activate perf-counter by default
This is needed at least by rump_ext2.run as it uses the perf-counter
in the jitterentropy-lib. On other platforms the perf-counter gets enabled
by the kernel by default. However, on HW, we keep the specifier to allow users
to disable it easily (e.g. for security reasons).

Ref #1393
2015-02-16 14:01:45 +01:00
Sebastian Sumpf
b4a880ca54 bender: restrict relocation below 2G physical
Fixes #1402
2015-02-16 14:01:24 +01:00
Alexander Boettcher
2e1686558c run: constrain physical memory for pci/acpi driver
Permit pci/acpi driver to constrain physical memory allocation to needs of
the driver it serves.

Fixes #1045
2015-02-16 13:40:38 +01:00
Alexander Boettcher
34719c4589 pci: allocate below 3G physical for 32bit & iommu
Related to #696.

Issue #1045
2015-02-16 13:40:38 +01:00
Alexander Boettcher
8c66a4b1be base: support phys range specifier in ram_session
Fixes #696
2015-02-16 13:40:38 +01:00
Alexander Boettcher
95ff5ba11d base: support range restriction in allocator
Issue #696
2015-02-16 13:40:38 +01:00
Alexander Boettcher
57c4678aa1 gdb: adapt gdb_monitor run scripts
Adjustment are required due to changes of the new run tool and the new shared
library implementation.

Issue #1192
2015-02-16 13:40:37 +01:00
Stefan Kalkowski
322be1b4fb hw: LPAE for Cortex a15 (fix #1387) 2015-02-16 13:40:37 +01:00
Stefan Kalkowski
21fd2fc582 hw: introduce ARM LPAE extension (ref #1387)
This patch adds support for the Large Physical Address Space Extension
for ARM v7.
2015-02-16 13:40:37 +01:00
Stefan Kalkowski
102444b82b hw: remove pointless, wasted memory in pd object
(ref #1387)
2015-02-16 13:40:37 +01:00
Stefan Kalkowski
34f169293f hw: fix page table handling of core (ref #1387)
There might be more then one nested slab allocation.
2015-02-16 13:40:37 +01:00
Josef Söntgen
4ca1284e0e vfs: do not return early on directory operations
When returning early on directory operations, file systems that might
be able to handle the request but come after the current one are not
tried.

Fixes #1400.
2015-02-16 13:40:36 +01:00
Sebastian Sumpf
c2c8483293 usb_drv: Fix controller initialization on RPI
Execute high priority tasklets immediately, these tasklets need to be processed
before any other work.

Issue #1401
2015-02-16 13:40:36 +01:00
Martin Stein
5dea0b40aa hw: don't use ARM CPU-state stuff in generic code
Fixes #1404
2015-02-16 13:40:36 +01:00
Martin Stein
63f8a38b5a hw: default boot-modules vpath is generic
Ref #1404
2015-02-16 13:40:36 +01:00
Norman Feske
cb579ec8d7 hw: minor 64-bit fixes 2015-02-16 13:40:36 +01:00
Stefan Kalkowski
7cb4d7bf41 run: support fastboot tool to load images
Fixes #1397
2015-02-16 13:40:36 +01:00
Stefan Kalkowski
a3abf74d1e hw: remove code duplication related to Exynos5 SoC
Fixes #1396
2015-02-16 13:40:36 +01:00
Josef Söntgen
4caf12cd16 tool/run: decrease timeout in log/serial
Set the timeout to 60s. The original value of 210s is too long and
delays the testing process unnecessarily.

Fixes #1395.
2015-02-16 13:40:35 +01:00
Josef Söntgen
a838b6a657 noux: add local nanosleep(2) and sleep(3)
Up to now Noux used the libc sleep functions, which actually is not
possible because the _nanosleep() function implemented by our libc
creates a new thread to handle the timeout. Noux childs may have
only one thread, e.g., the main thread, though. To fix this issue
sleeping is now handled directly by Noux. It is implemented by calling
select(2) with a timeout. This fix is needed for mutt(1), which calls
sleep when it prints a notification for the user.

Fixes #1374.
2015-02-16 13:40:35 +01:00
Sebastian Sumpf
7ecd83373c rump: Reduce startup latency
Since rump now requires large buffers of random numbers (>= 512 bytes), use the
jitterentropy library instead of the slow timer pseudo random number generation.

Fixes #1393
2015-02-16 13:40:35 +01:00
Sebastian Sumpf
ab0fd6510f jitterentropy: Fix foreign import
Make the jitterentropy library accessible from other repositories.

Noticed while working on issue #1393
2015-02-16 13:40:35 +01:00
Stefan Kalkowski
b69deec067 autopilot: adapt runscripts to run new tool
Related to #1372.
2015-02-16 13:40:35 +01:00
Stefan Kalkowski
0ac039fad7 L4Linux: make ballooning driver configureable
To circumvent compilation errors with the older L4Android Linux kernel
version, the ballooning driver is included in the more recent L4Linux
kernel only. Moreover, to be able to maintain L4Android / L4Linux in a more
convenient way, e.g. to apply patches valid for both versions, we use
the same git clone that is used for L4Linux instead of using the upstream
L4Android version by applying patches.

Fixes #1390
2015-02-16 13:40:35 +01:00
Josef Söntgen
78e8e04b88 tool/run/README: fix wrong examples
Fixes #1392.
2015-02-16 13:40:34 +01:00
Josef Söntgen
863b6fef80 noux: prevent override in SYSCALL_STAT
Fixes #1386.
2015-02-16 13:40:34 +01:00
Josef Söntgen
0a835e4ce9 os: structured timestamp in Rtc session
Instead of returning an uint64_t value, return a structured time stamp.
This change is only visible to components using Rtc_session directly.

Fixes #1381.
2015-02-16 13:40:34 +01:00
Sebastian Sumpf
6d2c697da1 lxip: Fix timeout handling for 'schedule_timeout'
Up until now 'schedule_timeout' did only wait for the next signal to occur.
However, we might run into situations where there won't occur signals for longer
periods of time. Therefore, we took care of the respective timeout handling.

This commit also adds Genode's tracing support

Issue #1310
2015-02-16 13:40:34 +01:00
Sebastian Sumpf
8843564850 usb_drv: USB terminal driver
Issue #1329
2015-02-16 13:40:34 +01:00
Sebastian Sumpf
3fd561aab6 terminal_echo: Add line feed end carriage return
Issue #1329
2015-02-16 13:40:33 +01:00
Sebastian Sumpf
0c2bdf9edd usb_drv: Remote USB driver interface
Issue #1329
2015-02-16 13:40:33 +01:00
Christian Helmuth
e479b9e8e8 ports: also hash patches with absolute path names
Fixes #1305
2015-01-27 12:17:53 +01:00
Norman Feske
1717d11742 doc: mention packages needed for using the ports
Fixes #1383
2015-01-27 10:09:19 +01:00
Sebastian Sumpf
15a379894a lxip: Fix on OKL4
This has been broken for a while now. Use correct (global) signal transmission,
do not use local signal transmission, as signals seems to get lost.

Issue #1310
2015-01-26 12:28:42 +01:00
Wolfgang Faust
b2947d2187 Add filenames to code snippets in hello_tutorial
Fixes #1369
2015-01-26 12:28:42 +01:00
Norman Feske
671682cb6a base: use reinterpret_cast for symbol lookup
This patch changes the Shared_object::lookup function to use a
reinterpret_cast instead of a static_cast to allow the conversion
from symbol addresses to arbitrary pointers.
2015-01-26 12:28:42 +01:00
Norman Feske
f68889ea0a arora: fix domain config in plugin demo
Fixes #1375
2015-01-26 12:28:42 +01:00
Norman Feske
cb4302d06a loader: make CPU session upgradable
Fixes #1379
2015-01-26 12:28:42 +01:00
Norman Feske
623bc82e07 fs_rom: realloc only when dataspace grew
Fixes #1377
2015-01-26 12:28:42 +01:00
Norman Feske
ff422ccc6e backdrop: respond to config changes
Fixes #1376
2015-01-26 12:28:42 +01:00
Norman Feske
db56946ba9 rom_prefetcher: Yield CPU after each request
By blocking on a timeout, we yield the CPU in order to give a
concurrently running sporadic process a chance to obtain ROM modules.
Otherwise, such requests would be deferred until the ROM prefetcher
completes its operation or in the unlikely event that the prefetcher
gets preempted.

Fixes #1378
2015-01-26 12:28:41 +01:00
Christian Helmuth
86eb3f4a0d rtc: rename get_current_time() to current_time()
Issue #1344
2015-01-26 12:28:41 +01:00
Josef Söntgen
026b5a66c9 autopilot: get settings via RUN_OPT_AUTOPILOT
If the variable RUN_OPT_AUTOPILOT is set the autopilot will override
the default RUN_OPT settings provided in build.conf.

Related to #1355.
2015-01-26 12:28:41 +01:00
Josef Söntgen
55bf0bb294 run: add power_on/softreset
The softreset module resets the target system by triggering a software
reset.

Fixes #1355.
2015-01-26 12:28:41 +01:00
Josef Söntgen
88f62b0988 autopilot: adapt runscripts to new run tool
Related to #1372.
2015-01-26 12:28:41 +01:00
Josef Söntgen
e3c37f43a0 build.mk: remove RUN_ENV usage 2015-01-26 12:28:41 +01:00
Josef Söntgen
ce24547eea create_builddir: add default RUN_OPT configuration 2015-01-26 12:28:40 +01:00
Josef Söntgen
c706b1c0a7 run: modularize run tool 2015-01-26 12:28:40 +01:00
Christian Helmuth
febca1b827 rtc: pseudo driver for linux + server framework
The commit also includes a test program incl. run script.

Fixes #1344.
2015-01-26 12:28:40 +01:00
Josef Söntgen
a36d0ec83a lxip: provide struct file pointer for udp_poll
Lxip may deference the file pointer in 'udp_poll()'. So we provide a
valid dummy object.

Fixes #1371.
2015-01-20 12:05:54 +01:00
Norman Feske
363fd6065d Init: support for aliases for child names
Fixes #1373
2015-01-20 11:25:59 +01:00
Norman Feske
a0abb093ed Remove output-section fill from linker scripts
The linker scripts use to fill alignment gaps within the text section
with the magic value 0x90909090, which correponds to the opcodes of four
nop instructions on x86. This patch removes this value because it
apparently solves no problem. If, for some reason (e.g., due to a dangling
pointer) a thread executes instructions within alignment paddings, NOP
instructions are not any better than any other instruction. The program
will eventually execute the instructions after the padding, which is
most likely fatal. It would be more reasonable to fill the padding with
the opcode of an illegal instruction so that such an error can be
immediately detected. That said, I cannot remember a single instance,
where the fill value has helped us during debugging.

Even if the mechanism served a purpose on x86, it is still better to
remove it because it does not equally work on the other architectures
where the linker scripts are used. I.e., on ARM, the opcode 0x90909090
is not a NOP instruction.
2015-01-20 11:25:59 +01:00
Emery Hemingway
e1667e61cc libports: sqlite
Issue #1357
2015-01-20 11:25:58 +01:00
Emery Hemingway
e4ac1f99ed tool/ports: run unzip with UNZIP_OPT
The patch supports both, a download-specific UNZIP_OPT(download) and a
general UNZIP_OPT that can be defined across downloads.
UNZIP_OPT(download) overrides UNZIP_OPT.

Note, the `--strip-components=1` argument is not required for unzip.

Issue #1357
2015-01-20 11:23:52 +01:00
Emery Hemingway
b5f1af6af0 libports: libbz2 (Bzip2)
Issue #1357
2015-01-20 11:23:52 +01:00
Norman Feske
cfea0ea97d News items for FOSDEM and roadmap 2015 2015-01-20 11:23:51 +01:00
Norman Feske
cbe835f2c8 Roadmap 2015 2015-01-20 11:23:51 +01:00
Christian Helmuth
ce15800beb vbox: loosen boot heuristics in auto-disk test 2015-01-20 11:23:51 +01:00
Alexander Boettcher
9262629a86 vbox: fix interrupt injection in recompiler mode
Fixes #1365
2015-01-20 11:23:51 +01:00
Christian Prochaska
50950ec248 vbox: 'poke' fixes
Fixes #1364
2015-01-20 11:23:51 +01:00
Alexander Boettcher
336018b493 base: append label per line properly (log service)
If newlines are in the string send to the core log service, they don't get
the label properly appended before each output. The messages then look like
they are coming from core.

Fixes #1368
2015-01-20 11:23:51 +01:00
Alexander Boettcher
25eec75ad8 vbox: be less verbose in vmx_invalid exit cases
Be less verbose regards warnings caused by vmx_invalid exits - which triggers
on T400 more often because it has no Unrestricted Guest support. This leads
to lot of log messages so that the test does not succeed in time. Additionally,
the virtualbox_auto_disk.run script is adjusted to check for some output to
exit earlier if something went wrong.

Fixes #1367
2015-01-20 11:23:51 +01:00
Alexander Boettcher
988a7962a8 nova: disable vpid feature
Workaround for issue #1343. By disabling the 'vpid' feature of the nova
kernel several VMs can be used concurrently. Applies for Seoul and VirtualBox.

Issue #1343
2015-01-20 11:23:50 +01:00
Alexander Boettcher
ee996d2280 vbox: enable dumping GuruMeditations messages
This typically is a sign that something went terribly wrong. The information
may help to debug issues.

Issue #1343
2015-01-20 11:23:50 +01:00
Stefan Kalkowski
e8d1d6e87c rpi: add missing drivers in run-scripts (Fix #1366)
Add platform driver and usb-network driver for platform_rpi where appropriated.
2015-01-20 11:23:50 +01:00
Stefan Kalkowski
28112d1ff9 rump: exclude ARM architectures apart from v7
Ref #1366
2015-01-20 11:23:50 +01:00
Stefan Kalkowski
df8bdaaf79 run: increase JTAG load timeout (Ref #1366) 2015-01-20 11:23:50 +01:00
Christian Helmuth
f99ca9e372 Tools for convenient handling of port contrib dirs
tool/ports/shortcut

  create symbolic link from 'contrib/<port-name>-<hash>' to
  contrib/<port-name>

tool/ports/current

  print current contrib directory of port

Fixes #1345.
2015-01-20 11:23:50 +01:00
Christian Prochaska
6791fd18cc vbox: use libc's 'gettimeofday()' function
Fixes #1363
2015-01-20 11:23:50 +01:00
Alexander Boettcher
4be7b3c3ad seoul: exclude 64bit guest in seoul-genode.run
Fixes #1358
2015-01-20 11:23:49 +01:00
Josef Söntgen
d58509f446 libc: create poll.h symlink
Since user-land tools tend to look for <poll.h> instead of <sys/poll.h>
make them happy like w/o resorting to patch the source.

Fixes #1356.
2015-01-20 11:23:49 +01:00
Josef Söntgen
f01472b308 dde_rump: Update to current version
Issue #1361
2015-01-20 11:23:49 +01:00
Stefan Kalkowski
2380fc442f ahci: avoid to reinstantiate backend driver
Instead of fixing the missing dynamic facilities of the AHCI driver
backends for x86 and Exynos5, just avoid to create/destroy the backend
for every new connection, but always use one and the same object.
The AHCI drivers need to be re-written anyway, see issue #1352 for instance,
we can make it more robust for the dynamic case then.

Fixes #786
Fixes #1133
2015-01-12 14:24:55 +01:00
Stefan Kalkowski
901bff813d imx31: remove platform completely (fix #1360) 2015-01-12 14:24:15 +01:00
Alexander Boettcher
0f18ecc142 base: handle input overflow exception
Fixes #1348
2015-01-09 11:52:06 +01:00
Sebastian Sumpf
1a26f33469 ldso: shared-object lock and ctor test
This has to be used during shared object creation and destruction because global
lists are manipulated. We cannot use the 'Elf_object::lock' here because there
may be jump-slot relocations during object initialization.

Fixes #1350
2015-01-09 11:31:21 +01:00
Alexander Boettcher
e5b509cabb nova: breakpoint handling
If no one is registered for a breakpoint trap - stop the thread. E.g. used
by virtualbox assertion implementation.
2015-01-09 11:03:29 +01:00
Martin Stein
9a4a0448be hw vea9x4: remove trustzone support
When building Genode for VEA9X4 as micro-hypervisor protected by the ARM
TrustZone hardware we ran into limitations regarding our basic daily
testing routines. The most significant is that, when speaking about RAM
partitioning, the only available options are to configure the whole SRAM
to be secure and the whole DDR-RAM to be non-secure or vice versa. The
SRAM however provides only 32 MB which isn't enough for both a
representative non-secure guest OS or a secure Genode that is still
capable of passing our basic tests. This initiated our decision to
remove the VEA9X4 TrustZone-support.

Fixes #1351
2015-01-08 13:28:42 +01:00
Alexander Boettcher
91daf433c5 seoul: transform absolute events to relative (PS2)
Fixes #1346
2015-01-07 15:17:51 +01:00
Martin Stein
be7d5b4827 hw: use context-area base that is ok for VEA9X4-TZ
On VEA9X4-TZ, the context-area overlaps with the virtual area of the
text, data and bss. However, we can't simply change the link address as
the core image (used physically respectively 1:1 mapped) needs to be in
this particular RAM-region as it is the only one that can be protected
against a VM. Thus I've moved the context area to a place where it
shouldn't disturb any HW-platform.

Fixes #1337
2015-01-07 10:41:22 +01:00
Martin Stein
e63092f1dd hw & cortex_a9: fix scheduling-timer speed
The estimation of the input clock of the Cortex A9 Private Timer module
was pretty miserable at every Cortex A9 board.

Fixes #1341
2015-01-06 15:22:07 +01:00
Martin Stein
ba321c20d1 hw vea9x4: let userland timer SP804 0/1 be secure
Declaring the SP804 0/1 module and its interrupt to be non-secure prevents the
secure Genode from receiving the interrupt and hence the timer driver in the
secure Genode doesn't work.

Fixes #1340
2015-01-06 15:16:02 +01:00
Sebastian Sumpf
6f8f9085f3 os: Add virtual destructor to block driver
Fixes #1339.
2015-01-06 15:10:17 +01:00
Christian Helmuth
11a513ac63 prepare_port: disable certificate checking in wget
Some downloads are available via HTTPS only, but wget < 3.14 does not
support server-name identification, which is used by some sites. So, we
disable certificate checking in wget and check the validity of the
download via SIG or SHA.

Fixes #1334.
2015-01-06 12:39:11 +01:00
Alexander Boettcher
8842ba2e1c nova: remove timer delay heuristic
The commit uses a fixed kernel branch (r8), which fixes a caching bug
observable in the Genode host. The quirk detecting the circumstance in the
timer service is obsolete now and is removed.

Fixes #1338
2015-01-06 12:39:11 +01:00
Alexander Boettcher
1d920fa1b5 nova: fix usage of portal permission
The commit
- fixes the syscall bindings for using portal permissions
- revokes PT_CTRL permission after pager in core set local badge name
- revokes PT_CTRL permission after server entrypoint code set local badge name

Fixes #1335
2015-01-06 12:39:11 +01:00
Christian Helmuth
2cd902f09f libc: warn on configuration errors in rtc wrapper
Fixes #1336.
2015-01-06 12:39:11 +01:00
Alexander Boettcher
bfa2ad7d47 nova: platform test for portal permission usage
Test and run script showcasing issue #1335.

The test mainly tries out syscalls which should not succeed.
2015-01-06 12:39:11 +01:00
Christian Helmuth
77410a08a8 libc: remove debug messages from vfs plugin 2015-01-06 12:39:10 +01:00
Martin Stein
659f6ff5c8 hw_vea9x4: quickfix for missing SMP awareness
This fix configures TTBRs and translation-table descriptors as if we would use
SMP although we don't to circumvent problems with UP-configurations.
This fix should be superseded later by full SMP support for the VEA9X4.

ref #1312
2014-12-19 13:58:49 +01:00
Christian Helmuth
59d26e040e ahci: enable benchmark on x86 2014-12-19 13:58:48 +01:00
Martin Stein
5783ba4b1f base: let context area RM session be expanding
Fixes #1331.
2014-12-19 13:58:48 +01:00
Martin Stein
d31492040c hw: fix race on pager-object dissolve
The HW-kernel, in contrast to other kernels, provides a direct reference
to the pager object with the fault signal that is send to the pager
activation. When accessing this reference directly we may fall into the
time span where the root parent-entrypoint of the faulter has alredy
dissolved the pager object from the pager entrypoint, but not yet
silenced the according signal context.  To avoid this we issue an
additional 'lookup_and_lock' with the received pager object. This isn't
optimal as we don't need the potentially cost-intensive lookup but only the
synchronization.

Fixes #1311.
Fixes #1332.
2014-12-19 13:58:48 +01:00
Alexander Boettcher
a59cf9f557 usb: wacom touchscreen support 2014-12-19 13:58:48 +01:00
Christian Helmuth
6344ab94b2 run: use predefined name for wsman script
"file tempfile" is not available in tcl versions below 8.6, which are
still wide spread, for example, in Ubuntu 12.04.5 LTS.

Fixes #1328.
2014-12-19 13:58:48 +01:00
Christian Helmuth
22db466194 wifi_drv: adapt wifi.run for iwl7260
Fixes #1317.
2014-12-19 13:58:48 +01:00
Christian Menard
fa0f7c0d6d wifi_drv: enable support for iwl7260
- essential support for 7260 chipset and DMA fixes
- assign mvm->pm_ops at beginning of function iwl_op_mode_mvm_start.
  iwl_mvm_mac_setup_register() uses mvm->pm_ops, but it is called
  before this field is set to a valid value.
- disable call to function iwl_mvm_prepare_multicast.
  This function leads to a pagefault, as it aspects a list of multicast
  addresses, but the list is empty as it is not generated by this port.
2014-12-19 13:58:48 +01:00
Christian Helmuth
727ac4bc0c Put entry point at start of binary on x86 platforms
Related to #881.
2014-12-19 13:58:47 +01:00
Martin Stein
d704563453 hw: helping on IPC
On base-hw, each thread owns exactly one scheduling context for its
whole lifetime. However, introducing helping on IPC, a thread might get
executed on scheduling contexts that it doesn't own. Figuratively
spoken, the IPC-helping relation spans trees between threads. These
trees are identical to those of the IPC relation between threads. The
root of such a tree is executed on all scheduling contexts in the tree.
All other threads in the tree are not executed on any scheduling context
as long as they remain in this position. Consequently, the ready-state
of all scheduling contexts in an IPC-helping tree always equals the
state of the root context.

fix #1102
2014-12-19 13:58:47 +01:00
Martin Stein
6370b6880a hw: rename Thread::State SCHEDULED in ACTIVE
As soon as helping is used, a thread may also be in a blocking state when its
scheduling context is ready. Hence, the state designation SCHEDULED for an active
thread would be pretty misleading.

ref #1102
2014-12-19 13:58:47 +01:00
Martin Stein
6f377ec4c5 hw: add FIFO variant with for_each() method
ref #1102
2014-12-19 13:58:47 +01:00
Martin Stein
9c027fd9bd hw: remove deprecated TLB declaration
fix #1320
2014-12-19 13:58:47 +01:00
Alexander Boettcher
cdaf6a502d vbox: support absolute mouse input events
Got broken during upgrade from 4.2 to 4.3.

Fixes #1321
2014-12-19 13:58:47 +01:00
Alexander Boettcher
6d02c4c89f vbox: use power of two priority levels
Avoids warnings of init in form of

"priority band too small, losing least-significant priority bits"

when virtualbox starts threads.

Fixes #1323
2014-12-19 13:58:47 +01:00
Alexander Boettcher
51489e2f82 vmm: fix overmap attempts by seoul and vbox
If the debug branch of the nova kernel is used, following messages are printed
by the kernel during vCPU setup phase:

[0] overmap attempt OBJ - tree - ...

Fixes #1324
2014-12-19 13:58:46 +01:00
Alexander Boettcher
f36c0f150f demo: support launchpad entries with mem >= 2048M
Fixes #1325
2014-12-19 13:58:46 +01:00
Josef Söntgen
b557fb13f9 wifi_drv: fix timer scheduling
The context of timer are now inserted correctly and the actual timer
triggering the exection of each context is always programmed if the
head of the timer list changes.

Fixes #1326.
2014-12-19 13:58:46 +01:00
Josef Söntgen
4c7a5bb388 wifi_drv: call schedule() in sleep functions
The jiffies are only updated on each round of scheduling the runnable
tasks. We have to schedule the current task that executes the sleep
call to update the jiffies count and thereby preventing the task from
entering an endless loop when using a statement like
'while (!time_after(jiffies, now + timeout)) { msleep(1); }'.

Related to #1326.
2014-12-16 15:08:07 +01:00
Josef Söntgen
9ed935ff2a wifi_drv: look for PCI_CLASS_NETWORK_OTHER only
Instead of probing all device on the PCI bus just look for devices
matching PCI_CLASS_NETWORK_OTHER. This fixes issues with other devices
on the PCI bus, e.g. the GPU, when access their extended config space.

Related to #1326.
2014-12-16 15:07:56 +01:00
Alexander Boettcher
183a2c1be6 vbox: support more graphic modes
Fixes #1319
2014-12-09 18:21:09 +01:00
Christian Prochaska
b4f41aecad vbox: enable 1-byte MMIO writes at 4-/8-byte aligned address
Fixes #1318
2014-12-08 17:39:23 +01:00
Stefan Kalkowski
3367fd27e4 run: avoid buffering of output for expect
Due to commit "run: relax IP power plug recognition + serial EOF",
when piping the serial command through 'tr', some characters might
get buffered, thereby preventing some run scripts to finish correctly.
This commit removes the 'tr' hack. Instead, to circumvent the 'expect'
problem, which kills under special conditions spawned childs used to
obtain serial line content, whenever EOF of the serial command is
recognized during the boot phase, the child process gets re-spawned.
2014-12-08 13:53:17 +01:00
Alexander Boettcher
68abf0616a dde_ipxe: enable Intel I218-LM/I218-V PCI ID
Commit inspired by patch from @alex-ab/@cnuke but uses only one patch
file for all added NICs.

Issue #1220
2014-12-05 15:17:00 +01:00
Christian Helmuth
cf358b5db1 Revert "foc: relax parsing of boot process termination"
This reverts commit a9a6e8df89.

Setting correct UART parameters in U-Boot also fixes the issue and
reenables us to observe L4 bootstrapper startup.
2014-12-05 15:16:47 +01:00
Alexander Boettcher
513be78c05 seoul: adapt to nitpicker and use fixed seoul repo
Fixes #1307
2014-12-05 11:01:24 +01:00
Christian Helmuth
9996acf091 dde_linux: check tools needed for libnl 2014-12-05 11:00:15 +01:00
Christian Prochaska
36ca0497de qt5: set explicit routes for Nitpicker's 'Framebuffer' and 'Input' sessions
Setting explicit routes for Nitpicker's 'Framebuffer' and 'Input' sessionsi
avoids ambiguities if a Qt application provides these services, too.

Fixes #1316
2014-12-04 17:17:23 +01:00
Christian Prochaska
136d87bd9a qt5: fix include dir of 'qt5_qpa_nitpicker' library
Fixes #1315
2014-12-04 17:17:23 +01:00
Christian Prochaska
21154d6866 qt5: let QNitpickerViewWidget react to focus event
With this patch, when calling 'setFocus()' on a QNitpickerViewWidget, the
Nitpicker view gets the input focus (provided that the parent Qt window
already had it).

Fixes #1314
2014-12-04 16:26:22 +01:00
Stefan Kalkowski
a9a6e8df89 foc: relax parsing of boot process termination
Until now, the successful termination of the boot process was recognized
when 'expect' saw the first L4 bootstrapper output on serial line. On sytems
with initially shaky serial connection like Versatile Express, where the serial
line baudrate changes with the bootstrapper initialization, the first expected
line might be missing. Therefore, change the expected line to the first
Fiasco.OC kernel output.
2014-12-03 11:41:47 +01:00
Stefan Kalkowski
726c32e5f6 run: relax IP power plug recognition + serial EOF
* To communicate with IP power plug devices from Koukaam, to remote
  control power supply of test boards, don't parse minor versions, but
  support different IP power plugs
* TCL's expect may report an EOF when reading from the spawned serial
  terminal, especially when using 'socat' to stream serial over TCP/IP,
  although the spawned child is still running and delivering content.
  This problem is clearly not dependent on the characters send, but
  possibly due to strange pipe signals. When piping the serial output
  through 'tr' the problem vanishs.
2014-12-03 11:41:13 +01:00
Alexander Boettcher
6d391aae10 vbox: support routing serial output to Genode
Fixes #1308
2014-12-01 17:29:17 +01:00
Alexander Boettcher
f970e4a71b libc: support F_SETFD && FD_CLOEXEC ioctl
Issue #1308
2014-12-01 17:29:17 +01:00
Christian Helmuth
f9422b241f Fix compiler warning about uninitialized variable
Fixes #1051
2014-12-01 17:29:17 +01:00
Alexander Boettcher
9c0ced0a85 ldso: add __L4_ThreadSwitch to ldso symbol.map
This wasn't necessary before because we built an l4 library for
Pistachio and linked it against each application. With the new linker,
we compile the required files from within Genode and create a syscall
library that is only linked to ldso. If a program uses system calls
directly, for example, DDE kit's spinlock implementation, the required
symbols must be made globally accessible.

Fixes #1306
2014-12-01 16:32:35 +01:00
602 changed files with 17510 additions and 7576 deletions

View File

@@ -1 +1 @@
14.11
15.02

View File

@@ -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].

View File

@@ -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
View 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.

View File

@@ -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

View File

@@ -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) }

View File

@@ -1 +1 @@
fa0ea19bd94fb109dac558e37996b60243eef785
ac9483f591c9b8dd4ed22b28e3a7e7ee382011bd

View File

@@ -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
}

View File

@@ -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)

View File

@@ -1 +1 @@
3456a52b6603b16c9f157c9b3e2045e0984028c0
3e7716b7918d12d3c2a545a36c949e97c3bb705c

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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; }

View File

@@ -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

View File

@@ -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;

View File

@@ -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; }
};
/**

View 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_ */

View File

@@ -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,
};
}

View 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_ */

View File

@@ -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_ */

View File

@@ -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); }
};
}

View File

@@ -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);
};
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View 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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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; }

View 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_ */

View File

@@ -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); } });
}
/**

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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:
/**

View File

@@ -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();
/***************

View File

@@ -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_ */

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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,
};

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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_ */

View File

@@ -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

View 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

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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 **
*************/

View 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

View File

@@ -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_ */

View 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

View File

@@ -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; }

View File

@@ -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_ */

View File

@@ -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) : ); }
};
/**

View 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

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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'

View File

@@ -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) { }
};
}

View File

@@ -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_ */

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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 **

View File

@@ -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

View 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_ */

View File

@@ -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) { }
};

View 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_ */

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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_ */

View File

@@ -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