mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37: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->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->cpsr = _regs.cpsr;
|
||||
}
|
||||
|
@ -5,14 +5,21 @@
|
||||
|
||||
Martin Stein
|
||||
|
||||
|
||||
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.
|
||||
Abstract
|
||||
########
|
||||
|
||||
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
|
||||
@ -35,6 +42,7 @@ need Qemu for ARM emulations to run them on your machine:
|
||||
|
||||
! apt-get install qemu-kvm-extras
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
build directory you want to create, and the hardware system to run
|
||||
Genode on. Choose 'hw_pbxa9', 'hw_vea9x4', or 'hw_panda_a2' depending on the
|
||||
hardware system you aim at.
|
||||
build directory you want to create, and the hardware target to run Genode on.
|
||||
|
||||
! <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:
|
||||
|
||||
@ -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
|
||||
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
|
||||
@ -9,9 +9,11 @@
|
||||
Abstract
|
||||
########
|
||||
|
||||
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
|
||||
Linux systems, but all examples originate from a Ubuntu 10.10.
|
||||
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. 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
|
||||
@ -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:
|
||||
|
||||
:[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.
|
||||
Get the linaro U-Boot repository and compile U-Boot for PandaBoard:
|
||||
Ensure that '<GENODE_TOOL_CHAIN_DIR>/bin/' is in your 'PATH' variable.
|
||||
Get the Linaro U-Boot repository and compile U-Boot for PandaBoard:
|
||||
|
||||
! git clone git://git.linaro.org/boot/u-boot-linaro-stable.git
|
||||
! cd <UBOOT_DIR>
|
||||
@ -40,32 +42,32 @@ the array elements separately.
|
||||
|
||||
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
|
||||
the following content:
|
||||
|
||||
! # /etc/default/tftpd-hpa
|
||||
! TFTP_USERNAME="tftp"
|
||||
! TFTP_DIRECTORY="/var/lib/tftpboot"
|
||||
! TFTP_ADDRESS="0.0.0.0:69"
|
||||
! TFTP_OPTIONS="-l"
|
||||
|
||||
Tell U-Boot wich image to load on boot command:
|
||||
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:
|
||||
|
||||
! sudo service tftp-hpa restart
|
||||
! service tftp-hpa restart
|
||||
|
||||
Start Minicom in configuration mode:
|
||||
|
||||
! minicom -s
|
||||
|
||||
Go to 'Serial port setting' and ensure that the device is set the
|
||||
TTY of the COM port you've conntected PandaBoard with, in my case it was
|
||||
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
|
||||
'/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:
|
||||
@ -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.
|
||||
Plug in the power connector or push the 'S1' button if the PandaBoard is
|
||||
already powered.
|
||||
|
||||
Minicom should now show the following message:
|
||||
already powered. Minicom should now show the following message below some
|
||||
bootloader info:
|
||||
|
||||
! Hit any key to stop autoboot:
|
||||
|
||||
@ -89,8 +90,8 @@ image via ethernet:
|
||||
|
||||
! usb start; dhcp; bootelf 0x82000000
|
||||
|
||||
Now the ELF image should start correctly and offer some debug output in
|
||||
minicom. You can now boot further images by redirecting the link
|
||||
'/var/lib/tftpboot/image.elf' accordingly, restarting your pandaboard
|
||||
and instructing 'uboot' again as described above.
|
||||
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 PandaBoard
|
||||
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_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/syscall.h>
|
||||
#include <base/syscall_types.h>
|
||||
|
||||
class Software_tlb;
|
||||
|
||||
@ -35,7 +35,7 @@ namespace Kernel
|
||||
|
||||
/* execution control */
|
||||
NEW_THREAD = 1,
|
||||
DELETE_THREAD = 24,
|
||||
DELETE_THREAD = 26,
|
||||
START_THREAD = 2,
|
||||
PAUSE_THREAD = 3,
|
||||
RESUME_THREAD = 4,
|
||||
@ -70,10 +70,45 @@ namespace Kernel
|
||||
SUBMIT_SIGNAL = 23,
|
||||
|
||||
/* vm specific */
|
||||
NEW_VM = 25,
|
||||
RUN_VM = 26,
|
||||
NEW_VM = 24,
|
||||
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
|
||||
*/
|
||||
@ -107,8 +142,8 @@ namespace Kernel
|
||||
* Restricted to core threads. Regaining of the supplied memory is not
|
||||
* supported by now.
|
||||
*/
|
||||
inline int new_pd(void * const dst)
|
||||
{ return syscall(NEW_PD, (Syscall_arg)dst); }
|
||||
inline int new_pd(void * const 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_
|
||||
#define _INCLUDE__VM_SESSION__CAPABILITY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/capability.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
|
||||
* \date 2012-10-02
|
||||
*/
|
||||
@ -14,16 +14,27 @@
|
||||
#ifndef _INCLUDE__VM_SESSION__CLIENT_H_
|
||||
#define _INCLUDE__VM_SESSION__CLIENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <vm_session/capability.h>
|
||||
#include <base/rpc_client.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Client-side VM session interface
|
||||
*/
|
||||
struct Vm_session_client : Rpc_client<Vm_session>
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
explicit Vm_session_client(Vm_session_capability session)
|
||||
: Rpc_client<Vm_session>(session) { }
|
||||
|
||||
/**************************
|
||||
** Vm_session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability 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
|
||||
* \date 2012-10-02
|
||||
*/
|
||||
@ -18,8 +18,11 @@
|
||||
#include <cpu_session/cpu_session.h>
|
||||
#include <base/connection.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
/**
|
||||
* Connection to a VM service
|
||||
*/
|
||||
struct Vm_connection : Connection<Vm_session>, Vm_session_client
|
||||
{
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Vm session interface
|
||||
* \brief VM-session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-02
|
||||
*/
|
||||
@ -14,6 +14,7 @@
|
||||
#ifndef _INCLUDE__VM_SESSION__VM_SESSION_H_
|
||||
#define _INCLUDE__VM_SESSION__VM_SESSION_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/rpc_args.h>
|
||||
#include <base/signal.h>
|
||||
#include <session/session.h>
|
||||
@ -25,6 +26,9 @@ namespace Genode {
|
||||
{
|
||||
static const char *service_name() { return "VM"; }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
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
|
||||
vpath crt0.s $(REP_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
|
||||
SRC_CC += kernel.cc rm_session_support.cc kernel_support.cc trustzone.cc
|
||||
|
||||
# add library dependencies
|
||||
LIBS += platform_support
|
||||
|
||||
# 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
|
||||
BOARD_DIR = $(REP_DIR)/src/core/panda_a2
|
||||
|
||||
SRC_CC = trustzone.cc
|
||||
|
||||
# include generic parts of core support
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||
include $(REP_DIR)/lib/mk/core_support.inc
|
||||
|
||||
|
@ -7,8 +7,7 @@
|
||||
# declare location of core files that are board specific
|
||||
BOARD_DIR = $(REP_DIR)/src/core/pbxa9
|
||||
|
||||
SRC_CC = trustzone.cc
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/arm_v7/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
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/arm_v7/core_support.inc
|
||||
include $(REP_DIR)/lib/mk/core_support.inc
|
||||
|
||||
|
@ -7,4 +7,5 @@
|
||||
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/arm_v7/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
|
||||
# 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 min_page_alignm 12
|
||||
@ -30,7 +30,7 @@ proc boot_modules_arm_v7a {{file} {binaries}} {
|
||||
exec echo -e \
|
||||
"/**" \
|
||||
"\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.section .data" \
|
||||
@ -194,8 +194,8 @@ proc build_boot_image {binaries} {
|
||||
|
||||
# create scenario-specific 'boot_modules.s' of all given binaries
|
||||
set boot_modules "[run_dir]/boot_modules.s"
|
||||
if { [have_spec {arm_v7a}] } {
|
||||
boot_modules_arm_v7a $boot_modules $binaries
|
||||
if { [have_spec {arm}] } {
|
||||
boot_modules_arm $boot_modules $binaries
|
||||
}
|
||||
|
||||
# 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
|
||||
* \date 2011-12-16
|
||||
*/
|
||||
@ -31,3 +31,4 @@ _boot_module_headers_end:
|
||||
|
||||
.global _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 Stefan Kalkowski
|
||||
* \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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Do no operation for 'count' cycles
|
||||
*/
|
||||
.macro _nop count
|
||||
.rept \count
|
||||
mov r8, r8
|
||||
.endr
|
||||
.endm
|
||||
|
||||
.section .text
|
||||
|
||||
/* ELF entry symbol */
|
||||
@ -19,9 +31,7 @@
|
||||
_start:
|
||||
|
||||
/* idle a little initially because 'u-boot' likes it this way */
|
||||
.rept 8
|
||||
nop
|
||||
.endr
|
||||
_nop 8
|
||||
|
||||
/* zero-fill BSS segment */
|
||||
.extern _bss_start
|
||||
@ -36,12 +46,19 @@
|
||||
cmp r0, r1
|
||||
bne 1b
|
||||
|
||||
/* enable C++ to prepare the first kernel run */
|
||||
ldr sp, =_kernel_stack_high
|
||||
bl init_phys_kernel
|
||||
|
||||
/* call kernel routine */
|
||||
.extern kernel
|
||||
_start_kernel:
|
||||
ldr sp, =_kernel_stack_high
|
||||
bl kernel
|
||||
|
||||
/* catch erroneous kernel return */
|
||||
2: b 2b
|
||||
|
||||
/* handle for dynamic symbol objects */
|
||||
.align 3
|
||||
.global __dso_handle
|
||||
@ -55,7 +72,7 @@
|
||||
.global _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
|
||||
.global _main_utcb
|
||||
_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.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Switch from an interrupted user context to a kernel context
|
||||
*
|
||||
@ -37,13 +38,14 @@
|
||||
** so we must avoid access to kernel memory **
|
||||
************************************************/
|
||||
|
||||
/* load kernel contextidr */
|
||||
adr sp, _mt_kernel_context_begin
|
||||
/* load kernel cidr */
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #18*4]
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
isb
|
||||
|
||||
/* load kernel section table */
|
||||
adr sp, _mt_kernel_context_begin
|
||||
adr sp, _mt_master_context_begin
|
||||
ldr sp, [sp, #19*4]
|
||||
mcr p15, 0, sp, c2, c0, 0
|
||||
isb
|
||||
@ -54,7 +56,7 @@
|
||||
*******************************************/
|
||||
|
||||
/* get user context pointer */
|
||||
ldr sp, _mt_context_ptr
|
||||
ldr sp, _mt_client_context_ptr
|
||||
|
||||
/*
|
||||
* Save user r0 ... r12. We explicitely target user registers
|
||||
@ -90,7 +92,7 @@
|
||||
cps #19
|
||||
|
||||
/* get kernel context pointer */
|
||||
adr r0, _mt_kernel_context_begin
|
||||
adr r0, _mt_master_context_begin
|
||||
|
||||
/* load kernel context */
|
||||
add r0, r0, #13*4
|
||||
@ -105,7 +107,7 @@
|
||||
.macro _kernel_to_user_pic
|
||||
|
||||
/* get user context pointer */
|
||||
ldr lr, _mt_context_ptr
|
||||
ldr lr, _mt_client_context_ptr
|
||||
|
||||
/* buffer user pc */
|
||||
ldr r0, [lr, #15*4]
|
||||
@ -154,7 +156,7 @@
|
||||
orr r8, #64
|
||||
msr spsr, r8
|
||||
subs pc, lr, #4 /* resume previous exception */
|
||||
1:
|
||||
1:
|
||||
.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 pc_adjust immediate value that gets subtracted from the
|
||||
* vm's PC before it gets saved
|
||||
*/
|
||||
.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 */
|
||||
add r0, sp, #15*4
|
||||
.if \pc_adjust != 0 /* adjust pc if necessary */
|
||||
@ -194,7 +196,7 @@
|
||||
_save_bank 17 /* save fiq banks */
|
||||
stmia r0!, {r8-r12} /* save fiq r8-r12 */
|
||||
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 */
|
||||
ldmia r0, {sp,lr,pc}
|
||||
.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
|
||||
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 */
|
||||
_restore_bank 27 /* load undefined banks */
|
||||
_restore_bank 19 /* load supervisor banks */
|
||||
@ -223,7 +225,7 @@
|
||||
_restore_bank 17 /* load fiq banks */
|
||||
ldmia r0!, {r8 - r12} /* load fiq r8-r12 */
|
||||
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 */
|
||||
ldr lr, [sp, #16*4] /* load vm's cpsr to lr */
|
||||
msr spsr_cxfs, lr /* save cpsr to be load when switching */
|
||||
@ -254,23 +256,23 @@
|
||||
.global _mt_kernel_entry_pic
|
||||
_mt_kernel_entry_pic:
|
||||
|
||||
b _rst_entry /* reset */
|
||||
b _und_entry /* undefined instruction */
|
||||
b _svc_entry /* supervisor call */
|
||||
b _pab_entry /* prefetch abort */
|
||||
b _dab_entry /* data abort */
|
||||
nop /* reserved */
|
||||
b _irq_entry /* interrupt request */
|
||||
_fiq_check_prior_mode /* fast interrupt request */
|
||||
_user_to_kernel_pic 6, 4
|
||||
b _rst_entry /* 0x00: reset */
|
||||
b _und_entry /* 0x04: undefined instruction */
|
||||
b _svc_entry /* 0x08: supervisor call */
|
||||
b _pab_entry /* 0x0c: prefetch abort */
|
||||
b _dab_entry /* 0x10: data abort */
|
||||
nop /* 0x14: reserved */
|
||||
b _irq_entry /* 0x18: interrupt request */
|
||||
_fiq_check_prior_mode /* 0x1c: fast interrupt request */
|
||||
_user_to_kernel_pic 7, 4
|
||||
|
||||
/* PICs that switch from an user exception to the kernel */
|
||||
_rst_entry: _user_to_kernel_pic 0, 0
|
||||
_und_entry: _user_to_kernel_pic 1, 4
|
||||
_svc_entry: _user_to_kernel_pic 2, 0
|
||||
_pab_entry: _user_to_kernel_pic 3, 4
|
||||
_dab_entry: _user_to_kernel_pic 4, 8
|
||||
_irq_entry: _user_to_kernel_pic 5, 4
|
||||
_rst_entry: _user_to_kernel_pic 1, 0
|
||||
_und_entry: _user_to_kernel_pic 2, 4
|
||||
_svc_entry: _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
|
||||
|
||||
/* kernel must jump to this point to switch to a user context */
|
||||
.p2align 2
|
||||
@ -280,15 +282,15 @@
|
||||
|
||||
/* leave some space for the kernel context */
|
||||
.p2align 2
|
||||
.global _mt_kernel_context_begin
|
||||
_mt_kernel_context_begin: .space 32*4
|
||||
.global _mt_kernel_context_end
|
||||
_mt_kernel_context_end:
|
||||
.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_context_ptr
|
||||
_mt_context_ptr: .long 0
|
||||
.global _mt_client_context_ptr
|
||||
_mt_client_context_ptr: .long 0
|
||||
|
||||
/* a local word-sized buffer */
|
||||
.p2align 2
|
||||
@ -302,7 +304,7 @@
|
||||
* On vm exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.p2align 2
|
||||
.p2align 4
|
||||
.global _mon_kernel_entry
|
||||
_mon_kernel_entry:
|
||||
b _mon_rst_entry /* reset */
|
||||
@ -312,15 +314,15 @@
|
||||
b _mon_dab_entry /* data abort */
|
||||
nop /* reserved */
|
||||
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 */
|
||||
_mon_rst_entry: _vm_to_kernel 0, 0
|
||||
_mon_und_entry: _vm_to_kernel 1, 4
|
||||
_mon_svc_entry: _vm_to_kernel 2, 0
|
||||
_mon_pab_entry: _vm_to_kernel 3, 4
|
||||
_mon_dab_entry: _vm_to_kernel 4, 8
|
||||
_mon_irq_entry: _vm_to_kernel 5, 4
|
||||
_mon_rst_entry: _vm_to_kernel 1, 0
|
||||
_mon_und_entry: _vm_to_kernel 2, 4
|
||||
_mon_svc_entry: _vm_to_kernel 3, 0
|
||||
_mon_pab_entry: _vm_to_kernel 4, 4
|
||||
_mon_dab_entry: _vm_to_kernel 5, 8
|
||||
_mon_irq_entry: _vm_to_kernel 6, 4
|
||||
|
||||
/* kernel must jump to this point to switch to a vm */
|
||||
.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
|
||||
* \date 2012-02-22
|
||||
*/
|
||||
@ -11,20 +11,21 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__CPU__CORTEX_A9__SECTION_TABLE_H_
|
||||
#define _INCLUDE__DRIVERS__CPU__CORTEX_A9__SECTION_TABLE_H_
|
||||
#ifndef _INCLUDE__ARM__SECTION_TABLE_H_
|
||||
#define _INCLUDE__ARM__SECTION_TABLE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/register.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'
|
||||
*/
|
||||
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);
|
||||
}
|
||||
@ -53,7 +54,6 @@ namespace Genode
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Permission configuration according to given access rights
|
||||
*
|
||||
@ -77,7 +77,7 @@ namespace Genode
|
||||
Ap_2::bits(Ap_2::KERNEL_RW_OR_NO_ACCESS),
|
||||
|
||||
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_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
|
||||
* translations done by this table apply domain 0. They are not shareable
|
||||
* and have zero-filled memory region attributes.
|
||||
* translations done by this table apply to domain 0. They are not
|
||||
* shareable and have zero-filled memory region attributes.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@ -234,17 +208,17 @@ namespace Genode
|
||||
VIRT_BASE_MASK = ~((1 << VIRT_SIZE_LOG2) - 1)
|
||||
};
|
||||
|
||||
struct Xn : Bitfield<0, 1> { }; /* execute never bit */
|
||||
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] */
|
||||
struct Xn : Bitfield<0, 1> { }; /* execute never */
|
||||
struct B : Bitfield<2, 1> { }; /* mem region attr. */
|
||||
struct C : Bitfield<3, 1> { }; /* mem region attr. */
|
||||
struct Ap_1_0 : Bitfield<4, 2>, /* access permission */
|
||||
Ap_1_0_bitfield { };
|
||||
struct Tex : Bitfield<6, 3> { }; /* part of the memory region attributes */
|
||||
struct Ap_2 : Bitfield<9, 1>, /* access permission bits [2] */
|
||||
struct Tex : Bitfield<6, 3> { }; /* mem region attr. */
|
||||
struct Ap_2 : Bitfield<9, 1>, /* access permission */
|
||||
Ap_2_bitfield { };
|
||||
struct S : Bitfield<10, 1> { }; /* shareable 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
|
||||
*
|
||||
* \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
|
||||
*
|
||||
* \retval 0 on success
|
||||
* \retval <0 If virtual offset couldn't be resolved.
|
||||
* In this case 'i' reside invalid
|
||||
* \retval <0 translation failed
|
||||
*/
|
||||
int _index_by_vo (unsigned long & i, addr_t const vo) const
|
||||
{
|
||||
@ -286,13 +259,12 @@ namespace Genode
|
||||
Page_table()
|
||||
{
|
||||
/* check table alignment */
|
||||
if (!aligned((addr_t)this, ALIGNM_LOG2)
|
||||
|| (addr_t)this != (addr_t)_entries)
|
||||
if (!aligned((addr_t)this, ALIGNM_LOG2) ||
|
||||
(addr_t)this != (addr_t)_entries)
|
||||
{
|
||||
PDBG("Insufficient table alignment");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/* start with an empty table */
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
@ -341,9 +313,9 @@ namespace Genode
|
||||
{
|
||||
/* compose new descriptor value */
|
||||
Descriptor::access_t entry =
|
||||
access_permission_bits<Small_page>(w, x, k)
|
||||
| Small_page::Ng::bits(!g)
|
||||
| Small_page::Pa_31_12::masked(pa);
|
||||
access_permission_bits<Small_page>(w, x, k) |
|
||||
Small_page::Ng::bits(!g) |
|
||||
Small_page::Pa_31_12::masked(pa);
|
||||
Descriptor::type(entry, Descriptor::SMALL_PAGE);
|
||||
|
||||
/* check if we can we write to the targeted entry */
|
||||
@ -375,7 +347,7 @@ namespace Genode
|
||||
* represented by this table
|
||||
* \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 */
|
||||
addr_t residual_vo = vo;
|
||||
@ -389,30 +361,28 @@ namespace Genode
|
||||
if (_index_by_vo(i, residual_vo)) return;
|
||||
|
||||
/* update current entry and recalculate residual region */
|
||||
switch (Descriptor::type(_entries[i]))
|
||||
{
|
||||
case Descriptor::FAULT:
|
||||
{
|
||||
switch (Descriptor::type(_entries[i])) {
|
||||
|
||||
case Descriptor::FAULT: {
|
||||
|
||||
residual_vo = (residual_vo & Fault::VIRT_BASE_MASK)
|
||||
+ Fault::VIRT_SIZE;
|
||||
break;
|
||||
}
|
||||
case Descriptor::SMALL_PAGE:
|
||||
{
|
||||
break; }
|
||||
|
||||
case Descriptor::SMALL_PAGE: {
|
||||
|
||||
residual_vo = (residual_vo & Small_page::VIRT_BASE_MASK)
|
||||
+ Small_page::VIRT_SIZE;
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
break;
|
||||
}
|
||||
case Descriptor::LARGE_PAGE:
|
||||
{
|
||||
break; }
|
||||
|
||||
case Descriptor::LARGE_PAGE: {
|
||||
|
||||
PDBG("Removal of large pages not implemented");
|
||||
while (1) ;
|
||||
break;
|
||||
}
|
||||
break; }
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -429,13 +399,13 @@ namespace Genode
|
||||
} __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
|
||||
* translations done by this table apply domain 0. They are not shareable
|
||||
* and have zero-filled memory region attributes. The size of this table is
|
||||
* fixed to such a value that this table translates a space wich is
|
||||
* addressable by 32 bit.
|
||||
* translations done by this table apply to domain 0. They are not
|
||||
* shareable and have zero-filled memory region attributes. The size
|
||||
* of this table is fixed to such a value that this table translates
|
||||
* a space wich is addressable by 32 bit.
|
||||
*/
|
||||
class Section_table
|
||||
{
|
||||
@ -443,6 +413,8 @@ namespace Genode
|
||||
_16KB_LOG2 = 14,
|
||||
_1MB_LOG2 = 20,
|
||||
_16MB_LOG2 = 24,
|
||||
|
||||
DOMAIN = 0,
|
||||
};
|
||||
|
||||
public:
|
||||
@ -458,12 +430,10 @@ namespace Genode
|
||||
|
||||
MAX_COSTS_PER_TRANSLATION = sizeof(Page_table),
|
||||
|
||||
MAX_TRANSL_SIZE_LOG2 = 20,
|
||||
MIN_TRANSL_SIZE_LOG2 = 12,
|
||||
MAX_PAGE_SIZE_LOG2 = 20,
|
||||
MIN_PAGE_SIZE_LOG2 = 12,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* A first level translation descriptor
|
||||
*/
|
||||
@ -474,8 +444,8 @@ namespace Genode
|
||||
*/
|
||||
enum Type { FAULT, PAGE_TABLE, SECTION, SUPERSECTION };
|
||||
|
||||
struct Type_1 : Bitfield<0, 2> { }; /* entry type encoding 1 */
|
||||
struct Type_2 : Bitfield<18, 1> { }; /* entry type encoding 2 */
|
||||
struct Type_1 : Bitfield<0, 2> { }; /* entry type code 1 */
|
||||
struct Type_2 : Bitfield<18, 1> { }; /* entry type code 2 */
|
||||
|
||||
/**
|
||||
* Get descriptor type of 'v'
|
||||
@ -538,43 +508,23 @@ namespace Genode
|
||||
*/
|
||||
struct Page_table_descriptor : Descriptor
|
||||
{
|
||||
struct Ns : Bitfield<3, 1> { }; /* non-secure bit */
|
||||
struct Domain : Bitfield<5, 4> { }; /* domain field */
|
||||
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical address bits [31:10] */
|
||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||
struct Pa_31_10 : Bitfield<10, 22> { }; /* physical base */
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
* Section translation descriptor
|
||||
*/
|
||||
struct Section : Descriptor
|
||||
{
|
||||
@ -584,29 +534,42 @@ namespace Genode
|
||||
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 Domain : Bitfield<5, 4> { }; /* domain field */
|
||||
struct Ap_1_0 : Bitfield<10, 2>, /* access permission bits [1:0] */
|
||||
struct B : Bitfield<2, 1> { }; /* mem. region attr. */
|
||||
struct C : Bitfield<3, 1> { }; /* mem. region attr. */
|
||||
struct Xn : Bitfield<4, 1> { }; /* execute never bit */
|
||||
struct Domain : Bitfield<5, 4> { }; /* domain */
|
||||
struct Ap_1_0 : Bitfield<10, 2>, /* access permission */
|
||||
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] */
|
||||
struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */
|
||||
struct Ap_2 : Bitfield<15, 1>, /* access permission */
|
||||
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_31_20 : Bitfield<20, 12> { }; /* physical address bits [31:20] */
|
||||
struct S : Bitfield<16, 1> { }; /* shared */
|
||||
struct Ng : Bitfield<17, 1> { }; /* not global */
|
||||
struct Pa_31_20 : Bitfield<20, 12> { }; /* physical base */
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)];
|
||||
|
||||
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
|
||||
*
|
||||
@ -628,18 +591,17 @@ namespace Genode
|
||||
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)
|
||||
|| (addr_t)this != (addr_t)_entries)
|
||||
{
|
||||
PDBG("Insufficient table alignment");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/* start with an empty table */
|
||||
for (unsigned i = 0; i <= MAX_INDEX; i++)
|
||||
Descriptor::invalidate(_entries[i]);
|
||||
@ -657,6 +619,8 @@ namespace Genode
|
||||
/**
|
||||
* 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
|
||||
* by the translation within the virtual
|
||||
* region represented by this table
|
||||
@ -691,19 +655,23 @@ namespace Genode
|
||||
* spans the the same virtual range and is not a link to another
|
||||
* table level.
|
||||
*/
|
||||
template <typename ST>
|
||||
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,
|
||||
ST * const st,
|
||||
void * const extra_space = 0)
|
||||
{
|
||||
typedef typename ST::Section Section;
|
||||
typedef typename ST::Page_table_descriptor Page_table_descriptor;
|
||||
|
||||
/* validate virtual address */
|
||||
unsigned long i;
|
||||
if (_index_by_vo (i, vo)) {
|
||||
PDBG("Invalid virtual offset");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
/* select descriptor type by translation size */
|
||||
if (size_log2 < Section::VIRT_SIZE_LOG2)
|
||||
{
|
||||
@ -723,11 +691,9 @@ namespace Genode
|
||||
}
|
||||
/* create and link page table */
|
||||
pt = new (extra_space) Page_table();
|
||||
_entries[i] = Page_table_descriptor::Ns::bits(!_secure)
|
||||
| Page_table_descriptor::Pa_31_10::masked((addr_t)pt);
|
||||
Descriptor::type(_entries[i], Descriptor::PAGE_TABLE);
|
||||
_entries[i] = Page_table_descriptor::create(pt, st);
|
||||
}
|
||||
/* Request additional memory to create a page table */
|
||||
/* request additional memory to create a page table */
|
||||
else return Page_table::SIZE_LOG2;
|
||||
|
||||
/* insert translation */
|
||||
@ -738,12 +704,8 @@ namespace Genode
|
||||
if (size_log2 == Section::VIRT_SIZE_LOG2)
|
||||
{
|
||||
/* compose section descriptor */
|
||||
Descriptor::access_t entry =
|
||||
access_permission_bits<Section>(w, x, k)
|
||||
| Section::Ns::bits(!_secure)
|
||||
| Section::Ng::bits(!g)
|
||||
| Section::Pa_31_20::masked(pa);
|
||||
Descriptor::type(entry, Descriptor::SECTION);
|
||||
Descriptor::access_t entry = Section::create(w, x, k,
|
||||
g, pa, st);
|
||||
|
||||
/* check if we can we write to the targeted entry */
|
||||
if (Descriptor::valid(_entries[i]))
|
||||
@ -774,7 +736,7 @@ namespace Genode
|
||||
* represented by this table
|
||||
* \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 */
|
||||
addr_t residual_vo = vo;
|
||||
@ -806,7 +768,7 @@ namespace Genode
|
||||
- Section::Pa_31_20::masked(residual_vo);
|
||||
pt->remove_region(pt_vo, residual_size);
|
||||
|
||||
/* Recalculate residual region */
|
||||
/* recalculate residual region */
|
||||
residual_vo = (residual_vo & Page_table::VIRT_BASE_MASK)
|
||||
+ Page_table::VIRT_SIZE;
|
||||
break;
|
||||
@ -834,6 +796,7 @@ namespace Genode
|
||||
* \param base base 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
|
||||
*/
|
||||
bool regain_memory (void * & base, size_t & s)
|
||||
@ -860,5 +823,5 @@ namespace Genode
|
||||
} __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_
|
||||
#define _CORE__INCLUDE__CORTEX_A9__KERNEL_SUPPORT_H_
|
||||
|
||||
/* Core includes */
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
/* core includes */
|
||||
#include <cortex_a9/cpu.h>
|
||||
#include <cortex_a9/timer.h>
|
||||
#include <cortex_a9/no_trustzone/pic.h>
|
||||
|
||||
/**
|
||||
* CPU driver
|
||||
*/
|
||||
class Cpu : public Genode::Cortex_a9 { };
|
||||
class Cpu : public Cortex_a9::Cpu { };
|
||||
|
||||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
class Pic : public Cortex_a9_no_trustzone::Pic { };
|
||||
|
||||
/**
|
||||
* Kernel timer
|
||||
*/
|
||||
class Timer : public Cortex_a9::Private_timer { };
|
||||
class Timer : public Cortex_a9::Timer { };
|
||||
}
|
||||
|
||||
#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
|
||||
* \date 2011-10-26
|
||||
*/
|
||||
@ -11,19 +11,20 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__PIC__PL390_BASE_H_
|
||||
#define _INCLUDE__DRIVERS__PIC__PL390_BASE_H_
|
||||
#ifndef _INCLUDE__CORTEX_A9__PIC_H_
|
||||
#define _INCLUDE__CORTEX_A9__PIC_H_
|
||||
|
||||
/* Genode includes */
|
||||
#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:
|
||||
|
||||
@ -41,7 +42,7 @@ namespace Genode
|
||||
*/
|
||||
struct Distr : public Mmio
|
||||
{
|
||||
Distr(addr_t const base) : Mmio(base) { }
|
||||
Distr() : Mmio(Cortex_a9::Cpu::PL390_DISTRIBUTOR_MMIO_BASE) { }
|
||||
|
||||
/**
|
||||
* Distributor control register
|
||||
@ -145,7 +146,7 @@ namespace Genode
|
||||
*/
|
||||
struct Cpu : public Mmio
|
||||
{
|
||||
Cpu(addr_t const base) : Mmio(base) { }
|
||||
Cpu() : Mmio(Cortex_a9::Cpu::PL390_CPU_MMIO_BASE) { }
|
||||
|
||||
/**
|
||||
* CPU interface control register
|
||||
@ -160,7 +161,7 @@ namespace Genode
|
||||
struct Enable_ns : Bitfield<1,1> { };
|
||||
struct Ack_ctl : Bitfield<2,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
|
||||
*/
|
||||
Pl390_base(addr_t const distributor, addr_t const cpu_interface) :
|
||||
_distr(distributor),
|
||||
_cpu(cpu_interface),
|
||||
_max_interrupt(_distr.max_interrupt()),
|
||||
_last_taken_request(SPURIOUS_ID) { }
|
||||
Pic() : _max_interrupt(_distr.max_interrupt()),
|
||||
_last_taken_request(SPURIOUS_ID) { }
|
||||
|
||||
/**
|
||||
* Get the ID of the last interrupt request
|
||||
@ -270,10 +268,8 @@ namespace Genode
|
||||
/**
|
||||
* Unmask interrupt 'i'
|
||||
*/
|
||||
void unmask(unsigned const i)
|
||||
{
|
||||
_distr.write<Distr::Icdiser::Set_enable>(1, i);
|
||||
}
|
||||
void unmask(unsigned const i) {
|
||||
_distr.write<Distr::Icdiser::Set_enable>(1, i); }
|
||||
|
||||
/**
|
||||
* Mask all interrupts
|
||||
@ -287,12 +283,10 @@ namespace Genode
|
||||
/**
|
||||
* Mask interrupt 'i'
|
||||
*/
|
||||
void mask(unsigned const i)
|
||||
{
|
||||
_distr.write<Distr::Icdicer::Clear_enable>(1, i);
|
||||
}
|
||||
void mask(unsigned const 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 _mt_user_entry_pic;
|
||||
extern int _mon_vm_entry;
|
||||
extern Genode::addr_t _mt_context_ptr;
|
||||
extern Genode::addr_t _mt_kernel_context_begin;
|
||||
extern Genode::addr_t _mt_kernel_context_end;
|
||||
extern Genode::addr_t _mt_client_context_ptr;
|
||||
extern Genode::addr_t _mt_master_context_begin;
|
||||
extern Genode::addr_t _mt_master_context_end;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
@ -68,7 +68,7 @@ namespace Kernel
|
||||
/* kernel configuration */
|
||||
enum {
|
||||
DEFAULT_STACK_SIZE = 1*1024*1024,
|
||||
USER_TIME_SLICE_MS = 10,
|
||||
USER_TIME_SLICE_MS = 100,
|
||||
MAX_PDS = 256,
|
||||
MAX_THREADS = 256,
|
||||
MAX_SIGNAL_RECEIVERS = 256,
|
||||
@ -720,17 +720,17 @@ namespace Kernel
|
||||
*
|
||||
* The code that switches between kernel/user mode must not exceed the
|
||||
* 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.
|
||||
* This class controls the settings like kernel, user, and vm states
|
||||
* that are handled by the PIC mode transition code.
|
||||
* This class controls the settings like kernel, user, and VM states
|
||||
* that are handled by the mode transition PIC.
|
||||
*/
|
||||
struct Mode_transition_control
|
||||
{
|
||||
enum {
|
||||
SIZE_LOG2 = Cpu::MIN_PAGE_SIZE_LOG2,
|
||||
SIZE_LOG2 = Software_tlb::MIN_PAGE_SIZE_LOG2,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
VIRT_BASE = Cpu::HIGHEST_EXCEPTION_ENTRY,
|
||||
VIRT_BASE = Cpu::EXCEPTION_ENTRY,
|
||||
VIRT_END = VIRT_BASE + SIZE,
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
};
|
||||
@ -751,20 +751,17 @@ namespace Kernel
|
||||
assert(pic_size <= SIZE);
|
||||
|
||||
/* check if kernel context fits into the mode transition */
|
||||
addr_t const kc_begin = (addr_t)&_mt_kernel_context_begin;
|
||||
addr_t const kc_end = (addr_t)&_mt_kernel_context_end;
|
||||
addr_t const kc_begin = (addr_t)&_mt_master_context_begin;
|
||||
addr_t const kc_end = (addr_t)&_mt_master_context_end;
|
||||
size_t const kc_size = kc_end - kc_begin;
|
||||
assert(sizeof(Cpu::Context) <= kc_size);
|
||||
|
||||
/* try to set CPU exception entry accordingly */
|
||||
assert(!Cpu::exception_entry_at(VIRT_BASE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch next kernelmode context
|
||||
*/
|
||||
void fetch_kernel_context(Cpu::Context * const c) {
|
||||
memcpy(&_mt_kernel_context_begin, c, sizeof(Cpu::Context)); }
|
||||
void fetch_master_context(Cpu::Context * const c) {
|
||||
memcpy(&_mt_master_context_begin, c, sizeof(Cpu::Context)); }
|
||||
|
||||
/**
|
||||
* Page aligned physical base of the mode transition PIC
|
||||
@ -836,7 +833,7 @@ namespace Kernel
|
||||
void append_context(Cpu::Context * const c)
|
||||
{
|
||||
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
|
||||
* addresses this thread */
|
||||
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
|
||||
@ -1135,12 +1137,6 @@ namespace Kernel
|
||||
_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:
|
||||
|
||||
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 */
|
||||
_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 */
|
||||
mtc()->virt_user_entry();
|
||||
@ -1344,7 +1341,6 @@ namespace Kernel
|
||||
|
||||
class Signal_receiver;
|
||||
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
_mt_context_ptr = (addr_t)_state;
|
||||
_mt_client_context_ptr = (addr_t)_state;
|
||||
|
||||
/* jump to assembler path */
|
||||
((void(*)(void))&_mon_vm_entry)();
|
||||
@ -1959,7 +1956,7 @@ namespace Kernel
|
||||
assert(c);
|
||||
|
||||
/* 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,
|
||||
/* 22 */ do_await_signal,
|
||||
/* 23 */ do_submit_signal,
|
||||
/* 24 */ do_delete_thread,
|
||||
/* 25 */ do_new_vm,
|
||||
/* 26 */ do_run_vm,
|
||||
/* 24 */ do_new_vm,
|
||||
/* 25 */ do_run_vm,
|
||||
/* 26 */ do_delete_thread,
|
||||
};
|
||||
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
|
||||
*/
|
||||
extern "C" void kernel()
|
||||
{
|
||||
unsigned const timer_value = timer()->stop();
|
||||
static unsigned user_time = 0;
|
||||
static bool initial_call = true;
|
||||
|
||||
@ -2068,6 +2069,7 @@ extern "C" void kernel()
|
||||
if (!initial_call)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* handle exception that interrupted the last user */
|
||||
@ -2082,7 +2084,7 @@ extern "C" void kernel()
|
||||
{
|
||||
/* map everything except the mode transition region */
|
||||
enum {
|
||||
SIZE_LOG2 = Software_tlb::MAX_TRANSL_SIZE_LOG2,
|
||||
SIZE_LOG2 = Software_tlb::MAX_PAGE_SIZE_LOG2,
|
||||
SIZE = 1 << SIZE_LOG2,
|
||||
};
|
||||
if (mtc()->VIRT_END <= a || mtc()->VIRT_BASE > (a + SIZE - 1))
|
||||
@ -2098,20 +2100,20 @@ extern "C" void kernel()
|
||||
}
|
||||
/* compose kernel CPU context */
|
||||
static Cpu::Context kernel_context;
|
||||
kernel_context.instruction_ptr((addr_t)kernel);
|
||||
kernel_context.stack_ptr((addr_t)&_kernel_stack_high);
|
||||
kernel_context.ip = (addr_t)kernel;
|
||||
kernel_context.sp = (addr_t)&_kernel_stack_high;
|
||||
|
||||
/* add kernel to the core PD */
|
||||
core()->append_context(&kernel_context);
|
||||
|
||||
/* 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(pic());
|
||||
|
||||
/* 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 */
|
||||
static Native_utcb cm_utcb;
|
||||
@ -2120,7 +2122,7 @@ extern "C" void kernel()
|
||||
static Thread core_main((Platform_thread *)0);
|
||||
_main_utcb = &cm_utcb;
|
||||
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],
|
||||
0, core_id(), &cm_utcb, &cm_utcb);
|
||||
|
||||
@ -2128,7 +2130,7 @@ extern "C" void kernel()
|
||||
initial_call = false;
|
||||
}
|
||||
/* 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 */
|
||||
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)
|
||||
{
|
||||
/* basic thread state */
|
||||
stack_ptr((addr_t)sp);
|
||||
instruction_ptr((addr_t)ip);
|
||||
sp = (addr_t)stack_p;
|
||||
ip = (addr_t)instr_p;
|
||||
|
||||
/* join a pd */
|
||||
_pd_id = pd_id;
|
||||
Pd * const pd = Pd::pool()->object(_pd_id);
|
||||
assert(pd)
|
||||
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 */
|
||||
assert(_pager);
|
||||
Software_tlb * const tlb =
|
||||
static_cast<Software_tlb *>(software_tlb());
|
||||
_pagefault =
|
||||
Pagefault(id(), tlb, instruction_ptr(), va, w);
|
||||
Software_tlb * const tlb = (Software_tlb *)software_tlb();
|
||||
_pagefault = Pagefault(id(), tlb, ip, va, w);
|
||||
Ipc_node::send_note(_pager, &_pagefault, sizeof(_pagefault));
|
||||
}
|
||||
|
||||
|
@ -11,13 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#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>
|
||||
|
||||
/* core includes */
|
||||
#include <cortex_a9/cpu.h>
|
||||
#include <cortex_a9/no_trustzone/pic.h>
|
||||
#include <platform.h>
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -37,7 +37,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -48,7 +48,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::TL16C750_3_IRQ, 1 }
|
||||
|
@ -15,12 +15,12 @@
|
||||
#define _SRC__CORE__PANDA_A2__SOFTWARE_TLB_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cortex_a9/cpu/section_table.h>
|
||||
#include <arm/v7/section_table.h>
|
||||
|
||||
/**
|
||||
* 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_ */
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
#
|
||||
# \brief Pandaboard-specific makefile for core
|
||||
# \brief Makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \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
|
||||
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
#include <cortex_a9/cpu.h>
|
||||
#include <cortex_a9/no_trustzone/pic.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -36,7 +37,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -47,7 +48,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* core timer */
|
||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
|
@ -14,13 +14,13 @@
|
||||
#ifndef _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
||||
#define _SRC__CORE__PBXA9__SOFTWARE_TLB_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cortex_a9/cpu/section_table.h>
|
||||
/* core includes */
|
||||
#include <arm/v7/section_table.h>
|
||||
|
||||
/**
|
||||
* 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_ */
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
#
|
||||
# \brief PBXA9-specific makefile for core
|
||||
# \brief Makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# declare wich specs must be given to build this target
|
||||
REQUIRES = platform_pbxa9
|
||||
|
||||
# include less specific target parts
|
||||
include $(REP_DIR)/src/core/target.inc
|
||||
|
||||
|
@ -142,6 +142,10 @@ Platform::Platform() :
|
||||
printf("-------------------\n");
|
||||
_io_mem_alloc.raw()->dump_addr_tree();
|
||||
printf("\n");
|
||||
printf("IRQ allocator\n");
|
||||
printf("-------------------\n");
|
||||
_irq_alloc.raw()->dump_addr_tree();
|
||||
printf("\n");
|
||||
printf("ROM filesystem\n");
|
||||
printf("--------------\n");
|
||||
_rom_fs.print_fs();
|
||||
|
@ -8,11 +8,11 @@
|
||||
TARGET = core
|
||||
|
||||
# use core specific startup library
|
||||
STARTUP_LIB = startup_core
|
||||
STARTUP_LIB = core_support
|
||||
|
||||
# add library dependencies
|
||||
LIBS += cxx raw_ipc heap child pager lock console signal raw_server \
|
||||
syscall startup_core core_support
|
||||
LIBS += cxx raw_ipc heap child process pager lock console signal raw_server \
|
||||
syscall core_support
|
||||
|
||||
# add include paths
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
/* Core includes */
|
||||
#include <platform.h>
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
#include <cortex_a9/cpu.h>
|
||||
#include <cortex_a9/no_trustzone/pic.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -36,7 +36,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -47,7 +47,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* Core timer */
|
||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
|
@ -15,12 +15,12 @@
|
||||
#define _SRC__CORE__VEA9X4__SOFTWARE_TLB_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <cortex_a9/cpu/section_table.h>
|
||||
#include <arm/v7/section_table.h>
|
||||
|
||||
/**
|
||||
* 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_ */
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
#
|
||||
# \brief VEA9x4-specific makefile for core
|
||||
# \brief Makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# declare wich specs must be given to build this target
|
||||
REQUIRES = platform_vea9x4
|
||||
|
||||
# adjust link address of a trustzone text segment
|
||||
ifeq ($(filter-out $(SPECS),trustzone),)
|
||||
LD_TEXT_ADDR = 0x48000000
|
||||
endif
|
||||
|
||||
# include less specific target parts
|
||||
include $(REP_DIR)/src/core/target.inc
|
||||
|
@ -14,11 +14,6 @@
|
||||
/* Core includes */
|
||||
#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_
|
||||
|
||||
/* Core includes */
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
#include <cortex_a9/cpu.h>
|
||||
#include <cortex_a9/timer.h>
|
||||
#include <vea9x4_trustzone/pic.h>
|
||||
|
||||
/**
|
||||
* CPU driver
|
||||
*/
|
||||
class Cpu : public Genode::Cortex_a9 { };
|
||||
class Cpu : public Cortex_a9::Cpu { };
|
||||
|
||||
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
|
||||
{
|
||||
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); }
|
||||
};
|
||||
class Pic : public Vea9x4_trustzone::Pic { };
|
||||
|
||||
/**
|
||||
* Kernel timer
|
||||
*/
|
||||
class Timer : public Cortex_a9::Private_timer { };
|
||||
class Timer : public Cortex_a9::Timer { };
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
/* Core includes */
|
||||
#include <platform.h>
|
||||
#include <pic/pl390_base.h>
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <vea9x4_trustzone/pic.h>
|
||||
#include <cortex_a9/cpu.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -39,7 +39,7 @@ Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{ 0, 34 },
|
||||
{ 37, 3 },
|
||||
{ 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;
|
||||
}
|
||||
@ -50,7 +50,7 @@ Native_region * Platform::_core_only_irq_regions(unsigned const i)
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
/* Core timer */
|
||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
||||
{ Cortex_a9::Cpu::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
|
@ -14,6 +14,7 @@
|
||||
/* Core includes */
|
||||
#include <trustzone.h>
|
||||
#include <kernel_support.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* monitor exception vector address */
|
||||
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
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
@ -17,7 +17,7 @@
|
||||
#include <root/root.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
/* Core includes */
|
||||
/* core includes */
|
||||
#include <vm_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
@ -17,19 +17,6 @@
|
||||
.global _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 */
|
||||
ldr r1, =_main_utcb
|
||||
str r0, [r1]
|
||||
@ -38,8 +25,7 @@
|
||||
ldr sp, =_main_stack_high
|
||||
.extern _main
|
||||
bl _main
|
||||
1:
|
||||
b 1b
|
||||
1: b 1b
|
||||
|
||||
/* dynamic symbol object handle */
|
||||
.align 3
|
||||
|
@ -2,6 +2,7 @@
|
||||
* \brief CPU state
|
||||
* \author Norman Feske
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2011-05-06
|
||||
*/
|
||||
|
||||
@ -15,37 +16,44 @@
|
||||
#ifndef _INCLUDE__ARM__CPU__CPU_STATE_H_
|
||||
#define _INCLUDE__ARM__CPU__CPU_STATE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
* Basic CPU state
|
||||
*/
|
||||
struct Cpu_state
|
||||
{
|
||||
/**
|
||||
* Native exception types
|
||||
*/
|
||||
enum Cpu_exception {
|
||||
RESET,
|
||||
UNDEFINED_INSTRUCTION,
|
||||
SUPERVISOR_CALL,
|
||||
PREFETCH_ABORT,
|
||||
DATA_ABORT,
|
||||
INTERRUPT_REQUEST,
|
||||
FAST_INTERRUPT_REQUEST,
|
||||
MAX_CPU_EXCEPTION,
|
||||
RESET = 1,
|
||||
UNDEFINED_INSTRUCTION = 2,
|
||||
SUPERVISOR_CALL = 3,
|
||||
PREFETCH_ABORT = 4,
|
||||
DATA_ABORT = 5,
|
||||
INTERRUPT_REQUEST = 6,
|
||||
FAST_INTERRUPT_REQUEST = 7,
|
||||
};
|
||||
|
||||
enum { MAX_GPR = 13 };
|
||||
|
||||
addr_t r[MAX_GPR]; /* r0-r12 - general purpose */
|
||||
addr_t sp; /* r13 - stack pointer */
|
||||
addr_t lr; /* r14 - link register */
|
||||
addr_t ip; /* r15 - instruction pointer */
|
||||
addr_t cpsr; /* current program status register */
|
||||
Cpu_exception cpu_exception; /* last exception */
|
||||
/**
|
||||
* Registers
|
||||
*/
|
||||
addr_t r0, r1, r2, r3, r4, r5, r6,
|
||||
r7, r8, r9, r10, r11, r12; /* general purpose register 0..12 */
|
||||
addr_t sp; /* stack pointer */
|
||||
addr_t lr; /* link register */
|
||||
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
|
||||
{
|
||||
/**
|
||||
|
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_SIZE = 0x2000,
|
||||
CORTEX_A9_CLOCK = MPU_DPLL_CLOCK,
|
||||
CORTEX_A9_SECURITY_EXTENSION = 0,
|
||||
|
||||
/* RAM */
|
||||
EMIF1_EMIF2_CS0_SDRAM_BASE = 0x80000000,
|
||||
EMIF1_EMIF2_CS0_SDRAM_SIZE = 0x40000000,
|
||||
|
||||
SECURITY_EXTENSION = 0,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ namespace Genode
|
||||
CORTEX_A9_CLOCK = OSC_7_CLOCK * 5,
|
||||
CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000,
|
||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000,
|
||||
CORTEX_A9_SECURITY_EXTENSION = 0,
|
||||
|
||||
/* UART */
|
||||
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_SIZE = 4*1024,
|
||||
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_SIZE = 0x2000,
|
||||
CORTEX_A9_CLOCK = TCREF_CLOCK,
|
||||
CORTEX_A9_SECURITY_EXTENSION = 1,
|
||||
|
||||
/* RAM */
|
||||
LOCAL_DDR2_BASE = 0x60000000,
|
||||
@ -68,6 +67,8 @@ namespace Genode
|
||||
/* SRAM */
|
||||
SRAM_BASE = SMB_CS2_BASE,
|
||||
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
|
||||
#
|
||||
|
||||
#
|
||||
# Configure target CPU
|
||||
#
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += arm_v7
|
||||
|
||||
# configure compiler
|
||||
CC_MARCH += -march=armv7-a
|
||||
|
||||
# add repository relative include paths
|
||||
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
|
||||
*
|
||||
* Uses only timer module 0.
|
||||
*/
|
||||
template <unsigned long CLK>
|
||||
class Sp804_base : public Mmio
|
||||
|
@ -152,8 +152,8 @@ namespace Genode {
|
||||
_load_initrd();
|
||||
_prepare_atag();
|
||||
_state->cpsr = 0x93; /* SVC mode and IRQs disabled */
|
||||
_state->r[1] = 2272; /* MACH_TYPE vexpress board */
|
||||
_state->r[2] = _ram.base() + ATAG_OFFSET; /* ATAG addr */
|
||||
_state->r1 = 2272; /* MACH_TYPE vexpress board */
|
||||
_state->r2 = _ram.base() + ATAG_OFFSET; /* ATAG addr */
|
||||
_vm_con.exception_handler(sig_cap);
|
||||
}
|
||||
|
||||
@ -168,8 +168,19 @@ namespace Genode {
|
||||
"data_abort", "irq", "fiq" };
|
||||
|
||||
printf("Cpu state:\n");
|
||||
for (unsigned i = 0; i<13; i++)
|
||||
printf(" r%x = %08lx\n", i, _state->r[i]);
|
||||
printf(" r0 = %08lx\n", _state->r0);
|
||||
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(" lr = %08lx\n", _state->lr);
|
||||
printf(" ip = %08lx\n", _state->ip);
|
||||
@ -220,8 +231,8 @@ namespace Genode {
|
||||
DVI_MODE = 0xc0b00000
|
||||
};
|
||||
|
||||
uint32_t ctrl = _vm->state()->r[2];
|
||||
uint32_t data = _vm->state()->r[0];
|
||||
uint32_t ctrl = _vm->state()->r2;
|
||||
uint32_t data = _vm->state()->r0;
|
||||
|
||||
switch(ctrl) {
|
||||
case OSC1:
|
||||
@ -241,25 +252,25 @@ namespace Genode {
|
||||
|
||||
void _handle_hypervisor_call()
|
||||
{
|
||||
switch (_vm->state()->r[1]) {
|
||||
switch (_vm->state()->r1) {
|
||||
case SP810_ENABLE:
|
||||
_sp810.enable_timer0();
|
||||
_sp810.enable_timer1();
|
||||
break;
|
||||
case CPU_ID:
|
||||
_vm->state()->r[0] = 0x0c000191; // Coretile A9 ID
|
||||
_vm->state()->r0 = 0x0c000191; // Coretile A9 ID
|
||||
break;
|
||||
case SYS_COUNTER:
|
||||
_vm->state()->r[0] = _sys.counter();
|
||||
_vm->state()->r0 = _sys.counter();
|
||||
break;
|
||||
case MISC_FLAGS:
|
||||
_vm->state()->r[0] = _sys.misc_flags();
|
||||
_vm->state()->r0 = _sys.misc_flags();
|
||||
break;
|
||||
case SYS_CTRL:
|
||||
_sys_ctrl();
|
||||
break;
|
||||
case MCI_STATUS:
|
||||
_vm->state()->r[0] = _sys.mci_status();
|
||||
_vm->state()->r0 = _sys.mci_status();
|
||||
break;
|
||||
default:
|
||||
PERR("Unknown hypervisor call!");
|
||||
|
@ -89,19 +89,19 @@ extern "C" int genode_fetch_register(int regno, unsigned long *reg_content)
|
||||
} else {
|
||||
switch((enum reg_index)regno)
|
||||
{
|
||||
case R0: *reg_content = thread_state.r[0]; PDBG("R0 = %8lx", *reg_content); return 0;
|
||||
case R1: *reg_content = thread_state.r[1]; PDBG("R1 = %8lx", *reg_content); return 0;
|
||||
case R2: *reg_content = thread_state.r[2]; PDBG("R2 = %8lx", *reg_content); return 0;
|
||||
case R3: *reg_content = thread_state.r[3]; PDBG("R3 = %8lx", *reg_content); return 0;
|
||||
case R4: *reg_content = thread_state.r[4]; PDBG("R4 = %8lx", *reg_content); return 0;
|
||||
case R5: *reg_content = thread_state.r[5]; PDBG("R5 = %8lx", *reg_content); return 0;
|
||||
case R6: *reg_content = thread_state.r[6]; PDBG("R6 = %8lx", *reg_content); return 0;
|
||||
case R7: *reg_content = thread_state.r[7]; PDBG("R7 = %8lx", *reg_content); return 0;
|
||||
case R8: *reg_content = thread_state.r[8]; PDBG("R8 = %8lx", *reg_content); return 0;
|
||||
case R9: *reg_content = thread_state.r[9]; PDBG("R9 = %8lx", *reg_content); return 0;
|
||||
case R10: *reg_content = thread_state.r[10]; PDBG("R10 = %8lx", *reg_content); return 0;
|
||||
case R11: *reg_content = thread_state.r[11]; PDBG("FP = %8lx", *reg_content); return 0;
|
||||
case R12: *reg_content = thread_state.r[12]; PDBG("R12 = %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.r1; PDBG("R1 = %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.r3; PDBG("R3 = %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.r5; PDBG("R5 = %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.r7; PDBG("R7 = %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.r9; PDBG("R9 = %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.r11; PDBG("FP = %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 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;
|
||||
|
Loading…
Reference in New Issue
Block a user