mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-20 17:32:54 +00:00
Nested init on i.MX31 via base_hw. Rework base_hw.
Implies support for the ARMv6 architecture through 'base-hw'. Get rid of 'base/include/drivers' expect of 'base/include/drivers/uart'. Merge with the support for trustzone on VEA9X4 that came from Stefan Kalkowski. Leave board drivers in 'base/include/platform'. Rework structure of the other drivers that were moved to 'base_hw/src/core' and those that came with the trustzone support. Beautify further stuff in 'base_hw'. Test 'nested_init' with 'hw_imx31' (hardware) and 'hw_panda_a2' (hardware), 'demo' and 'signal' with 'hw_pbxa9' (qemu) and 'hw_vea9x4' (hardware, no trustzone), and 'vmm' with 'hw_vea9x4' (hardware, with trustzone).
This commit is contained in:
parent
5b4edeb031
commit
31d57a6257
@ -21,7 +21,19 @@ void Genode::Ipc_pager::copy_regs(Thread_state *state)
|
|||||||
{
|
{
|
||||||
state->ip = _regs.pc;
|
state->ip = _regs.pc;
|
||||||
state->sp = _regs.sp;
|
state->sp = _regs.sp;
|
||||||
Genode::memcpy(&state->r, &_regs.r, sizeof(state->r));
|
state->r0 = _regs.r[0];
|
||||||
|
state->r1 = _regs.r[1];
|
||||||
|
state->r2 = _regs.r[2];
|
||||||
|
state->r3 = _regs.r[3];
|
||||||
|
state->r4 = _regs.r[4];
|
||||||
|
state->r5 = _regs.r[5];
|
||||||
|
state->r6 = _regs.r[6];
|
||||||
|
state->r7 = _regs.r[7];
|
||||||
|
state->r8 = _regs.r[8];
|
||||||
|
state->r9 = _regs.r[9];
|
||||||
|
state->r10 = _regs.r[10];
|
||||||
|
state->r11 = _regs.r[11];
|
||||||
|
state->r12 = _regs.r[12];
|
||||||
state->lr = _regs.ulr;
|
state->lr = _regs.ulr;
|
||||||
state->cpsr = _regs.cpsr;
|
state->cpsr = _regs.cpsr;
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,21 @@
|
|||||||
|
|
||||||
Martin Stein
|
Martin Stein
|
||||||
|
|
||||||
|
Abstract
|
||||||
The 'base-hw' repository provides an implementation of Genodes core that runs
|
########
|
||||||
directly on hardware, without an intermediate third-party kernel. Currently it
|
|
||||||
runs on the ARM platforms Realview PBXA9, Versatile Express A9X4 and
|
|
||||||
PandaBoard A2.
|
|
||||||
|
|
||||||
This document provides brief instructions about building and booting Genode
|
This document provides brief instructions about building and booting Genode
|
||||||
directly on hardware.
|
with the 'base-hw' repository. The 'base-hw' repository provides an
|
||||||
|
implementation of the Genode core that runs directly on hardware, without an
|
||||||
|
intermediate third-party kernel. It supports a limited range of target boards.
|
||||||
|
For further target specific informations, have a look at
|
||||||
|
'<GENODE_DIR>/base-hw/doc/<TARGET>.txt' where '<TARGET>'
|
||||||
|
is one of the following:
|
||||||
|
|
||||||
|
'pbxa9' - Realview PBXA9
|
||||||
|
'vea9x4' - Versatile Express A9X4
|
||||||
|
'imx31' - Freescale i.MX31
|
||||||
|
'panda_a2' - PandaBoard A2
|
||||||
|
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
@ -35,6 +42,7 @@ need Qemu for ARM emulations to run them on your machine:
|
|||||||
|
|
||||||
! apt-get install qemu-kvm-extras
|
! apt-get install qemu-kvm-extras
|
||||||
|
|
||||||
|
|
||||||
Building Genode to run directly on hardware
|
Building Genode to run directly on hardware
|
||||||
###########################################
|
###########################################
|
||||||
|
|
||||||
@ -46,11 +54,22 @@ The current version of the Genode source code is available at this page:
|
|||||||
Now, go to a directory where you want the Genode build directory to
|
Now, go to a directory where you want the Genode build directory to
|
||||||
remain. Use the helper script in the 'tool' directory of the Genode
|
remain. Use the helper script in the 'tool' directory of the Genode
|
||||||
source tree to create the initial build environment. You need to state the
|
source tree to create the initial build environment. You need to state the
|
||||||
build directory you want to create, and the hardware system to run
|
build directory you want to create, and the hardware target to run Genode on.
|
||||||
Genode on. Choose 'hw_pbxa9', 'hw_vea9x4', or 'hw_panda_a2' depending on the
|
|
||||||
hardware system you aim at.
|
|
||||||
|
|
||||||
! <genode-dir>/tool/create_builddir hw_pbxa9 BUILD_DIR=<build-dir>
|
! <genode-dir>/tool/create_builddir hw_<TARGET> BUILD_DIR=<build-dir>
|
||||||
|
|
||||||
|
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_a2' - PandaBoard A2
|
||||||
|
|
||||||
|
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
|
||||||
|
'base-hw' images on real hardware have a look at
|
||||||
|
'<GENODE_DIR>/base-hw/doc/<TARGET>.txt'.
|
||||||
|
|
||||||
Now, go to the newly created build directory make a test:
|
Now, go to the newly created build directory make a test:
|
||||||
|
|
||||||
@ -60,8 +79,4 @@ Now, go to the newly created build directory make a test:
|
|||||||
This will build the Genode components that are needed to run a simple test
|
This will build the Genode components that are needed to run a simple test
|
||||||
with 3 nested init programs, and than execute it via Qemu.
|
with 3 nested init programs, and than execute it via Qemu.
|
||||||
|
|
||||||
For further informations according to the specific hardware systems, have
|
|
||||||
look into the other documentations:
|
|
||||||
|
|
||||||
! base-hw/doc/<system>.txt
|
|
||||||
|
|
||||||
|
92
base-hw/doc/imx31.txt
Normal file
92
base-hw/doc/imx31.txt
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
==================================================
|
||||||
|
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>/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.
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
======================================================
|
===============================================
|
||||||
Getting started with 'genode/base-hw' on PandaBoard A2
|
Getting started with 'base-hw' on PandaBoard A2
|
||||||
======================================================
|
===============================================
|
||||||
|
|
||||||
|
|
||||||
Martin Stein
|
Martin Stein
|
||||||
@ -9,9 +9,11 @@
|
|||||||
Abstract
|
Abstract
|
||||||
########
|
########
|
||||||
|
|
||||||
This is a short tutorial that depicts a handy way to get a Genode ELF image,
|
This is a short tutorial that depicts a handy way to get a Genode ELF-image,
|
||||||
build with 'base-hw', started on the PandaBoard A2. It is dedicated to common
|
build with 'base-hw', started on the PandaBoard A2. For informations
|
||||||
Linux systems, but all examples originate from a Ubuntu 10.10.
|
about how to build Genode images with 'base-hw', have a look at
|
||||||
|
'<GENODE_DIR>/base-hw/doc/hw.txt'. This tutorial is dedicated to common
|
||||||
|
Linux systems, but all examples originate from a Ubuntu 11.10.
|
||||||
|
|
||||||
|
|
||||||
Tutorial
|
Tutorial
|
||||||
@ -22,10 +24,10 @@ Additionally connect the PandaBoard to your machine through its COM port.
|
|||||||
Ensure that you have installed the genode tool chain that is available at:
|
Ensure that you have installed the genode tool chain that is available at:
|
||||||
|
|
||||||
:[http://genode.org/download/tool-chain]:
|
:[http://genode.org/download/tool-chain]:
|
||||||
Get the genode tool chain]
|
Genode tool-chain
|
||||||
|
|
||||||
Ensure that '<GENODE_GCC_DIR>/bin/' is in your 'PATH' variable.
|
Ensure that '<GENODE_TOOL_CHAIN_DIR>/bin/' is in your 'PATH' variable.
|
||||||
Get the linaro U-Boot repository and compile U-Boot for PandaBoard:
|
Get the Linaro U-Boot repository and compile U-Boot for PandaBoard:
|
||||||
|
|
||||||
! git clone git://git.linaro.org/boot/u-boot-linaro-stable.git
|
! git clone git://git.linaro.org/boot/u-boot-linaro-stable.git
|
||||||
! cd <UBOOT_DIR>
|
! cd <UBOOT_DIR>
|
||||||
@ -40,32 +42,32 @@ the array elements separately.
|
|||||||
|
|
||||||
Now install the following packages to communicate with the PandaBoard:
|
Now install the following packages to communicate with the PandaBoard:
|
||||||
|
|
||||||
! sudo apt-get install tftp-hpa minicom
|
! apt-get install tftp-hpa minicom
|
||||||
|
|
||||||
Open '/etc/default/tftpd-hpa' with a text editor and ensure that it has
|
Open '/etc/default/tftpd-hpa' with a text editor and ensure that it has
|
||||||
the following content:
|
the following content:
|
||||||
|
|
||||||
! # /etc/default/tftpd-hpa
|
|
||||||
! TFTP_USERNAME="tftp"
|
! TFTP_USERNAME="tftp"
|
||||||
! TFTP_DIRECTORY="/var/lib/tftpboot"
|
! TFTP_DIRECTORY="/var/lib/tftpboot"
|
||||||
! TFTP_ADDRESS="0.0.0.0:69"
|
! TFTP_ADDRESS="0.0.0.0:69"
|
||||||
! TFTP_OPTIONS="-l"
|
! TFTP_OPTIONS="-l"
|
||||||
|
|
||||||
Tell U-Boot wich image to load on boot command:
|
Tell TFTP wich image to provide:
|
||||||
|
|
||||||
! cd /var/lib/tftpboot/
|
! cd /var/lib/tftpboot/
|
||||||
! ln -s <GENODE_BOOT_ELF> image.elf
|
! 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:
|
Start TFTP to enable the upload of the image:
|
||||||
|
|
||||||
! sudo service tftp-hpa restart
|
! service tftp-hpa restart
|
||||||
|
|
||||||
Start Minicom in configuration mode:
|
Start Minicom in configuration mode:
|
||||||
|
|
||||||
! minicom -s
|
! minicom -s
|
||||||
|
|
||||||
Go to 'Serial port setting' and ensure that the device is set the
|
Go to 'Serial port setting' and ensure that the device is set to the
|
||||||
TTY of the COM port you've conntected PandaBoard with, in my case it was
|
TTY of the COM port you've conntected PandaBoard with. In my case it was
|
||||||
'/dev/ttyS0'. Configure the other settings for a baud rate of '115200',
|
'/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
|
8 bit char length, no parity and 1 stop bit. Quit Minicom and start
|
||||||
it once more:
|
it once more:
|
||||||
@ -78,9 +80,8 @@ Mount your SD-card and copy the U-Boot files to its boot partition:
|
|||||||
|
|
||||||
Unmount the SD card and insert it into the appropriate PandaBoard slot.
|
Unmount the SD card and insert it into the appropriate PandaBoard slot.
|
||||||
Plug in the power connector or push the 'S1' button if the PandaBoard is
|
Plug in the power connector or push the 'S1' button if the PandaBoard is
|
||||||
already powered.
|
already powered. Minicom should now show the following message below some
|
||||||
|
bootloader info:
|
||||||
Minicom should now show the following message:
|
|
||||||
|
|
||||||
! Hit any key to stop autoboot:
|
! Hit any key to stop autoboot:
|
||||||
|
|
||||||
@ -89,8 +90,8 @@ image via ethernet:
|
|||||||
|
|
||||||
! usb start; dhcp; bootelf 0x82000000
|
! usb start; dhcp; bootelf 0x82000000
|
||||||
|
|
||||||
Now the ELF image should start correctly and offer some debug output in
|
Now your Genode scenario should start and offer its debug output
|
||||||
minicom. You can now boot further images by redirecting the link
|
in Minicom. You can boot other images by redirecting the link
|
||||||
'/var/lib/tftpboot/image.elf' accordingly, restarting your pandaboard
|
'/var/lib/tftpboot/image.elf' accordingly, restarting your PandaBoard
|
||||||
and instructing 'uboot' again as described above.
|
and instructing U-boot again as described above.
|
||||||
|
|
||||||
|
27
base-hw/include/arm/base/syscall_types.h
Normal file
27
base-hw/include/arm/base/syscall_types.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* \brief Syscall declarations specific for ARM V7A systems
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2011-11-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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__ARM__BASE__SYSCALL_H_
|
||||||
|
#define _INCLUDE__ARM__BASE__SYSCALL_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/stdint.h>
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
typedef Genode::uint32_t Syscall_arg;
|
||||||
|
typedef Genode::uint32_t Syscall_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM__BASE__SYSCALL_H_ */
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Syscall declarations specific for ARM V7A systems
|
|
||||||
* \author Martin Stein
|
|
||||||
* \date 2011-11-30
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2012 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__ARM_V7A__BASE__SYSCALL_H_
|
|
||||||
#define _INCLUDE__ARM_V7A__BASE__SYSCALL_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <base/stdint.h>
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
typedef Genode::uint32_t Syscall_arg;
|
|
||||||
typedef Genode::uint32_t Syscall_ret;
|
|
||||||
|
|
||||||
/*****************************************************************
|
|
||||||
** Syscall with 1 to 6 arguments **
|
|
||||||
** **
|
|
||||||
** These functions must not be inline to ensure that objects, **
|
|
||||||
** wich are referenced by arguments, are tagged as "used" even **
|
|
||||||
** though only the pointer gets handled in here. **
|
|
||||||
*****************************************************************/
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0);
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0,
|
|
||||||
Syscall_arg arg_1);
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0,
|
|
||||||
Syscall_arg arg_1,
|
|
||||||
Syscall_arg arg_2);
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0,
|
|
||||||
Syscall_arg arg_1,
|
|
||||||
Syscall_arg arg_2,
|
|
||||||
Syscall_arg arg_3);
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0,
|
|
||||||
Syscall_arg arg_1,
|
|
||||||
Syscall_arg arg_2,
|
|
||||||
Syscall_arg arg_3,
|
|
||||||
Syscall_arg arg_4);
|
|
||||||
|
|
||||||
Syscall_ret syscall(Syscall_arg arg_0,
|
|
||||||
Syscall_arg arg_1,
|
|
||||||
Syscall_arg arg_2,
|
|
||||||
Syscall_arg arg_3,
|
|
||||||
Syscall_arg arg_4,
|
|
||||||
Syscall_arg arg_5);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _INCLUDE__ARM_V7A__BASE__SYSCALL_H_ */
|
|
||||||
|
|
43
base-hw/include/cpu_session/connection.h
Normal file
43
base-hw/include/cpu_session/connection.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* \brief Connection to CPU service
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2008-08-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2008-2012 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__CPU_SESSION__CONNECTION_H_
|
||||||
|
#define _INCLUDE__CPU_SESSION__CONNECTION_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <cpu_session/client.h>
|
||||||
|
#include <base/connection.h>
|
||||||
|
|
||||||
|
namespace Genode {
|
||||||
|
|
||||||
|
struct Cpu_connection : Connection<Cpu_session>, Cpu_session_client
|
||||||
|
{
|
||||||
|
enum { RAM_QUOTA = 128*1024 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* \param label initial session label
|
||||||
|
* \param priority designated priority of all threads created
|
||||||
|
* with this CPU session
|
||||||
|
*/
|
||||||
|
Cpu_connection(const char *label = "", long priority = DEFAULT_PRIORITY)
|
||||||
|
:
|
||||||
|
Connection<Cpu_session>(
|
||||||
|
session("priority=0x%lx, ram_quota=128K, label=\"%s\"",
|
||||||
|
priority, label)),
|
||||||
|
Cpu_session_client(cap()) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__CPU_SESSION__CONNECTION_H_ */
|
@ -15,7 +15,7 @@
|
|||||||
#define _INCLUDE__KERNEL__SYSCALLS_H_
|
#define _INCLUDE__KERNEL__SYSCALLS_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/syscall.h>
|
#include <base/syscall_types.h>
|
||||||
|
|
||||||
class Software_tlb;
|
class Software_tlb;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ namespace Kernel
|
|||||||
|
|
||||||
/* execution control */
|
/* execution control */
|
||||||
NEW_THREAD = 1,
|
NEW_THREAD = 1,
|
||||||
DELETE_THREAD = 24,
|
DELETE_THREAD = 26,
|
||||||
START_THREAD = 2,
|
START_THREAD = 2,
|
||||||
PAUSE_THREAD = 3,
|
PAUSE_THREAD = 3,
|
||||||
RESUME_THREAD = 4,
|
RESUME_THREAD = 4,
|
||||||
@ -70,10 +70,45 @@ namespace Kernel
|
|||||||
SUBMIT_SIGNAL = 23,
|
SUBMIT_SIGNAL = 23,
|
||||||
|
|
||||||
/* vm specific */
|
/* vm specific */
|
||||||
NEW_VM = 25,
|
NEW_VM = 24,
|
||||||
RUN_VM = 26,
|
RUN_VM = 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*****************************************************************
|
||||||
|
** Syscall with 1 to 6 arguments **
|
||||||
|
** **
|
||||||
|
** These functions must not be inline to ensure that objects, **
|
||||||
|
** wich are referenced by arguments, are tagged as "used" even **
|
||||||
|
** though only the pointer gets handled in here. **
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0);
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1);
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2);
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3);
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3,
|
||||||
|
Syscall_arg arg_4);
|
||||||
|
|
||||||
|
Syscall_ret syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3,
|
||||||
|
Syscall_arg arg_4,
|
||||||
|
Syscall_arg arg_5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Virtual range of the mode transition region in every PD
|
* Virtual range of the mode transition region in every PD
|
||||||
*/
|
*/
|
||||||
@ -107,8 +142,8 @@ namespace Kernel
|
|||||||
* Restricted to core threads. Regaining of the supplied memory is not
|
* Restricted to core threads. Regaining of the supplied memory is not
|
||||||
* supported by now.
|
* supported by now.
|
||||||
*/
|
*/
|
||||||
inline int new_pd(void * const dst)
|
inline int new_pd(void * const dst) {
|
||||||
{ return syscall(NEW_PD, (Syscall_arg)dst); }
|
return syscall(NEW_PD, (Syscall_arg)dst); }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
38
base-hw/include/platform/imx31/drivers/serial_log.h
Normal file
38
base-hw/include/platform/imx31/drivers/serial_log.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* \brief Serial output driver specific for the i.MX31
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__IMX31__DRIVERS__SERIAL_LOG_H_
|
||||||
|
#define _INCLUDE__PLATFORM__IMX31__DRIVERS__SERIAL_LOG_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board.h>
|
||||||
|
#include <drivers/uart/imx31_uart_base.h>
|
||||||
|
|
||||||
|
namespace Genode
|
||||||
|
{
|
||||||
|
struct Serial_log : Imx31_uart_base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* \param baud_rate targeted transfer baud-rate
|
||||||
|
*
|
||||||
|
* XXX: The 'baud_rate' argument is ignored for now.
|
||||||
|
*/
|
||||||
|
Serial_log(unsigned const baud_rate)
|
||||||
|
: Imx31_uart_base(Board::UART_1_MMIO_BASE) { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__PLATFORM__IMX31__DRIVERS__SERIAL_LOG_H_ */
|
||||||
|
|
@ -14,6 +14,7 @@
|
|||||||
#ifndef _INCLUDE__VM_SESSION__CAPABILITY_H_
|
#ifndef _INCLUDE__VM_SESSION__CAPABILITY_H_
|
||||||
#define _INCLUDE__VM_SESSION__CAPABILITY_H_
|
#define _INCLUDE__VM_SESSION__CAPABILITY_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/capability.h>
|
#include <base/capability.h>
|
||||||
#include <vm_session/vm_session.h>
|
#include <vm_session/vm_session.h>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Client-side vm session interface
|
* \brief Client-side VM session interface
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-10-02
|
* \date 2012-10-02
|
||||||
*/
|
*/
|
||||||
@ -14,16 +14,27 @@
|
|||||||
#ifndef _INCLUDE__VM_SESSION__CLIENT_H_
|
#ifndef _INCLUDE__VM_SESSION__CLIENT_H_
|
||||||
#define _INCLUDE__VM_SESSION__CLIENT_H_
|
#define _INCLUDE__VM_SESSION__CLIENT_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <vm_session/capability.h>
|
#include <vm_session/capability.h>
|
||||||
#include <base/rpc_client.h>
|
#include <base/rpc_client.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Client-side VM session interface
|
||||||
|
*/
|
||||||
struct Vm_session_client : Rpc_client<Vm_session>
|
struct Vm_session_client : Rpc_client<Vm_session>
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
explicit Vm_session_client(Vm_session_capability session)
|
explicit Vm_session_client(Vm_session_capability session)
|
||||||
: Rpc_client<Vm_session>(session) { }
|
: Rpc_client<Vm_session>(session) { }
|
||||||
|
|
||||||
|
/**************************
|
||||||
|
** Vm_session interface **
|
||||||
|
**************************/
|
||||||
|
|
||||||
Dataspace_capability cpu_state() {
|
Dataspace_capability cpu_state() {
|
||||||
return call<Rpc_cpu_state>(); }
|
return call<Rpc_cpu_state>(); }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Connection to VM service
|
* \brief Connection to VM a service
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-10-02
|
* \date 2012-10-02
|
||||||
*/
|
*/
|
||||||
@ -18,8 +18,11 @@
|
|||||||
#include <cpu_session/cpu_session.h>
|
#include <cpu_session/cpu_session.h>
|
||||||
#include <base/connection.h>
|
#include <base/connection.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Connection to a VM service
|
||||||
|
*/
|
||||||
struct Vm_connection : Connection<Vm_session>, Vm_session_client
|
struct Vm_connection : Connection<Vm_session>, Vm_session_client
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Vm session interface
|
* \brief VM-session interface
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-10-02
|
* \date 2012-10-02
|
||||||
*/
|
*/
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#ifndef _INCLUDE__VM_SESSION__VM_SESSION_H_
|
#ifndef _INCLUDE__VM_SESSION__VM_SESSION_H_
|
||||||
#define _INCLUDE__VM_SESSION__VM_SESSION_H_
|
#define _INCLUDE__VM_SESSION__VM_SESSION_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/rpc_args.h>
|
#include <base/rpc_args.h>
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
#include <session/session.h>
|
#include <session/session.h>
|
||||||
@ -25,6 +26,9 @@ namespace Genode {
|
|||||||
{
|
{
|
||||||
static const char *service_name() { return "VM"; }
|
static const char *service_name() { return "VM"; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~Vm_session() { }
|
virtual ~Vm_session() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
27
base-hw/lib/mk/arm/core_support.inc
Normal file
27
base-hw/lib/mk/arm/core_support.inc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# \brief Parts of core that depend on ARM
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-04-16
|
||||||
|
#
|
||||||
|
|
||||||
|
# add C++ sources
|
||||||
|
SRC_CC += syscall.cc
|
||||||
|
|
||||||
|
# add assembly sources
|
||||||
|
SRC_S += crt0.s boot_modules.s
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if there are other images wich shall be linked to core.
|
||||||
|
# If not use a dummy boot-modules file wich includes only the symbols.
|
||||||
|
#
|
||||||
|
ifeq ($(wildcard $(BUILD_BASE_DIR)/boot_modules.s),)
|
||||||
|
vpath boot_modules.s $(REP_DIR)/src/core/arm
|
||||||
|
else
|
||||||
|
INC_DIR += $(BUILD_BASE_DIR)
|
||||||
|
vpath boot_modules.s $(BUILD_BASE_DIR)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# declare source paths
|
||||||
|
vpath syscall.cc $(REP_DIR)/src/base/arm
|
||||||
|
vpath % $(REP_DIR)/src/core/arm
|
||||||
|
|
15
base-hw/lib/mk/arm_v6/core_support.inc
Normal file
15
base-hw/lib/mk/arm_v6/core_support.inc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# \brief Parts of core that depend on ARMv6
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-04-16
|
||||||
|
#
|
||||||
|
|
||||||
|
# add assembly sources
|
||||||
|
SRC_S += mode_transition.s
|
||||||
|
|
||||||
|
# declare source paths
|
||||||
|
vpath % $(REP_DIR)/src/core/arm_v6
|
||||||
|
|
||||||
|
# include less specific parts
|
||||||
|
include $(REP_DIR)/lib/mk/arm/core_support.inc
|
||||||
|
|
25
base-hw/lib/mk/arm_v6/startup.mk
Executable file
25
base-hw/lib/mk/arm_v6/startup.mk
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# \brief Essential platform specific sources for common programs
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-04-16
|
||||||
|
#
|
||||||
|
# FIXME: This is an almost verbatim copy of 'armv7a/startup.mk'. We should move
|
||||||
|
# the common parts to a separate file.
|
||||||
|
#
|
||||||
|
|
||||||
|
# add libraries
|
||||||
|
LIBS += cxx lock
|
||||||
|
|
||||||
|
# add C++ sources
|
||||||
|
SRC_CC += _main.cc
|
||||||
|
|
||||||
|
# add assembly sources
|
||||||
|
SRC_S += crt0.s syscall.cc
|
||||||
|
|
||||||
|
# add include paths
|
||||||
|
INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform
|
||||||
|
|
||||||
|
# declare source paths
|
||||||
|
vpath crt0.s $(REP_DIR)/src/platform
|
||||||
|
vpath _main.cc $(BASE_DIR)/src/platform
|
||||||
|
vpath syscall.cc $(REP_DIR)/src/base/arm
|
15
base-hw/lib/mk/arm_v7/core_support.inc
Normal file
15
base-hw/lib/mk/arm_v7/core_support.inc
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# \brief Parts of core that depend on ARMv7
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-04-16
|
||||||
|
#
|
||||||
|
|
||||||
|
# add assembly sources
|
||||||
|
SRC_S += mode_transition.s
|
||||||
|
|
||||||
|
# declare source paths
|
||||||
|
vpath % $(REP_DIR)/src/core/arm_v7
|
||||||
|
|
||||||
|
# include less specific parts
|
||||||
|
include $(REP_DIR)/lib/mk/arm/core_support.inc
|
||||||
|
|
@ -19,4 +19,4 @@ INC_DIR += $(REP_DIR)/src/platform $(BASE_DIR)/src/platform
|
|||||||
# declare source paths
|
# declare source paths
|
||||||
vpath crt0.s $(REP_DIR)/src/platform
|
vpath crt0.s $(REP_DIR)/src/platform
|
||||||
vpath _main.cc $(BASE_DIR)/src/platform
|
vpath _main.cc $(BASE_DIR)/src/platform
|
||||||
vpath syscall.cc $(REP_DIR)/src/base/arm_v7a
|
vpath syscall.cc $(REP_DIR)/src/base/arm
|
@ -14,6 +14,7 @@ CC_OPT += -DCORE_MAIN=_main
|
|||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += kernel.cc rm_session_support.cc kernel_support.cc trustzone.cc
|
SRC_CC += kernel.cc rm_session_support.cc kernel_support.cc trustzone.cc
|
||||||
|
|
||||||
|
# add library dependencies
|
||||||
LIBS += platform_support
|
LIBS += platform_support
|
||||||
|
|
||||||
# declare source paths
|
# declare source paths
|
||||||
|
17
base-hw/lib/mk/platform_imx31/core_support.mk
Normal file
17
base-hw/lib/mk/platform_imx31/core_support.mk
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#
|
||||||
|
# \brief Parts of core that depend on i.MX31
|
||||||
|
# \author Norman Feske
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-08-30
|
||||||
|
#
|
||||||
|
|
||||||
|
# declare location of core files that are board specific
|
||||||
|
BOARD_DIR = $(REP_DIR)/src/core/imx31
|
||||||
|
|
||||||
|
# add includes to search path
|
||||||
|
INC_DIR += $(REP_DIR)/src/core/include/imx31
|
||||||
|
|
||||||
|
# include less specific parts
|
||||||
|
include $(REP_DIR)/lib/mk/arm_v6/core_support.inc
|
||||||
|
include $(REP_DIR)/lib/mk/core_support.inc
|
||||||
|
|
18
base-hw/lib/mk/platform_imx31/platform_support.mk
Normal file
18
base-hw/lib/mk/platform_imx31/platform_support.mk
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#
|
||||||
|
# \brief Platform implementations specific for base-hw and i.MX31
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-05-10
|
||||||
|
#
|
||||||
|
|
||||||
|
# add include paths
|
||||||
|
INC_DIR += $(REP_DIR)/src/core/include \
|
||||||
|
$(REP_DIR)/src/core/include/imx31 \
|
||||||
|
$(BASE_DIR)/src/core/include
|
||||||
|
|
||||||
|
# add C++ sources
|
||||||
|
SRC_CC += platform_support.cc platform_services.cc
|
||||||
|
|
||||||
|
# declare source paths
|
||||||
|
vpath % $(REP_DIR)/src/core/imx31
|
||||||
|
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||||
|
|
@ -7,8 +7,7 @@
|
|||||||
# declare location of core files that are board specific
|
# declare location of core files that are board specific
|
||||||
BOARD_DIR = $(REP_DIR)/src/core/panda_a2
|
BOARD_DIR = $(REP_DIR)/src/core/panda_a2
|
||||||
|
|
||||||
SRC_CC = trustzone.cc
|
|
||||||
|
|
||||||
# include generic parts of core support
|
# include generic parts of core support
|
||||||
|
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||||
include $(REP_DIR)/lib/mk/core_support.inc
|
include $(REP_DIR)/lib/mk/core_support.inc
|
||||||
|
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
# declare location of core files that are board specific
|
# declare location of core files that are board specific
|
||||||
BOARD_DIR = $(REP_DIR)/src/core/pbxa9
|
BOARD_DIR = $(REP_DIR)/src/core/pbxa9
|
||||||
|
|
||||||
SRC_CC = trustzone.cc
|
|
||||||
|
|
||||||
# include generic part of core support
|
# include generic part of core support
|
||||||
|
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||||
include $(REP_DIR)/lib/mk/core_support.inc
|
include $(REP_DIR)/lib/mk/core_support.inc
|
||||||
|
|
||||||
|
@ -13,5 +13,6 @@ vpath kernel_support.cc $(BOARD_DIR)/trustzone
|
|||||||
vpath trustzone.cc $(BOARD_DIR)/trustzone
|
vpath trustzone.cc $(BOARD_DIR)/trustzone
|
||||||
|
|
||||||
# include generic part of core support
|
# include generic part of core support
|
||||||
|
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||||
include $(REP_DIR)/lib/mk/core_support.inc
|
include $(REP_DIR)/lib/mk/core_support.inc
|
||||||
|
|
||||||
|
@ -7,4 +7,5 @@
|
|||||||
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
||||||
|
|
||||||
# include generic part of core support
|
# include generic part of core support
|
||||||
|
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||||
include $(REP_DIR)/lib/mk/core_support.inc
|
include $(REP_DIR)/lib/mk/core_support.inc
|
||||||
|
15
base-hw/mk/spec-hw_imx31.mk
Normal file
15
base-hw/mk/spec-hw_imx31.mk
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# \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
|
||||||
|
|
||||||
|
# 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)
|
@ -21,7 +21,7 @@
|
|||||||
# 'binaries', minus 'core' if given, plus 'config' if available. It also
|
# 'binaries', minus 'core' if given, plus 'config' if available. It also
|
||||||
# provides a simple file system that enables Genode to access these BLOBs.
|
# provides a simple file system that enables Genode to access these BLOBs.
|
||||||
#
|
#
|
||||||
proc boot_modules_arm_v7a {{file} {binaries}} {
|
proc boot_modules_arm {{file} {binaries}} {
|
||||||
|
|
||||||
set load_store_alignm 0x3
|
set load_store_alignm 0x3
|
||||||
set min_page_alignm 12
|
set min_page_alignm 12
|
||||||
@ -30,7 +30,7 @@ proc boot_modules_arm_v7a {{file} {binaries}} {
|
|||||||
exec echo -e \
|
exec echo -e \
|
||||||
"/**" \
|
"/**" \
|
||||||
"\n * This file was automatically generated by the procedure" \
|
"\n * This file was automatically generated by the procedure" \
|
||||||
"\n * 'boot_modules_arm_v7a' in 'run/env'." \
|
"\n * 'boot_modules_arm' in 'run/env'." \
|
||||||
"\n */" \
|
"\n */" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"\n.section .data" \
|
"\n.section .data" \
|
||||||
@ -194,8 +194,8 @@ proc build_boot_image {binaries} {
|
|||||||
|
|
||||||
# create scenario-specific 'boot_modules.s' of all given binaries
|
# create scenario-specific 'boot_modules.s' of all given binaries
|
||||||
set boot_modules "[run_dir]/boot_modules.s"
|
set boot_modules "[run_dir]/boot_modules.s"
|
||||||
if { [have_spec {arm_v7a}] } {
|
if { [have_spec {arm}] } {
|
||||||
boot_modules_arm_v7a $boot_modules $binaries
|
boot_modules_arm $boot_modules $binaries
|
||||||
}
|
}
|
||||||
|
|
||||||
# preserve stand-alone core for debugging
|
# preserve stand-alone core for debugging
|
||||||
|
163
base-hw/src/base/arm/syscall.cc
Normal file
163
base-hw/src/base/arm/syscall.cc
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* \brief Syscall-framework implementation for ARM
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2011-11-30
|
||||||
|
*
|
||||||
|
* The code in this file is compliant to the general ARM instruction- and
|
||||||
|
* register-set but the semantics are tested only on ARMv6 and ARMv7 by now.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <kernel/syscalls.h>
|
||||||
|
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
** Inline assembly templates for syscalls with 1 to 6 arguments **
|
||||||
|
******************************************************************/
|
||||||
|
|
||||||
|
#define SYSCALL_6_ASM_OPS \
|
||||||
|
"mov r5, #0 \n" \
|
||||||
|
"add r5, %[arg_5] \n" \
|
||||||
|
SYSCALL_5_ASM_OPS
|
||||||
|
|
||||||
|
#define SYSCALL_5_ASM_OPS \
|
||||||
|
"mov r4, #0 \n" \
|
||||||
|
"add r4, %[arg_4] \n" \
|
||||||
|
SYSCALL_4_ASM_OPS
|
||||||
|
|
||||||
|
#define SYSCALL_4_ASM_OPS \
|
||||||
|
"mov r3, #0 \n" \
|
||||||
|
"add r3, %[arg_3] \n" \
|
||||||
|
SYSCALL_3_ASM_OPS
|
||||||
|
|
||||||
|
#define SYSCALL_3_ASM_OPS \
|
||||||
|
"mov r2, #0 \n" \
|
||||||
|
"add r2, %[arg_2] \n" \
|
||||||
|
SYSCALL_2_ASM_OPS
|
||||||
|
|
||||||
|
#define SYSCALL_2_ASM_OPS \
|
||||||
|
"mov r1, #0 \n" \
|
||||||
|
"add r1, %[arg_1] \n" \
|
||||||
|
SYSCALL_1_ASM_OPS
|
||||||
|
|
||||||
|
#define SYSCALL_1_ASM_OPS \
|
||||||
|
"mov r0, #0 \n" \
|
||||||
|
"add r0, %[arg_0] \n" \
|
||||||
|
"swi 0 \n" \
|
||||||
|
"mov %[result], #0 \n" \
|
||||||
|
"add %[result], r0 "
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Inline assembly "writeable" template-args for syscalls with 1 to 6 args **
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#define SYSCALL_6_ASM_WRITE [arg_5] "+r" (arg_5), SYSCALL_5_ASM_WRITE
|
||||||
|
#define SYSCALL_5_ASM_WRITE [arg_4] "+r" (arg_4), SYSCALL_4_ASM_WRITE
|
||||||
|
#define SYSCALL_4_ASM_WRITE [arg_3] "+r" (arg_3), SYSCALL_3_ASM_WRITE
|
||||||
|
#define SYSCALL_3_ASM_WRITE [arg_2] "+r" (arg_2), SYSCALL_2_ASM_WRITE
|
||||||
|
#define SYSCALL_2_ASM_WRITE [arg_1] "+r" (arg_1), SYSCALL_1_ASM_WRITE
|
||||||
|
#define SYSCALL_1_ASM_WRITE \
|
||||||
|
[arg_0] "+r" (arg_0), \
|
||||||
|
[result] "+r" (result)
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
** Inline assembly clobber lists for syscalls with 1 to 6 arguments **
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#define SYSCALL_6_ASM_CLOBBER "r5", SYSCALL_5_ASM_CLOBBER
|
||||||
|
#define SYSCALL_5_ASM_CLOBBER "r4", SYSCALL_4_ASM_CLOBBER
|
||||||
|
#define SYSCALL_4_ASM_CLOBBER "r3", SYSCALL_3_ASM_CLOBBER
|
||||||
|
#define SYSCALL_3_ASM_CLOBBER "r2", SYSCALL_2_ASM_CLOBBER
|
||||||
|
#define SYSCALL_2_ASM_CLOBBER "r1", SYSCALL_1_ASM_CLOBBER
|
||||||
|
#define SYSCALL_1_ASM_CLOBBER "r0"
|
||||||
|
|
||||||
|
|
||||||
|
/************************************
|
||||||
|
** Syscalls with 1 to 6 arguments **
|
||||||
|
************************************/
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_1_ASM_OPS
|
||||||
|
: SYSCALL_1_ASM_WRITE
|
||||||
|
:: SYSCALL_1_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_2_ASM_OPS
|
||||||
|
: SYSCALL_2_ASM_WRITE
|
||||||
|
:: SYSCALL_2_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_3_ASM_OPS
|
||||||
|
: SYSCALL_3_ASM_WRITE
|
||||||
|
:: SYSCALL_3_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_4_ASM_OPS
|
||||||
|
: SYSCALL_4_ASM_WRITE
|
||||||
|
:: SYSCALL_4_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3,
|
||||||
|
Syscall_arg arg_4)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_5_ASM_OPS
|
||||||
|
: SYSCALL_5_ASM_WRITE
|
||||||
|
:: SYSCALL_5_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Syscall_ret Kernel::syscall(Syscall_arg arg_0,
|
||||||
|
Syscall_arg arg_1,
|
||||||
|
Syscall_arg arg_2,
|
||||||
|
Syscall_arg arg_3,
|
||||||
|
Syscall_arg arg_4,
|
||||||
|
Syscall_arg arg_5)
|
||||||
|
{
|
||||||
|
Syscall_ret result = 0;
|
||||||
|
asm volatile(SYSCALL_6_ASM_OPS
|
||||||
|
: SYSCALL_6_ASM_WRITE
|
||||||
|
:: SYSCALL_6_ASM_CLOBBER);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Dummy version of a boot modules file to enable a 'core' standalone image
|
* \brief Dummy boot-modules-file to enable a 'core' standalone image
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
* \date 2011-12-16
|
* \date 2011-12-16
|
||||||
*/
|
*/
|
||||||
@ -31,3 +31,4 @@ _boot_module_headers_end:
|
|||||||
|
|
||||||
.global _boot_modules_end
|
.global _boot_modules_end
|
||||||
_boot_modules_end:
|
_boot_modules_end:
|
||||||
|
|
@ -1,8 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Startup code for the Genode Kernel on ARM
|
* \brief Startup code for core on ARM
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
* \date 2011-10-01
|
* \date 2011-10-01
|
||||||
|
*
|
||||||
|
* The code in this file is compliant to the general ARM instruction- and
|
||||||
|
* register-set but the semantics are tested only on ARMv6 and ARMv7 by now.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -12,6 +15,15 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do no operation for 'count' cycles
|
||||||
|
*/
|
||||||
|
.macro _nop count
|
||||||
|
.rept \count
|
||||||
|
mov r8, r8
|
||||||
|
.endr
|
||||||
|
.endm
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
/* ELF entry symbol */
|
/* ELF entry symbol */
|
||||||
@ -19,9 +31,7 @@
|
|||||||
_start:
|
_start:
|
||||||
|
|
||||||
/* idle a little initially because 'u-boot' likes it this way */
|
/* idle a little initially because 'u-boot' likes it this way */
|
||||||
.rept 8
|
_nop 8
|
||||||
nop
|
|
||||||
.endr
|
|
||||||
|
|
||||||
/* zero-fill BSS segment */
|
/* zero-fill BSS segment */
|
||||||
.extern _bss_start
|
.extern _bss_start
|
||||||
@ -36,12 +46,19 @@
|
|||||||
cmp r0, r1
|
cmp r0, r1
|
||||||
bne 1b
|
bne 1b
|
||||||
|
|
||||||
|
/* enable C++ to prepare the first kernel run */
|
||||||
|
ldr sp, =_kernel_stack_high
|
||||||
|
bl init_phys_kernel
|
||||||
|
|
||||||
/* call kernel routine */
|
/* call kernel routine */
|
||||||
.extern kernel
|
.extern kernel
|
||||||
_start_kernel:
|
_start_kernel:
|
||||||
ldr sp, =_kernel_stack_high
|
ldr sp, =_kernel_stack_high
|
||||||
bl kernel
|
bl kernel
|
||||||
|
|
||||||
|
/* catch erroneous kernel return */
|
||||||
|
2: b 2b
|
||||||
|
|
||||||
/* handle for dynamic symbol objects */
|
/* handle for dynamic symbol objects */
|
||||||
.align 3
|
.align 3
|
||||||
.global __dso_handle
|
.global __dso_handle
|
||||||
@ -55,7 +72,7 @@
|
|||||||
.global _kernel_stack_high
|
.global _kernel_stack_high
|
||||||
_kernel_stack_high:
|
_kernel_stack_high:
|
||||||
|
|
||||||
/* main thread UTCB pointer for the Genode thread API */
|
/* main-thread UTCB-pointer for the Genode thread-API */
|
||||||
.align 3
|
.align 3
|
||||||
.global _main_utcb
|
.global _main_utcb
|
||||||
_main_utcb: .long 0
|
_main_utcb: .long 0
|
234
base-hw/src/core/arm_v6/mode_transition.s
Normal file
234
base-hw/src/core/arm_v6/mode_transition.s
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* \brief Transition between kernel and userland
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2011-11-15
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate all entries of the branch prediction cache
|
||||||
|
*
|
||||||
|
* FIXME branch prediction shall not be activated for now because we have no
|
||||||
|
* support for instruction barriers. The manual says that one should
|
||||||
|
* implement this via 'swi 0xf00000', but when we do this in SVC mode it
|
||||||
|
* pollutes our SP and this is not acceptable with the current mode
|
||||||
|
* transition implementation
|
||||||
|
*/
|
||||||
|
.macro _flush_branch_predictor
|
||||||
|
mcr p15, 0, sp, c7, c5, 6
|
||||||
|
/* swi 0xf00000 */
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch from an interrupted user context to a kernel context
|
||||||
|
*
|
||||||
|
* \param exception_type immediate exception type ID
|
||||||
|
* \param pc_adjust immediate value that gets subtracted from the
|
||||||
|
* user PC before it gets saved
|
||||||
|
*/
|
||||||
|
.macro _user_to_kernel_pic exception_type, pc_adjust
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We expect that privileged modes are never interrupted by an
|
||||||
|
* exception. Thus we can assume that we always come from
|
||||||
|
* user mode at this point.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/************************************************
|
||||||
|
** We're still in the user protection domain, **
|
||||||
|
** so we must avoid access to kernel memory **
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
/* load kernel cidr */
|
||||||
|
adr sp, _mt_master_context_begin
|
||||||
|
ldr sp, [sp, #18*4]
|
||||||
|
mcr p15, 0, sp, c13, c0, 1
|
||||||
|
_flush_branch_predictor
|
||||||
|
|
||||||
|
/* load kernel section table */
|
||||||
|
adr sp, _mt_master_context_begin
|
||||||
|
ldr sp, [sp, #19*4]
|
||||||
|
mcr p15, 0, sp, c2, c0, 0
|
||||||
|
_flush_branch_predictor
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
** Now it's save to access kernel memory **
|
||||||
|
*******************************************/
|
||||||
|
|
||||||
|
/* get user context pointer */
|
||||||
|
ldr sp, _mt_client_context_ptr
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save user r0 ... r12. We explicitely target user registers
|
||||||
|
* via '^' because we might be in FIQ exception-mode where
|
||||||
|
* some of them are banked. Doesn't affect other modes.
|
||||||
|
*/
|
||||||
|
stmia sp, {r0-r12}^
|
||||||
|
|
||||||
|
/* save user lr and sp */
|
||||||
|
add r0, sp, #13*4
|
||||||
|
stmia r0, {sp,lr}^
|
||||||
|
|
||||||
|
/* adjust and save user pc */
|
||||||
|
.if \pc_adjust != 0
|
||||||
|
sub lr, lr, #\pc_adjust
|
||||||
|
.endif
|
||||||
|
str lr, [sp, #15*4]
|
||||||
|
|
||||||
|
/* save user psr */
|
||||||
|
mrs r0, spsr
|
||||||
|
str r0, [sp, #16*4]
|
||||||
|
|
||||||
|
/* save type of exception that interrupted the user */
|
||||||
|
mov r0, #\exception_type
|
||||||
|
str r0, [sp, #17*4]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to supervisor mode
|
||||||
|
*
|
||||||
|
* FIXME This is done due to incorrect behavior when running the kernel
|
||||||
|
* high-level-code in FIQ-exception mode. Please debug this behavior
|
||||||
|
* and remove this switch.
|
||||||
|
*/
|
||||||
|
cps #19
|
||||||
|
|
||||||
|
/* get kernel context pointer */
|
||||||
|
adr r0, _mt_master_context_begin
|
||||||
|
|
||||||
|
/* load kernel context */
|
||||||
|
add r0, r0, #13*4
|
||||||
|
ldmia r0, {sp, lr, pc}
|
||||||
|
|
||||||
|
.endm
|
||||||
|
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The mode transition PIC switches between a kernel context and a user
|
||||||
|
* context and thereby between their address spaces. Due to the latter
|
||||||
|
* it must be mapped executable to the same region in every address space.
|
||||||
|
* To enable such switching, the kernel context must be stored within this
|
||||||
|
* region, thus one should map it solely accessable for privileged modes.
|
||||||
|
*/
|
||||||
|
.p2align 12
|
||||||
|
.global _mode_transition_begin
|
||||||
|
_mode_transition_begin:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On user exceptions the CPU has to jump to one of the following
|
||||||
|
* 7 entry vectors to switch to a kernel context.
|
||||||
|
*/
|
||||||
|
.global _mt_kernel_entry_pic
|
||||||
|
_mt_kernel_entry_pic:
|
||||||
|
|
||||||
|
b _rst_entry /* 0x00: reset */
|
||||||
|
b _und_entry /* 0x04: undefined instruction */
|
||||||
|
b _swi_entry /* 0x08: software interrupt */
|
||||||
|
b _pab_entry /* 0x0c: prefetch abort */
|
||||||
|
b _dab_entry /* 0x10: data abort */
|
||||||
|
nop /* 0x14: reserved */
|
||||||
|
b _irq_entry /* 0x18: interrupt request */
|
||||||
|
b _fiq_entry /* 0x1c: fast interrupt request */
|
||||||
|
|
||||||
|
/* PICs that switch from an user exception to the kernel */
|
||||||
|
_rst_entry: _user_to_kernel_pic 1, 0
|
||||||
|
_und_entry: _user_to_kernel_pic 2, 4
|
||||||
|
_swi_entry:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME fast SWI routines pollute the SVC SP but we have
|
||||||
|
* to call them especially in SVC mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* check if SWI requests a fast service routine */
|
||||||
|
/* ldr sp, [r14, #-0x4]
|
||||||
|
and sp, sp, #0xffffff
|
||||||
|
*/
|
||||||
|
/* fast "instruction barrier" service routine */
|
||||||
|
/* cmp sp, #0xf00000
|
||||||
|
bne _mt_slow_swi
|
||||||
|
movs pc, r14
|
||||||
|
*/
|
||||||
|
/* slow high level service routine */
|
||||||
|
_mt_slow_swi:
|
||||||
|
_user_to_kernel_pic 3, 0
|
||||||
|
|
||||||
|
_pab_entry: _user_to_kernel_pic 4, 4
|
||||||
|
_dab_entry: _user_to_kernel_pic 5, 8
|
||||||
|
_irq_entry: _user_to_kernel_pic 6, 4
|
||||||
|
_fiq_entry: _user_to_kernel_pic 7, 4
|
||||||
|
|
||||||
|
/* kernel must jump to this point to switch to a user context */
|
||||||
|
.p2align 2
|
||||||
|
.global _mt_user_entry_pic
|
||||||
|
_mt_user_entry_pic:
|
||||||
|
|
||||||
|
/* get user context pointer */
|
||||||
|
ldr lr, _mt_client_context_ptr
|
||||||
|
|
||||||
|
/* buffer user pc */
|
||||||
|
ldr r0, [lr, #15*4]
|
||||||
|
adr r1, _mt_buffer
|
||||||
|
str r0, [r1]
|
||||||
|
|
||||||
|
/* buffer user psr */
|
||||||
|
ldr r0, [lr, #16*4]
|
||||||
|
msr spsr, r0
|
||||||
|
|
||||||
|
/* load user r0 ... r12 */
|
||||||
|
ldmia lr, {r0-r12}
|
||||||
|
|
||||||
|
/* load user sp and lr */
|
||||||
|
add sp, lr, #13*4
|
||||||
|
ldmia sp, {sp,lr}^
|
||||||
|
|
||||||
|
/* get user cidr and section table */
|
||||||
|
ldr sp, [lr, #18*4]
|
||||||
|
ldr lr, [lr, #19*4]
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
** From now on, until we leave kernel mode, we must **
|
||||||
|
** avoid access to memory that is not mapped globally **
|
||||||
|
********************************************************/
|
||||||
|
|
||||||
|
/* apply user contextidr and section table */
|
||||||
|
mcr p15, 0, sp, c13, c0, 1
|
||||||
|
mcr p15, 0, lr, c2, c0, 0
|
||||||
|
_flush_branch_predictor
|
||||||
|
|
||||||
|
/* load user pc (implies application of the user psr) */
|
||||||
|
adr lr, _mt_buffer
|
||||||
|
ldmia lr, {pc}^
|
||||||
|
|
||||||
|
/* leave some space for 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:
|
||||||
|
|
||||||
|
/* pointer to the context backup space */
|
||||||
|
.p2align 2
|
||||||
|
.global _mt_client_context_ptr
|
||||||
|
_mt_client_context_ptr: .long 0
|
||||||
|
|
||||||
|
/* a local word-sized buffer */
|
||||||
|
.p2align 2
|
||||||
|
.global _mt_buffer
|
||||||
|
_mt_buffer: .long 0
|
||||||
|
|
||||||
|
.p2align 2
|
||||||
|
.global _mode_transition_end
|
||||||
|
_mode_transition_end:
|
||||||
|
|
||||||
|
/* FIXME this exists only because _vm_mon_entry pollutes kernel.cc */
|
||||||
|
.global _mon_vm_entry
|
||||||
|
_mon_vm_entry:
|
||||||
|
1: b 1b
|
@ -12,6 +12,7 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch from an interrupted user context to a kernel context
|
* Switch from an interrupted user context to a kernel context
|
||||||
*
|
*
|
||||||
@ -37,13 +38,14 @@
|
|||||||
** so we must avoid access to kernel memory **
|
** so we must avoid access to kernel memory **
|
||||||
************************************************/
|
************************************************/
|
||||||
|
|
||||||
/* load kernel contextidr */
|
/* load kernel cidr */
|
||||||
adr sp, _mt_kernel_context_begin
|
adr sp, _mt_master_context_begin
|
||||||
ldr sp, [sp, #18*4]
|
ldr sp, [sp, #18*4]
|
||||||
mcr p15, 0, sp, c13, c0, 1
|
mcr p15, 0, sp, c13, c0, 1
|
||||||
|
isb
|
||||||
|
|
||||||
/* load kernel section table */
|
/* load kernel section table */
|
||||||
adr sp, _mt_kernel_context_begin
|
adr sp, _mt_master_context_begin
|
||||||
ldr sp, [sp, #19*4]
|
ldr sp, [sp, #19*4]
|
||||||
mcr p15, 0, sp, c2, c0, 0
|
mcr p15, 0, sp, c2, c0, 0
|
||||||
isb
|
isb
|
||||||
@ -54,7 +56,7 @@
|
|||||||
*******************************************/
|
*******************************************/
|
||||||
|
|
||||||
/* get user context pointer */
|
/* get user context pointer */
|
||||||
ldr sp, _mt_context_ptr
|
ldr sp, _mt_client_context_ptr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save user r0 ... r12. We explicitely target user registers
|
* Save user r0 ... r12. We explicitely target user registers
|
||||||
@ -90,7 +92,7 @@
|
|||||||
cps #19
|
cps #19
|
||||||
|
|
||||||
/* get kernel context pointer */
|
/* get kernel context pointer */
|
||||||
adr r0, _mt_kernel_context_begin
|
adr r0, _mt_master_context_begin
|
||||||
|
|
||||||
/* load kernel context */
|
/* load kernel context */
|
||||||
add r0, r0, #13*4
|
add r0, r0, #13*4
|
||||||
@ -105,7 +107,7 @@
|
|||||||
.macro _kernel_to_user_pic
|
.macro _kernel_to_user_pic
|
||||||
|
|
||||||
/* get user context pointer */
|
/* get user context pointer */
|
||||||
ldr lr, _mt_context_ptr
|
ldr lr, _mt_client_context_ptr
|
||||||
|
|
||||||
/* buffer user pc */
|
/* buffer user pc */
|
||||||
ldr r0, [lr, #15*4]
|
ldr r0, [lr, #15*4]
|
||||||
@ -154,7 +156,7 @@
|
|||||||
orr r8, #64
|
orr r8, #64
|
||||||
msr spsr, r8
|
msr spsr, r8
|
||||||
subs pc, lr, #4 /* resume previous exception */
|
subs pc, lr, #4 /* resume previous exception */
|
||||||
1:
|
1:
|
||||||
.endm /* _fiq_check_prior_mode */
|
.endm /* _fiq_check_prior_mode */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -168,14 +170,14 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch from an interrupted vm to the kernel context
|
* Switch from an interrupted VM to the kernel context
|
||||||
*
|
*
|
||||||
* \param exception_type immediate exception type ID
|
* \param exception_type immediate exception type ID
|
||||||
* \param pc_adjust immediate value that gets subtracted from the
|
* \param pc_adjust immediate value that gets subtracted from the
|
||||||
* vm's PC before it gets saved
|
* vm's PC before it gets saved
|
||||||
*/
|
*/
|
||||||
.macro _vm_to_kernel exception_type, pc_adjust
|
.macro _vm_to_kernel exception_type, pc_adjust
|
||||||
ldr sp, _mt_context_ptr /* load context pointer */
|
ldr sp, _mt_client_context_ptr /* load context pointer */
|
||||||
stmia sp, {r0-lr}^ /* save user regs r0-r12,sp,lr */
|
stmia sp, {r0-lr}^ /* save user regs r0-r12,sp,lr */
|
||||||
add r0, sp, #15*4
|
add r0, sp, #15*4
|
||||||
.if \pc_adjust != 0 /* adjust pc if necessary */
|
.if \pc_adjust != 0 /* adjust pc if necessary */
|
||||||
@ -194,7 +196,7 @@
|
|||||||
_save_bank 17 /* save fiq banks */
|
_save_bank 17 /* save fiq banks */
|
||||||
stmia r0!, {r8-r12} /* save fiq r8-r12 */
|
stmia r0!, {r8-r12} /* save fiq r8-r12 */
|
||||||
cps #19 /* switch to supervisor mode */
|
cps #19 /* switch to supervisor mode */
|
||||||
adr r0, _mt_kernel_context_begin /* get kernel context pointer */
|
adr r0, _mt_master_context_begin /* get kernel context pointer */
|
||||||
add r0, r0, #13*4 /* load kernel context */
|
add r0, r0, #13*4 /* load kernel context */
|
||||||
ldmia r0, {sp,lr,pc}
|
ldmia r0, {sp,lr,pc}
|
||||||
.endm /* _vm_to_kernel */
|
.endm /* _vm_to_kernel */
|
||||||
@ -211,10 +213,10 @@
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch from kernel context to a vm
|
* Switch from kernel context to a VM
|
||||||
*/
|
*/
|
||||||
.macro _kernel_to_vm
|
.macro _kernel_to_vm
|
||||||
ldr r0, _mt_context_ptr /* get vm context pointer */
|
ldr r0, _mt_client_context_ptr /* get vm context pointer */
|
||||||
add r0, r0, #18*4 /* add offset of banked modes */
|
add r0, r0, #18*4 /* add offset of banked modes */
|
||||||
_restore_bank 27 /* load undefined banks */
|
_restore_bank 27 /* load undefined banks */
|
||||||
_restore_bank 19 /* load supervisor banks */
|
_restore_bank 19 /* load supervisor banks */
|
||||||
@ -223,7 +225,7 @@
|
|||||||
_restore_bank 17 /* load fiq banks */
|
_restore_bank 17 /* load fiq banks */
|
||||||
ldmia r0!, {r8 - r12} /* load fiq r8-r12 */
|
ldmia r0!, {r8 - r12} /* load fiq r8-r12 */
|
||||||
cps #22 /* switch to monitor mode */
|
cps #22 /* switch to monitor mode */
|
||||||
ldr sp, _mt_context_ptr /* get vm context pointer */
|
ldr sp, _mt_client_context_ptr /* get vm context pointer */
|
||||||
ldmia sp, {r0-lr}^ /* load user r0-r12,sp,lr */
|
ldmia sp, {r0-lr}^ /* load user r0-r12,sp,lr */
|
||||||
ldr lr, [sp, #16*4] /* load vm's cpsr to lr */
|
ldr lr, [sp, #16*4] /* load vm's cpsr to lr */
|
||||||
msr spsr_cxfs, lr /* save cpsr to be load when switching */
|
msr spsr_cxfs, lr /* save cpsr to be load when switching */
|
||||||
@ -254,23 +256,23 @@
|
|||||||
.global _mt_kernel_entry_pic
|
.global _mt_kernel_entry_pic
|
||||||
_mt_kernel_entry_pic:
|
_mt_kernel_entry_pic:
|
||||||
|
|
||||||
b _rst_entry /* reset */
|
b _rst_entry /* 0x00: reset */
|
||||||
b _und_entry /* undefined instruction */
|
b _und_entry /* 0x04: undefined instruction */
|
||||||
b _svc_entry /* supervisor call */
|
b _svc_entry /* 0x08: supervisor call */
|
||||||
b _pab_entry /* prefetch abort */
|
b _pab_entry /* 0x0c: prefetch abort */
|
||||||
b _dab_entry /* data abort */
|
b _dab_entry /* 0x10: data abort */
|
||||||
nop /* reserved */
|
nop /* 0x14: reserved */
|
||||||
b _irq_entry /* interrupt request */
|
b _irq_entry /* 0x18: interrupt request */
|
||||||
_fiq_check_prior_mode /* fast interrupt request */
|
_fiq_check_prior_mode /* 0x1c: fast interrupt request */
|
||||||
_user_to_kernel_pic 6, 4
|
_user_to_kernel_pic 7, 4
|
||||||
|
|
||||||
/* PICs that switch from an user exception to the kernel */
|
/* PICs that switch from an user exception to the kernel */
|
||||||
_rst_entry: _user_to_kernel_pic 0, 0
|
_rst_entry: _user_to_kernel_pic 1, 0
|
||||||
_und_entry: _user_to_kernel_pic 1, 4
|
_und_entry: _user_to_kernel_pic 2, 4
|
||||||
_svc_entry: _user_to_kernel_pic 2, 0
|
_svc_entry: _user_to_kernel_pic 3, 0
|
||||||
_pab_entry: _user_to_kernel_pic 3, 4
|
_pab_entry: _user_to_kernel_pic 4, 4
|
||||||
_dab_entry: _user_to_kernel_pic 4, 8
|
_dab_entry: _user_to_kernel_pic 5, 8
|
||||||
_irq_entry: _user_to_kernel_pic 5, 4
|
_irq_entry: _user_to_kernel_pic 6, 4
|
||||||
|
|
||||||
/* kernel must jump to this point to switch to a user context */
|
/* kernel must jump to this point to switch to a user context */
|
||||||
.p2align 2
|
.p2align 2
|
||||||
@ -280,15 +282,15 @@
|
|||||||
|
|
||||||
/* leave some space for the kernel context */
|
/* leave some space for the kernel context */
|
||||||
.p2align 2
|
.p2align 2
|
||||||
.global _mt_kernel_context_begin
|
.global _mt_master_context_begin
|
||||||
_mt_kernel_context_begin: .space 32*4
|
_mt_master_context_begin: .space 32*4
|
||||||
.global _mt_kernel_context_end
|
.global _mt_master_context_end
|
||||||
_mt_kernel_context_end:
|
_mt_master_context_end:
|
||||||
|
|
||||||
/* pointer to the context backup space */
|
/* pointer to the context backup space */
|
||||||
.p2align 2
|
.p2align 2
|
||||||
.global _mt_context_ptr
|
.global _mt_client_context_ptr
|
||||||
_mt_context_ptr: .long 0
|
_mt_client_context_ptr: .long 0
|
||||||
|
|
||||||
/* a local word-sized buffer */
|
/* a local word-sized buffer */
|
||||||
.p2align 2
|
.p2align 2
|
||||||
@ -302,7 +304,7 @@
|
|||||||
* On vm exceptions the CPU has to jump to one of the following
|
* On vm exceptions the CPU has to jump to one of the following
|
||||||
* 7 entry vectors to switch to a kernel context.
|
* 7 entry vectors to switch to a kernel context.
|
||||||
*/
|
*/
|
||||||
.p2align 2
|
.p2align 4
|
||||||
.global _mon_kernel_entry
|
.global _mon_kernel_entry
|
||||||
_mon_kernel_entry:
|
_mon_kernel_entry:
|
||||||
b _mon_rst_entry /* reset */
|
b _mon_rst_entry /* reset */
|
||||||
@ -312,15 +314,15 @@
|
|||||||
b _mon_dab_entry /* data abort */
|
b _mon_dab_entry /* data abort */
|
||||||
nop /* reserved */
|
nop /* reserved */
|
||||||
b _mon_irq_entry /* interrupt request */
|
b _mon_irq_entry /* interrupt request */
|
||||||
_vm_to_kernel 6, 4 /* fast interrupt request */
|
_vm_to_kernel 7, 4 /* fast interrupt request */
|
||||||
|
|
||||||
/* PICs that switch from a vm exception to the kernel */
|
/* PICs that switch from a vm exception to the kernel */
|
||||||
_mon_rst_entry: _vm_to_kernel 0, 0
|
_mon_rst_entry: _vm_to_kernel 1, 0
|
||||||
_mon_und_entry: _vm_to_kernel 1, 4
|
_mon_und_entry: _vm_to_kernel 2, 4
|
||||||
_mon_svc_entry: _vm_to_kernel 2, 0
|
_mon_svc_entry: _vm_to_kernel 3, 0
|
||||||
_mon_pab_entry: _vm_to_kernel 3, 4
|
_mon_pab_entry: _vm_to_kernel 4, 4
|
||||||
_mon_dab_entry: _vm_to_kernel 4, 8
|
_mon_dab_entry: _vm_to_kernel 5, 8
|
||||||
_mon_irq_entry: _vm_to_kernel 5, 4
|
_mon_irq_entry: _vm_to_kernel 6, 4
|
||||||
|
|
||||||
/* kernel must jump to this point to switch to a vm */
|
/* kernel must jump to this point to switch to a vm */
|
||||||
.p2align 2
|
.p2align 2
|
21
base-hw/src/core/imx31/kernel_support.h
Normal file
21
base-hw/src/core/imx31/kernel_support.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* \brief Platform specific parts of kernel
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-04-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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 _SRC__CORE__KERNEL_SUPPORT_H_
|
||||||
|
#define _SRC__CORE__KERNEL_SUPPORT_H_
|
||||||
|
|
||||||
|
/* local includes */
|
||||||
|
#include <arm1136/kernel_support.h>
|
||||||
|
|
||||||
|
#endif /* _SRC__CORE__KERNEL_SUPPORT_H_ */
|
||||||
|
|
96
base-hw/src/core/imx31/platform_support.cc
Normal file
96
base-hw/src/core/imx31/platform_support.cc
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* \brief Platform implementations specific for base-hw and i.MX31
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board.h>
|
||||||
|
#include <imx31/pic.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <platform.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
Native_region * Platform::_ram_regions(unsigned const i)
|
||||||
|
{
|
||||||
|
static Native_region _regions[] =
|
||||||
|
{
|
||||||
|
{ Board::CSD0_SDRAM_BASE, Board::CSD0_SDRAM_SIZE }
|
||||||
|
};
|
||||||
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Native_region * Platform::_irq_regions(unsigned const i)
|
||||||
|
{
|
||||||
|
static Native_region _regions[] =
|
||||||
|
{
|
||||||
|
{ 0, Imx31::Pic::MAX_INTERRUPT_ID + 1 }
|
||||||
|
};
|
||||||
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||||
|
{
|
||||||
|
static Native_region _regions[] =
|
||||||
|
{
|
||||||
|
/* core timer */
|
||||||
|
{ Board::EPIT_1_IRQ, 1 },
|
||||||
|
|
||||||
|
/* core UART */
|
||||||
|
{ Board::UART_1_IRQ, 1 }
|
||||||
|
};
|
||||||
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||||
|
{
|
||||||
|
static Native_region _regions[] =
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The address range below 0x30000000 is used for secure ROM, ROM, and
|
||||||
|
* internal RAM.
|
||||||
|
*/
|
||||||
|
{ 0x30000000, 0x50000000 },
|
||||||
|
/*
|
||||||
|
* The address range between 0x8000000 and 0x9fffffff is designated for
|
||||||
|
* SDRAM. The remaining address range is populated with peripherals.
|
||||||
|
*/
|
||||||
|
{ 0xa0000000, 0x24000000 }
|
||||||
|
};
|
||||||
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Native_region * Platform::_core_only_mmio_regions(unsigned const i)
|
||||||
|
{
|
||||||
|
static Native_region _regions[] =
|
||||||
|
{
|
||||||
|
/* core UART */
|
||||||
|
{ Board::UART_1_MMIO_BASE, Board::UART_1_MMIO_SIZE },
|
||||||
|
|
||||||
|
/* core timer */
|
||||||
|
{ Board::EPIT_1_MMIO_BASE, Board::EPIT_1_MMIO_SIZE },
|
||||||
|
|
||||||
|
/* interrupt controller */
|
||||||
|
{ Board::AVIC_MMIO_BASE, Board::AVIC_MMIO_SIZE },
|
||||||
|
|
||||||
|
/* bus interface controller */
|
||||||
|
{ Board::AIPS_1_MMIO_BASE, Board::AIPS_1_MMIO_SIZE },
|
||||||
|
{ Board::AIPS_2_MMIO_BASE, Board::AIPS_2_MMIO_SIZE },
|
||||||
|
};
|
||||||
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
|
}
|
||||||
|
|
26
base-hw/src/core/imx31/software_tlb.h
Normal file
26
base-hw/src/core/imx31/software_tlb.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* \brief Software TLB controls specific for the i.MX31
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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 _SRC__CORE__IMX31__SOFTWARE_TLB_H_
|
||||||
|
#define _SRC__CORE__IMX31__SOFTWARE_TLB_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <arm/v6/section_table.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Software TLB controls
|
||||||
|
*/
|
||||||
|
class Software_tlb : public Arm_v6::Section_table { };
|
||||||
|
|
||||||
|
#endif /* _SRC__CORE__IMX31__SOFTWARE_TLB_H_ */
|
||||||
|
|
11
base-hw/src/core/imx31/target.mk
Normal file
11
base-hw/src/core/imx31/target.mk
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#
|
||||||
|
# \brief Makefile for core
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-10-04
|
||||||
|
#
|
||||||
|
|
||||||
|
# declare wich specs must be given to build this target
|
||||||
|
REQUIRES = platform_imx31
|
||||||
|
|
||||||
|
# include less specific target parts
|
||||||
|
include $(REP_DIR)/src/core/target.inc
|
660
base-hw/src/core/include/arm/cpu.h
Normal file
660
base-hw/src/core/include/arm/cpu.h
Normal file
@ -0,0 +1,660 @@
|
|||||||
|
/*
|
||||||
|
* \brief Simple driver for the ARM core
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2012-09-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__ARM__CPU_H_
|
||||||
|
#define _INCLUDE__ARM__CPU_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/register.h>
|
||||||
|
#include <cpu/cpu_state.h>
|
||||||
|
|
||||||
|
namespace Arm
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARM core
|
||||||
|
*/
|
||||||
|
struct Cpu
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
TTBCR_N = 0,
|
||||||
|
EXCEPTION_ENTRY = 0xffff0000,
|
||||||
|
DATA_ACCESS_ALIGNM = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache type register
|
||||||
|
*/
|
||||||
|
struct Ctr : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c0, c0, 1" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System control register
|
||||||
|
*/
|
||||||
|
struct Sctlr : Register<32>
|
||||||
|
{
|
||||||
|
struct M : Bitfield<0,1> { }; /* enable MMU */
|
||||||
|
struct A : Bitfield<1,1> { }; /* strict data addr. alignment on */
|
||||||
|
struct C : Bitfield<2,1> { }; /* enable L1 data cache */
|
||||||
|
struct Z : Bitfield<11,1> { }; /* enable program flow prediction */
|
||||||
|
struct I : Bitfield<12,1> { }; /* enable L1 instruction-cache */
|
||||||
|
|
||||||
|
struct V : Bitfield<13,1> /* select exception-entry base */
|
||||||
|
{
|
||||||
|
enum { XFFFF0000 = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Rr : Bitfield<14,1> /* replacement strategy */
|
||||||
|
{
|
||||||
|
enum { RANDOM = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Fi : Bitfield<21,1> { }; /* enable fast IRQ config */
|
||||||
|
|
||||||
|
struct Ve : Bitfield<24,1> /* interrupt vector config */
|
||||||
|
{
|
||||||
|
enum { FIXED = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ee : Bitfield<25,1> { }; /* raise CPSR.E on exceptions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel()
|
||||||
|
{
|
||||||
|
return M::bits(1) |
|
||||||
|
A::bits(0) |
|
||||||
|
C::bits(0) |
|
||||||
|
Z::bits(0) |
|
||||||
|
I::bits(0) |
|
||||||
|
V::bits(V::XFFFF0000) |
|
||||||
|
Rr::bits(Rr::RANDOM) |
|
||||||
|
Fi::bits(0) |
|
||||||
|
Ve::bits(Ve::FIXED) |
|
||||||
|
Ee::bits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the initial kernel entry
|
||||||
|
*/
|
||||||
|
static access_t init_phys_kernel()
|
||||||
|
{
|
||||||
|
return M::bits(0) |
|
||||||
|
A::bits(0) |
|
||||||
|
C::bits(0) |
|
||||||
|
Z::bits(0) |
|
||||||
|
I::bits(0) |
|
||||||
|
V::bits(V::XFFFF0000) |
|
||||||
|
Rr::bits(Rr::RANDOM) |
|
||||||
|
Fi::bits(0) |
|
||||||
|
Ve::bits(Ve::FIXED) |
|
||||||
|
Ee::bits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c1, c0, 0" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register value
|
||||||
|
*/
|
||||||
|
static void write(access_t const v)
|
||||||
|
{
|
||||||
|
asm volatile ("mcr p15, 0, %[v], c1, c0, 0" :: [v]"r"(v) : );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation table base control register
|
||||||
|
*/
|
||||||
|
struct Ttbcr : Register<32>
|
||||||
|
{
|
||||||
|
struct N : Bitfield<0, 3> { }; /* base address width */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register, only in privileged CPU mode
|
||||||
|
*/
|
||||||
|
static void write(access_t const v) {
|
||||||
|
asm volatile ("mcr p15, 0, %[v], c2, c0, 2" :: [v]"r"(v) : ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c2, c0, 2" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel() { return N::bits(TTBCR_N); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation table base register 0
|
||||||
|
*/
|
||||||
|
struct Ttbr0 : Register<32>
|
||||||
|
{
|
||||||
|
struct Irgn_1 : Bitfield<0,1> /* inner cachable mode */
|
||||||
|
{
|
||||||
|
enum { NON_CACHEABLE = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S : Bitfield<1,1> { }; /* shareable */
|
||||||
|
|
||||||
|
struct Rgn : Bitfield<3, 2> /* outer cachable attributes */
|
||||||
|
{
|
||||||
|
enum { NON_CACHEABLE = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ba : Bitfield<14-TTBCR_N, 18+TTBCR_N> { }; /* translation
|
||||||
|
* table base */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register, only in privileged CPU mode
|
||||||
|
*/
|
||||||
|
static void write(access_t const v) {
|
||||||
|
asm volatile ("mcr p15, 0, %[v], c2, c0, 0" :: [v]"r"(v) : ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c2, c0, 0" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*
|
||||||
|
* \param sect_table pointer to initial section table
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel(addr_t const sect_table)
|
||||||
|
{
|
||||||
|
return S::bits(0) |
|
||||||
|
Irgn_1::bits(Irgn_1::NON_CACHEABLE) |
|
||||||
|
Rgn::bits(Rgn::NON_CACHEABLE) |
|
||||||
|
Ba::masked((addr_t)sect_table);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Domain access control register
|
||||||
|
*/
|
||||||
|
struct Dacr : Register<32>
|
||||||
|
{
|
||||||
|
enum Dx_values { NO_ACCESS = 0, CLIENT = 1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access values for the 16 available domains
|
||||||
|
*/
|
||||||
|
struct D0 : Bitfield<0,2> { };
|
||||||
|
struct D1 : Bitfield<2,2> { };
|
||||||
|
struct D2 : Bitfield<4,2> { };
|
||||||
|
struct D3 : Bitfield<6,2> { };
|
||||||
|
struct D4 : Bitfield<8,2> { };
|
||||||
|
struct D5 : Bitfield<10,2> { };
|
||||||
|
struct D6 : Bitfield<12,2> { };
|
||||||
|
struct D7 : Bitfield<14,2> { };
|
||||||
|
struct D8 : Bitfield<16,2> { };
|
||||||
|
struct D9 : Bitfield<18,2> { };
|
||||||
|
struct D10 : Bitfield<20,2> { };
|
||||||
|
struct D11 : Bitfield<22,2> { };
|
||||||
|
struct D12 : Bitfield<24,2> { };
|
||||||
|
struct D13 : Bitfield<26,2> { };
|
||||||
|
struct D14 : Bitfield<28,2> { };
|
||||||
|
struct D15 : Bitfield<30,2> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register, only in privileged CPU mode
|
||||||
|
*/
|
||||||
|
static void write(access_t const v) {
|
||||||
|
asm volatile ("mcr p15, 0, %[v], c3, c0, 0" :: [v]"r"(v) : ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize for Genodes operational mode
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel()
|
||||||
|
{
|
||||||
|
return D0::bits(CLIENT) | D1::bits(NO_ACCESS) |
|
||||||
|
D2::bits(NO_ACCESS) | D3::bits(NO_ACCESS) |
|
||||||
|
D4::bits(NO_ACCESS) | D5::bits(NO_ACCESS) |
|
||||||
|
D6::bits(NO_ACCESS) | D7::bits(NO_ACCESS) |
|
||||||
|
D8::bits(NO_ACCESS) | D9::bits(NO_ACCESS) |
|
||||||
|
D10::bits(NO_ACCESS) | D11::bits(NO_ACCESS) |
|
||||||
|
D12::bits(NO_ACCESS) | D13::bits(NO_ACCESS) |
|
||||||
|
D14::bits(NO_ACCESS) | D15::bits(NO_ACCESS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context identification register
|
||||||
|
*/
|
||||||
|
struct Cidr : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Write register value
|
||||||
|
*/
|
||||||
|
static void write(access_t const v)
|
||||||
|
{
|
||||||
|
asm volatile ("mcr p15, 0, %[v], c13, c0, 1" :: [v]"r"(v) : );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c13, c0, 1" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program status register
|
||||||
|
*/
|
||||||
|
struct Psr : Register<32>
|
||||||
|
{
|
||||||
|
struct M : Bitfield<0,5> /* processor mode */
|
||||||
|
{
|
||||||
|
enum { USER = 0b10000, SUPERVISOR = 0b10011 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct T : Bitfield<5,1> /* instruction state */
|
||||||
|
{
|
||||||
|
enum { ARM = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct F : Bitfield<6,1> { }; /* FIQ disable */
|
||||||
|
struct I : Bitfield<7,1> { }; /* IRQ disable */
|
||||||
|
struct A : Bitfield<8,1> { }; /* asynchronous abort disable */
|
||||||
|
|
||||||
|
struct E : Bitfield<9,1> /* load/store endianess */
|
||||||
|
{
|
||||||
|
enum { LITTLE = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct J : Bitfield<24,1> /* instruction state */
|
||||||
|
{
|
||||||
|
enum { ARM = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrs %[v], cpsr" : [v] "=r" (v) : : );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write register
|
||||||
|
*/
|
||||||
|
static void write(access_t const v) {
|
||||||
|
asm volatile ("msr cpsr, %[v]" : : [v] "r" (v) : ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial value for a user execution context with trustzone
|
||||||
|
*
|
||||||
|
* FIXME: This function should not be declared in 'Arm' but in
|
||||||
|
* 'Arm_v7', but for now the declaration is necessary
|
||||||
|
* because of 'User_context::User_context()'.
|
||||||
|
*/
|
||||||
|
inline static access_t init_user_with_trustzone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial value for an userland execution context
|
||||||
|
*/
|
||||||
|
static access_t init_user()
|
||||||
|
{
|
||||||
|
return M::bits(M::USER) |
|
||||||
|
T::bits(T::ARM) |
|
||||||
|
F::bits(1) |
|
||||||
|
I::bits(0) |
|
||||||
|
A::bits(1) |
|
||||||
|
E::bits(E::LITTLE) |
|
||||||
|
J::bits(J::ARM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initial value for the kernel execution context
|
||||||
|
*/
|
||||||
|
static access_t init_kernel()
|
||||||
|
{
|
||||||
|
return M::bits(M::SUPERVISOR) |
|
||||||
|
T::bits(T::ARM) |
|
||||||
|
F::bits(1) |
|
||||||
|
I::bits(1) |
|
||||||
|
A::bits(1) |
|
||||||
|
E::bits(E::LITTLE) |
|
||||||
|
J::bits(J::ARM);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common parts of fault status registers
|
||||||
|
*/
|
||||||
|
struct Fsr : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Fault status encoding
|
||||||
|
*/
|
||||||
|
enum Fault_status
|
||||||
|
{
|
||||||
|
SECTION_TRANSLATION = 5,
|
||||||
|
PAGE_TRANSLATION = 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Fs_3_0 : Bitfield<0, 4> { }; /* fault status */
|
||||||
|
struct Fs_4 : Bitfield<10, 1> { }; /* fault status */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruction fault status register
|
||||||
|
*/
|
||||||
|
struct Ifsr : Fsr
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c5, c0, 1" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read fault status
|
||||||
|
*/
|
||||||
|
static Fault_status fault_status()
|
||||||
|
{
|
||||||
|
access_t const v = read();
|
||||||
|
return (Fault_status)(Fs_3_0::get(v) |
|
||||||
|
(Fs_4::get(v) << Fs_3_0::WIDTH));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data fault status register
|
||||||
|
*/
|
||||||
|
struct Dfsr : Fsr
|
||||||
|
{
|
||||||
|
struct Wnr : Bitfield<11, 1> { }; /* write not read bit */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c5, c0, 0" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read fault status
|
||||||
|
*/
|
||||||
|
static Fault_status fault_status() {
|
||||||
|
access_t const v = read();
|
||||||
|
return (Fault_status)(Fs_3_0::get(v) |
|
||||||
|
(Fs_4::get(v) << Fs_3_0::WIDTH));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data fault address register
|
||||||
|
*/
|
||||||
|
struct Dfar : Register<32>
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read() {
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c6, c0, 0" : [v]"=r"(v) :: );
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend basic CPU state by members relevant for 'base-hw' only
|
||||||
|
*/
|
||||||
|
struct Context : Cpu_state
|
||||||
|
{
|
||||||
|
/**********************************************************
|
||||||
|
** The offset and width of any of these classmembers is **
|
||||||
|
** silently expected to be this way by several assembly **
|
||||||
|
** files. So take care if you attempt to change them. **
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
uint32_t cidr; /* context ID register backup */
|
||||||
|
uint32_t section_table; /* base address of applied section table */
|
||||||
|
|
||||||
|
/***************
|
||||||
|
** Accessors **
|
||||||
|
***************/
|
||||||
|
|
||||||
|
void software_tlb(addr_t const st) { section_table = st; }
|
||||||
|
|
||||||
|
addr_t software_tlb() const { return section_table; }
|
||||||
|
|
||||||
|
void protection_domain(unsigned const id) { cidr = id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An usermode execution state
|
||||||
|
*/
|
||||||
|
struct User_context : Context
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
User_context();
|
||||||
|
|
||||||
|
/***************************************************
|
||||||
|
** Communication between user and context holder **
|
||||||
|
***************************************************/
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a general purpose register
|
||||||
|
*
|
||||||
|
* \param id ID of the targeted register
|
||||||
|
* \param v Holds register value if this returns 1
|
||||||
|
*/
|
||||||
|
bool get_gpr(unsigned id, unsigned & v) const
|
||||||
|
{
|
||||||
|
switch(id)
|
||||||
|
{
|
||||||
|
case 0: v = r0; return 1;
|
||||||
|
case 1: v = r1; return 1;
|
||||||
|
case 2: v = r2; return 1;
|
||||||
|
case 3: v = r3; return 1;
|
||||||
|
case 4: v = r4; return 1;
|
||||||
|
case 5: v = r5; return 1;
|
||||||
|
case 6: v = r6; return 1;
|
||||||
|
case 7: v = r7; return 1;
|
||||||
|
case 8: v = r8; return 1;
|
||||||
|
case 9: v = r9; return 1;
|
||||||
|
case 10: v = r10; return 1;
|
||||||
|
case 11: v = r11; return 1;
|
||||||
|
case 12: v = r12; return 1;
|
||||||
|
case 13: v = sp; return 1;
|
||||||
|
case 14: v = lr; return 1;
|
||||||
|
case 15: v = ip; return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override a general purpose register
|
||||||
|
*
|
||||||
|
* \param id ID of the targeted register
|
||||||
|
* \param v Has been written to register if this returns 1
|
||||||
|
*/
|
||||||
|
bool set_gpr(unsigned id, unsigned const v)
|
||||||
|
{
|
||||||
|
switch(id)
|
||||||
|
{
|
||||||
|
case 0: r0 = v; return 1;
|
||||||
|
case 1: r1 = v; return 1;
|
||||||
|
case 2: r2 = v; return 1;
|
||||||
|
case 3: r3 = v; return 1;
|
||||||
|
case 4: r4 = v; return 1;
|
||||||
|
case 5: r5 = v; return 1;
|
||||||
|
case 6: r6 = v; return 1;
|
||||||
|
case 7: r7 = v; return 1;
|
||||||
|
case 8: r8 = v; return 1;
|
||||||
|
case 9: r9 = v; return 1;
|
||||||
|
case 10: r10 = v; return 1;
|
||||||
|
case 11: r11 = v; return 1;
|
||||||
|
case 12: r12 = v; return 1;
|
||||||
|
case 13: sp = v; return 1;
|
||||||
|
case 14: lr = v; return 1;
|
||||||
|
case 15: ip = v; return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a pagefault has occured due to a translation miss
|
||||||
|
*
|
||||||
|
* \param va holds the virtual fault-address if this returns 1
|
||||||
|
* \param w wether it is a write fault if this returns 1
|
||||||
|
*/
|
||||||
|
bool translation_miss(addr_t & va, bool & w) const
|
||||||
|
{
|
||||||
|
/* determine fault type */
|
||||||
|
switch (cpu_exception) {
|
||||||
|
|
||||||
|
case PREFETCH_ABORT: {
|
||||||
|
|
||||||
|
/* check if fault was caused by a translation miss */
|
||||||
|
Ifsr::Fault_status const fs = Ifsr::fault_status();
|
||||||
|
if (fs == Ifsr::SECTION_TRANSLATION ||
|
||||||
|
fs == Ifsr::PAGE_TRANSLATION)
|
||||||
|
{
|
||||||
|
/* fetch fault data */
|
||||||
|
w = 0;
|
||||||
|
va = ip;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0; }
|
||||||
|
|
||||||
|
case DATA_ABORT: {
|
||||||
|
|
||||||
|
/* check if fault was caused by translation miss */
|
||||||
|
Dfsr::Fault_status const fs = Dfsr::fault_status();
|
||||||
|
if(fs == Dfsr::SECTION_TRANSLATION ||
|
||||||
|
fs == Dfsr::PAGE_TRANSLATION)
|
||||||
|
{
|
||||||
|
/* fetch fault data */
|
||||||
|
Dfsr::access_t const dfsr = Dfsr::read();
|
||||||
|
w = Dfsr::Wnr::get(dfsr);
|
||||||
|
va = Dfar::read();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0; }
|
||||||
|
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all instruction caches
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline)) static void flush_instr_caches() {
|
||||||
|
asm volatile ("mcr p15, 0, %[rd], c7, c5, 0" :: [rd]"r"(0) : ); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all data caches
|
||||||
|
*/
|
||||||
|
inline static void flush_data_caches();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all caches
|
||||||
|
*/
|
||||||
|
static void flush_caches()
|
||||||
|
{
|
||||||
|
flush_data_caches();
|
||||||
|
flush_instr_caches();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate all TLB entries of one address space
|
||||||
|
*
|
||||||
|
* \param pid ID of the targeted address space
|
||||||
|
*/
|
||||||
|
static void flush_tlb_by_pid(unsigned const pid)
|
||||||
|
{
|
||||||
|
asm volatile ("mcr p15, 0, %[pid], c8, c7, 2" :: [pid]"r"(pid) : );
|
||||||
|
flush_caches();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate all TLB entries
|
||||||
|
*/
|
||||||
|
static void flush_tlb()
|
||||||
|
{
|
||||||
|
asm volatile ("mcr p15, 0, %[rd], c8, c7, 0" :: [rd]"r"(0) : );
|
||||||
|
flush_caches();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM__CPU_H_ */
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Driver for Cortex A9 section tables as software TLB
|
* \brief Driver for ARM section tables
|
||||||
* \author Martin Stein
|
* \author Martin Stein
|
||||||
* \date 2012-02-22
|
* \date 2012-02-22
|
||||||
*/
|
*/
|
||||||
@ -11,20 +11,21 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE__DRIVERS__CPU__CORTEX_A9__SECTION_TABLE_H_
|
#ifndef _INCLUDE__ARM__SECTION_TABLE_H_
|
||||||
#define _INCLUDE__DRIVERS__CPU__CORTEX_A9__SECTION_TABLE_H_
|
#define _INCLUDE__ARM__SECTION_TABLE_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <util/register.h>
|
#include <util/register.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
#include <cortex_a9/cpu/core.h>
|
|
||||||
|
|
||||||
namespace Genode
|
namespace Arm
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if 'p' is aligned to 1 << 'alignm_log2'
|
* Check if 'p' is aligned to 1 << 'alignm_log2'
|
||||||
*/
|
*/
|
||||||
bool inline aligned(addr_t const a, unsigned long const alignm_log2)
|
inline bool aligned(addr_t const a, unsigned long const alignm_log2)
|
||||||
{
|
{
|
||||||
return a == ((a >> alignm_log2) << alignm_log2);
|
return a == ((a >> alignm_log2) << alignm_log2);
|
||||||
}
|
}
|
||||||
@ -53,7 +54,6 @@ namespace Genode
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Permission configuration according to given access rights
|
* Permission configuration according to given access rights
|
||||||
*
|
*
|
||||||
@ -77,7 +77,7 @@ namespace Genode
|
|||||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||||
|
|
||||||
Ap_1_0::bits(Ap_1_0::USER_NO_ACCESS) | /* -k */
|
Ap_1_0::bits(Ap_1_0::USER_NO_ACCESS) | /* -k */
|
||||||
Ap_2::bits(Ap_2::KERNEL_RO_ACCESS) }, {
|
Ap_2::bits(Ap_2::KERNEL_RO_ACCESS) }, {
|
||||||
|
|
||||||
Ap_1_0::bits(Ap_1_0::KERNEL_AND_USER_SAME_ACCESS) | /* w- */
|
Ap_1_0::bits(Ap_1_0::KERNEL_AND_USER_SAME_ACCESS) | /* w- */
|
||||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||||
@ -91,11 +91,11 @@ namespace Genode
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cortex A9 second level translation table
|
* Second level translation table
|
||||||
*
|
*
|
||||||
* A table is dedicated to either secure or non-secure mode. All
|
* A table is dedicated to either secure or non-secure mode. All
|
||||||
* translations done by this table apply domain 0. They are not shareable
|
* translations done by this table apply to domain 0. They are not
|
||||||
* and have zero-filled memory region attributes.
|
* shareable and have zero-filled memory region attributes.
|
||||||
*/
|
*/
|
||||||
class Page_table
|
class Page_table
|
||||||
{
|
{
|
||||||
@ -197,32 +197,6 @@ namespace Genode
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Large page descriptor structure
|
|
||||||
*
|
|
||||||
* Must always occur as group of 16 consecutive copies, this groups
|
|
||||||
* must be aligned on a 16 word boundary (Represents 64KB = 16 *
|
|
||||||
* Small page size)
|
|
||||||
*/
|
|
||||||
struct Large_page : Descriptor
|
|
||||||
{
|
|
||||||
enum { VIRT_SIZE_LOG2 = _64KB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1) };
|
|
||||||
|
|
||||||
struct B : Bitfield<2, 1> { }; /* part of the memory region attributes */
|
|
||||||
struct C : Bitfield<3, 1> { }; /* part of the memory region attributes */
|
|
||||||
struct Ap_1_0 : Bitfield<4, 2>, /* access permission bits [1:0] */
|
|
||||||
Ap_1_0_bitfield { };
|
|
||||||
struct Ap_2 : Bitfield<9, 1>, /* access permission bits [2] */
|
|
||||||
Ap_2_bitfield { };
|
|
||||||
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
|
||||||
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
|
||||||
struct Tex : Bitfield<12, 3> { }; /* part of the memory region attributes */
|
|
||||||
struct Xn : Bitfield<15, 1> { }; /* execute never bit */
|
|
||||||
struct Pa_31_16 : Bitfield<16, 16> { }; /* physical address bits [31:16] */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small page descriptor structure
|
* Small page descriptor structure
|
||||||
*/
|
*/
|
||||||
@ -234,17 +208,17 @@ namespace Genode
|
|||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Xn : Bitfield<0, 1> { }; /* execute never bit */
|
struct Xn : Bitfield<0, 1> { }; /* execute never */
|
||||||
struct B : Bitfield<2, 1> { }; /* part of the memory region attributes */
|
struct B : Bitfield<2, 1> { }; /* mem region attr. */
|
||||||
struct C : Bitfield<3, 1> { }; /* part of the memory region attributes */
|
struct C : Bitfield<3, 1> { }; /* mem region attr. */
|
||||||
struct Ap_1_0 : Bitfield<4, 2>, /* access permission bits [1:0] */
|
struct Ap_1_0 : Bitfield<4, 2>, /* access permission */
|
||||||
Ap_1_0_bitfield { };
|
Ap_1_0_bitfield { };
|
||||||
struct Tex : Bitfield<6, 3> { }; /* part of the memory region attributes */
|
struct Tex : Bitfield<6, 3> { }; /* mem region attr. */
|
||||||
struct Ap_2 : Bitfield<9, 1>, /* access permission bits [2] */
|
struct Ap_2 : Bitfield<9, 1>, /* access permission */
|
||||||
Ap_2_bitfield { };
|
Ap_2_bitfield { };
|
||||||
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
struct S : Bitfield<10, 1> { }; /* shareable bit */
|
||||||
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
struct Ng : Bitfield<11, 1> { }; /* not global bit */
|
||||||
struct Pa_31_12 : Bitfield<12, 20> { }; /* physical address bits [31:12] */
|
struct Pa_31_12 : Bitfield<12, 20> { }; /* physical base */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -259,12 +233,11 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Get entry index by virtual offset
|
* Get entry index by virtual offset
|
||||||
*
|
*
|
||||||
* \param i is overridden with the resulting index
|
* \param i is overridden with the index if call returns 0
|
||||||
* \param vo virtual offset relative to the virtual table base
|
* \param vo virtual offset relative to the virtual table base
|
||||||
*
|
*
|
||||||
* \retval 0 on success
|
* \retval 0 on success
|
||||||
* \retval <0 If virtual offset couldn't be resolved.
|
* \retval <0 translation failed
|
||||||
* In this case 'i' reside invalid
|
|
||||||
*/
|
*/
|
||||||
int _index_by_vo (unsigned long & i, addr_t const vo) const
|
int _index_by_vo (unsigned long & i, addr_t const vo) const
|
||||||
{
|
{
|
||||||
@ -286,13 +259,12 @@ namespace Genode
|
|||||||
Page_table()
|
Page_table()
|
||||||
{
|
{
|
||||||
/* check table alignment */
|
/* check table alignment */
|
||||||
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
if (!aligned((addr_t)this, ALIGNM_LOG2) ||
|
||||||
|| (addr_t)this != (addr_t)_entries)
|
(addr_t)this != (addr_t)_entries)
|
||||||
{
|
{
|
||||||
PDBG("Insufficient table alignment");
|
PDBG("Insufficient table alignment");
|
||||||
while (1) ;
|
while (1) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start with an empty table */
|
/* start with an empty table */
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||||
Descriptor::invalidate(_entries[i]);
|
Descriptor::invalidate(_entries[i]);
|
||||||
@ -341,9 +313,9 @@ namespace Genode
|
|||||||
{
|
{
|
||||||
/* compose new descriptor value */
|
/* compose new descriptor value */
|
||||||
Descriptor::access_t entry =
|
Descriptor::access_t entry =
|
||||||
access_permission_bits<Small_page>(w, x, k)
|
access_permission_bits<Small_page>(w, x, k) |
|
||||||
| Small_page::Ng::bits(!g)
|
Small_page::Ng::bits(!g) |
|
||||||
| Small_page::Pa_31_12::masked(pa);
|
Small_page::Pa_31_12::masked(pa);
|
||||||
Descriptor::type(entry, Descriptor::SMALL_PAGE);
|
Descriptor::type(entry, Descriptor::SMALL_PAGE);
|
||||||
|
|
||||||
/* check if we can we write to the targeted entry */
|
/* check if we can we write to the targeted entry */
|
||||||
@ -375,7 +347,7 @@ namespace Genode
|
|||||||
* represented by this table
|
* represented by this table
|
||||||
* \param size region size
|
* \param size region size
|
||||||
*/
|
*/
|
||||||
void remove_region (addr_t const vo, size_t const size)
|
void remove_region(addr_t const vo, size_t const size)
|
||||||
{
|
{
|
||||||
/* traverse all possibly affected entries */
|
/* traverse all possibly affected entries */
|
||||||
addr_t residual_vo = vo;
|
addr_t residual_vo = vo;
|
||||||
@ -389,30 +361,28 @@ namespace Genode
|
|||||||
if (_index_by_vo(i, residual_vo)) return;
|
if (_index_by_vo(i, residual_vo)) return;
|
||||||
|
|
||||||
/* update current entry and recalculate residual region */
|
/* update current entry and recalculate residual region */
|
||||||
switch (Descriptor::type(_entries[i]))
|
switch (Descriptor::type(_entries[i])) {
|
||||||
{
|
|
||||||
case Descriptor::FAULT:
|
case Descriptor::FAULT: {
|
||||||
{
|
|
||||||
residual_vo = (residual_vo & Fault::VIRT_BASE_MASK)
|
residual_vo = (residual_vo & Fault::VIRT_BASE_MASK)
|
||||||
+ Fault::VIRT_SIZE;
|
+ Fault::VIRT_SIZE;
|
||||||
break;
|
break; }
|
||||||
}
|
|
||||||
case Descriptor::SMALL_PAGE:
|
case Descriptor::SMALL_PAGE: {
|
||||||
{
|
|
||||||
residual_vo = (residual_vo & Small_page::VIRT_BASE_MASK)
|
residual_vo = (residual_vo & Small_page::VIRT_BASE_MASK)
|
||||||
+ Small_page::VIRT_SIZE;
|
+ Small_page::VIRT_SIZE;
|
||||||
Descriptor::invalidate(_entries[i]);
|
Descriptor::invalidate(_entries[i]);
|
||||||
break;
|
break; }
|
||||||
}
|
|
||||||
case Descriptor::LARGE_PAGE:
|
case Descriptor::LARGE_PAGE: {
|
||||||
{
|
|
||||||
PDBG("Removal of large pages not implemented");
|
PDBG("Removal of large pages not implemented");
|
||||||
while (1) ;
|
while (1) ;
|
||||||
break;
|
break; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,13 +399,13 @@ namespace Genode
|
|||||||
} __attribute__((aligned(1<<Page_table::ALIGNM_LOG2)));
|
} __attribute__((aligned(1<<Page_table::ALIGNM_LOG2)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cortex A9 first level translation table
|
* First level translation table
|
||||||
*
|
*
|
||||||
* A table is dedicated to either secure or non-secure mode. All
|
* A table is dedicated to either secure or non-secure mode. All
|
||||||
* translations done by this table apply domain 0. They are not shareable
|
* translations done by this table apply to domain 0. They are not
|
||||||
* and have zero-filled memory region attributes. The size of this table is
|
* shareable and have zero-filled memory region attributes. The size
|
||||||
* fixed to such a value that this table translates a space wich is
|
* of this table is fixed to such a value that this table translates
|
||||||
* addressable by 32 bit.
|
* a space wich is addressable by 32 bit.
|
||||||
*/
|
*/
|
||||||
class Section_table
|
class Section_table
|
||||||
{
|
{
|
||||||
@ -443,6 +413,8 @@ namespace Genode
|
|||||||
_16KB_LOG2 = 14,
|
_16KB_LOG2 = 14,
|
||||||
_1MB_LOG2 = 20,
|
_1MB_LOG2 = 20,
|
||||||
_16MB_LOG2 = 24,
|
_16MB_LOG2 = 24,
|
||||||
|
|
||||||
|
DOMAIN = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -458,12 +430,10 @@ namespace Genode
|
|||||||
|
|
||||||
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
||||||
|
|
||||||
MAX_TRANSL_SIZE_LOG2 = 20,
|
MAX_PAGE_SIZE_LOG2 = 20,
|
||||||
MIN_TRANSL_SIZE_LOG2 = 12,
|
MIN_PAGE_SIZE_LOG2 = 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A first level translation descriptor
|
* A first level translation descriptor
|
||||||
*/
|
*/
|
||||||
@ -474,8 +444,8 @@ namespace Genode
|
|||||||
*/
|
*/
|
||||||
enum Type { FAULT, PAGE_TABLE, SECTION, SUPERSECTION };
|
enum Type { FAULT, PAGE_TABLE, SECTION, SUPERSECTION };
|
||||||
|
|
||||||
struct Type_1 : Bitfield<0, 2> { }; /* entry type encoding 1 */
|
struct Type_1 : Bitfield<0, 2> { }; /* entry type code 1 */
|
||||||
struct Type_2 : Bitfield<18, 1> { }; /* entry type encoding 2 */
|
struct Type_2 : Bitfield<18, 1> { }; /* entry type code 2 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get descriptor type of 'v'
|
* Get descriptor type of 'v'
|
||||||
@ -538,43 +508,23 @@ namespace Genode
|
|||||||
*/
|
*/
|
||||||
struct Page_table_descriptor : Descriptor
|
struct Page_table_descriptor : Descriptor
|
||||||
{
|
{
|
||||||
struct Ns : Bitfield<3, 1> { }; /* non-secure bit */
|
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||||
struct Domain : Bitfield<5, 4> { }; /* domain field */
|
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical base */
|
||||||
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical address bits [31:10] */
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Page_table * const pt)
|
||||||
|
{
|
||||||
|
access_t v = Domain::bits(DOMAIN) |
|
||||||
|
Pa_31_10::masked((addr_t)pt);
|
||||||
|
Descriptor::type(v, Descriptor::PAGE_TABLE);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supersection-descriptor structure
|
* Section translation descriptor
|
||||||
*
|
|
||||||
* Must always occur as group of 16 consecutive copies, this groups
|
|
||||||
* must be aligned on a 16 word boundary.
|
|
||||||
*/
|
|
||||||
struct Supersection : Descriptor
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
VIRT_SIZE_LOG2 = _16MB_LOG2,
|
|
||||||
VIRT_SIZE = 1 << VIRT_SIZE_LOG2,
|
|
||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct B : Bitfield<2, 1> { }; /* part of the memory region attributes */
|
|
||||||
struct C : Bitfield<3, 1> { }; /* part of the memory region attributes */
|
|
||||||
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
|
||||||
struct Pa_39_36 : Bitfield<5, 4> { }; /* extendend physical address bits [39:36] */
|
|
||||||
struct Ap_1_0 : Bitfield<10, 2>, /* access permission bits [1:0] */
|
|
||||||
Ap_1_0_bitfield { };
|
|
||||||
struct Tex : Bitfield<12, 3> { }; /* part of the memory region attributes */
|
|
||||||
struct Ap_2 : Bitfield<15, 1>, /* access permission bits [2] */
|
|
||||||
Ap_2_bitfield { };
|
|
||||||
struct S : Bitfield<16, 1> { }; /* shareable bit */
|
|
||||||
struct Ng : Bitfield<17, 1> { }; /* not global bit */
|
|
||||||
struct Ns : Bitfield<19, 1> { }; /* non-secure bit */
|
|
||||||
struct Pa_35_32 : Bitfield<20, 4> { }; /* extendend physical address bits [35:32] */
|
|
||||||
struct Pa_31_24 : Bitfield<24, 8> { }; /* physical address bits [31:24] */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Section-descriptor structure
|
|
||||||
*/
|
*/
|
||||||
struct Section : Descriptor
|
struct Section : Descriptor
|
||||||
{
|
{
|
||||||
@ -584,29 +534,42 @@ namespace Genode
|
|||||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct B : Bitfield<2, 1> { }; /* part of the memory region attributes */
|
struct B : Bitfield<2, 1> { }; /* mem. region attr. */
|
||||||
struct C : Bitfield<3, 1> { }; /* part of the memory region attributes */
|
struct C : Bitfield<3, 1> { }; /* mem. region attr. */
|
||||||
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
||||||
struct Domain : Bitfield<5, 4> { }; /* domain field */
|
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||||
struct Ap_1_0 : Bitfield<10, 2>, /* access permission bits [1:0] */
|
struct Ap_1_0 : Bitfield<10, 2>, /* access permission */
|
||||||
Ap_1_0_bitfield { };
|
Ap_1_0_bitfield { };
|
||||||
struct Tex : Bitfield<12, 3> { }; /* part of the memory region attributes */
|
struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */
|
||||||
struct Ap_2 : Bitfield<15, 1>, /* access permission bits [2] */
|
struct Ap_2 : Bitfield<15, 1>, /* access permission */
|
||||||
Ap_2_bitfield { };
|
Ap_2_bitfield { };
|
||||||
struct S : Bitfield<16, 1> { }; /* shareable bit */
|
struct S : Bitfield<16, 1> { }; /* shared */
|
||||||
struct Ng : Bitfield<17, 1> { }; /* not global bit */
|
struct Ng : Bitfield<17, 1> { }; /* not global */
|
||||||
struct Ns : Bitfield<19, 1> { }; /* non-secure bit */
|
struct Pa_31_20 : Bitfield<20, 12> { }; /* physical base */
|
||||||
struct Pa_31_20 : Bitfield<20, 12> { }; /* physical address bits [31:20] */
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(bool const w, bool const x,
|
||||||
|
bool const k, bool const g,
|
||||||
|
addr_t const pa)
|
||||||
|
{
|
||||||
|
access_t v = access_permission_bits<Section>(w, x, k) |
|
||||||
|
Domain::bits(DOMAIN) |
|
||||||
|
Ng::bits(!g) |
|
||||||
|
Pa_31_20::masked(pa);
|
||||||
|
Descriptor::type(v, Descriptor::SECTION);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
/* table payload, must be the first member of this class */
|
/* table payload, must be the first member of this class */
|
||||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||||
|
|
||||||
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 };
|
||||||
|
|
||||||
/* if this table dedicated to secure mode or to non-secure mode */
|
|
||||||
bool _secure;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get entry index by virtual offset
|
* Get entry index by virtual offset
|
||||||
*
|
*
|
||||||
@ -628,18 +591,17 @@ namespace Genode
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a table that adopts current secure mode status
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Section_table() : _secure(Cortex_a9::secure_mode_active())
|
Section_table()
|
||||||
{
|
{
|
||||||
/* check table alignment */
|
/* check for appropriate positioning of the table */
|
||||||
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
||||||
|| (addr_t)this != (addr_t)_entries)
|
|| (addr_t)this != (addr_t)_entries)
|
||||||
{
|
{
|
||||||
PDBG("Insufficient table alignment");
|
PDBG("Insufficient table alignment");
|
||||||
while (1) ;
|
while (1) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* start with an empty table */
|
/* start with an empty table */
|
||||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||||
Descriptor::invalidate(_entries[i]);
|
Descriptor::invalidate(_entries[i]);
|
||||||
@ -657,6 +619,8 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Insert one atomic translation into this table
|
* Insert one atomic translation into this table
|
||||||
*
|
*
|
||||||
|
* \param ST platform specific section-table type
|
||||||
|
* \param st platform specific section table
|
||||||
* \param vo offset of the virtual region represented
|
* \param vo offset of the virtual region represented
|
||||||
* by the translation within the virtual
|
* by the translation within the virtual
|
||||||
* region represented by this table
|
* region represented by this table
|
||||||
@ -691,19 +655,23 @@ namespace Genode
|
|||||||
* spans the the same virtual range and is not a link to another
|
* spans the the same virtual range and is not a link to another
|
||||||
* table level.
|
* table level.
|
||||||
*/
|
*/
|
||||||
|
template <typename ST>
|
||||||
unsigned long insert_translation(addr_t const vo, addr_t const pa,
|
unsigned long insert_translation(addr_t const vo, addr_t const pa,
|
||||||
unsigned long const size_log2,
|
unsigned long const size_log2,
|
||||||
bool const w, bool const x,
|
bool const w, bool const x,
|
||||||
bool const k, bool const g,
|
bool const k, bool const g,
|
||||||
|
ST * const st,
|
||||||
void * const extra_space = 0)
|
void * const extra_space = 0)
|
||||||
{
|
{
|
||||||
|
typedef typename ST::Section Section;
|
||||||
|
typedef typename ST::Page_table_descriptor Page_table_descriptor;
|
||||||
|
|
||||||
/* validate virtual address */
|
/* validate virtual address */
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
if (_index_by_vo (i, vo)) {
|
if (_index_by_vo (i, vo)) {
|
||||||
PDBG("Invalid virtual offset");
|
PDBG("Invalid virtual offset");
|
||||||
while (1) ;
|
while (1) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* select descriptor type by translation size */
|
/* select descriptor type by translation size */
|
||||||
if (size_log2 < Section::VIRT_SIZE_LOG2)
|
if (size_log2 < Section::VIRT_SIZE_LOG2)
|
||||||
{
|
{
|
||||||
@ -723,11 +691,9 @@ namespace Genode
|
|||||||
}
|
}
|
||||||
/* create and link page table */
|
/* create and link page table */
|
||||||
pt = new (extra_space) Page_table();
|
pt = new (extra_space) Page_table();
|
||||||
_entries[i] = Page_table_descriptor::Ns::bits(!_secure)
|
_entries[i] = Page_table_descriptor::create(pt, st);
|
||||||
| Page_table_descriptor::Pa_31_10::masked((addr_t)pt);
|
|
||||||
Descriptor::type(_entries[i], Descriptor::PAGE_TABLE);
|
|
||||||
}
|
}
|
||||||
/* Request additional memory to create a page table */
|
/* request additional memory to create a page table */
|
||||||
else return Page_table::SIZE_LOG2;
|
else return Page_table::SIZE_LOG2;
|
||||||
|
|
||||||
/* insert translation */
|
/* insert translation */
|
||||||
@ -738,12 +704,8 @@ namespace Genode
|
|||||||
if (size_log2 == Section::VIRT_SIZE_LOG2)
|
if (size_log2 == Section::VIRT_SIZE_LOG2)
|
||||||
{
|
{
|
||||||
/* compose section descriptor */
|
/* compose section descriptor */
|
||||||
Descriptor::access_t entry =
|
Descriptor::access_t entry = Section::create(w, x, k,
|
||||||
access_permission_bits<Section>(w, x, k)
|
g, pa, st);
|
||||||
| Section::Ns::bits(!_secure)
|
|
||||||
| Section::Ng::bits(!g)
|
|
||||||
| Section::Pa_31_20::masked(pa);
|
|
||||||
Descriptor::type(entry, Descriptor::SECTION);
|
|
||||||
|
|
||||||
/* check if we can we write to the targeted entry */
|
/* check if we can we write to the targeted entry */
|
||||||
if (Descriptor::valid(_entries[i]))
|
if (Descriptor::valid(_entries[i]))
|
||||||
@ -774,7 +736,7 @@ namespace Genode
|
|||||||
* represented by this table
|
* represented by this table
|
||||||
* \param size region size
|
* \param size region size
|
||||||
*/
|
*/
|
||||||
void remove_region (addr_t const vo, size_t const size)
|
void remove_region(addr_t const vo, size_t const size)
|
||||||
{
|
{
|
||||||
/* traverse all possibly affected entries */
|
/* traverse all possibly affected entries */
|
||||||
addr_t residual_vo = vo;
|
addr_t residual_vo = vo;
|
||||||
@ -806,7 +768,7 @@ namespace Genode
|
|||||||
- Section::Pa_31_20::masked(residual_vo);
|
- Section::Pa_31_20::masked(residual_vo);
|
||||||
pt->remove_region(pt_vo, residual_size);
|
pt->remove_region(pt_vo, residual_size);
|
||||||
|
|
||||||
/* Recalculate residual region */
|
/* recalculate residual region */
|
||||||
residual_vo = (residual_vo & Page_table::VIRT_BASE_MASK)
|
residual_vo = (residual_vo & Page_table::VIRT_BASE_MASK)
|
||||||
+ Page_table::VIRT_SIZE;
|
+ Page_table::VIRT_SIZE;
|
||||||
break;
|
break;
|
||||||
@ -834,6 +796,7 @@ namespace Genode
|
|||||||
* \param base base of regained mem portion if method returns 1
|
* \param base base of regained mem portion if method returns 1
|
||||||
* \param s size of regained mem portion if method returns 1
|
* \param s size of regained mem portion if method returns 1
|
||||||
*
|
*
|
||||||
|
* \retval 1 successfully regained memory
|
||||||
* \retval 0 no more memory to regain
|
* \retval 0 no more memory to regain
|
||||||
*/
|
*/
|
||||||
bool regain_memory (void * & base, size_t & s)
|
bool regain_memory (void * & base, size_t & s)
|
||||||
@ -860,5 +823,5 @@ namespace Genode
|
|||||||
} __attribute__((aligned(1<<Section_table::ALIGNM_LOG2)));
|
} __attribute__((aligned(1<<Section_table::ALIGNM_LOG2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _INCLUDE__DRIVERS__CPU__CORTEX_A9__SECTION_TABLE_H_ */
|
#endif /* _INCLUDE__ARM__SECTION_TABLE_H_ */
|
||||||
|
|
174
base-hw/src/core/include/arm/v6/cpu.h
Normal file
174
base-hw/src/core/include/arm/v6/cpu.h
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* \brief Simple driver for the ARMv6 CPU core
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__ARM_V6__CPU_H_
|
||||||
|
#define _INCLUDE__ARM_V6__CPU_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/cpu.h>
|
||||||
|
|
||||||
|
namespace Arm_v6
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARMv6 core
|
||||||
|
*/
|
||||||
|
struct Cpu : Arm::Cpu
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Cache type register
|
||||||
|
*/
|
||||||
|
struct Ctr : Arm::Cpu::Ctr
|
||||||
|
{
|
||||||
|
struct P : Bitfield<23, 1> { }; /* page mapping restriction on */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System control register
|
||||||
|
*/
|
||||||
|
struct Sctlr : Arm::Cpu::Sctlr
|
||||||
|
{
|
||||||
|
struct W : Bitfield<3,1> { }; /* enable write buffer */
|
||||||
|
|
||||||
|
struct Unused_0 : Bitfield<4,3> { }; /* shall be ones */
|
||||||
|
|
||||||
|
struct B : Bitfield<7,1> /* Memory system endianess */
|
||||||
|
{
|
||||||
|
enum { LITTLE = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct S : Bitfield<8,1> { }; /* enbale MMU protection */
|
||||||
|
struct R : Bitfield<9,1> { }; /* enbale ROM protection */
|
||||||
|
struct L4 : Bitfield<15,1> { }; /* raise T bit on LOAD-to-PC */
|
||||||
|
struct Dt : Bitfield<16,1> { }; /* global data TCM enable */
|
||||||
|
struct It : Bitfield<18,1> { }; /* global instruction TCM enable */
|
||||||
|
struct U : Bitfield<22,1> { }; /* enable unaligned data access */
|
||||||
|
struct Xp : Bitfield<23,1> { }; /* disable subpage AP bits */
|
||||||
|
|
||||||
|
struct Unused_1 : Bitfield<26,6> { }; /* shall not be modified */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get static base value for writes
|
||||||
|
*/
|
||||||
|
static access_t base_value() {
|
||||||
|
return Unused_0::reg_mask() | Unused_1::masked(read()); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel()
|
||||||
|
{
|
||||||
|
return base_value() |
|
||||||
|
Arm::Cpu::Sctlr::init_virt_kernel() |
|
||||||
|
W::bits(0) |
|
||||||
|
B::bits(B::LITTLE) |
|
||||||
|
S::bits(0) |
|
||||||
|
R::bits(0) |
|
||||||
|
L4::bits(0) |
|
||||||
|
Dt::bits(0) |
|
||||||
|
It::bits(0) |
|
||||||
|
U::bits(0) |
|
||||||
|
Xp::bits(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the initial kernel entry
|
||||||
|
*/
|
||||||
|
static access_t init_phys_kernel()
|
||||||
|
{
|
||||||
|
return base_value() |
|
||||||
|
Arm::Cpu::Sctlr::init_phys_kernel() |
|
||||||
|
W::bits(0) |
|
||||||
|
B::bits(B::LITTLE) |
|
||||||
|
S::bits(0) |
|
||||||
|
R::bits(0) |
|
||||||
|
L4::bits(0) |
|
||||||
|
Dt::bits(1) |
|
||||||
|
It::bits(1) |
|
||||||
|
U::bits(0) |
|
||||||
|
Xp::bits(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation table base control register 0
|
||||||
|
*/
|
||||||
|
struct Ttbr0 : Arm::Cpu::Ttbr0
|
||||||
|
{
|
||||||
|
struct P : Bitfield<2,1> { }; /* memory controller ECC enabled */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*
|
||||||
|
* \param section_table initial section table
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel(addr_t const sect_table)
|
||||||
|
{
|
||||||
|
return Arm::Cpu::Ttbr0::init_virt_kernel(sect_table) |
|
||||||
|
P::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If page descriptor bits [13:12] are restricted
|
||||||
|
*/
|
||||||
|
static bool restricted_page_mappings() {
|
||||||
|
return Ctr::P::get(Ctr::read()); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure this module appropriately for the first kernel run
|
||||||
|
*/
|
||||||
|
static void init_phys_kernel()
|
||||||
|
{
|
||||||
|
::Board::prepare_kernel();
|
||||||
|
Sctlr::write(Sctlr::init_phys_kernel());
|
||||||
|
flush_tlb();
|
||||||
|
|
||||||
|
/* check for mapping restrictions */
|
||||||
|
if (restricted_page_mappings()) {
|
||||||
|
PDBG("Insufficient driver for page tables");
|
||||||
|
while (1) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to the virtual mode in kernel
|
||||||
|
*
|
||||||
|
* \param section_table section translation table of the initial
|
||||||
|
* address space this function switches to
|
||||||
|
* \param process_id process ID of the initial address space
|
||||||
|
*/
|
||||||
|
static void init_virt_kernel(addr_t const section_table,
|
||||||
|
unsigned long const process_id)
|
||||||
|
{
|
||||||
|
Cidr::write(process_id);
|
||||||
|
Dacr::write(Dacr::init_virt_kernel());
|
||||||
|
Ttbr0::write(Ttbr0::init_virt_kernel(section_table));
|
||||||
|
Ttbcr::write(Ttbcr::init_virt_kernel());
|
||||||
|
Sctlr::write(Sctlr::init_virt_kernel());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Arm::Cpu::flush_data_caches() {
|
||||||
|
asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); }
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM_V6__CPU_H_ */
|
||||||
|
|
85
base-hw/src/core/include/arm/v6/section_table.h
Normal file
85
base-hw/src/core/include/arm/v6/section_table.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* \brief Driver for ARMv6 section tables
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-02-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__ARM_V6__SECTION_TABLE_H_
|
||||||
|
#define _INCLUDE__ARM_V6__SECTION_TABLE_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/section_table.h>
|
||||||
|
|
||||||
|
namespace Arm_v6
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First level translation table
|
||||||
|
*/
|
||||||
|
class Section_table : public Arm::Section_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to second level translation-table
|
||||||
|
*/
|
||||||
|
struct Page_table_descriptor : Arm::Section_table::Page_table_descriptor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Arm::Page_table * const pt,
|
||||||
|
Section_table *)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::Page_table_descriptor::create(pt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section translation descriptor
|
||||||
|
*/
|
||||||
|
struct Section : Arm::Section_table::Section
|
||||||
|
{
|
||||||
|
struct P : Bitfield<9, 1> { }; /* enable ECC */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(bool const w, bool const x,
|
||||||
|
bool const k, bool const g,
|
||||||
|
addr_t const pa,
|
||||||
|
Section_table *)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::Section::create(w, x, k, g, pa) |
|
||||||
|
P::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert one atomic translation into this table
|
||||||
|
*
|
||||||
|
* For details see 'Arm::Section_table::insert_translation'
|
||||||
|
*/
|
||||||
|
unsigned long insert_translation(addr_t const vo, addr_t const pa,
|
||||||
|
unsigned long const size_log2,
|
||||||
|
bool const w, bool const x,
|
||||||
|
bool const k, bool const g,
|
||||||
|
void * const extra_space = 0)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::
|
||||||
|
insert_translation<Section_table>(vo, pa, size_log2, w,
|
||||||
|
x, k, g, this, extra_space);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM_V6__SECTION_TABLE_H_ */
|
||||||
|
|
309
base-hw/src/core/include/arm/v7/cpu.h
Normal file
309
base-hw/src/core/include/arm/v7/cpu.h
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
/*
|
||||||
|
* \brief Simple driver for the ARMv7 core
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2011-11-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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__ARM_V7__CPU_H_
|
||||||
|
#define _INCLUDE__ARM_V7__CPU_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/cpu.h>
|
||||||
|
|
||||||
|
namespace Arm_v7
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARMv7 core
|
||||||
|
*/
|
||||||
|
struct Cpu : Arm::Cpu
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Secure configuration register
|
||||||
|
*/
|
||||||
|
struct Scr : Register<32>
|
||||||
|
{
|
||||||
|
struct Ns : Bitfield<0, 1> { }; /* not secure */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read register value
|
||||||
|
*/
|
||||||
|
static access_t read()
|
||||||
|
{
|
||||||
|
access_t v;
|
||||||
|
asm volatile ("mrc p15, 0, %[v], c1, c1, 0" : [v]"=r"(v) ::);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-secure access control register
|
||||||
|
*/
|
||||||
|
struct Nsacr : Register<32>
|
||||||
|
{
|
||||||
|
/************************************************
|
||||||
|
** Coprocessor 0-13 non-secure acccess enable **
|
||||||
|
************************************************/
|
||||||
|
|
||||||
|
struct Cpnsae10 : Bitfield<10, 1> { };
|
||||||
|
struct Cpnsae11 : Bitfield<11, 1> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System control register
|
||||||
|
*/
|
||||||
|
struct Sctlr : Arm::Cpu::Sctlr
|
||||||
|
{
|
||||||
|
struct Unused_0 : Bitfield<3,4> { }; /* shall be ~0 */
|
||||||
|
struct Sw : Bitfield<10,1> { }; /* support SWP and SWPB */
|
||||||
|
struct Unused_1 : Bitfield<16,1> { }; /* shall be ~0 */
|
||||||
|
struct Ha : Bitfield<17,1> { }; /* enable HW access flag */
|
||||||
|
struct Unused_2 : Bitfield<18,1> { }; /* shall be ~0 */
|
||||||
|
struct Unused_3 : Bitfield<22,2> { }; /* shall be ~0 */
|
||||||
|
struct Nmfi : Bitfield<27,1> { }; /* FIQs are non-maskable */
|
||||||
|
struct Tre : Bitfield<28,1> { }; /* remap TEX[2:1] for OS */
|
||||||
|
|
||||||
|
struct Afe : Bitfield<29,1> /* translation access perm. mode */
|
||||||
|
{
|
||||||
|
enum { FULL_RANGE_OF_PERMISSIONS = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Te : Bitfield<30,1> { }; /* do exceptions in Thumb state */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static base value
|
||||||
|
*/
|
||||||
|
static access_t base_value()
|
||||||
|
{
|
||||||
|
return Unused_0::bits(~0) |
|
||||||
|
Unused_1::bits(~0) |
|
||||||
|
Unused_2::bits(~0) |
|
||||||
|
Unused_3::bits(~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the first kernel run
|
||||||
|
*/
|
||||||
|
static access_t init_phys_kernel()
|
||||||
|
{
|
||||||
|
return base_value() |
|
||||||
|
Arm::Cpu::Sctlr::init_virt_kernel() |
|
||||||
|
Sw::bits(0) |
|
||||||
|
Ha::bits(0) |
|
||||||
|
Nmfi::bits(0) |
|
||||||
|
Tre::bits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel()
|
||||||
|
{
|
||||||
|
return base_value() |
|
||||||
|
Arm::Cpu::Sctlr::init_virt_kernel() |
|
||||||
|
Sw::bits(0) |
|
||||||
|
Ha::bits(0) |
|
||||||
|
Nmfi::bits(0) |
|
||||||
|
Tre::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation table base register 0
|
||||||
|
*/
|
||||||
|
struct Ttbr0 : Arm::Cpu::Ttbr0
|
||||||
|
{
|
||||||
|
struct Nos : Bitfield<6,1> { }; /* not outer shareable */
|
||||||
|
|
||||||
|
struct Irgn_0 : Bitfield<6,1> /* inner cachable mode */
|
||||||
|
{
|
||||||
|
enum { NON_CACHEABLE = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*
|
||||||
|
* \param sect_table pointer to initial section table
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel(addr_t const sect_table)
|
||||||
|
{
|
||||||
|
return Arm::Cpu::Ttbr0::init_virt_kernel(sect_table) |
|
||||||
|
Nos::bits(0) |
|
||||||
|
Irgn_0::bits(Irgn_0::NON_CACHEABLE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translation table base control register
|
||||||
|
*/
|
||||||
|
struct Ttbcr : Arm::Cpu::Ttbcr
|
||||||
|
{
|
||||||
|
struct Pd0 : Bitfield<4,1> { }; /* disable walk for TTBR0 */
|
||||||
|
struct Pd1 : Bitfield<5,1> { }; /* disable walk for TTBR1 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for the switch to virtual mode in kernel
|
||||||
|
*/
|
||||||
|
static access_t init_virt_kernel()
|
||||||
|
{
|
||||||
|
return Arm::Cpu::Ttbcr::init_virt_kernel() |
|
||||||
|
Pd0::bits(0) |
|
||||||
|
Pd1::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to the virtual mode in kernel
|
||||||
|
*
|
||||||
|
* \param section_table section translation table of the initial
|
||||||
|
* address space this function switches to
|
||||||
|
* \param process_id process ID of the initial address space
|
||||||
|
*/
|
||||||
|
static void init_virt_kernel(addr_t const section_table,
|
||||||
|
unsigned long const process_id)
|
||||||
|
{
|
||||||
|
Cidr::write(process_id);
|
||||||
|
Dacr::write(Dacr::init_virt_kernel());
|
||||||
|
Ttbr0::write(Ttbr0::init_virt_kernel(section_table));
|
||||||
|
Ttbcr::write(Ttbcr::init_virt_kernel());
|
||||||
|
Sctlr::write(Sctlr::init_virt_kernel());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure this module appropriately for the first kernel run
|
||||||
|
*/
|
||||||
|
static void init_phys_kernel()
|
||||||
|
{
|
||||||
|
Psr::write(Psr::init_kernel());
|
||||||
|
flush_tlb();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wether we are in secure mode
|
||||||
|
*/
|
||||||
|
static bool secure_mode()
|
||||||
|
{
|
||||||
|
if (!Board::SECURITY_EXTENSION) return 0;
|
||||||
|
return !Cpu::Scr::Ns::get(Cpu::Scr::read());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************
|
||||||
|
** Trustzone specific API **
|
||||||
|
******************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the exception-vector's base-address for the monitor mode
|
||||||
|
* software stack.
|
||||||
|
*
|
||||||
|
* \param addr address of the exception vector's base
|
||||||
|
*/
|
||||||
|
static inline void mon_exception_entry_at(addr_t const addr)
|
||||||
|
{
|
||||||
|
asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable access of co-processors cp10 and cp11 from non-secure mode.
|
||||||
|
*/
|
||||||
|
static inline void allow_coprocessor_nonsecure()
|
||||||
|
{
|
||||||
|
Nsacr::access_t rd = Nsacr::Cpnsae10::bits(1) |
|
||||||
|
Nsacr::Cpnsae11::bits(1);
|
||||||
|
asm volatile ("mcr p15, 0, %[rd], c1, c1, 2" : : [rd] "r" (rd));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************
|
||||||
|
** Arm::Cpu **
|
||||||
|
**************/
|
||||||
|
|
||||||
|
void Arm::Cpu::flush_data_caches()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* FIXME This routine is taken from the ARMv7 reference manual by
|
||||||
|
* applying the inline-assembly framework and replacing 'Loop1'
|
||||||
|
* with '1:', 'Loop2' with '2:', 'Loop3' with '3:', 'Skip'
|
||||||
|
* with '4:' and 'Finished' with '5:'. It might get implemented
|
||||||
|
* with more beauty.
|
||||||
|
*/
|
||||||
|
asm volatile (
|
||||||
|
"mrc p15, 1, r0, c0, c0, 1\n" /* read CLIDR into R0 */
|
||||||
|
"ands r3, r0, #0x7000000\n"
|
||||||
|
"mov r3, r3, lsr #23\n" /* cache level value (naturally aligned) */
|
||||||
|
"beq 5f\n"
|
||||||
|
"mov r10, #0\n"
|
||||||
|
|
||||||
|
"1:\n"
|
||||||
|
|
||||||
|
"add r2, r10, r10, lsr #1\n" /* work out 3 x cachelevel */
|
||||||
|
"mov r1, r0, lsr r2\n" /* bottom 3 bits are the Cache type for this level */
|
||||||
|
"and r1, r1, #7\n" /* get those 3 bits alone */
|
||||||
|
"cmp r1, #2\n"
|
||||||
|
"blt 4f\n" /* no cache or only instruction cache at this level */
|
||||||
|
"mcr p15, 2, r10, c0, c0, 0\n" /* write CSSELR from R10 */
|
||||||
|
"isb\n" /* ISB to sync the change to the CCSIDR */
|
||||||
|
"mrc p15, 1, r1, c0, c0, 0\n" /* read current CCSIDR to R1 */
|
||||||
|
"and r2, r1, #0x7\n" /* extract the line length field */
|
||||||
|
"add r2, r2, #4\n" /* add 4 for the line length offset (log2 16 bytes) */
|
||||||
|
"ldr r4, =0x3ff\n"
|
||||||
|
"ands r4, r4, r1, lsr #3\n" /* R4 is the max number on the way size (right aligned) */
|
||||||
|
"clz r5, r4\n" /* R5 is the bit position of the way size increment */
|
||||||
|
"mov r9, r4\n" /* R9 working copy of the max way size (right aligned) */
|
||||||
|
|
||||||
|
"2:\n"
|
||||||
|
|
||||||
|
"ldr r7, =0x00007fff\n"
|
||||||
|
"ands r7, r7, r1, lsr #13\n" /* R7 is the max number of the index size (right aligned) */
|
||||||
|
|
||||||
|
"3:\n"
|
||||||
|
|
||||||
|
"orr r11, r10, r9, lsl r5\n" /* factor in the way number and cache number into R11 */
|
||||||
|
"orr r11, r11, r7, lsl r2\n" /* factor in the index number */
|
||||||
|
"mcr p15, 0, r11, c7, c10, 2\n" /* DCCSW, clean by set/way */
|
||||||
|
"subs r7, r7, #1\n" /* decrement the index */
|
||||||
|
"bge 3b\n"
|
||||||
|
"subs r9, r9, #1\n" /* decrement the way number */
|
||||||
|
"bge 2b\n"
|
||||||
|
|
||||||
|
"4:\n"
|
||||||
|
|
||||||
|
"add r10, r10, #2\n" /* increment the cache number */
|
||||||
|
"cmp r3, r10\n"
|
||||||
|
"bgt 1b\n"
|
||||||
|
"dsb\n"
|
||||||
|
|
||||||
|
"5:\n"
|
||||||
|
|
||||||
|
::: "r0", "r1", "r2", "r3", "r4",
|
||||||
|
"r5", "r7", "r9", "r10", "r11");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Arm::Cpu::Psr::access_t Arm::Cpu::Psr::init_user_with_trustzone()
|
||||||
|
{
|
||||||
|
return M::bits(M::USER) |
|
||||||
|
T::bits(T::ARM) |
|
||||||
|
F::bits(0) |
|
||||||
|
I::bits(1) |
|
||||||
|
A::bits(1) |
|
||||||
|
E::bits(E::LITTLE) |
|
||||||
|
J::bits(J::ARM);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM_V7__CPU_H_ */
|
||||||
|
|
107
base-hw/src/core/include/arm/v7/section_table.h
Normal file
107
base-hw/src/core/include/arm/v7/section_table.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* \brief Driver for ARMv7 section tables
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-02-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__ARM_V7__SECTION_TABLE_H_
|
||||||
|
#define _INCLUDE__ARM_V7__SECTION_TABLE_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/section_table.h>
|
||||||
|
#include <arm/v7/cpu.h>
|
||||||
|
|
||||||
|
namespace Arm_v7
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARMv7 first level translation table
|
||||||
|
*/
|
||||||
|
class Section_table : public Arm::Section_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link to second level translation-table
|
||||||
|
*/
|
||||||
|
struct Page_table_descriptor : Arm::Section_table::Page_table_descriptor
|
||||||
|
{
|
||||||
|
struct Ns : Bitfield<3, 1> { }; /* non-secure bit */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(Arm::Page_table * const pt,
|
||||||
|
Section_table * const st)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::Page_table_descriptor::create(pt) |
|
||||||
|
Ns::bits(!st->secure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Section translation descriptor
|
||||||
|
*/
|
||||||
|
struct Section : Arm::Section_table::Section
|
||||||
|
{
|
||||||
|
struct Ns : Bitfield<19, 1> { }; /* non-secure bit */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compose descriptor value
|
||||||
|
*/
|
||||||
|
static access_t create(bool const w, bool const x,
|
||||||
|
bool const k, bool const g,
|
||||||
|
addr_t const pa,
|
||||||
|
Section_table * const st)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::Section::create(w, x, k, g, pa) |
|
||||||
|
Ns::bits(!st->secure());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/* if this table is dedicated to secure mode or to non-secure mode */
|
||||||
|
bool _secure;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Section_table() : _secure(Arm_v7::Cpu::secure_mode()) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert one atomic translation into this table
|
||||||
|
*
|
||||||
|
* For details see 'Arm::Section_table::insert_translation'
|
||||||
|
*/
|
||||||
|
unsigned long insert_translation(addr_t const vo, addr_t const pa,
|
||||||
|
unsigned long const size_log2,
|
||||||
|
bool const w, bool const x,
|
||||||
|
bool const k, bool const g,
|
||||||
|
void * const extra_space = 0)
|
||||||
|
{
|
||||||
|
return Arm::Section_table::
|
||||||
|
insert_translation<Section_table>(vo, pa, size_log2, w,
|
||||||
|
x, k, g, this, extra_space);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************
|
||||||
|
** Accessors **
|
||||||
|
***************/
|
||||||
|
|
||||||
|
bool secure() { return _secure; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__ARM_V7__SECTION_TABLE_H_ */
|
||||||
|
|
54
base-hw/src/core/include/cortex_a9/cpu.h
Normal file
54
base-hw/src/core/include/cortex_a9/cpu.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* \brief Simple driver for the Cortex A9
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2011-11-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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__CORTEX_A9__CPU_H_
|
||||||
|
#define _INCLUDE__CORTEX_A9__CPU_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <arm/v7/cpu.h>
|
||||||
|
|
||||||
|
namespace Cortex_a9
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cortex A9 CPU
|
||||||
|
*/
|
||||||
|
struct Cpu : Arm_v7::Cpu
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* common */
|
||||||
|
CLK = Board::CORTEX_A9_CLOCK, /* CPU interface clock */
|
||||||
|
PERIPH_CLK = CLK, /* clock for CPU internal components */
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__CORTEX_A9__CPU_H_ */
|
||||||
|
|
@ -1,683 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Simple Driver for the ARM Cortex A9
|
|
||||||
* \author Martin stein
|
|
||||||
* \date 2011-11-03
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2012 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__CORTEX_A9__CPU__CORE_H_
|
|
||||||
#define _INCLUDE__CORTEX_A9__CPU__CORE_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/register.h>
|
|
||||||
#include <util/mmio.h>
|
|
||||||
#include <drivers/board.h>
|
|
||||||
#include <cpu/cpu_state.h>
|
|
||||||
#include <cortex_a9/cpu/timer.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
class Section_table;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cortex A9 driver
|
|
||||||
*/
|
|
||||||
struct Cortex_a9
|
|
||||||
{
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* common */
|
|
||||||
DATA_ACCESS_ALIGNM = 4,
|
|
||||||
CLK = Board::CORTEX_A9_CLOCK, /* CPU interface clock */
|
|
||||||
PERIPH_CLK = CLK, /* clock for CPU internal components */
|
|
||||||
MIN_PAGE_SIZE_LOG2 = 12,
|
|
||||||
MAX_PAGE_SIZE_LOG2 = 20,
|
|
||||||
HIGHEST_EXCEPTION_ENTRY = 0xffff0000,
|
|
||||||
|
|
||||||
/* 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,
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CPU local timer module
|
|
||||||
*/
|
|
||||||
class Private_timer : public Cortex_a9_timer<PRIVATE_TIMER_CLK>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum { IRQ = PRIVATE_TIMER_IRQ };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Private_timer() :
|
|
||||||
Cortex_a9_timer<PRIVATE_TIMER_CLK>(PRIVATE_TIMER_MMIO_BASE)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Cortex_a9_timer<PERIPH_CLK> Timer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common parts of fault status registers
|
|
||||||
*/
|
|
||||||
struct Fsr : Register<32>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Fault status encoding
|
|
||||||
*/
|
|
||||||
enum Fault_status {
|
|
||||||
SECTION_TRANSLATION_FAULT = 5,
|
|
||||||
PAGE_TRANSLATION_FAULT = 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Fs_3_0 : Bitfield<0, 4> { }; /* fault status bits [3:0] */
|
|
||||||
struct Fs_4 : Bitfield<10, 1> { }; /* fault status bits [4] */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instruction fault status register
|
|
||||||
*/
|
|
||||||
struct Ifsr : Fsr
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Read register
|
|
||||||
*/
|
|
||||||
static access_t read() {
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c5, c0, 1\n" : [v]"=r"(v) :: );
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read fault status
|
|
||||||
*/
|
|
||||||
static Fault_status fault_status() {
|
|
||||||
access_t const v = read();
|
|
||||||
return (Fault_status)(Fs_3_0::get(v) |
|
|
||||||
(Fs_4::get(v) << Fs_3_0::WIDTH));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instruction fault address register
|
|
||||||
*/
|
|
||||||
struct Ifar : Register<32>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Read register
|
|
||||||
*/
|
|
||||||
static access_t read() {
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c6, c0, 2\n" : [v]"=r"(v) :: );
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data fault status register
|
|
||||||
*/
|
|
||||||
struct Dfsr : Fsr
|
|
||||||
{
|
|
||||||
struct Wnr : Bitfield<11, 1> { }; /* write not read bit */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read register
|
|
||||||
*/
|
|
||||||
static access_t read() {
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c5, c0, 0\n" : [v]"=r"(v) :: );
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read fault status
|
|
||||||
*/
|
|
||||||
static Fault_status fault_status() {
|
|
||||||
access_t const v = read();
|
|
||||||
return (Fault_status)(Fs_3_0::get(v) | (4<<Fs_4::get(v)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data fault address register
|
|
||||||
*/
|
|
||||||
struct Dfar : Register<32>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Read register
|
|
||||||
*/
|
|
||||||
static access_t read() {
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c6, c0, 0\n" : [v]"=r"(v) :: );
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process identification register
|
|
||||||
*/
|
|
||||||
struct Contextidr : Register<32>
|
|
||||||
{
|
|
||||||
struct Asid : Bitfield<0,8> { }; /* ID part used by MMU */
|
|
||||||
struct Procid : Bitfield<8,24> { }; /* ID part used by debug/trace */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register
|
|
||||||
*/
|
|
||||||
static void write(access_t const v)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[v], c13, c0, 1\n" :: [v]"r"(v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A system control register
|
|
||||||
*/
|
|
||||||
struct Sctlr : Register<32>
|
|
||||||
{
|
|
||||||
struct M : Bitfield<0,1> { }; /* MMU enable bit */
|
|
||||||
struct C : Bitfield<2,1> { }; /* cache enable bit */
|
|
||||||
struct I : Bitfield<12,1> { }; /* instruction cache enable bit */
|
|
||||||
struct V : Bitfield<13,1> { }; /* exception vectors bit */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read whole register
|
|
||||||
*/
|
|
||||||
static access_t read()
|
|
||||||
{
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c1, c0, 0\n" : [v]"=r"(v) :: );
|
|
||||||
return v;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register
|
|
||||||
*/
|
|
||||||
static void write(access_t const v)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[v], c1, c0, 0\n" :: [v]"r"(v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The translation table base control register
|
|
||||||
*/
|
|
||||||
struct Ttbcr : Register<32>
|
|
||||||
{
|
|
||||||
/**********************
|
|
||||||
** Always available **
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
struct N : Bitfield<0,3> /* base address width */
|
|
||||||
{ };
|
|
||||||
|
|
||||||
/********************************************
|
|
||||||
** Only available with security extension **
|
|
||||||
********************************************/
|
|
||||||
|
|
||||||
struct Pd0 : Bitfield<4,1> { }; /* translation table walk disable bit for TTBR0 */
|
|
||||||
struct Pd1 : Bitfield<5,1> { }; /* translation table walk disable bit for TTBR1 */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read whole register, only in privileged CPU mode
|
|
||||||
*/
|
|
||||||
static access_t read();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register, only in privileged CPU mode
|
|
||||||
*/
|
|
||||||
static void write(access_t const v)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[v], c2, c0, 2" :: [v]"r"(v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The domain access control register
|
|
||||||
*/
|
|
||||||
struct Dacr : Register<32>
|
|
||||||
{
|
|
||||||
enum Dx_values { NO_ACCESS = 0, CLIENT = 1, MANAGER = 3 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access values for the 16 available domains
|
|
||||||
*/
|
|
||||||
struct D0 : Bitfield<0,2> { };
|
|
||||||
struct D1 : Bitfield<2,2> { };
|
|
||||||
struct D2 : Bitfield<4,2> { };
|
|
||||||
struct D3 : Bitfield<6,2> { };
|
|
||||||
struct D4 : Bitfield<8,2> { };
|
|
||||||
struct D5 : Bitfield<10,2> { };
|
|
||||||
struct D6 : Bitfield<12,2> { };
|
|
||||||
struct D7 : Bitfield<14,2> { };
|
|
||||||
struct D8 : Bitfield<16,2> { };
|
|
||||||
struct D9 : Bitfield<18,2> { };
|
|
||||||
struct D10 : Bitfield<20,2> { };
|
|
||||||
struct D11 : Bitfield<22,2> { };
|
|
||||||
struct D12 : Bitfield<24,2> { };
|
|
||||||
struct D13 : Bitfield<26,2> { };
|
|
||||||
struct D14 : Bitfield<28,2> { };
|
|
||||||
struct D15 : Bitfield<30,2> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register, only in privileged CPU mode
|
|
||||||
*/
|
|
||||||
static void write(access_t const v)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[v], c3, c0, 0" :: [v]"r"(v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translation table base register 0
|
|
||||||
*
|
|
||||||
* Typically for process specific spaces, references first level
|
|
||||||
* table with a size between 128B and 16KB according to 'Ttbcr::N'.
|
|
||||||
*/
|
|
||||||
struct Ttbr0 : Register<32>
|
|
||||||
{
|
|
||||||
/**********************
|
|
||||||
** Always available **
|
|
||||||
**********************/
|
|
||||||
|
|
||||||
struct S : Bitfield<1,1> { }; /* shareable bit */
|
|
||||||
struct Rgn : Bitfield<3,2> /* region bits */
|
|
||||||
{
|
|
||||||
enum { OUTER_NON_CACHEABLE = 0b00,
|
|
||||||
OUTER_WBACK_WALLOCATE_CACHEABLE = 0b01,
|
|
||||||
OUTER_WTHROUGH_CACHEABLE = 0b10,
|
|
||||||
OUTER_WBACK_NO_WALLCOATE_CACHEABLE = 0b11,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Nos : Bitfield<5,1> { }; /* not outer shareable bit */
|
|
||||||
struct Base_address : Bitfield<14,18> { }; /* translation table base address
|
|
||||||
(Driver supports only 16KB alignment) */
|
|
||||||
|
|
||||||
/***********************************************
|
|
||||||
** Only available without security extension **
|
|
||||||
***********************************************/
|
|
||||||
|
|
||||||
struct C : Bitfield<0,1> { }; /* cacheable bit */
|
|
||||||
|
|
||||||
/********************************************
|
|
||||||
** Only available with security extension **
|
|
||||||
********************************************/
|
|
||||||
|
|
||||||
struct Irgn_1 : Bitfield<0,1> /* inner region bit 0 */
|
|
||||||
{
|
|
||||||
enum { INNER_NON_CACHEABLE = 0b0,
|
|
||||||
INNER_WBACK_WALLOCATE_CACHEABLE = 0b0,
|
|
||||||
INNER_WTHROUGH_CACHEABLE = 0b1,
|
|
||||||
INNER_WBACK_NO_WALLCOATE_CACHEABLE = 0b1,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Irgn_0 : Bitfield<6,1> /* inner region bit 1 */
|
|
||||||
{
|
|
||||||
enum { INNER_NON_CACHEABLE = 0b0,
|
|
||||||
INNER_WBACK_WALLOCATE_CACHEABLE = 0b1,
|
|
||||||
INNER_WTHROUGH_CACHEABLE = 0b0,
|
|
||||||
INNER_WBACK_NO_WALLCOATE_CACHEABLE = 0b1,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read whole register, only in privileged CPU mode
|
|
||||||
*/
|
|
||||||
static access_t read();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register, only in privileged CPU mode
|
|
||||||
*/
|
|
||||||
static void write(access_t const v)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[v], c2, c0, 0" :: [v]"r"(v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A current program status register
|
|
||||||
*/
|
|
||||||
struct Cpsr : Register<32>
|
|
||||||
{
|
|
||||||
struct M : Bitfield<0,5> /* processor mode */
|
|
||||||
{
|
|
||||||
enum { /* <Privileged>, <Description> */
|
|
||||||
USER = 0b10000, /* 0, application code */
|
|
||||||
FIQ = 0b10001, /* 1, entered at fast interrupt */
|
|
||||||
IRQ = 0b10010, /* 1, entered at normal interrupt */
|
|
||||||
SUPERVISOR = 0b10011, /* 1, most kernel code */
|
|
||||||
MONITOR = 0b10110, /* 1, a secure mode, switch sec./non-sec. */
|
|
||||||
ABORT = 0b10111, /* 1, entered at aborts */
|
|
||||||
UNDEFINED = 0b11011, /* 1, entered at instruction-related error */
|
|
||||||
SYSTEM = 0b11111, /* 1, applications that require privileged */
|
|
||||||
};
|
|
||||||
};
|
|
||||||
struct F : Bitfield<6,1> { }; /* fast interrupt request disable */
|
|
||||||
struct I : Bitfield<7,1> { }; /* interrupt request disable */
|
|
||||||
struct A : Bitfield<8,1> { }; /* asynchronous abort disable */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read whole register
|
|
||||||
*/
|
|
||||||
static access_t read()
|
|
||||||
{
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrs %[v], cpsr\n" : [v] "=r" (v) : : );
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write whole register
|
|
||||||
*/
|
|
||||||
static void write(access_t & v)
|
|
||||||
{
|
|
||||||
asm volatile ("msr cpsr, %[v]\n" : : [v] "r" (v) : );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Secure configuration register
|
|
||||||
*/
|
|
||||||
struct Scr : Register<32>
|
|
||||||
{
|
|
||||||
struct Ns : Bitfield<0, 1> { }; /* non secure bit */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read whole register
|
|
||||||
*/
|
|
||||||
static access_t read()
|
|
||||||
{
|
|
||||||
access_t v;
|
|
||||||
asm volatile ("mrc p15, 0, %[v], c1, c1, 0" : [v]"=r"(v) ::);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Context : Cpu_state
|
|
||||||
{
|
|
||||||
uint32_t contextidr; /* contextidr register backup, offset 18*4 */
|
|
||||||
uint32_t section_table; /* base address of applied section table,
|
|
||||||
* offset 19*4 */
|
|
||||||
|
|
||||||
/***************
|
|
||||||
** Accessors **
|
|
||||||
***************/
|
|
||||||
|
|
||||||
void software_tlb(Section_table * const st) {
|
|
||||||
section_table = (addr_t)st; }
|
|
||||||
|
|
||||||
Section_table * software_tlb() const {
|
|
||||||
return (Section_table *)section_table; }
|
|
||||||
|
|
||||||
void instruction_ptr(addr_t const p) { ip = p; }
|
|
||||||
|
|
||||||
addr_t instruction_ptr() const { return ip; }
|
|
||||||
|
|
||||||
void return_ptr(addr_t const p) { lr = p; }
|
|
||||||
|
|
||||||
void stack_ptr(addr_t const p) { sp = p; }
|
|
||||||
|
|
||||||
void protection_domain(unsigned const id) { contextidr = id; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read a general purpose register
|
|
||||||
*
|
|
||||||
* \param id ID of the targeted register
|
|
||||||
* \param v Holds register value if this returns 1
|
|
||||||
*/
|
|
||||||
bool get_gpr(unsigned id, unsigned & v) const
|
|
||||||
{
|
|
||||||
if (id >= MAX_GPR) return 0;
|
|
||||||
v = r[id];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override a general purpose register
|
|
||||||
*
|
|
||||||
* \param id ID of the targeted register
|
|
||||||
* \param v Has been written to register if this returns 1
|
|
||||||
*/
|
|
||||||
bool set_gpr(unsigned id, unsigned const v)
|
|
||||||
{
|
|
||||||
if (id >= MAX_GPR) return 0;
|
|
||||||
r[id] = v;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An usermode execution state
|
|
||||||
*/
|
|
||||||
struct User_context : Context
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
User_context(void);
|
|
||||||
|
|
||||||
/***************************************************
|
|
||||||
** Communication between user and context holder **
|
|
||||||
***************************************************/
|
|
||||||
|
|
||||||
void user_arg_0(unsigned const arg) { r[0] = arg; }
|
|
||||||
void user_arg_1(unsigned const arg) { r[1] = arg; }
|
|
||||||
void user_arg_2(unsigned const arg) { r[2] = arg; }
|
|
||||||
void user_arg_3(unsigned const arg) { r[3] = arg; }
|
|
||||||
void user_arg_4(unsigned const arg) { r[4] = arg; }
|
|
||||||
void user_arg_5(unsigned const arg) { r[5] = arg; }
|
|
||||||
void user_arg_6(unsigned const arg) { r[6] = arg; }
|
|
||||||
void user_arg_7(unsigned const arg) { r[7] = arg; }
|
|
||||||
unsigned user_arg_0() const { return r[0]; }
|
|
||||||
unsigned user_arg_1() const { return r[1]; }
|
|
||||||
unsigned user_arg_2() const { return r[2]; }
|
|
||||||
unsigned user_arg_3() const { return r[3]; }
|
|
||||||
unsigned user_arg_4() const { return r[4]; }
|
|
||||||
unsigned user_arg_5() const { return r[5]; }
|
|
||||||
unsigned user_arg_6() const { return r[6]; }
|
|
||||||
unsigned user_arg_7() const { return r[7]; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does a pagefault exist and originate from a lack of translation?
|
|
||||||
*
|
|
||||||
* \param va Holds the virtual fault-address if this
|
|
||||||
* function returns 1
|
|
||||||
* \param w Indicates wether the fault was caused by a write
|
|
||||||
* access if this function returns 1
|
|
||||||
*/
|
|
||||||
bool translation_miss(addr_t & va, bool & w) const
|
|
||||||
{
|
|
||||||
/* determine fault type */
|
|
||||||
switch (cpu_exception)
|
|
||||||
{
|
|
||||||
case PREFETCH_ABORT: {
|
|
||||||
|
|
||||||
/* check if fault was caused by a translation miss */
|
|
||||||
Ifsr::Fault_status const fs = Ifsr::fault_status();
|
|
||||||
if(fs == Ifsr::SECTION_TRANSLATION_FAULT ||
|
|
||||||
fs == Ifsr::PAGE_TRANSLATION_FAULT)
|
|
||||||
{
|
|
||||||
/* fetch fault data */
|
|
||||||
w = 0;
|
|
||||||
va = Ifar::read();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0; }
|
|
||||||
case DATA_ABORT: {
|
|
||||||
|
|
||||||
/* check if fault was caused by translation miss */
|
|
||||||
Dfsr::Fault_status const fs = Dfsr::fault_status();
|
|
||||||
if(fs == Dfsr::SECTION_TRANSLATION_FAULT ||
|
|
||||||
fs == Dfsr::PAGE_TRANSLATION_FAULT)
|
|
||||||
{
|
|
||||||
/* fetch fault data */
|
|
||||||
Dfsr::access_t const dfsr = Dfsr::read();
|
|
||||||
w = Dfsr::Wnr::get(dfsr);
|
|
||||||
va = Dfar::read();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0; }
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable interrupt requests
|
|
||||||
*/
|
|
||||||
static void enable_irqs()
|
|
||||||
{
|
|
||||||
Cpsr::access_t cpsr = Cpsr::read();
|
|
||||||
Cpsr::I::clear(cpsr);
|
|
||||||
Cpsr::write(cpsr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set CPU exception entry to a given address
|
|
||||||
*
|
|
||||||
* \return 0 exception entry set to the given address
|
|
||||||
* <0 otherwise
|
|
||||||
*/
|
|
||||||
static int exception_entry_at(addr_t a)
|
|
||||||
{
|
|
||||||
Sctlr::access_t sctlr = Sctlr::read();
|
|
||||||
switch (a) {
|
|
||||||
case 0x0:
|
|
||||||
Sctlr::V::clear(sctlr);
|
|
||||||
break;
|
|
||||||
case 0xffff0000:
|
|
||||||
Sctlr::V::set(sctlr);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
Sctlr::write(sctlr);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Are we in secure mode?
|
|
||||||
*/
|
|
||||||
static bool secure_mode_active()
|
|
||||||
{
|
|
||||||
if (!Board::CORTEX_A9_SECURITY_EXTENSION) return 0;
|
|
||||||
return !Scr::Ns::get(Scr::read());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable the MMU
|
|
||||||
*
|
|
||||||
* \param section_table section translation table of the initial
|
|
||||||
* address space this function switches to
|
|
||||||
* \param process_id process ID of the initial address space
|
|
||||||
*/
|
|
||||||
static void enable_mmu (Section_table * const section_table,
|
|
||||||
unsigned long const process_id)
|
|
||||||
{
|
|
||||||
/* initialize domains */
|
|
||||||
Dacr::write (Dacr::D0::bits (Dacr::CLIENT)
|
|
||||||
| Dacr::D1::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D2::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D3::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D4::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D5::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D6::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D7::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D8::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D9::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D10::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D11::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D12::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D13::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D14::bits (Dacr::NO_ACCESS)
|
|
||||||
| Dacr::D15::bits (Dacr::NO_ACCESS));
|
|
||||||
|
|
||||||
/* switch process ID */
|
|
||||||
Contextidr::write(process_id);
|
|
||||||
|
|
||||||
/* install section table */
|
|
||||||
Ttbr0::write (Ttbr0::Base_address::masked ((addr_t)section_table));
|
|
||||||
Ttbcr::write (Ttbcr::N::bits(0)
|
|
||||||
| Ttbcr::Pd0::bits(0)
|
|
||||||
| Ttbcr::Pd1::bits(0) );
|
|
||||||
|
|
||||||
/* enable MMU without instruction-, data-, or unified caches */
|
|
||||||
Sctlr::access_t sctlr = Sctlr::read();
|
|
||||||
Sctlr::M::set(sctlr);
|
|
||||||
Sctlr::I::clear(sctlr);
|
|
||||||
Sctlr::C::clear(sctlr);
|
|
||||||
Sctlr::write(sctlr);
|
|
||||||
flush_branch_prediction();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate all entries of the branch predictor array
|
|
||||||
*
|
|
||||||
* Must be inline to avoid dependence on the branch predictor.
|
|
||||||
*/
|
|
||||||
__attribute__((always_inline)) inline static void flush_branch_prediction()
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, r0, c7, c5, 6\n"
|
|
||||||
"isb");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidate at least all TLB entries regarding a specific process
|
|
||||||
*
|
|
||||||
* \param process_id ID of the targeted process
|
|
||||||
*/
|
|
||||||
static void flush_tlb_by_pid (unsigned const process_id)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %[asid], c8, c7, 2 \n"
|
|
||||||
:: [asid]"r"(Contextidr::Asid::masked(process_id)) : );
|
|
||||||
flush_branch_prediction();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************
|
|
||||||
** Trustzone specific API **
|
|
||||||
******************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the exception-vector's base-address for the monitor mode
|
|
||||||
* software stack.
|
|
||||||
*
|
|
||||||
* \param addr address of the exception vector's base
|
|
||||||
*/
|
|
||||||
static inline void mon_exception_entry_at(addr_t addr)
|
|
||||||
{
|
|
||||||
asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (addr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable access of co-processors cp10 and cp11 from non-secure mode.
|
|
||||||
*/
|
|
||||||
static inline void allow_coprocessor_nonsecure(void)
|
|
||||||
{
|
|
||||||
uint32_t val = (1 << 10) | (1 << 11);
|
|
||||||
asm volatile ("mcr p15, 0, %0, c1, c1, 2" : : "r" (val));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _INCLUDE__DRIVERS__CPU__CORTEX_A9__CORE_H_ */
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief Driver base for the private timer of the ARM Cortex-A9
|
|
||||||
* \author Martin stein
|
|
||||||
* \date 2011-12-13
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2012 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__DRIVERS__CPU__CORTEX_A9__TIMER_H_
|
|
||||||
#define _INCLUDE__DRIVERS__CPU__CORTEX_A9__TIMER_H_
|
|
||||||
|
|
||||||
/* Genode includes */
|
|
||||||
#include <util/mmio.h>
|
|
||||||
|
|
||||||
namespace Genode
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Driver base for the private timer of the ARM Cortex-A9
|
|
||||||
*/
|
|
||||||
template <unsigned long CLK>
|
|
||||||
struct Cortex_a9_timer : public Mmio
|
|
||||||
{
|
|
||||||
enum { TICS_PER_MS = CLK / 1000, };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load value register
|
|
||||||
*/
|
|
||||||
struct Load : Register<0x0, 32> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer counter value register
|
|
||||||
*/
|
|
||||||
struct Counter : Register<0x4, 32> { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer control register
|
|
||||||
*/
|
|
||||||
struct Control : Register<0x8, 32>
|
|
||||||
{
|
|
||||||
struct Timer_enable : Bitfield<0,1> { }; /* 1: 'Counter' decrements, 0: 'Counter' stays 0 */
|
|
||||||
struct Auto_reload : Bitfield<1,1> { }; /* 1: Auto reload mode, 0: One shot mode */
|
|
||||||
struct Irq_enable : Bitfield<2,1> { }; /* 1: IRQ = 'Interrupt_status::Event' 0: IRQ = 0 */
|
|
||||||
struct Prescaler : Bitfield<8,8> { }; /* modifies the clock period for the decrementing */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Timer interrupt status register
|
|
||||||
*/
|
|
||||||
struct Interrupt_status : Register<0xc, 32>
|
|
||||||
{
|
|
||||||
struct Event : Bitfield<0,1> { }; /* 'Event' = !'Counter' */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, clears the interrupt output
|
|
||||||
*/
|
|
||||||
Cortex_a9_timer(addr_t const mmio_base) : Mmio(mmio_base) {
|
|
||||||
clear_interrupt(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start a one-shot run
|
|
||||||
* \param tics native timer value used to assess the delay
|
|
||||||
* of the timer interrupt as of the call
|
|
||||||
*/
|
|
||||||
inline void start_one_shot(uint32_t const tics);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Translate milliseconds to a native timer value
|
|
||||||
*/
|
|
||||||
static uint32_t ms_to_tics(unsigned long const ms) {
|
|
||||||
return ms * TICS_PER_MS; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the timer and return last timer value
|
|
||||||
*/
|
|
||||||
unsigned long stop()
|
|
||||||
{
|
|
||||||
unsigned long const v = read<Counter>();
|
|
||||||
write<typename Control::Timer_enable>(0);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear interrupt output line
|
|
||||||
*/
|
|
||||||
void clear_interrupt() { write<typename Interrupt_status::Event>(1); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <unsigned long CLOCK>
|
|
||||||
void Genode::Cortex_a9_timer<CLOCK>::start_one_shot(uint32_t const tics)
|
|
||||||
{
|
|
||||||
/* reset timer */
|
|
||||||
clear_interrupt();
|
|
||||||
write<Control>(Control::Timer_enable::bits(0) |
|
|
||||||
Control::Auto_reload::bits(0) |
|
|
||||||
Control::Irq_enable::bits(1) |
|
|
||||||
Control::Prescaler::bits(0));
|
|
||||||
|
|
||||||
/* load timer and start decrementing */
|
|
||||||
write<Load>(tics);
|
|
||||||
write<typename Control::Timer_enable>(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _INCLUDE__DRIVERS__CPU__CORTEX_A9__TIMER_H_ */
|
|
@ -14,68 +14,27 @@
|
|||||||
#ifndef _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
|
#ifndef _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
|
||||||
#define _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
|
#define _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
|
||||||
|
|
||||||
/* Core includes */
|
/* core includes */
|
||||||
#include <cortex_a9/cpu/core.h>
|
#include <cortex_a9/cpu.h>
|
||||||
#include <pic/pl390_base.h>
|
#include <cortex_a9/timer.h>
|
||||||
|
#include <cortex_a9/no_trustzone/pic.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU driver
|
* CPU driver
|
||||||
*/
|
*/
|
||||||
class Cpu : public Genode::Cortex_a9 { };
|
class Cpu : public Cortex_a9::Cpu { };
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
/* import Genode types */
|
|
||||||
typedef Genode::Cortex_a9 Cortex_a9;
|
|
||||||
typedef Genode::Pl390_base Pl390_base;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel interrupt-controller
|
* Programmable interrupt controller
|
||||||
*/
|
*/
|
||||||
class Pic : public Pl390_base
|
class Pic : public Cortex_a9_no_trustzone::Pic { };
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Pic() : Pl390_base(Cortex_a9::PL390_DISTRIBUTOR_MMIO_BASE,
|
|
||||||
Cortex_a9::PL390_CPU_MMIO_BASE)
|
|
||||||
{
|
|
||||||
/* disable device */
|
|
||||||
_distr.write<Distr::Icddcr::Enable>(0);
|
|
||||||
_cpu.write<Cpu::Iccicr::Enable>(0);
|
|
||||||
mask();
|
|
||||||
|
|
||||||
/* supported priority range */
|
|
||||||
unsigned const min_prio = _distr.min_priority();
|
|
||||||
unsigned const max_prio = _distr.max_priority();
|
|
||||||
|
|
||||||
/* configure every shared peripheral interrupt */
|
|
||||||
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++)
|
|
||||||
{
|
|
||||||
_distr.write<Distr::Icdicr::Edge_triggered>(0, i);
|
|
||||||
_distr.write<Distr::Icdipr::Priority>(max_prio, i);
|
|
||||||
_distr.write<Distr::Icdiptr::Cpu_targets>(Distr::Icdiptr::Cpu_targets::ALL, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable the priority filter */
|
|
||||||
_cpu.write<Cpu::Iccpmr::Priority>(min_prio);
|
|
||||||
|
|
||||||
/* disable preemption of interrupt handling by interrupts */
|
|
||||||
_cpu.write<Cpu::Iccbpr::Binary_point>(
|
|
||||||
Cpu::Iccbpr::Binary_point::NO_PREEMPTION);
|
|
||||||
|
|
||||||
/* enable device */
|
|
||||||
_distr.write<Distr::Icddcr::Enable>(1);
|
|
||||||
_cpu.write<Cpu::Iccicr::Enable>(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel timer
|
* Kernel timer
|
||||||
*/
|
*/
|
||||||
class Timer : public Cortex_a9::Private_timer { };
|
class Timer : public Cortex_a9::Timer { };
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_ */
|
#endif /* _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_ */
|
||||||
|
70
base-hw/src/core/include/cortex_a9/no_trustzone/pic.h
Normal file
70
base-hw/src/core/include/cortex_a9/no_trustzone/pic.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* \brief Programmable interrupt controller for core
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-10-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__CORTEX_A9__NO_TRUSTZONE__PIC_H_
|
||||||
|
#define _INCLUDE__CORTEX_A9__NO_TRUSTZONE__PIC_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <cortex_a9/cpu.h>
|
||||||
|
#include <cortex_a9/pic.h>
|
||||||
|
|
||||||
|
namespace Cortex_a9_no_trustzone
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Programmable interrupt controller for core
|
||||||
|
*/
|
||||||
|
class Pic : public Cortex_a9::Pic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Pic()
|
||||||
|
{
|
||||||
|
/* disable device */
|
||||||
|
_distr.write<Distr::Icddcr::Enable>(0);
|
||||||
|
_cpu.write<Cpu::Iccicr::Enable>(0);
|
||||||
|
mask();
|
||||||
|
|
||||||
|
/* supported priority range */
|
||||||
|
unsigned const min_prio = _distr.min_priority();
|
||||||
|
unsigned const max_prio = _distr.max_priority();
|
||||||
|
|
||||||
|
/* configure every shared peripheral interrupt */
|
||||||
|
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++)
|
||||||
|
{
|
||||||
|
_distr.write<Distr::Icdicr::Edge_triggered>(0, i);
|
||||||
|
_distr.write<Distr::Icdipr::Priority>(max_prio, i);
|
||||||
|
_distr.write<Distr::Icdiptr::Cpu_targets>(
|
||||||
|
Distr::Icdiptr::Cpu_targets::ALL, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable the priority filter */
|
||||||
|
_cpu.write<Cpu::Iccpmr::Priority>(min_prio);
|
||||||
|
|
||||||
|
/* disable preemption of interrupt handling by interrupts */
|
||||||
|
_cpu.write<Cpu::Iccbpr::Binary_point>(
|
||||||
|
Cpu::Iccbpr::Binary_point::NO_PREEMPTION);
|
||||||
|
|
||||||
|
/* enable device */
|
||||||
|
_distr.write<Distr::Icddcr::Enable>(1);
|
||||||
|
_cpu.write<Cpu::Iccicr::Enable>(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__CORTEX_A9__NO_TRUSTZONE__PIC_H_ */
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Base driver for the ARM PL390 interrupt controller
|
* \brief Programmable interrupt controller for core
|
||||||
* \author Martin stein
|
* \author Martin stein
|
||||||
* \date 2011-10-26
|
* \date 2011-10-26
|
||||||
*/
|
*/
|
||||||
@ -11,19 +11,20 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _INCLUDE__DRIVERS__PIC__PL390_BASE_H_
|
#ifndef _INCLUDE__CORTEX_A9__PIC_H_
|
||||||
#define _INCLUDE__DRIVERS__PIC__PL390_BASE_H_
|
#define _INCLUDE__CORTEX_A9__PIC_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <util/mmio.h>
|
#include <util/mmio.h>
|
||||||
#include <base/printf.h>
|
|
||||||
|
|
||||||
namespace Genode
|
namespace Cortex_a9
|
||||||
{
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base driver for the ARM PL390 interrupt controller
|
* Programmable interrupt controller for core
|
||||||
*/
|
*/
|
||||||
class Pl390_base
|
class Pic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ namespace Genode
|
|||||||
*/
|
*/
|
||||||
struct Distr : public Mmio
|
struct Distr : public Mmio
|
||||||
{
|
{
|
||||||
Distr(addr_t const base) : Mmio(base) { }
|
Distr() : Mmio(Cortex_a9::Cpu::PL390_DISTRIBUTOR_MMIO_BASE) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Distributor control register
|
* Distributor control register
|
||||||
@ -145,7 +146,7 @@ namespace Genode
|
|||||||
*/
|
*/
|
||||||
struct Cpu : public Mmio
|
struct Cpu : public Mmio
|
||||||
{
|
{
|
||||||
Cpu(addr_t const base) : Mmio(base) { }
|
Cpu() : Mmio(Cortex_a9::Cpu::PL390_CPU_MMIO_BASE) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU interface control register
|
* CPU interface control register
|
||||||
@ -160,7 +161,7 @@ namespace Genode
|
|||||||
struct Enable_ns : Bitfield<1,1> { };
|
struct Enable_ns : Bitfield<1,1> { };
|
||||||
struct Ack_ctl : Bitfield<2,1> { };
|
struct Ack_ctl : Bitfield<2,1> { };
|
||||||
struct Fiq_en : Bitfield<3,1> { };
|
struct Fiq_en : Bitfield<3,1> { };
|
||||||
struct Cbpr : Bitfield<4,1> { };
|
struct Sbpr : Bitfield<4,1> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,11 +222,8 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Constructor, all interrupts get masked
|
* Constructor, all interrupts get masked
|
||||||
*/
|
*/
|
||||||
Pl390_base(addr_t const distributor, addr_t const cpu_interface) :
|
Pic() : _max_interrupt(_distr.max_interrupt()),
|
||||||
_distr(distributor),
|
_last_taken_request(SPURIOUS_ID) { }
|
||||||
_cpu(cpu_interface),
|
|
||||||
_max_interrupt(_distr.max_interrupt()),
|
|
||||||
_last_taken_request(SPURIOUS_ID) { }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID of the last interrupt request
|
* Get the ID of the last interrupt request
|
||||||
@ -270,10 +268,8 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Unmask interrupt 'i'
|
* Unmask interrupt 'i'
|
||||||
*/
|
*/
|
||||||
void unmask(unsigned const i)
|
void unmask(unsigned const i) {
|
||||||
{
|
_distr.write<Distr::Icdiser::Set_enable>(1, i); }
|
||||||
_distr.write<Distr::Icdiser::Set_enable>(1, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mask all interrupts
|
* Mask all interrupts
|
||||||
@ -287,12 +283,10 @@ namespace Genode
|
|||||||
/**
|
/**
|
||||||
* Mask interrupt 'i'
|
* Mask interrupt 'i'
|
||||||
*/
|
*/
|
||||||
void mask(unsigned const i)
|
void mask(unsigned const i) {
|
||||||
{
|
_distr.write<Distr::Icdicer::Clear_enable>(1, i); }
|
||||||
_distr.write<Distr::Icdicer::Clear_enable>(1, i);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _INCLUDE__DRIVERS__PIC__PL390_BASE_H_ */
|
#endif /* _INCLUDE__CORTEX_A9__PIC_H_ */
|
||||||
|
|
131
base-hw/src/core/include/cortex_a9/timer.h
Normal file
131
base-hw/src/core/include/cortex_a9/timer.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* \brief Timer for core
|
||||||
|
* \author Martin stein
|
||||||
|
* \date 2011-12-13
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2012 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__CORTEX_A9__TIMER_H_
|
||||||
|
#define _INCLUDE__CORTEX_A9__TIMER_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <cortex_a9/cpu.h>
|
||||||
|
|
||||||
|
namespace Cortex_a9
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Timer for core
|
||||||
|
*/
|
||||||
|
class Timer : public Mmio
|
||||||
|
{
|
||||||
|
enum { TICS_PER_MS = Cortex_a9::Cpu::PRIVATE_TIMER_CLK / 1000, };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load value register
|
||||||
|
*/
|
||||||
|
struct Load : Register<0x0, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer counter value register
|
||||||
|
*/
|
||||||
|
struct Counter : Register<0x4, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer control register
|
||||||
|
*/
|
||||||
|
struct Control : Register<0x8, 32>
|
||||||
|
{
|
||||||
|
struct Timer_enable : Bitfield<0,1> { }; /* enable counting */
|
||||||
|
struct Auto_reload : Bitfield<1,1> { }; /* reload at zero */
|
||||||
|
struct Irq_enable : Bitfield<2,1> { }; /* unmask interrupt */
|
||||||
|
struct Prescaler : Bitfield<8,8> { }; /* modify frequency */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure for a one-shot
|
||||||
|
*/
|
||||||
|
static access_t init_one_shot()
|
||||||
|
{
|
||||||
|
return Timer_enable::bits(0) |
|
||||||
|
Auto_reload::bits(0) |
|
||||||
|
Irq_enable::bits(1) |
|
||||||
|
Prescaler::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer interrupt status register
|
||||||
|
*/
|
||||||
|
struct Interrupt_status : Register<0xc, 32>
|
||||||
|
{
|
||||||
|
struct Event : Bitfield<0,1> { }; /* if counter hit zero */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop counting
|
||||||
|
*/
|
||||||
|
void _disable() { write<Control::Timer_enable>(0); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum { IRQ = Cortex_a9::Cpu::PRIVATE_TIMER_IRQ };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor, clears the interrupt output
|
||||||
|
*/
|
||||||
|
Timer() : Mmio(Cortex_a9::Cpu::PRIVATE_TIMER_MMIO_BASE)
|
||||||
|
{
|
||||||
|
_disable();
|
||||||
|
clear_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a one-shot run
|
||||||
|
* \param tics native timer value used to assess the delay
|
||||||
|
* of the timer interrupt as of the call
|
||||||
|
*/
|
||||||
|
inline void start_one_shot(uint32_t const tics)
|
||||||
|
{
|
||||||
|
/* reset timer */
|
||||||
|
clear_interrupt();
|
||||||
|
write<Control>(Control::init_one_shot());
|
||||||
|
|
||||||
|
/* load timer and start decrementing */
|
||||||
|
write<Load>(tics);
|
||||||
|
write<Control::Timer_enable>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate milliseconds to a native timer value
|
||||||
|
*/
|
||||||
|
static uint32_t ms_to_tics(unsigned long const ms) {
|
||||||
|
return ms * TICS_PER_MS; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the timer and return last timer value
|
||||||
|
*/
|
||||||
|
unsigned long stop_one_shot()
|
||||||
|
{
|
||||||
|
unsigned long const v = read<Counter>();
|
||||||
|
_disable();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear interrupt output line
|
||||||
|
*/
|
||||||
|
void clear_interrupt() {
|
||||||
|
write<Interrupt_status::Event>(1); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__CORTEX_A9__TIMER_H_ */
|
||||||
|
|
99
base-hw/src/core/include/imx31/drivers/board.h
Normal file
99
base-hw/src/core/include/imx31/drivers/board.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* \brief Board definitions for core
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-11-01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE__IMX31__DRIVERS__BOARD_H_
|
||||||
|
#define _INCLUDE__IMX31__DRIVERS__BOARD_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <platform/imx31/drivers/board.h>
|
||||||
|
|
||||||
|
namespace Imx31
|
||||||
|
{
|
||||||
|
using 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Board : Genode::Board
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef Imx31::Board Board;
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__IMX31__DRIVERS__BOARD_H_ */
|
39
base-hw/src/core/include/imx31/kernel_support.h
Normal file
39
base-hw/src/core/include/imx31/kernel_support.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* \brief Kernel support for i.MX31
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__IMX31__KERNEL_SUPPORT_H_
|
||||||
|
#define _CORE__INCLUDE__IMX31__KERNEL_SUPPORT_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <arm/v6/cpu.h>
|
||||||
|
#include <imx31/timer.h>
|
||||||
|
#include <imx31/pic.h>
|
||||||
|
|
||||||
|
struct Cpu : Arm_v6::Cpu { };
|
||||||
|
|
||||||
|
namespace Kernel
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Programmable interrupt controller
|
||||||
|
*/
|
||||||
|
class Pic : public Imx31::Pic { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timer
|
||||||
|
*/
|
||||||
|
class Timer : public Imx31::Timer { };
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _CORE__INCLUDE__IMX31__KERNEL_SUPPORT_H_ */
|
||||||
|
|
197
base-hw/src/core/include/imx31/pic.h
Normal file
197
base-hw/src/core/include/imx31/pic.h
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* \brief Programmable interrupt controller for core
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__IMX31__PIC_H_
|
||||||
|
#define _INCLUDE__IMX31__PIC_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
#include <drivers/board.h>
|
||||||
|
|
||||||
|
namespace Imx31
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Programmable interrupt controller for core
|
||||||
|
*/
|
||||||
|
class Pic : public Mmio
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Interrupt control register
|
||||||
|
*/
|
||||||
|
struct Intcntl : Register<0x0, 32>
|
||||||
|
{
|
||||||
|
struct Nm : Bitfield<18,1> /* IRQ mode */
|
||||||
|
{
|
||||||
|
enum { SW_CONTROL = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Fiad : Bitfield<19,1> { }; /* FIQ rises prio in arbiter */
|
||||||
|
struct Niad : Bitfield<20,1> { }; /* IRQ rises prio in arbiter */
|
||||||
|
struct Fidis : Bitfield<21,1> { }; /* FIQ disable */
|
||||||
|
struct Nidis : Bitfield<22,1> { }; /* IRQ disable */
|
||||||
|
struct Abfen : Bitfield<24,1> { }; /* if ABFLAG is sticky */
|
||||||
|
struct Abflag : Bitfield<25,1> { }; /* rise prio in bus arbiter */
|
||||||
|
|
||||||
|
static access_t init_value()
|
||||||
|
{
|
||||||
|
return Nm::bits(Nm::SW_CONTROL) |
|
||||||
|
Fiad::bits(0) |
|
||||||
|
Niad::bits(0) |
|
||||||
|
Fidis::bits(0) |
|
||||||
|
Nidis::bits(0) |
|
||||||
|
Abfen::bits(0) |
|
||||||
|
Abflag::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal interrupt mask register
|
||||||
|
*/
|
||||||
|
struct Nimask : Register<0x4, 32>
|
||||||
|
{
|
||||||
|
enum { NONE_MASKED = ~0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt enable number register
|
||||||
|
*/
|
||||||
|
struct Intennum : Register<0x8, 32>
|
||||||
|
{
|
||||||
|
struct Enable : Bitfield<0,6> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt disable number register
|
||||||
|
*/
|
||||||
|
struct Intdisnum : Register<0xc, 32>
|
||||||
|
{
|
||||||
|
struct Disable : Bitfield<0,6> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt enable register
|
||||||
|
*/
|
||||||
|
struct Intenableh : Register<0x10, 32> { };
|
||||||
|
struct Intenablel : Register<0x14, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt type register
|
||||||
|
*/
|
||||||
|
struct Inttype { enum { ALL_IRQS = 0 }; };
|
||||||
|
struct Inttypeh : Register<0x18, 32> { };
|
||||||
|
struct Inttypel : Register<0x1c, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal interrupt priority registers
|
||||||
|
*/
|
||||||
|
struct Nipriority : Register_array<0x20, 32, 8, 32>
|
||||||
|
{
|
||||||
|
enum { ALL_LOWEST = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interrupt source registers
|
||||||
|
*/
|
||||||
|
struct Intsrch : Register<0x48, 32> { };
|
||||||
|
struct Intsrcl : Register<0x4c, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal interrupt pending registers
|
||||||
|
*/
|
||||||
|
struct Nipndh : Register<0x58, 32> { };
|
||||||
|
struct Nipndl : Register<0x5c, 32> { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normal interrupt vector and status register
|
||||||
|
*/
|
||||||
|
struct Nivecsr : Register<0x40, 32>
|
||||||
|
{
|
||||||
|
struct Nvector : Bitfield<16, 16> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum { MAX_INTERRUPT_ID = 63 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor, enables all interrupts
|
||||||
|
*/
|
||||||
|
Pic() : Mmio(Board::AVIC_MMIO_BASE)
|
||||||
|
{
|
||||||
|
mask();
|
||||||
|
write<Nimask>(Nimask::NONE_MASKED);
|
||||||
|
write<Intcntl>(Intcntl::init_value());
|
||||||
|
write<Inttypeh>(Inttype::ALL_IRQS);
|
||||||
|
write<Inttypel>(Inttype::ALL_IRQS);
|
||||||
|
for (unsigned i = 0; i < Nipriority::ITEMS; i++)
|
||||||
|
write<Nipriority>(Nipriority::ALL_LOWEST, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receive a pending request number 'i'
|
||||||
|
*/
|
||||||
|
bool take_request(unsigned & i)
|
||||||
|
{
|
||||||
|
i = read<Nivecsr::Nvector>();
|
||||||
|
return valid(i) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the last taken request
|
||||||
|
*/
|
||||||
|
void finish_request() {
|
||||||
|
/* requests disappear by source retraction or masking */ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate request number 'i'
|
||||||
|
*/
|
||||||
|
bool valid(unsigned const i) const {
|
||||||
|
return i <= MAX_INTERRUPT_ID; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmask all interrupts
|
||||||
|
*/
|
||||||
|
void unmask()
|
||||||
|
{
|
||||||
|
write<Intenablel>(~0);
|
||||||
|
write<Intenableh>(~0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mask all interrupts
|
||||||
|
*/
|
||||||
|
void mask()
|
||||||
|
{
|
||||||
|
write<Intenablel>(0);
|
||||||
|
write<Intenableh>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unmask interrupt 'i'
|
||||||
|
*/
|
||||||
|
void unmask(unsigned const i) {
|
||||||
|
if (i <= MAX_INTERRUPT_ID) write<Intennum>(i); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mask interrupt 'i'
|
||||||
|
*/
|
||||||
|
void mask(unsigned const i) {
|
||||||
|
if (i <= MAX_INTERRUPT_ID) write<Intdisnum>(i); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__IMX31__PIC_H_ */
|
||||||
|
|
176
base-hw/src/core/include/imx31/timer.h
Normal file
176
base-hw/src/core/include/imx31/timer.h
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* \brief Core timer
|
||||||
|
* \author Martin Stein
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__IMX31__TIMER_H_
|
||||||
|
#define _INCLUDE__IMX31__TIMER_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
namespace Imx31
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core timer
|
||||||
|
*/
|
||||||
|
class Timer : public Mmio
|
||||||
|
{
|
||||||
|
enum { TICS_PER_MS = 32 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control register
|
||||||
|
*/
|
||||||
|
struct Cr : Register<0x0, 32>
|
||||||
|
{
|
||||||
|
struct En : Bitfield<0, 1> { }; /* enable timer */
|
||||||
|
|
||||||
|
struct En_mod : Bitfield<1, 1> /* reload or continue on enable */
|
||||||
|
{
|
||||||
|
enum { RELOAD = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Oci_en : Bitfield<2, 1> { }; /* interrupt on compare */
|
||||||
|
|
||||||
|
struct Rld : Bitfield<3, 1> /* reload or roll-over */
|
||||||
|
{
|
||||||
|
enum { RELOAD_FROM_LR = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Prescaler : Bitfield<4, 12> /* clock input divisor */
|
||||||
|
{
|
||||||
|
enum { DIVIDE_BY_1 = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Swr : Bitfield<16, 1> { }; /* software reset bit */
|
||||||
|
struct Iovw : Bitfield<17, 1> { }; /* enable overwrite */
|
||||||
|
struct Dbg_en : Bitfield<18, 1> { }; /* enable in debug mode */
|
||||||
|
struct Wait_en : Bitfield<19, 1> { }; /* enable in wait mode */
|
||||||
|
struct Doz_en : Bitfield<20, 1> { }; /* enable in doze mode */
|
||||||
|
struct Stop_en : Bitfield<21, 1> { }; /* enable in stop mode */
|
||||||
|
|
||||||
|
struct Om : Bitfield<22, 2> /* mode of the output pin */
|
||||||
|
{
|
||||||
|
enum { DISCONNECTED = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Clk_src : Bitfield<24, 2> /* select clock input */
|
||||||
|
{
|
||||||
|
enum { IPG_CLK_32K = 3 };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register value that configures the timer for a one-shot run
|
||||||
|
*/
|
||||||
|
static access_t prepare_one_shot()
|
||||||
|
{
|
||||||
|
return En::bits(0) |
|
||||||
|
En_mod::bits(En_mod::RELOAD) |
|
||||||
|
Oci_en::bits(1) |
|
||||||
|
Rld::bits(Rld::RELOAD_FROM_LR) |
|
||||||
|
Prescaler::bits(Prescaler::DIVIDE_BY_1) |
|
||||||
|
Swr::bits(0) |
|
||||||
|
Iovw::bits(0) |
|
||||||
|
Dbg_en::bits(0) |
|
||||||
|
Wait_en::bits(0) |
|
||||||
|
Doz_en::bits(0) |
|
||||||
|
Stop_en::bits(0) |
|
||||||
|
Om::bits(Om::DISCONNECTED) |
|
||||||
|
Clk_src::bits(Clk_src::IPG_CLK_32K);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status register
|
||||||
|
*/
|
||||||
|
struct Sr : Register<0x4, 32>
|
||||||
|
{
|
||||||
|
struct Ocif : Bitfield<0, 1> { }; /* IRQ status, write 1 clears */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Lr : Register<0x8, 32> { }; /* load value register */
|
||||||
|
struct Cmpr : Register<0xc, 32> { }; /* compare value register */
|
||||||
|
struct Cnt : Register<0x10, 32> { }; /* counter register */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable timer and clear its interrupt output
|
||||||
|
*/
|
||||||
|
void _reset()
|
||||||
|
{
|
||||||
|
/* wait until ongoing reset operations are finished */
|
||||||
|
while (read<Cr::Swr>()) ;
|
||||||
|
|
||||||
|
/* disable timer */
|
||||||
|
write<Cr::En>(0);
|
||||||
|
clear_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum { IRQ = Board::EPIT_1_IRQ };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Timer() : Mmio(Board::EPIT_1_MMIO_BASE) { _reset(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a one-shot run
|
||||||
|
*
|
||||||
|
* \param tics native timer value used to assess the delay
|
||||||
|
* of the timer interrupt as of the call
|
||||||
|
*/
|
||||||
|
void start_one_shot(unsigned const tics)
|
||||||
|
{
|
||||||
|
/* stop timer */
|
||||||
|
_reset();
|
||||||
|
|
||||||
|
/* configure timer for a one-shot */
|
||||||
|
write<Cr>(Cr::prepare_one_shot());
|
||||||
|
write<Lr>(tics);
|
||||||
|
write<Cmpr>(0);
|
||||||
|
|
||||||
|
/* start timer */
|
||||||
|
write<Cr::En>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the timer from a one-shot run
|
||||||
|
*
|
||||||
|
* \return last native timer value of the one-shot run
|
||||||
|
*/
|
||||||
|
unsigned long stop_one_shot()
|
||||||
|
{
|
||||||
|
/* disable timer */
|
||||||
|
write<Cr::En>(0);
|
||||||
|
|
||||||
|
/* if the timer has hit zero already return 0 */
|
||||||
|
return read<Sr::Ocif>() ? 0 : read<Cnt>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear interrupt output line
|
||||||
|
*/
|
||||||
|
void clear_interrupt() { write<Sr::Ocif>(1); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate milliseconds to a native timer value
|
||||||
|
*/
|
||||||
|
static unsigned ms_to_tics(unsigned const ms) {
|
||||||
|
return TICS_PER_MS * ms; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__IMX31__TIMER_H_ */
|
||||||
|
|
68
base-hw/src/core/include/vea9x4_trustzone/pic.h
Normal file
68
base-hw/src/core/include/vea9x4_trustzone/pic.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* \brief Programmable interrupt controller for core
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2012-10-11
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__VEA9X4_TRUSTZONE__PIC_H_
|
||||||
|
#define _INCLUDE__VEA9X4_TRUSTZONE__PIC_H_
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
|
#include <cortex_a9/cpu.h>
|
||||||
|
#include <cortex_a9/pic.h>
|
||||||
|
|
||||||
|
namespace Vea9x4_trustzone
|
||||||
|
{
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Programmable interrupt controller for core
|
||||||
|
*/
|
||||||
|
class Pic : public Cortex_a9::Pic
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
Pic()
|
||||||
|
{
|
||||||
|
/* configure every shared peripheral interrupt */
|
||||||
|
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) {
|
||||||
|
_distr.write<Distr::Icdicr::Edge_triggered>(0, i);
|
||||||
|
_distr.write<Distr::Icdipr::Priority>(0, i);
|
||||||
|
_distr.write<Distr::Icdiptr::Cpu_targets>(Distr::Icdiptr::Cpu_targets::ALL, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable the priority filter */
|
||||||
|
_cpu.write<Cpu::Iccpmr::Priority>(0xff);
|
||||||
|
|
||||||
|
/* signal secure IRQ via FIQ interface */
|
||||||
|
_cpu.write<Cpu::Iccicr>(Cpu::Iccicr::Enable_s::bits(1) |
|
||||||
|
Cpu::Iccicr::Enable_ns::bits(1) |
|
||||||
|
Cpu::Iccicr::Fiq_en::bits(1));
|
||||||
|
|
||||||
|
/* use whole band of prios */
|
||||||
|
_cpu.write<Cpu::Iccbpr::Binary_point>(Cpu::Iccbpr::Binary_point::NO_PREEMPTION);
|
||||||
|
|
||||||
|
/* enable device */
|
||||||
|
_distr.write<Distr::Icddcr>(Distr::Icddcr::Enable::bits(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark interrupt 'i' unsecure
|
||||||
|
*/
|
||||||
|
void unsecure(unsigned const i) {
|
||||||
|
_distr.write<Distr::Icdisr::Nonsecure>(1, i); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__VEA9X4_TRUSTZONE__PIC_H_ */
|
||||||
|
|
@ -47,9 +47,9 @@ extern int _mode_transition_begin;
|
|||||||
extern int _mode_transition_end;
|
extern int _mode_transition_end;
|
||||||
extern int _mt_user_entry_pic;
|
extern int _mt_user_entry_pic;
|
||||||
extern int _mon_vm_entry;
|
extern int _mon_vm_entry;
|
||||||
extern Genode::addr_t _mt_context_ptr;
|
extern Genode::addr_t _mt_client_context_ptr;
|
||||||
extern Genode::addr_t _mt_kernel_context_begin;
|
extern Genode::addr_t _mt_master_context_begin;
|
||||||
extern Genode::addr_t _mt_kernel_context_end;
|
extern Genode::addr_t _mt_master_context_end;
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ namespace Kernel
|
|||||||
/* kernel configuration */
|
/* kernel configuration */
|
||||||
enum {
|
enum {
|
||||||
DEFAULT_STACK_SIZE = 1*1024*1024,
|
DEFAULT_STACK_SIZE = 1*1024*1024,
|
||||||
USER_TIME_SLICE_MS = 10,
|
USER_TIME_SLICE_MS = 100,
|
||||||
MAX_PDS = 256,
|
MAX_PDS = 256,
|
||||||
MAX_THREADS = 256,
|
MAX_THREADS = 256,
|
||||||
MAX_SIGNAL_RECEIVERS = 256,
|
MAX_SIGNAL_RECEIVERS = 256,
|
||||||
@ -720,17 +720,17 @@ namespace Kernel
|
|||||||
*
|
*
|
||||||
* The code that switches between kernel/user mode must not exceed the
|
* The code that switches between kernel/user mode must not exceed the
|
||||||
* smallest page size supported by the MMU. The Code must be position
|
* smallest page size supported by the MMU. The Code must be position
|
||||||
* independent. This code has to be mapped to in every PD, to ensure
|
* independent. This code has to be mapped in every PD, to ensure
|
||||||
* appropriate kernel invokation on CPU interrupts.
|
* appropriate kernel invokation on CPU interrupts.
|
||||||
* This class controls the settings like kernel, user, and vm states
|
* This class controls the settings like kernel, user, and VM states
|
||||||
* that are handled by the PIC mode transition code.
|
* that are handled by the mode transition PIC.
|
||||||
*/
|
*/
|
||||||
struct Mode_transition_control
|
struct Mode_transition_control
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
SIZE_LOG2 = Cpu::MIN_PAGE_SIZE_LOG2,
|
SIZE_LOG2 = Software_tlb::MIN_PAGE_SIZE_LOG2,
|
||||||
SIZE = 1 << SIZE_LOG2,
|
SIZE = 1 << SIZE_LOG2,
|
||||||
VIRT_BASE = Cpu::HIGHEST_EXCEPTION_ENTRY,
|
VIRT_BASE = Cpu::EXCEPTION_ENTRY,
|
||||||
VIRT_END = VIRT_BASE + SIZE,
|
VIRT_END = VIRT_BASE + SIZE,
|
||||||
ALIGNM_LOG2 = SIZE_LOG2,
|
ALIGNM_LOG2 = SIZE_LOG2,
|
||||||
};
|
};
|
||||||
@ -751,20 +751,17 @@ namespace Kernel
|
|||||||
assert(pic_size <= SIZE);
|
assert(pic_size <= SIZE);
|
||||||
|
|
||||||
/* check if kernel context fits into the mode transition */
|
/* check if kernel context fits into the mode transition */
|
||||||
addr_t const kc_begin = (addr_t)&_mt_kernel_context_begin;
|
addr_t const kc_begin = (addr_t)&_mt_master_context_begin;
|
||||||
addr_t const kc_end = (addr_t)&_mt_kernel_context_end;
|
addr_t const kc_end = (addr_t)&_mt_master_context_end;
|
||||||
size_t const kc_size = kc_end - kc_begin;
|
size_t const kc_size = kc_end - kc_begin;
|
||||||
assert(sizeof(Cpu::Context) <= kc_size);
|
assert(sizeof(Cpu::Context) <= kc_size);
|
||||||
|
|
||||||
/* try to set CPU exception entry accordingly */
|
|
||||||
assert(!Cpu::exception_entry_at(VIRT_BASE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch next kernelmode context
|
* Fetch next kernelmode context
|
||||||
*/
|
*/
|
||||||
void fetch_kernel_context(Cpu::Context * const c) {
|
void fetch_master_context(Cpu::Context * const c) {
|
||||||
memcpy(&_mt_kernel_context_begin, c, sizeof(Cpu::Context)); }
|
memcpy(&_mt_master_context_begin, c, sizeof(Cpu::Context)); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page aligned physical base of the mode transition PIC
|
* Page aligned physical base of the mode transition PIC
|
||||||
@ -836,7 +833,7 @@ namespace Kernel
|
|||||||
void append_context(Cpu::Context * const c)
|
void append_context(Cpu::Context * const c)
|
||||||
{
|
{
|
||||||
c->protection_domain(id());
|
c->protection_domain(id());
|
||||||
c->software_tlb((Software_tlb *)this);
|
c->software_tlb((addr_t)static_cast<Software_tlb *>(this));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1125,6 +1122,11 @@ namespace Kernel
|
|||||||
Platform_thread * const _platform_thread; /* userland object wich
|
Platform_thread * const _platform_thread; /* userland object wich
|
||||||
* addresses this thread */
|
* addresses this thread */
|
||||||
State _state; /* thread state, description given at the beginning */
|
State _state; /* thread state, description given at the beginning */
|
||||||
|
Pagefault _pagefault; /* last pagefault triggered by this thread */
|
||||||
|
Thread * _pager; /* gets informed if thread throws a pagefault */
|
||||||
|
unsigned _pd_id; /* ID of the PD this thread runs on */
|
||||||
|
Native_utcb * _phys_utcb; /* physical UTCB base */
|
||||||
|
Native_utcb * _virt_utcb; /* virtual UTCB base */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume execution
|
* Resume execution
|
||||||
@ -1135,12 +1137,6 @@ namespace Kernel
|
|||||||
_state = ACTIVE;
|
_state = ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pagefault _pagefault; /* last pagefault triggered by this thread */
|
|
||||||
Thread * _pager; /* gets informed if thread throws a pagefault */
|
|
||||||
unsigned _pd_id; /* ID of the PD this thread runs on */
|
|
||||||
Native_utcb * _phys_utcb; /* physical UTCB base */
|
|
||||||
Native_utcb * _virt_utcb; /* virtual UTCB base */
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void * operator new (size_t, void * p) { return p; }
|
void * operator new (size_t, void * p) { return p; }
|
||||||
@ -1288,9 +1284,10 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduled_next() {
|
void scheduled_next()
|
||||||
|
{
|
||||||
/* set context pointer for mode switch */
|
/* set context pointer for mode switch */
|
||||||
_mt_context_ptr = (addr_t)static_cast<Genode::Cpu_state*>(this);
|
_mt_client_context_ptr = (addr_t)static_cast<Genode::Cpu_state*>(this);
|
||||||
|
|
||||||
/* jump to user entry assembler path */
|
/* jump to user entry assembler path */
|
||||||
mtc()->virt_user_entry();
|
mtc()->virt_user_entry();
|
||||||
@ -1344,7 +1341,6 @@ namespace Kernel
|
|||||||
|
|
||||||
class Signal_receiver;
|
class Signal_receiver;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific signal type, owned by a receiver, can be triggered asynchr.
|
* Specific signal type, owned by a receiver, can be triggered asynchr.
|
||||||
*/
|
*/
|
||||||
@ -1472,9 +1468,10 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduled_next() {
|
void scheduled_next()
|
||||||
|
{
|
||||||
/* set context pointer for mode switch */
|
/* set context pointer for mode switch */
|
||||||
_mt_context_ptr = (addr_t)_state;
|
_mt_client_context_ptr = (addr_t)_state;
|
||||||
|
|
||||||
/* jump to assembler path */
|
/* jump to assembler path */
|
||||||
((void(*)(void))&_mon_vm_entry)();
|
((void(*)(void))&_mon_vm_entry)();
|
||||||
@ -1959,7 +1956,7 @@ namespace Kernel
|
|||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
/* trigger signal at context */
|
/* trigger signal at context */
|
||||||
c->trigger_signal(1);
|
c->trigger_signal(user->user_arg_2());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2041,9 +2038,9 @@ namespace Kernel
|
|||||||
/* 21 */ do_new_signal_context,
|
/* 21 */ do_new_signal_context,
|
||||||
/* 22 */ do_await_signal,
|
/* 22 */ do_await_signal,
|
||||||
/* 23 */ do_submit_signal,
|
/* 23 */ do_submit_signal,
|
||||||
/* 24 */ do_delete_thread,
|
/* 24 */ do_new_vm,
|
||||||
/* 25 */ do_new_vm,
|
/* 25 */ do_run_vm,
|
||||||
/* 26 */ do_run_vm,
|
/* 26 */ do_delete_thread,
|
||||||
};
|
};
|
||||||
enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 };
|
enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 };
|
||||||
|
|
||||||
@ -2054,13 +2051,17 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the system for the first run of 'kernel'
|
||||||
|
*/
|
||||||
|
extern "C" void init_phys_kernel() {
|
||||||
|
Cpu::init_phys_kernel(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel main routine
|
* Kernel main routine
|
||||||
*/
|
*/
|
||||||
extern "C" void kernel()
|
extern "C" void kernel()
|
||||||
{
|
{
|
||||||
unsigned const timer_value = timer()->stop();
|
|
||||||
static unsigned user_time = 0;
|
static unsigned user_time = 0;
|
||||||
static bool initial_call = true;
|
static bool initial_call = true;
|
||||||
|
|
||||||
@ -2068,6 +2069,7 @@ extern "C" void kernel()
|
|||||||
if (!initial_call)
|
if (!initial_call)
|
||||||
{
|
{
|
||||||
/* update how much time the last user has consumed */
|
/* update how much time the last user has consumed */
|
||||||
|
unsigned const timer_value = timer()->stop_one_shot();
|
||||||
user_time = timer_value < user_time ? user_time - timer_value : 0;
|
user_time = timer_value < user_time ? user_time - timer_value : 0;
|
||||||
|
|
||||||
/* handle exception that interrupted the last user */
|
/* handle exception that interrupted the last user */
|
||||||
@ -2082,7 +2084,7 @@ extern "C" void kernel()
|
|||||||
{
|
{
|
||||||
/* map everything except the mode transition region */
|
/* map everything except the mode transition region */
|
||||||
enum {
|
enum {
|
||||||
SIZE_LOG2 = Software_tlb::MAX_TRANSL_SIZE_LOG2,
|
SIZE_LOG2 = Software_tlb::MAX_PAGE_SIZE_LOG2,
|
||||||
SIZE = 1 << SIZE_LOG2,
|
SIZE = 1 << SIZE_LOG2,
|
||||||
};
|
};
|
||||||
if (mtc()->VIRT_END <= a || mtc()->VIRT_BASE > (a + SIZE - 1))
|
if (mtc()->VIRT_END <= a || mtc()->VIRT_BASE > (a + SIZE - 1))
|
||||||
@ -2098,20 +2100,20 @@ extern "C" void kernel()
|
|||||||
}
|
}
|
||||||
/* compose kernel CPU context */
|
/* compose kernel CPU context */
|
||||||
static Cpu::Context kernel_context;
|
static Cpu::Context kernel_context;
|
||||||
kernel_context.instruction_ptr((addr_t)kernel);
|
kernel_context.ip = (addr_t)kernel;
|
||||||
kernel_context.stack_ptr((addr_t)&_kernel_stack_high);
|
kernel_context.sp = (addr_t)&_kernel_stack_high;
|
||||||
|
|
||||||
/* add kernel to the core PD */
|
/* add kernel to the core PD */
|
||||||
core()->append_context(&kernel_context);
|
core()->append_context(&kernel_context);
|
||||||
|
|
||||||
/* offer the final kernel context to the mode transition page */
|
/* offer the final kernel context to the mode transition page */
|
||||||
mtc()->fetch_kernel_context(&kernel_context);
|
mtc()->fetch_master_context(&kernel_context);
|
||||||
|
|
||||||
/* TrustZone initialization code */
|
/* TrustZone initialization code */
|
||||||
trustzone_initialization(pic());
|
trustzone_initialization(pic());
|
||||||
|
|
||||||
/* switch to core address space */
|
/* switch to core address space */
|
||||||
Cpu::enable_mmu(core(), core_id());
|
Cpu::init_virt_kernel((addr_t)static_cast<Software_tlb *>(core()), core_id());
|
||||||
|
|
||||||
/* create the core main thread */
|
/* create the core main thread */
|
||||||
static Native_utcb cm_utcb;
|
static Native_utcb cm_utcb;
|
||||||
@ -2120,7 +2122,7 @@ extern "C" void kernel()
|
|||||||
static Thread core_main((Platform_thread *)0);
|
static Thread core_main((Platform_thread *)0);
|
||||||
_main_utcb = &cm_utcb;
|
_main_utcb = &cm_utcb;
|
||||||
enum { CM_STACK_SIZE = sizeof(cm_stack)/sizeof(cm_stack[0]) + 1 };
|
enum { CM_STACK_SIZE = sizeof(cm_stack)/sizeof(cm_stack[0]) + 1 };
|
||||||
core_main.start((void *)&CORE_MAIN,
|
core_main.start((void *)CORE_MAIN,
|
||||||
(void *)&cm_stack[CM_STACK_SIZE - 1],
|
(void *)&cm_stack[CM_STACK_SIZE - 1],
|
||||||
0, core_id(), &cm_utcb, &cm_utcb);
|
0, core_id(), &cm_utcb, &cm_utcb);
|
||||||
|
|
||||||
@ -2128,7 +2130,7 @@ extern "C" void kernel()
|
|||||||
initial_call = false;
|
initial_call = false;
|
||||||
}
|
}
|
||||||
/* offer next user context to the mode transition PIC */
|
/* offer next user context to the mode transition PIC */
|
||||||
Schedule_context* const next = cpu_scheduler()->next_entry(user_time);
|
Schedule_context * const next = cpu_scheduler()->next_entry(user_time);
|
||||||
|
|
||||||
/* limit user mode execution in time */
|
/* limit user mode execution in time */
|
||||||
timer()->start_one_shot(user_time);
|
timer()->start_one_shot(user_time);
|
||||||
@ -2167,19 +2169,19 @@ int Thread::start(void *ip, void *sp, unsigned cpu_no,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Thread::init_context(void * const ip, void * const sp,
|
void Thread::init_context(void * const instr_p, void * const stack_p,
|
||||||
unsigned const pd_id)
|
unsigned const pd_id)
|
||||||
{
|
{
|
||||||
/* basic thread state */
|
/* basic thread state */
|
||||||
stack_ptr((addr_t)sp);
|
sp = (addr_t)stack_p;
|
||||||
instruction_ptr((addr_t)ip);
|
ip = (addr_t)instr_p;
|
||||||
|
|
||||||
/* join a pd */
|
/* join a pd */
|
||||||
_pd_id = pd_id;
|
_pd_id = pd_id;
|
||||||
Pd * const pd = Pd::pool()->object(_pd_id);
|
Pd * const pd = Pd::pool()->object(_pd_id);
|
||||||
assert(pd)
|
assert(pd)
|
||||||
protection_domain(pd_id);
|
protection_domain(pd_id);
|
||||||
software_tlb(pd);
|
software_tlb((addr_t)static_cast<Software_tlb *>(pd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2191,10 +2193,8 @@ void Thread::pagefault(addr_t const va, bool const w)
|
|||||||
|
|
||||||
/* inform pager through IPC */
|
/* inform pager through IPC */
|
||||||
assert(_pager);
|
assert(_pager);
|
||||||
Software_tlb * const tlb =
|
Software_tlb * const tlb = (Software_tlb *)software_tlb();
|
||||||
static_cast<Software_tlb *>(software_tlb());
|
_pagefault = Pagefault(id(), tlb, ip, va, w);
|
||||||
_pagefault =
|
|
||||||
Pagefault(id(), tlb, instruction_ptr(), va, w);
|
|
||||||
Ipc_node::send_note(_pager, &_pagefault, sizeof(_pagefault));
|
Ipc_node::send_note(_pager, &_pagefault, sizeof(_pagefault));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,13 +11,8 @@
|
|||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* core includes */
|
||||||
#include <kernel_support.h>
|
#include <kernel_support.h>
|
||||||
|
|
||||||
|
Cpu::User_context::User_context() { cpsr = Psr::init_user(); }
|
||||||
|
|
||||||
Cpu::User_context::User_context()
|
|
||||||
{
|
|
||||||
/* Execute in usermode with IRQ's enabled and FIQ's and
|
|
||||||
* asynchronous aborts disabled */
|
|
||||||
cpsr = Cpsr::M::bits(Cpsr::M::USER) | Cpsr::F::bits(1) |
|
|
||||||
Cpsr::I::bits(0) | Cpsr::A::bits(1);
|
|
||||||
}
|
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
#include <drivers/board.h>
|
#include <drivers/board.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
#include <cortex_a9/cpu.h>
|
||||||
|
#include <cortex_a9/no_trustzone/pic.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <cortex_a9/cpu/core.h>
|
|
||||||
#include <pic/pl390_base.h>
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
|||||||
{
|
{
|
||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
|
{ 0, Cortex_a9_no_trustzone::Pic::MAX_INTERRUPT_ID + 1 }
|
||||||
};
|
};
|
||||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
|||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
/* core timer */
|
/* core timer */
|
||||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||||
|
|
||||||
/* core UART */
|
/* core UART */
|
||||||
{ Board::TL16C750_3_IRQ, 1 }
|
{ Board::TL16C750_3_IRQ, 1 }
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
#define _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_
|
#define _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <cortex_a9/cpu/section_table.h>
|
#include <arm/v7/section_table.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software TLB controls
|
* Software TLB controls
|
||||||
*/
|
*/
|
||||||
class Software_tlb : public Genode::Section_table { };
|
class Software_tlb : public Arm_v7::Section_table { };
|
||||||
|
|
||||||
#endif /* _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_ */
|
#endif /* _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_ */
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#
|
#
|
||||||
# \brief Pandaboard-specific makefile for core
|
# \brief Makefile for core
|
||||||
# \author Stefan Kalkowski
|
# \author Stefan Kalkowski
|
||||||
# \date 2012-10-04
|
# \date 2012-10-04
|
||||||
#
|
#
|
||||||
|
|
||||||
REQUIRES = platform_panda_a2
|
# declare wich specs must be given to build this target
|
||||||
|
REQUIRES += platform_panda_a2
|
||||||
|
|
||||||
|
# include less specific target parts
|
||||||
include $(REP_DIR)/src/core/target.inc
|
include $(REP_DIR)/src/core/target.inc
|
||||||
|
|
||||||
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <cortex_a9/cpu/core.h>
|
#include <cortex_a9/cpu.h>
|
||||||
#include <pic/pl390_base.h>
|
#include <cortex_a9/no_trustzone/pic.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
|||||||
{
|
{
|
||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
|
{ 0, Cortex_a9_no_trustzone::Pic::MAX_INTERRUPT_ID + 1 }
|
||||||
};
|
};
|
||||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
}
|
}
|
||||||
@ -47,7 +48,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
|||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
/* core timer */
|
/* core timer */
|
||||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||||
|
|
||||||
/* core UART */
|
/* core UART */
|
||||||
{ Board::PL011_0_IRQ, 1 }
|
{ Board::PL011_0_IRQ, 1 }
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
#ifndef _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
#ifndef _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
||||||
#define _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
#define _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* core includes */
|
||||||
#include <cortex_a9/cpu/section_table.h>
|
#include <arm/v7/section_table.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software TLB controls
|
* Software TLB controls
|
||||||
*/
|
*/
|
||||||
class Software_tlb : public Genode::Section_table { };
|
class Software_tlb : public Arm_v7::Section_table { };
|
||||||
|
|
||||||
#endif /* _SRC__CORE__PBXA9__SOFTWARE_TLB_H_ */
|
#endif /* _SRC__CORE__PBXA9__SOFTWARE_TLB_H_ */
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#
|
#
|
||||||
# \brief PBXA9-specific makefile for core
|
# \brief Makefile for core
|
||||||
# \author Stefan Kalkowski
|
# \author Stefan Kalkowski
|
||||||
# \date 2012-10-04
|
# \date 2012-10-04
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# declare wich specs must be given to build this target
|
||||||
REQUIRES = platform_pbxa9
|
REQUIRES = platform_pbxa9
|
||||||
|
|
||||||
|
# include less specific target parts
|
||||||
include $(REP_DIR)/src/core/target.inc
|
include $(REP_DIR)/src/core/target.inc
|
||||||
|
|
||||||
|
@ -142,6 +142,10 @@ Platform::Platform() :
|
|||||||
printf("-------------------\n");
|
printf("-------------------\n");
|
||||||
_io_mem_alloc.raw()->dump_addr_tree();
|
_io_mem_alloc.raw()->dump_addr_tree();
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
printf("IRQ allocator\n");
|
||||||
|
printf("-------------------\n");
|
||||||
|
_irq_alloc.raw()->dump_addr_tree();
|
||||||
|
printf("\n");
|
||||||
printf("ROM filesystem\n");
|
printf("ROM filesystem\n");
|
||||||
printf("--------------\n");
|
printf("--------------\n");
|
||||||
_rom_fs.print_fs();
|
_rom_fs.print_fs();
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
TARGET = core
|
TARGET = core
|
||||||
|
|
||||||
# use core specific startup library
|
# use core specific startup library
|
||||||
STARTUP_LIB = startup_core
|
STARTUP_LIB = core_support
|
||||||
|
|
||||||
# add library dependencies
|
# add library dependencies
|
||||||
LIBS += cxx raw_ipc heap child pager lock console signal raw_server \
|
LIBS += cxx raw_ipc heap child process pager lock console signal raw_server \
|
||||||
syscall startup_core core_support
|
syscall core_support
|
||||||
|
|
||||||
# add include paths
|
# add include paths
|
||||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <cortex_a9/cpu/core.h>
|
#include <cortex_a9/cpu.h>
|
||||||
#include <pic/pl390_base.h>
|
#include <cortex_a9/no_trustzone/pic.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
|||||||
{
|
{
|
||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
{ 0, Pl390_base::MAX_INTERRUPT_ID + 1 }
|
{ 0, Cortex_a9_no_trustzone::Pic::MAX_INTERRUPT_ID + 1 }
|
||||||
};
|
};
|
||||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
|||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
/* Core timer */
|
/* Core timer */
|
||||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||||
|
|
||||||
/* Core UART */
|
/* Core UART */
|
||||||
{ Board::PL011_0_IRQ, 1 }
|
{ Board::PL011_0_IRQ, 1 }
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
#define _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_
|
#define _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <cortex_a9/cpu/section_table.h>
|
#include <arm/v7/section_table.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Software TLB controls
|
* Software TLB controls
|
||||||
*/
|
*/
|
||||||
class Software_tlb : public Genode::Section_table { };
|
class Software_tlb : public Arm_v7::Section_table { };
|
||||||
|
|
||||||
#endif /* _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_ */
|
#endif /* _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_ */
|
||||||
|
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
#
|
#
|
||||||
# \brief VEA9x4-specific makefile for core
|
# \brief Makefile for core
|
||||||
# \author Stefan Kalkowski
|
# \author Stefan Kalkowski
|
||||||
# \date 2012-10-04
|
# \date 2012-10-04
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# declare wich specs must be given to build this target
|
||||||
REQUIRES = platform_vea9x4
|
REQUIRES = platform_vea9x4
|
||||||
|
|
||||||
|
# adjust link address of a trustzone text segment
|
||||||
ifeq ($(filter-out $(SPECS),trustzone),)
|
ifeq ($(filter-out $(SPECS),trustzone),)
|
||||||
LD_TEXT_ADDR = 0x48000000
|
LD_TEXT_ADDR = 0x48000000
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# include less specific target parts
|
||||||
include $(REP_DIR)/src/core/target.inc
|
include $(REP_DIR)/src/core/target.inc
|
||||||
|
@ -14,11 +14,6 @@
|
|||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <kernel_support.h>
|
#include <kernel_support.h>
|
||||||
|
|
||||||
|
Cpu::User_context::User_context() {
|
||||||
|
cpsr = Psr::init_user_with_trustzone(); }
|
||||||
|
|
||||||
Genode::Cortex_a9::User_context::User_context()
|
|
||||||
{
|
|
||||||
/* Execute in usermode with FIQ's enabled and IRQ's and
|
|
||||||
* asynchronous aborts disabled */
|
|
||||||
cpsr = Cpsr::M::bits(Cpsr::M::USER) | Cpsr::F::bits(0) |
|
|
||||||
Cpsr::I::bits(1) | Cpsr::A::bits(1);
|
|
||||||
}
|
|
||||||
|
@ -15,66 +15,26 @@
|
|||||||
#define _SRC__CORE__VEA9X4__TRUSTZONE__KERNEL_SUPPORT_H_
|
#define _SRC__CORE__VEA9X4__TRUSTZONE__KERNEL_SUPPORT_H_
|
||||||
|
|
||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <cortex_a9/cpu/core.h>
|
#include <cortex_a9/cpu.h>
|
||||||
#include <pic/pl390_base.h>
|
#include <cortex_a9/timer.h>
|
||||||
|
#include <vea9x4_trustzone/pic.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPU driver
|
* CPU driver
|
||||||
*/
|
*/
|
||||||
class Cpu : public Genode::Cortex_a9 { };
|
class Cpu : public Cortex_a9::Cpu { };
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
/* import Genode types */
|
|
||||||
typedef Genode::Cortex_a9 Cortex_a9;
|
|
||||||
typedef Genode::Pl390_base Pl390_base;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel interrupt-controller
|
* Programmable interrupt controller
|
||||||
*/
|
*/
|
||||||
class Pic : public Pl390_base
|
class Pic : public Vea9x4_trustzone::Pic { };
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
Pic() : Pl390_base(Cortex_a9::PL390_DISTRIBUTOR_MMIO_BASE,
|
|
||||||
Cortex_a9::PL390_CPU_MMIO_BASE)
|
|
||||||
{
|
|
||||||
/* configure every shared peripheral interrupt */
|
|
||||||
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) {
|
|
||||||
_distr.write<Distr::Icdicr::Edge_triggered>(0, i);
|
|
||||||
_distr.write<Distr::Icdipr::Priority>(0, i);
|
|
||||||
_distr.write<Distr::Icdiptr::Cpu_targets>(Distr::Icdiptr::Cpu_targets::ALL, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable the priority filter */
|
|
||||||
_cpu.write<Cpu::Iccpmr::Priority>(0xff);
|
|
||||||
|
|
||||||
/* signal secure IRQ via FIQ interface */
|
|
||||||
_cpu.write<Cpu::Iccicr>(Cpu::Iccicr::Enable_s::bits(1) |
|
|
||||||
Cpu::Iccicr::Enable_ns::bits(1) |
|
|
||||||
Cpu::Iccicr::Fiq_en::bits(1));
|
|
||||||
|
|
||||||
/* use whole band of prios */
|
|
||||||
_cpu.write<Cpu::Iccbpr::Binary_point>(Cpu::Iccbpr::Binary_point::NO_PREEMPTION);
|
|
||||||
|
|
||||||
/* enable device */
|
|
||||||
_distr.write<Distr::Icddcr>(Distr::Icddcr::Enable::bits(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark interrupt i unsecure
|
|
||||||
*/
|
|
||||||
void unsecure(unsigned i) {
|
|
||||||
_distr.write<Distr::Icdisr::Nonsecure>(1, i); }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel timer
|
* Kernel timer
|
||||||
*/
|
*/
|
||||||
class Timer : public Cortex_a9::Private_timer { };
|
class Timer : public Cortex_a9::Timer { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
#include <pic/pl390_base.h>
|
#include <vea9x4_trustzone/pic.h>
|
||||||
#include <cortex_a9/cpu/core.h>
|
#include <cortex_a9/cpu.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
|||||||
{ 0, 34 },
|
{ 0, 34 },
|
||||||
{ 37, 3 },
|
{ 37, 3 },
|
||||||
{ 46, 1 },
|
{ 46, 1 },
|
||||||
{ 49, Pl390_base::MAX_INTERRUPT_ID - 49 }
|
{ 49, Vea9x4_trustzone::Pic::MAX_INTERRUPT_ID - 49 }
|
||||||
};
|
};
|
||||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
|||||||
static Native_region _regions[] =
|
static Native_region _regions[] =
|
||||||
{
|
{
|
||||||
/* Core timer */
|
/* Core timer */
|
||||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||||
|
|
||||||
/* Core UART */
|
/* Core UART */
|
||||||
{ Board::PL011_0_IRQ, 1 }
|
{ Board::PL011_0_IRQ, 1 }
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
/* Core includes */
|
/* Core includes */
|
||||||
#include <trustzone.h>
|
#include <trustzone.h>
|
||||||
#include <kernel_support.h>
|
#include <kernel_support.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
/* monitor exception vector address */
|
/* monitor exception vector address */
|
||||||
extern int _mon_kernel_entry;
|
extern int _mon_kernel_entry;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Vm_session_component for base-hw
|
* \brief VM session component for 'base-hw'
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
* \date 2012-10-08
|
* \date 2012-10-08
|
||||||
*/
|
*/
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include <root/root.h>
|
#include <root/root.h>
|
||||||
#include <cpu/cpu_state.h>
|
#include <cpu/cpu_state.h>
|
||||||
|
|
||||||
/* Core includes */
|
/* core includes */
|
||||||
#include <vm_session_component.h>
|
#include <vm_session_component.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
@ -17,19 +17,6 @@
|
|||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
|
|
||||||
/* zero-fill BSS segment but don't pollute thread-entry arguments */
|
|
||||||
.extern _bss_start
|
|
||||||
ldr r4, =_bss_start
|
|
||||||
.extern _bss_end
|
|
||||||
ldr r3, =_bss_end
|
|
||||||
mov r2, #0
|
|
||||||
sub r3, r3, #4
|
|
||||||
1:
|
|
||||||
str r2, [r4]
|
|
||||||
add r4, r4, #4
|
|
||||||
cmp r4, r3
|
|
||||||
bne 1b
|
|
||||||
|
|
||||||
/* fetch thread-entry arguments to their destinations in BSS */
|
/* fetch thread-entry arguments to their destinations in BSS */
|
||||||
ldr r1, =_main_utcb
|
ldr r1, =_main_utcb
|
||||||
str r0, [r1]
|
str r0, [r1]
|
||||||
@ -38,8 +25,7 @@
|
|||||||
ldr sp, =_main_stack_high
|
ldr sp, =_main_stack_high
|
||||||
.extern _main
|
.extern _main
|
||||||
bl _main
|
bl _main
|
||||||
1:
|
1: b 1b
|
||||||
b 1b
|
|
||||||
|
|
||||||
/* dynamic symbol object handle */
|
/* dynamic symbol object handle */
|
||||||
.align 3
|
.align 3
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* \brief CPU state
|
* \brief CPU state
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
* \author Stefan Kalkowski
|
* \author Stefan Kalkowski
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2011-05-06
|
* \date 2011-05-06
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,37 +16,44 @@
|
|||||||
#ifndef _INCLUDE__ARM__CPU__CPU_STATE_H_
|
#ifndef _INCLUDE__ARM__CPU__CPU_STATE_H_
|
||||||
#define _INCLUDE__ARM__CPU__CPU_STATE_H_
|
#define _INCLUDE__ARM__CPU__CPU_STATE_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
#include <base/stdint.h>
|
#include <base/stdint.h>
|
||||||
|
|
||||||
namespace Genode {
|
namespace Genode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic CPU state
|
||||||
|
*/
|
||||||
struct Cpu_state
|
struct Cpu_state
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Native exception types
|
* Native exception types
|
||||||
*/
|
*/
|
||||||
enum Cpu_exception {
|
enum Cpu_exception {
|
||||||
RESET,
|
RESET = 1,
|
||||||
UNDEFINED_INSTRUCTION,
|
UNDEFINED_INSTRUCTION = 2,
|
||||||
SUPERVISOR_CALL,
|
SUPERVISOR_CALL = 3,
|
||||||
PREFETCH_ABORT,
|
PREFETCH_ABORT = 4,
|
||||||
DATA_ABORT,
|
DATA_ABORT = 5,
|
||||||
INTERRUPT_REQUEST,
|
INTERRUPT_REQUEST = 6,
|
||||||
FAST_INTERRUPT_REQUEST,
|
FAST_INTERRUPT_REQUEST = 7,
|
||||||
MAX_CPU_EXCEPTION,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { MAX_GPR = 13 };
|
/**
|
||||||
|
* Registers
|
||||||
addr_t r[MAX_GPR]; /* r0-r12 - general purpose */
|
*/
|
||||||
addr_t sp; /* r13 - stack pointer */
|
addr_t r0, r1, r2, r3, r4, r5, r6,
|
||||||
addr_t lr; /* r14 - link register */
|
r7, r8, r9, r10, r11, r12; /* general purpose register 0..12 */
|
||||||
addr_t ip; /* r15 - instruction pointer */
|
addr_t sp; /* stack pointer */
|
||||||
addr_t cpsr; /* current program status register */
|
addr_t lr; /* link register */
|
||||||
Cpu_exception cpu_exception; /* last exception */
|
addr_t ip; /* instruction pointer */
|
||||||
|
addr_t cpsr; /* current program status register */
|
||||||
|
addr_t cpu_exception; /* last hardware exception */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend CPU state by banked registers
|
||||||
|
*/
|
||||||
struct Cpu_state_modes : Cpu_state
|
struct Cpu_state_modes : Cpu_state
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
274
base/include/drivers/uart/imx31_uart_base.h
Normal file
274
base/include/drivers/uart/imx31_uart_base.h
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
* \brief Driver base for i.MX31 UART-module
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
|
* \date 2012-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__DRIVERS__UART__IMX31_UART_BASE_H_
|
||||||
|
#define _INCLUDE__DRIVERS__UART__IMX31_UART_BASE_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
namespace Genode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Driver base for i.MX31 UART-module
|
||||||
|
*/
|
||||||
|
class Imx31_uart_base : Mmio
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Control register 1
|
||||||
|
*/
|
||||||
|
struct Cr1 : Register<0x80, 32>
|
||||||
|
{
|
||||||
|
struct Uart_en : Bitfield<0, 1> { }; /* enable UART */
|
||||||
|
struct Doze : Bitfield<1, 1> { }; /* disable on doze */
|
||||||
|
struct At_dma_en : Bitfield<2, 1> { }; /* aging DMA
|
||||||
|
* timer on */
|
||||||
|
struct Tx_dma_en : Bitfield<3, 1> { }; /* TX ready DMA on */
|
||||||
|
struct Snd_brk : Bitfield<4, 1> { }; /* send breaks */
|
||||||
|
struct Rtsd_en : Bitfield<5, 1> { }; /* RTS delta IRQ on */
|
||||||
|
struct Tx_mpty_en : Bitfield<6, 1> { }; /* TX empty IRQ on */
|
||||||
|
struct Ir_en : Bitfield<7, 1> { }; /* enable infrared */
|
||||||
|
struct Rx_dma_en : Bitfield<8, 1> { }; /* RX ready DMA on */
|
||||||
|
struct R_rdy_en : Bitfield<9, 1> { }; /* RX ready IRQ on */
|
||||||
|
|
||||||
|
struct Icd : Bitfield<10, 2> /* idle IRQ condition */
|
||||||
|
{
|
||||||
|
enum { IDLE_4_FRAMES = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Id_en : Bitfield<12, 1> { }; /* enable idle IRQ */
|
||||||
|
struct T_rdy_en : Bitfield<13, 1> { }; /* TX ready IRQ on */
|
||||||
|
struct Adbr : Bitfield<14, 1> { }; /* enable baud-rate
|
||||||
|
* auto detect */
|
||||||
|
struct Ad_en : Bitfield<15, 1> { }; /* enable ADBR IRQ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization value
|
||||||
|
*/
|
||||||
|
static access_t init_value()
|
||||||
|
{
|
||||||
|
return Uart_en::bits(1) |
|
||||||
|
Doze::bits(0) |
|
||||||
|
At_dma_en::bits(0) |
|
||||||
|
Tx_dma_en::bits(0) |
|
||||||
|
Snd_brk::bits(0) |
|
||||||
|
Rtsd_en::bits(0) |
|
||||||
|
Tx_mpty_en::bits(0) |
|
||||||
|
Ir_en::bits(0) |
|
||||||
|
Rx_dma_en::bits(0) |
|
||||||
|
R_rdy_en::bits(0) |
|
||||||
|
Id_en::bits(0) |
|
||||||
|
T_rdy_en::bits(0) |
|
||||||
|
Adbr::bits(0) |
|
||||||
|
Ad_en::bits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control register 2
|
||||||
|
*/
|
||||||
|
struct Cr2 : Register<0x84, 32>
|
||||||
|
{
|
||||||
|
struct S_rst : Bitfield<0, 1> /* SW reset bit */
|
||||||
|
{
|
||||||
|
enum { NO_RESET = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Rx_en : Bitfield<1, 1> { }; /* enable receiver */
|
||||||
|
struct Tx_en : Bitfield<2, 1> { }; /* enable transmitter */
|
||||||
|
struct At_en : Bitfield<3, 1> { }; /* enable aging timer */
|
||||||
|
struct Rts_en : Bitfield<4, 1> { }; /* send request IRQ on */
|
||||||
|
|
||||||
|
struct Ws : Bitfield<5, 1> /* select word size */
|
||||||
|
{
|
||||||
|
enum { _8_BITS = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stpb : Bitfield<6, 1> /* number of stop bits */
|
||||||
|
{
|
||||||
|
enum { _1_BIT = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Pr_en : Bitfield<8, 1> { }; /* enable parity */
|
||||||
|
struct Esc_en : Bitfield<11, 1> { }; /* escape detection on */
|
||||||
|
|
||||||
|
struct Ctsc : Bitfield<13, 1> /* select CTS control */
|
||||||
|
{
|
||||||
|
enum { BY_RECEIVER = 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Irts : Bitfield<14, 1> { }; /* ignore RTS pin */
|
||||||
|
struct Esci : Bitfield<15, 1> { }; /* enable escape IRQ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization value
|
||||||
|
*/
|
||||||
|
static access_t init_value()
|
||||||
|
{
|
||||||
|
return S_rst::bits(S_rst::NO_RESET) |
|
||||||
|
Rx_en::bits(0) |
|
||||||
|
Tx_en::bits(1) |
|
||||||
|
At_en::bits(0) |
|
||||||
|
Rts_en::bits(0) |
|
||||||
|
Ws::bits(Ws::_8_BITS) |
|
||||||
|
Stpb::bits(Stpb::_1_BIT) |
|
||||||
|
Pr_en::bits(0) |
|
||||||
|
Esc_en::bits(0) |
|
||||||
|
Ctsc::bits(Ctsc::BY_RECEIVER) |
|
||||||
|
Irts::bits(1) |
|
||||||
|
Esci::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control register 3
|
||||||
|
*/
|
||||||
|
struct Cr3 : Register<0x88, 32>
|
||||||
|
{
|
||||||
|
struct Rxdmux_sel : Bitfield<2, 1> { }; /* use muxed RXD */
|
||||||
|
struct Aci_en : Bitfield<0, 1> { }; /* autobaud count IRQ on */
|
||||||
|
struct Dtrd_en : Bitfield<3, 1> { }; /* data terminal ready
|
||||||
|
* delta IRQ on */
|
||||||
|
struct Awak_en : Bitfield<4, 1> { }; /* wake IRQ on */
|
||||||
|
struct Air_int_en : Bitfield<5, 1> { }; /* IR wake IRQ on */
|
||||||
|
struct Rx_ds_en : Bitfield<6, 1> { }; /* RX status IRQ on */
|
||||||
|
struct Ad_nimp : Bitfield<7, 1> { }; /* autobaud detect off */
|
||||||
|
struct Ri_en : Bitfield<8, 1> { }; /* ring indicator IRQ on */
|
||||||
|
struct Dcd_en : Bitfield<9, 1> { }; /* data carrier detect
|
||||||
|
* IRQ on */
|
||||||
|
struct Dsr : Bitfield<10,1> { }; /* DSR/DTR output */
|
||||||
|
struct Frame_en : Bitfield<11,1> { }; /* frame error IRQ on */
|
||||||
|
struct Parity_en : Bitfield<12,1> { }; /* parity error IRQ on */
|
||||||
|
struct Dtr_en : Bitfield<13,1> { }; /* data terminal ready
|
||||||
|
* IRQ on */
|
||||||
|
struct Dpec_ctrl : Bitfield<14,2> { }; /* DTR/DSR IRQ edge
|
||||||
|
* control */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization value
|
||||||
|
*/
|
||||||
|
static access_t init_value()
|
||||||
|
{
|
||||||
|
return Aci_en::bits(0) |
|
||||||
|
Rxdmux_sel::bits(0) |
|
||||||
|
Dtrd_en::bits(0) |
|
||||||
|
Awak_en::bits(0) |
|
||||||
|
Air_int_en::bits(0) |
|
||||||
|
Rx_ds_en::bits(0) |
|
||||||
|
Ad_nimp::bits(1) |
|
||||||
|
Ri_en::bits(0) |
|
||||||
|
Dcd_en::bits(0) |
|
||||||
|
Dsr::bits(0) |
|
||||||
|
Frame_en::bits(0) |
|
||||||
|
Parity_en::bits(0) |
|
||||||
|
Dtr_en::bits(0) |
|
||||||
|
Dpec_ctrl::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Control register 4
|
||||||
|
*/
|
||||||
|
struct Cr4 : Register<0x8c, 32>
|
||||||
|
{
|
||||||
|
struct Dr_en : Bitfield<0, 1> { }; /* RX data ready IRQ on */
|
||||||
|
struct Or_en : Bitfield<1, 1> { }; /* RX overrun IRQ on */
|
||||||
|
struct Bk_en : Bitfield<2, 1> { }; /* BREAK IRQ on */
|
||||||
|
struct Tc_en : Bitfield<3, 1> { }; /* TX complete IRQ on */
|
||||||
|
struct Lp_dis : Bitfield<4, 1> { }; /* low power off */
|
||||||
|
struct IR_sc : Bitfield<5, 1> { }; /* use UART ref clock
|
||||||
|
* for vote logic */
|
||||||
|
struct Id_dma_en : Bitfield<6, 1> { }; /* idle DMA IRQ on */
|
||||||
|
struct Wake_en : Bitfield<7, 1> { }; /* WAKE IRQ on */
|
||||||
|
struct IR_en : Bitfield<8, 1> { }; /* serial IR IRQ on */
|
||||||
|
struct Cts_level : Bitfield<10,6> { }; /* CTS trigger level*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization value
|
||||||
|
*/
|
||||||
|
static access_t init_value()
|
||||||
|
{
|
||||||
|
return Dr_en::bits(0) |
|
||||||
|
Or_en::bits(0) |
|
||||||
|
Bk_en::bits(0) |
|
||||||
|
Tc_en::bits(0) |
|
||||||
|
Lp_dis::bits(0) |
|
||||||
|
IR_sc::bits(0) |
|
||||||
|
Id_dma_en::bits(0) |
|
||||||
|
Wake_en::bits(0) |
|
||||||
|
IR_en::bits(0) |
|
||||||
|
Cts_level::bits(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status register 2
|
||||||
|
*/
|
||||||
|
struct Sr2 : Register<0x98, 32>
|
||||||
|
{
|
||||||
|
struct Txdc : Bitfield<3, 1> { }; /* transmission complete */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmitter register
|
||||||
|
*/
|
||||||
|
struct Txd : Register<0x40, 32>
|
||||||
|
{
|
||||||
|
struct Tx_data : Bitfield<0, 8> { }; /* transmit data */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transmit character 'c' without care about its type
|
||||||
|
*/
|
||||||
|
inline void _put_char(char const c)
|
||||||
|
{
|
||||||
|
while (!read<Sr2::Txdc>()) ;
|
||||||
|
write<Txd::Tx_data>(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* \param base device MMIO base
|
||||||
|
*/
|
||||||
|
explicit Imx31_uart_base(addr_t const base) : Mmio(base)
|
||||||
|
{
|
||||||
|
write<Cr1>(Cr1::init_value());
|
||||||
|
write<Cr2>(Cr2::init_value());
|
||||||
|
write<Cr3>(Cr3::init_value());
|
||||||
|
write<Cr4>(Cr4::init_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print character 'c' through the UART
|
||||||
|
*/
|
||||||
|
inline void put_char(char const c)
|
||||||
|
{
|
||||||
|
enum { ASCII_LINE_FEED = 10,
|
||||||
|
ASCII_CARRIAGE_RETURN = 13 };
|
||||||
|
|
||||||
|
/* prepend line feed with carriage return */
|
||||||
|
if (c == ASCII_LINE_FEED) _put_char(ASCII_CARRIAGE_RETURN);
|
||||||
|
|
||||||
|
/* transmit character */
|
||||||
|
_put_char(c);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__DRIVERS__UART__IMX31_UART_BASE_H_ */
|
||||||
|
|
53
base/include/platform/imx31/drivers/board.h
Normal file
53
base/include/platform/imx31/drivers/board.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* \brief Board definitions for the i.MX31
|
||||||
|
* \author Martin Stein
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2011-11-03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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__BOARD_H_
|
||||||
|
#define _INCLUDE__PLATFORM__BOARD_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
namespace Genode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* i.MX31 motherboard
|
||||||
|
*/
|
||||||
|
struct Board
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
CSD0_SDRAM_BASE = 0x80000000,
|
||||||
|
CSD0_SDRAM_SIZE = 0x10000000,
|
||||||
|
|
||||||
|
UART_1_IRQ = 45,
|
||||||
|
UART_1_MMIO_BASE = 0x43f90000,
|
||||||
|
UART_1_MMIO_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
EPIT_1_IRQ = 28,
|
||||||
|
EPIT_1_MMIO_BASE = 0x53f94000,
|
||||||
|
EPIT_1_MMIO_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
AVIC_MMIO_BASE = 0x68000000,
|
||||||
|
AVIC_MMIO_SIZE = 0x04000000,
|
||||||
|
|
||||||
|
AIPS_1_MMIO_BASE = 0x43F00000,
|
||||||
|
AIPS_1_MMIO_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
AIPS_2_MMIO_BASE = 0x53F00000,
|
||||||
|
AIPS_2_MMIO_SIZE = 0x00004000,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _INCLUDE__PLATFORM__BOARD_H_ */
|
||||||
|
|
@ -42,11 +42,12 @@ namespace Genode
|
|||||||
CORTEX_A9_PRIVATE_MEM_BASE = L4_PER_BASE + 0x240000,
|
CORTEX_A9_PRIVATE_MEM_BASE = L4_PER_BASE + 0x240000,
|
||||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
||||||
CORTEX_A9_CLOCK = MPU_DPLL_CLOCK,
|
CORTEX_A9_CLOCK = MPU_DPLL_CLOCK,
|
||||||
CORTEX_A9_SECURITY_EXTENSION = 0,
|
|
||||||
|
|
||||||
/* RAM */
|
/* RAM */
|
||||||
EMIF1_EMIF2_CS0_SDRAM_BASE = 0x80000000,
|
EMIF1_EMIF2_CS0_SDRAM_BASE = 0x80000000,
|
||||||
EMIF1_EMIF2_CS0_SDRAM_SIZE = 0x40000000,
|
EMIF1_EMIF2_CS0_SDRAM_SIZE = 0x40000000,
|
||||||
|
|
||||||
|
SECURITY_EXTENSION = 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,6 @@ namespace Genode
|
|||||||
CORTEX_A9_CLOCK = OSC_7_CLOCK * 5,
|
CORTEX_A9_CLOCK = OSC_7_CLOCK * 5,
|
||||||
CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000,
|
CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000,
|
||||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000,
|
CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000,
|
||||||
CORTEX_A9_SECURITY_EXTENSION = 0,
|
|
||||||
|
|
||||||
/* UART */
|
/* UART */
|
||||||
PL011_0_MMIO_BASE = SOUTHBRIDGE_APB_BASE + 0x9000,
|
PL011_0_MMIO_BASE = SOUTHBRIDGE_APB_BASE + 0x9000,
|
||||||
@ -54,7 +53,9 @@ namespace Genode
|
|||||||
SP804_0_1_MMIO_BASE = SOUTHBRIDGE_APB_BASE + 0x11000,
|
SP804_0_1_MMIO_BASE = SOUTHBRIDGE_APB_BASE + 0x11000,
|
||||||
SP804_0_1_MMIO_SIZE = 4*1024,
|
SP804_0_1_MMIO_SIZE = 4*1024,
|
||||||
SP804_0_1_IRQ = 36,
|
SP804_0_1_IRQ = 36,
|
||||||
SP804_0_1_CLOCK = 1*1000*1000,
|
SP804_0_1_CLOCK = 1000*1000,
|
||||||
|
|
||||||
|
SECURITY_EXTENSION = 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ namespace Genode
|
|||||||
CORTEX_A9_PRIVATE_MEM_BASE = 0x1e000000,
|
CORTEX_A9_PRIVATE_MEM_BASE = 0x1e000000,
|
||||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
||||||
CORTEX_A9_CLOCK = TCREF_CLOCK,
|
CORTEX_A9_CLOCK = TCREF_CLOCK,
|
||||||
CORTEX_A9_SECURITY_EXTENSION = 1,
|
|
||||||
|
|
||||||
/* RAM */
|
/* RAM */
|
||||||
LOCAL_DDR2_BASE = 0x60000000,
|
LOCAL_DDR2_BASE = 0x60000000,
|
||||||
@ -68,6 +67,8 @@ namespace Genode
|
|||||||
/* SRAM */
|
/* SRAM */
|
||||||
SRAM_BASE = SMB_CS2_BASE,
|
SRAM_BASE = SMB_CS2_BASE,
|
||||||
SRAM_SIZE = 0x01ffffff,
|
SRAM_SIZE = 0x01ffffff,
|
||||||
|
|
||||||
|
SECURITY_EXTENSION = 1,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
18
base/mk/spec-arm_v6.mk
Normal file
18
base/mk/spec-arm_v6.mk
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#
|
||||||
|
# \brief Build-system configurations for ARMv6
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-09-26
|
||||||
|
#
|
||||||
|
|
||||||
|
# denote wich specs are also fullfilled by this spec
|
||||||
|
SPECS += arm
|
||||||
|
|
||||||
|
# configure compiler
|
||||||
|
CC_MARCH += -march=armv6
|
||||||
|
|
||||||
|
# add repository relative include paths
|
||||||
|
REP_INC_DIR += include/arm_v6
|
||||||
|
|
||||||
|
# include implied specs
|
||||||
|
include $(call select_from_repositories,mk/spec-arm.mk)
|
||||||
|
|
15
base/mk/spec-arm_v7.mk
Normal file
15
base/mk/spec-arm_v7.mk
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# \brief Build-system configurations for ARMv7
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-09-26
|
||||||
|
#
|
||||||
|
|
||||||
|
# denote wich specs are also fullfilled by this spec
|
||||||
|
SPECS += arm
|
||||||
|
|
||||||
|
# add repository relative include paths
|
||||||
|
REP_INC_DIR += include/arm_v7
|
||||||
|
|
||||||
|
# include implied specs
|
||||||
|
include $(call select_from_repositories,mk/spec-arm.mk)
|
||||||
|
|
@ -1,10 +1,18 @@
|
|||||||
SPECS += arm
|
#
|
||||||
|
# \brief Build-system configurations for ARMv7a
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-09-26
|
||||||
|
#
|
||||||
|
|
||||||
#
|
# denote wich specs are also fullfilled by this spec
|
||||||
# Configure target CPU
|
SPECS += arm_v7
|
||||||
#
|
|
||||||
|
# configure compiler
|
||||||
CC_MARCH += -march=armv7-a
|
CC_MARCH += -march=armv7-a
|
||||||
|
|
||||||
|
# add repository relative include paths
|
||||||
REP_INC_DIR += include/arm_v7a
|
REP_INC_DIR += include/arm_v7a
|
||||||
|
|
||||||
include $(call select_from_repositories,mk/spec-arm.mk)
|
# include implied specs
|
||||||
|
include $(call select_from_repositories,mk/spec-arm_v7.mk)
|
||||||
|
|
||||||
|
15
base/mk/spec-platform_imx31.mk
Normal file
15
base/mk/spec-platform_imx31.mk
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#
|
||||||
|
# \brief Build-system configurations for Freescale i.MX31
|
||||||
|
# \author Martin Stein
|
||||||
|
# \date 2012-09-26
|
||||||
|
#
|
||||||
|
|
||||||
|
# denote wich specs are also fullfilled by this spec
|
||||||
|
SPECS += arm_v6
|
||||||
|
|
||||||
|
# add repository relative include paths
|
||||||
|
REP_INC_DIR += include/platform/imx31
|
||||||
|
|
||||||
|
# include implied specs
|
||||||
|
include $(call select_from_repositories,mk/spec-arm_v6.mk)
|
||||||
|
|
@ -21,8 +21,6 @@ namespace Genode
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Basic driver for the ARM SP804 timer
|
* Basic driver for the ARM SP804 timer
|
||||||
*
|
|
||||||
* Uses only timer module 0.
|
|
||||||
*/
|
*/
|
||||||
template <unsigned long CLK>
|
template <unsigned long CLK>
|
||||||
class Sp804_base : public Mmio
|
class Sp804_base : public Mmio
|
||||||
|
@ -152,8 +152,8 @@ namespace Genode {
|
|||||||
_load_initrd();
|
_load_initrd();
|
||||||
_prepare_atag();
|
_prepare_atag();
|
||||||
_state->cpsr = 0x93; /* SVC mode and IRQs disabled */
|
_state->cpsr = 0x93; /* SVC mode and IRQs disabled */
|
||||||
_state->r[1] = 2272; /* MACH_TYPE vexpress board */
|
_state->r1 = 2272; /* MACH_TYPE vexpress board */
|
||||||
_state->r[2] = _ram.base() + ATAG_OFFSET; /* ATAG addr */
|
_state->r2 = _ram.base() + ATAG_OFFSET; /* ATAG addr */
|
||||||
_vm_con.exception_handler(sig_cap);
|
_vm_con.exception_handler(sig_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,8 +168,19 @@ namespace Genode {
|
|||||||
"data_abort", "irq", "fiq" };
|
"data_abort", "irq", "fiq" };
|
||||||
|
|
||||||
printf("Cpu state:\n");
|
printf("Cpu state:\n");
|
||||||
for (unsigned i = 0; i<13; i++)
|
printf(" r0 = %08lx\n", _state->r0);
|
||||||
printf(" r%x = %08lx\n", i, _state->r[i]);
|
printf(" r1 = %08lx\n", _state->r1);
|
||||||
|
printf(" r2 = %08lx\n", _state->r2);
|
||||||
|
printf(" r3 = %08lx\n", _state->r3);
|
||||||
|
printf(" r4 = %08lx\n", _state->r4);
|
||||||
|
printf(" r5 = %08lx\n", _state->r5);
|
||||||
|
printf(" r6 = %08lx\n", _state->r6);
|
||||||
|
printf(" r7 = %08lx\n", _state->r7);
|
||||||
|
printf(" r8 = %08lx\n", _state->r8);
|
||||||
|
printf(" r9 = %08lx\n", _state->r9);
|
||||||
|
printf(" r10 = %08lx\n", _state->r10);
|
||||||
|
printf(" r11 = %08lx\n", _state->r11);
|
||||||
|
printf(" r12 = %08lx\n", _state->r12);
|
||||||
printf(" sp = %08lx\n", _state->sp);
|
printf(" sp = %08lx\n", _state->sp);
|
||||||
printf(" lr = %08lx\n", _state->lr);
|
printf(" lr = %08lx\n", _state->lr);
|
||||||
printf(" ip = %08lx\n", _state->ip);
|
printf(" ip = %08lx\n", _state->ip);
|
||||||
@ -220,8 +231,8 @@ namespace Genode {
|
|||||||
DVI_MODE = 0xc0b00000
|
DVI_MODE = 0xc0b00000
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t ctrl = _vm->state()->r[2];
|
uint32_t ctrl = _vm->state()->r2;
|
||||||
uint32_t data = _vm->state()->r[0];
|
uint32_t data = _vm->state()->r0;
|
||||||
|
|
||||||
switch(ctrl) {
|
switch(ctrl) {
|
||||||
case OSC1:
|
case OSC1:
|
||||||
@ -241,25 +252,25 @@ namespace Genode {
|
|||||||
|
|
||||||
void _handle_hypervisor_call()
|
void _handle_hypervisor_call()
|
||||||
{
|
{
|
||||||
switch (_vm->state()->r[1]) {
|
switch (_vm->state()->r1) {
|
||||||
case SP810_ENABLE:
|
case SP810_ENABLE:
|
||||||
_sp810.enable_timer0();
|
_sp810.enable_timer0();
|
||||||
_sp810.enable_timer1();
|
_sp810.enable_timer1();
|
||||||
break;
|
break;
|
||||||
case CPU_ID:
|
case CPU_ID:
|
||||||
_vm->state()->r[0] = 0x0c000191; // Coretile A9 ID
|
_vm->state()->r0 = 0x0c000191; // Coretile A9 ID
|
||||||
break;
|
break;
|
||||||
case SYS_COUNTER:
|
case SYS_COUNTER:
|
||||||
_vm->state()->r[0] = _sys.counter();
|
_vm->state()->r0 = _sys.counter();
|
||||||
break;
|
break;
|
||||||
case MISC_FLAGS:
|
case MISC_FLAGS:
|
||||||
_vm->state()->r[0] = _sys.misc_flags();
|
_vm->state()->r0 = _sys.misc_flags();
|
||||||
break;
|
break;
|
||||||
case SYS_CTRL:
|
case SYS_CTRL:
|
||||||
_sys_ctrl();
|
_sys_ctrl();
|
||||||
break;
|
break;
|
||||||
case MCI_STATUS:
|
case MCI_STATUS:
|
||||||
_vm->state()->r[0] = _sys.mci_status();
|
_vm->state()->r0 = _sys.mci_status();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PERR("Unknown hypervisor call!");
|
PERR("Unknown hypervisor call!");
|
||||||
|
@ -89,19 +89,19 @@ extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
|
|||||||
} else {
|
} else {
|
||||||
switch((enum reg_index)regno)
|
switch((enum reg_index)regno)
|
||||||
{
|
{
|
||||||
case R0: *reg_content = thread_state.r[0]; PDBG("R0 = %8lx", *reg_content); return 0;
|
case R0: *reg_content = thread_state.r0; PDBG("R0 = %8lx", *reg_content); return 0;
|
||||||
case R1: *reg_content = thread_state.r[1]; PDBG("R1 = %8lx", *reg_content); return 0;
|
case R1: *reg_content = thread_state.r1; PDBG("R1 = %8lx", *reg_content); return 0;
|
||||||
case R2: *reg_content = thread_state.r[2]; PDBG("R2 = %8lx", *reg_content); return 0;
|
case R2: *reg_content = thread_state.r2; PDBG("R2 = %8lx", *reg_content); return 0;
|
||||||
case R3: *reg_content = thread_state.r[3]; PDBG("R3 = %8lx", *reg_content); return 0;
|
case R3: *reg_content = thread_state.r3; PDBG("R3 = %8lx", *reg_content); return 0;
|
||||||
case R4: *reg_content = thread_state.r[4]; PDBG("R4 = %8lx", *reg_content); return 0;
|
case R4: *reg_content = thread_state.r4; PDBG("R4 = %8lx", *reg_content); return 0;
|
||||||
case R5: *reg_content = thread_state.r[5]; PDBG("R5 = %8lx", *reg_content); return 0;
|
case R5: *reg_content = thread_state.r5; PDBG("R5 = %8lx", *reg_content); return 0;
|
||||||
case R6: *reg_content = thread_state.r[6]; PDBG("R6 = %8lx", *reg_content); return 0;
|
case R6: *reg_content = thread_state.r6; PDBG("R6 = %8lx", *reg_content); return 0;
|
||||||
case R7: *reg_content = thread_state.r[7]; PDBG("R7 = %8lx", *reg_content); return 0;
|
case R7: *reg_content = thread_state.r7; PDBG("R7 = %8lx", *reg_content); return 0;
|
||||||
case R8: *reg_content = thread_state.r[8]; PDBG("R8 = %8lx", *reg_content); return 0;
|
case R8: *reg_content = thread_state.r8; PDBG("R8 = %8lx", *reg_content); return 0;
|
||||||
case R9: *reg_content = thread_state.r[9]; PDBG("R9 = %8lx", *reg_content); return 0;
|
case R9: *reg_content = thread_state.r9; PDBG("R9 = %8lx", *reg_content); return 0;
|
||||||
case R10: *reg_content = thread_state.r[10]; PDBG("R10 = %8lx", *reg_content); return 0;
|
case R10: *reg_content = thread_state.r10; PDBG("R10 = %8lx", *reg_content); return 0;
|
||||||
case R11: *reg_content = thread_state.r[11]; PDBG("FP = %8lx", *reg_content); return 0;
|
case R11: *reg_content = thread_state.r11; PDBG("FP = %8lx", *reg_content); return 0;
|
||||||
case R12: *reg_content = thread_state.r[12]; PDBG("R12 = %8lx", *reg_content); return 0;
|
case R12: *reg_content = thread_state.r12; PDBG("R12 = %8lx", *reg_content); return 0;
|
||||||
case SP: *reg_content = thread_state.sp; PDBG("SP = %8lx", *reg_content); return 0;
|
case SP: *reg_content = thread_state.sp; PDBG("SP = %8lx", *reg_content); return 0;
|
||||||
case LR: *reg_content = thread_state.lr; PDBG("LR = %8lx", *reg_content); return 0;
|
case LR: *reg_content = thread_state.lr; PDBG("LR = %8lx", *reg_content); return 0;
|
||||||
case PC: *reg_content = thread_state.ip; PDBG("PC = %8lx", *reg_content); return 0;
|
case PC: *reg_content = thread_state.ip; PDBG("PC = %8lx", *reg_content); return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user