mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 03:45:24 +00:00
base-hw: implement vm_session for TrustZone
* Introduces Schedule_context * Use fast-interrupts or normal interrupts * Add mode-transition between secure/non-secure world * Limit system resources for Genode apps due to non-secure world This commit implements the newly introduced Vm session interface to be used on top of TrustZone capable Armv7 CPUs. Therefore a new Schedule_context is introduced in the kernel. Threads and Vms are both Schedule_contexts used by the scheduler. In contrast to a thread a vm uses a different assembler mode switch to the non-secure, virtual world, as well as another exception is used, when the non-secure world is left. For both worlds to co-exist the interrupt-controller needs to be configured, so that the secure (Genode) world uses fast-interrupts only, and the non-secure world only legacy interrupts. The only TrustZone capable platform the base-hw kernel works on top of is the CoreTile Express 9x4 for the Versatile Express motherboard. For a virtual machine working properly on top some platform resources must be reserved. Therefore there exist two flavours of this platform now, one with the 'trustzone' spec-variable enabled, and one without. If 'trustzone' is specified most platform resources (DDR-RAM, and most IRQs) are reserved for the Vm and not available to the secure Genode world.
This commit is contained in:
parent
965ffc1df2
commit
8393ac6895
@ -68,6 +68,10 @@ namespace Kernel
|
||||
NEW_SIGNAL_CONTEXT = 21,
|
||||
AWAIT_SIGNAL = 22,
|
||||
SUBMIT_SIGNAL = 23,
|
||||
|
||||
/* vm specific */
|
||||
NEW_VM = 25,
|
||||
RUN_VM = 26,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -83,6 +87,7 @@ namespace Kernel
|
||||
Genode::size_t pd_size();
|
||||
Genode::size_t signal_context_size();
|
||||
Genode::size_t signal_receiver_size();
|
||||
Genode::size_t vm_size();
|
||||
|
||||
/**
|
||||
* Get alignment constraints of the kernel objects
|
||||
@ -433,6 +438,37 @@ namespace Kernel
|
||||
*/
|
||||
inline void submit_signal(unsigned long context_id, int num)
|
||||
{ syscall(SUBMIT_SIGNAL, (Syscall_arg)context_id, (Syscall_arg)num); }
|
||||
|
||||
|
||||
/**
|
||||
* Create a new vm that is stopped initially
|
||||
*
|
||||
* \param dst physical base of an appropriate portion of memory
|
||||
* that is thereupon allocated to the kernel
|
||||
* \param state location of the cpu state of the VM
|
||||
* \param context_id ID of the targeted signal context
|
||||
*
|
||||
* \retval >0 ID of the new vm
|
||||
* \retval 0 if no new vm was created
|
||||
*
|
||||
* Restricted to core threads. Regaining of the supplied memory is not
|
||||
* supported by now.
|
||||
*/
|
||||
inline int new_vm(void * const dst, void * const state,
|
||||
unsigned long context_id)
|
||||
{
|
||||
return syscall(NEW_VM, (Syscall_arg)dst, (Syscall_arg)state,
|
||||
(Syscall_arg)context_id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a virtual-machine (again)
|
||||
*
|
||||
* \param id ID of the targeted vm
|
||||
*/
|
||||
inline void run_vm(unsigned long const id = 0) {
|
||||
syscall(RUN_VM, (Syscall_arg)id); }
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__KERNEL__SYSCALLS_H_ */
|
||||
|
@ -33,7 +33,7 @@ namespace Genode {
|
||||
long priority = Cpu_session::DEFAULT_PRIORITY,
|
||||
unsigned long affinity = 0)
|
||||
: Connection<Vm_session>(
|
||||
session("priority=0x%lx, affinity=0x%lx, ram_quota=8K, label=\"%s\"",
|
||||
session("priority=0x%lx, affinity=0x%lx, ram_quota=16K, label=\"%s\"",
|
||||
priority, affinity, label)),
|
||||
Vm_session_client(cap()) { }
|
||||
};
|
||||
|
@ -12,9 +12,10 @@ INC_DIR += $(BOARD_DIR) $(REP_DIR)/src/core/include $(REP_DIR)/include \
|
||||
CC_OPT += -DCORE_MAIN=_main
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_support.cc kernel.cc rm_session_support.cc
|
||||
SRC_CC += kernel.cc rm_session_support.cc kernel_support.cc trustzone.cc
|
||||
|
||||
LIBS += platform_support
|
||||
|
||||
# declare source paths
|
||||
vpath platform_support.cc $(BOARD_DIR)
|
||||
vpath % $(REP_DIR)/src/core
|
||||
vpath %.cc $(REP_DIR)/src/core
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
# 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/core_support.inc
|
||||
|
||||
|
@ -9,8 +9,9 @@ INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/core/include
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_support.cc
|
||||
SRC_CC += platform_services.cc platform_support.cc
|
||||
|
||||
# declare source paths
|
||||
vpath % $(REP_DIR)/src/core/panda_a2
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/panda_a2
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
# 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/core_support.inc
|
||||
|
||||
|
17
base-hw/lib/mk/platform_pbxa9/platform_support.mk
Normal file
17
base-hw/lib/mk/platform_pbxa9/platform_support.mk
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# \brief Platform implementations specific for base-hw and PBXA9
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/core/include
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc platform_support.cc
|
||||
|
||||
# declare source paths
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/pbxa9
|
||||
|
@ -4,9 +4,4 @@
|
||||
# \date 2012-04-27
|
||||
#
|
||||
|
||||
# declare location of core files that are board specific
|
||||
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/core_support.inc
|
||||
|
||||
LIBS += vea9x4_core_support
|
||||
|
7
base-hw/lib/mk/platform_vea9x4/platform_support.mk
Normal file
7
base-hw/lib/mk/platform_vea9x4/platform_support.mk
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# \brief Platform implementations specific for base-hw and VEA9X4
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
LIBS += vea9x4_platform_support
|
17
base-hw/lib/mk/trustzone/vea9x4_core_support.mk
Normal file
17
base-hw/lib/mk/trustzone/vea9x4_core_support.mk
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# \brief Trustzone support for VEA9X4 with TZ enabled
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-10
|
||||
#
|
||||
|
||||
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
||||
|
||||
INC_DIR += $(BOARD_DIR)/trustzone
|
||||
|
||||
# declare source paths
|
||||
vpath kernel_support.cc $(BOARD_DIR)/trustzone
|
||||
vpath trustzone.cc $(BOARD_DIR)/trustzone
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/core_support.inc
|
||||
|
17
base-hw/lib/mk/trustzone/vea9x4_platform_support.mk
Normal file
17
base-hw/lib/mk/trustzone/vea9x4_platform_support.mk
Normal file
@ -0,0 +1,17 @@
|
||||
#
|
||||
# \brief Platform implementations specific for base-hw and VEA9X4 (TrustZone)
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/core/include
|
||||
|
||||
SRC_CC = platform_services.cc \
|
||||
platform_support.cc \
|
||||
vm_session_component.cc
|
||||
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/vea9x4/trustzone
|
||||
vpath platform_services.cc $(REP_DIR)/src/core/vea9x4/trustzone
|
||||
vpath vm_session_component.cc $(REP_DIR)/src/core
|
10
base-hw/lib/mk/vea9x4_core_support.mk
Normal file
10
base-hw/lib/mk/vea9x4_core_support.mk
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# \brief Trustzone support for VEA9X4 with TZ disabled
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-10
|
||||
#
|
||||
|
||||
BOARD_DIR = $(REP_DIR)/src/core/vea9x4
|
||||
|
||||
# include generic part of core support
|
||||
include $(REP_DIR)/lib/mk/core_support.inc
|
14
base-hw/lib/mk/vea9x4_platform_support.mk
Normal file
14
base-hw/lib/mk/vea9x4_platform_support.mk
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# \brief Platform implementations specific for base-hw and VEA9X4
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
# add include paths
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
$(BASE_DIR)/src/core/include
|
||||
|
||||
SRC_CC = platform_support.cc platform_services.cc
|
||||
|
||||
vpath platform_support.cc $(REP_DIR)/src/core/vea9x4
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core
|
@ -199,15 +199,16 @@ proc build_boot_image {binaries} {
|
||||
}
|
||||
|
||||
# preserve stand-alone core for debugging
|
||||
exec mv core/core core/core.standalone
|
||||
exec cp -L bin/core core/core.standalone
|
||||
|
||||
# apply the new 'boot_modules.s' to 'core' to create single boot image
|
||||
apply_boot_modules_to_core $boot_modules
|
||||
exec mv core/core [run_dir]/image.elf
|
||||
exec cp -L bin/core [run_dir]/image.elf
|
||||
exec [cross_dev_prefix]strip [run_dir]/image.elf
|
||||
|
||||
# remove stripped binaries and retrieve stand-alone core
|
||||
exec mv core/core.standalone core/core
|
||||
exec cp core/core.standalone bin/core
|
||||
exec rm core/core.standalone
|
||||
exec rm -r [run_dir]/genode
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,6 @@
|
||||
ldr sp, =_kernel_stack_high
|
||||
bl kernel
|
||||
|
||||
/* jump to code that kernel has designated for when he has returned */
|
||||
ldr r1, =_call_after_kernel
|
||||
ldr r1, [r1]
|
||||
add pc, r1, #0
|
||||
|
||||
/* handle for dynamic symbol objects */
|
||||
.align 3
|
||||
.global __dso_handle
|
||||
@ -54,11 +49,6 @@
|
||||
|
||||
.section .bss
|
||||
|
||||
/* instruction pointer wich gets loaded when kernel returns */
|
||||
.align 3
|
||||
.global _call_after_kernel
|
||||
_call_after_kernel: .long 0
|
||||
|
||||
/* kernel stack */
|
||||
.align 3
|
||||
.space 64*1024
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Transition between kernel and userland
|
||||
* \brief Transition between kernel/userland, and secure/non-secure world
|
||||
* \author Martin stein
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2011-11-15
|
||||
*/
|
||||
|
||||
@ -11,14 +12,6 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Invalidate all entries of the branch predictor array
|
||||
*/
|
||||
.macro _flush_branch_predictor
|
||||
mcr p15, 0, sp, c7, c5, 6
|
||||
isb
|
||||
.endm
|
||||
|
||||
/**
|
||||
* Switch from an interrupted user context to a kernel context
|
||||
*
|
||||
@ -34,6 +27,11 @@
|
||||
* user mode at this point.
|
||||
*/
|
||||
|
||||
/* when not in FIQ mode disable FIQs */
|
||||
.if \exception_type != 6
|
||||
cpsid f
|
||||
.endif
|
||||
|
||||
/************************************************
|
||||
** We're still in the user protection domain, **
|
||||
** so we must avoid access to kernel memory **
|
||||
@ -43,20 +41,20 @@
|
||||
adr sp, _mt_kernel_context_begin
|
||||
ldr sp, [sp, #18*4]
|
||||
mcr p15, 0, sp, c13, c0, 1
|
||||
_flush_branch_predictor
|
||||
|
||||
/* load kernel section table */
|
||||
adr sp, _mt_kernel_context_begin
|
||||
ldr sp, [sp, #19*4]
|
||||
mcr p15, 0, sp, c2, c0, 0
|
||||
_flush_branch_predictor
|
||||
isb
|
||||
dsb
|
||||
|
||||
/*******************************************
|
||||
** Now it's save to access kernel memory **
|
||||
*******************************************/
|
||||
|
||||
/* get user context pointer */
|
||||
ldr sp, _mt_user_context_ptr
|
||||
ldr sp, _mt_context_ptr
|
||||
|
||||
/*
|
||||
* Save user r0 ... r12. We explicitely target user registers
|
||||
@ -98,9 +96,144 @@
|
||||
add r0, r0, #13*4
|
||||
ldmia r0, {sp, lr, pc}
|
||||
|
||||
.endm /* _user_to_kernel_pic */
|
||||
|
||||
|
||||
/**
|
||||
* Switch from kernel context to a user context
|
||||
*/
|
||||
.macro _kernel_to_user_pic
|
||||
|
||||
/* get user context pointer */
|
||||
ldr lr, _mt_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 contextidr 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
|
||||
isb
|
||||
dsb
|
||||
|
||||
/* load user pc (implies application of the user psr) */
|
||||
adr lr, _mt_buffer
|
||||
ldmia lr, {pc}^
|
||||
|
||||
.endm /* _kernel_to_user_pic */
|
||||
|
||||
|
||||
.macro _fiq_check_prior_mode
|
||||
mrs r8, spsr /* load fiq-spsr */
|
||||
and r8, #31
|
||||
cmp r8, #16 /* check whether we come from user-mode */
|
||||
beq 1f
|
||||
mrs r8, spsr /* enable fiq-ignore bit */
|
||||
orr r8, #64
|
||||
msr spsr, r8
|
||||
subs pc, lr, #4 /* resume previous exception */
|
||||
1:
|
||||
.endm /* _fiq_check_prior_mode */
|
||||
|
||||
/**
|
||||
* Save sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _save_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
mrs r1, spsr /* store mode-specific spsr */
|
||||
stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */
|
||||
.endm /* _save_bank mode */
|
||||
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
stmia sp, {r0-lr}^ /* save user regs r0-r12,sp,lr */
|
||||
add r0, sp, #15*4
|
||||
.if \pc_adjust != 0 /* adjust pc if necessary */
|
||||
sub lr, lr, #\pc_adjust
|
||||
.endif
|
||||
stmia r0!, {lr} /* save pc */
|
||||
mrs r1, spsr /* spsr to r0 */
|
||||
mov r2, #\exception_type /* exception reason to r1 */
|
||||
stmia r0!, {r1-r2} /* save spsr, and exception reason */
|
||||
mov r1, #0
|
||||
mcr p15, 0, r1, c1, c1, 0 /* disable non-secure bit */
|
||||
_save_bank 27 /* save undefined banks */
|
||||
_save_bank 19 /* save supervisor banks */
|
||||
_save_bank 23 /* save abort banks */
|
||||
_save_bank 18 /* save irq banks */
|
||||
_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 */
|
||||
add r0, r0, #13*4 /* load kernel context */
|
||||
ldmia r0, {sp,lr,pc}
|
||||
.endm /* _vm_to_kernel */
|
||||
|
||||
|
||||
/**
|
||||
* Restore sp, lr and spsr register banks of specified exception mode
|
||||
*/
|
||||
.macro _restore_bank mode
|
||||
cps #\mode /* switch to given mode */
|
||||
ldmia r0!, {r1,sp,lr} /* load mode-specific sp, lr, and spsr into r1 */
|
||||
msr spsr_cxfs, r1 /* load mode-specific spsr */
|
||||
.endm
|
||||
|
||||
|
||||
/**
|
||||
* Switch from kernel context to a vm
|
||||
*/
|
||||
.macro _kernel_to_vm
|
||||
ldr r0, _mt_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 */
|
||||
_restore_bank 23 /* load abort banks */
|
||||
_restore_bank 18 /* load irq banks */
|
||||
_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 */
|
||||
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 */
|
||||
mov lr, #13
|
||||
mcr p15, 0, lr, c1, c1, 0 /* enable EA, FIQ, and NS bit in SCTRL */
|
||||
ldr lr, [sp, #15*4] /* load vm's ip */
|
||||
subs pc, lr, #0
|
||||
.endm /* _kernel_to_vm */
|
||||
|
||||
|
||||
.section .text
|
||||
|
||||
/*
|
||||
@ -110,7 +243,7 @@
|
||||
* To enable such switching, the kernel context must be stored within this
|
||||
* region, thus one should map it solely accessable for privileged modes.
|
||||
*/
|
||||
.align 3
|
||||
.p2align 12 /* page-aligned */
|
||||
.global _mode_transition_begin
|
||||
_mode_transition_begin:
|
||||
|
||||
@ -118,88 +251,79 @@
|
||||
* On user exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.align 3
|
||||
.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 */
|
||||
b _fiq_entry /* fast interrupt request */
|
||||
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
|
||||
|
||||
/* 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
|
||||
_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
|
||||
_fiq_entry: _user_to_kernel_pic 7, 4
|
||||
_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
|
||||
|
||||
/* kernel must jump to this point to switch to a user context */
|
||||
.align 3
|
||||
.p2align 2
|
||||
.global _mt_user_entry_pic
|
||||
_mt_user_entry_pic:
|
||||
|
||||
/* get user context pointer */
|
||||
ldr lr, _mt_user_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 contextidr 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}^
|
||||
_kernel_to_user_pic
|
||||
|
||||
/* leave some space for the kernel context */
|
||||
.align 3
|
||||
.p2align 2
|
||||
.global _mt_kernel_context_begin
|
||||
_mt_kernel_context_begin: .space 32*4
|
||||
.global _mt_kernel_context_end
|
||||
_mt_kernel_context_end:
|
||||
|
||||
/* pointer to the user context backup space */
|
||||
.align 3
|
||||
.global _mt_user_context_ptr
|
||||
_mt_user_context_ptr: .long 0
|
||||
/* pointer to the context backup space */
|
||||
.p2align 2
|
||||
.global _mt_context_ptr
|
||||
_mt_context_ptr: .long 0
|
||||
|
||||
/* a local word-sized buffer */
|
||||
.align 3
|
||||
.p2align 2
|
||||
.global _mt_buffer
|
||||
_mt_buffer: .long 0
|
||||
|
||||
.align 3
|
||||
.global _mode_transition_end
|
||||
_mode_transition_end:
|
||||
|
||||
/*
|
||||
* On vm exceptions the CPU has to jump to one of the following
|
||||
* 7 entry vectors to switch to a kernel context.
|
||||
*/
|
||||
.p2align 2
|
||||
.global _mon_kernel_entry
|
||||
_mon_kernel_entry:
|
||||
b _mon_rst_entry /* reset */
|
||||
b _mon_und_entry /* undefined instruction */
|
||||
b _mon_svc_entry /* supervisor call */
|
||||
b _mon_pab_entry /* prefetch abort */
|
||||
b _mon_dab_entry /* data abort */
|
||||
nop /* reserved */
|
||||
b _mon_irq_entry /* interrupt request */
|
||||
_vm_to_kernel 6, 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
|
||||
|
||||
/* kernel must jump to this point to switch to a vm */
|
||||
.p2align 2
|
||||
.global _mon_vm_entry
|
||||
_mon_vm_entry:
|
||||
_kernel_to_vm
|
||||
|
@ -473,13 +473,7 @@ namespace Genode
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
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);
|
||||
}
|
||||
User_context(void);
|
||||
|
||||
/***************************************************
|
||||
** Communication between user and context holder **
|
||||
@ -502,33 +496,6 @@ namespace Genode
|
||||
unsigned user_arg_6() const { return r[6]; }
|
||||
unsigned user_arg_7() const { return r[7]; }
|
||||
|
||||
/**
|
||||
* Determine wich type of exception occured on this context lastly
|
||||
*
|
||||
* \return 0 If the exception is unknown by the kernel
|
||||
* 1 If the exception is an interrupt
|
||||
* 2 If the exception is a pagefault
|
||||
* 3 If the exception is a syscall
|
||||
*/
|
||||
unsigned exception() const
|
||||
{
|
||||
/* map all CPU-exception types to kernel-exception types */
|
||||
enum { INVALID = 0, INTERRUPT = 1, PAGEFAULT = 2, SYSCALL = 3 };
|
||||
static unsigned cpu_excpt_to_excpt[MAX_CPU_EXCEPTION + 1] = {
|
||||
INVALID, /* 0 */
|
||||
INVALID, /* 1 */
|
||||
INVALID, /* 2 */
|
||||
SYSCALL, /* 3 */
|
||||
PAGEFAULT, /* 4 */
|
||||
PAGEFAULT, /* 5 */
|
||||
INTERRUPT, /* 6 */
|
||||
INVALID /* 7 */
|
||||
};
|
||||
/* determine exception type */
|
||||
if (cpu_exception > MAX_CPU_EXCEPTION) return INVALID;
|
||||
return cpu_excpt_to_excpt[cpu_exception];
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a pagefault exist and originate from a lack of translation?
|
||||
*
|
||||
@ -684,6 +651,31 @@ namespace Genode
|
||||
:: [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));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,35 @@ namespace Kernel
|
||||
*/
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -60,6 +60,14 @@ namespace Genode
|
||||
struct Cpu_number : Bitfield<5,3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt security registers
|
||||
*/
|
||||
struct Icdisr : Register_array<0x80, 32, MAX_INTERRUPT_ID+1, 1>
|
||||
{
|
||||
struct Nonsecure : Bitfield<0, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Interrupt set enable registers
|
||||
*/
|
||||
@ -152,7 +160,7 @@ namespace Genode
|
||||
struct Enable_ns : Bitfield<1,1> { };
|
||||
struct Ack_ctl : Bitfield<2,1> { };
|
||||
struct Fiq_en : Bitfield<3,1> { };
|
||||
struct Sbpr : Bitfield<4,1> { };
|
||||
struct Cbpr : Bitfield<4,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
@ -192,6 +200,17 @@ namespace Genode
|
||||
struct Cpu_id : Bitfield<10,3> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Non-secure Binary point register
|
||||
*/
|
||||
struct Iccabpr : Register<0x1c, 32>
|
||||
{
|
||||
struct Binary_point : Bitfield<0,3>
|
||||
{
|
||||
enum { NO_PREEMPTION = 7 };
|
||||
};
|
||||
};
|
||||
|
||||
} _cpu;
|
||||
|
||||
unsigned const _max_interrupt;
|
||||
@ -206,36 +225,7 @@ namespace Genode
|
||||
_distr(distributor),
|
||||
_cpu(cpu_interface),
|
||||
_max_interrupt(_distr.max_interrupt()),
|
||||
_last_taken_request(SPURIOUS_ID)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
_last_taken_request(SPURIOUS_ID) { }
|
||||
|
||||
/**
|
||||
* Get the ID of the last interrupt request
|
||||
|
25
base-hw/src/core/include/trustzone.h
Normal file
25
base-hw/src/core/include/trustzone.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief TrustZone specific functions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__TRUSTZONE_H_
|
||||
#define _CORE__INCLUDE__TRUSTZONE_H_
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class Pic;
|
||||
|
||||
|
||||
void trustzone_initialization(Pic *pic);
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__TRUSTZONE_H_ */
|
56
base-hw/src/core/include/vm_root.h
Normal file
56
base-hw/src/core/include/vm_root.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* \brief Vm root interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__VM_ROOT_H_
|
||||
#define _CORE__INCLUDE__VM_ROOT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <root/component.h>
|
||||
|
||||
/* core includes */
|
||||
#include <vm_session_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Vm_root : public Root_component<Vm_session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Range_allocator *_ram_alloc;
|
||||
|
||||
protected:
|
||||
|
||||
Vm_session_component *_create_session(const char *args)
|
||||
{
|
||||
size_t ram_quota = Arg_string::find_arg(args, "ram_quota").long_value(0);
|
||||
return new (md_alloc())
|
||||
Vm_session_component(ep(), _ram_alloc, ram_quota);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session_ep entrypoint managing vm_session components
|
||||
* \param md_alloc meta-data allocator to be used by root component
|
||||
*/
|
||||
Vm_root(Rpc_entrypoint *session_ep,
|
||||
Allocator *md_alloc,
|
||||
Range_allocator *ram_alloc)
|
||||
: Root_component<Vm_session_component>(session_ep, md_alloc),
|
||||
_ram_alloc(ram_alloc){ }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__VM_ROOT_H_ */
|
73
base-hw/src/core/include/vm_session_component.h
Normal file
73
base-hw/src/core/include/vm_session_component.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__VM_SESSION_COMPONENT_H_
|
||||
#define _CORE__INCLUDE__VM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <vm_session/vm_session.h>
|
||||
#include <dataspace/capability.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <dataspace_component.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Vm_session_component : public Rpc_object<Vm_session>
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint *_ds_ep;
|
||||
Range_allocator *_ram_alloc;
|
||||
unsigned long _vm_id;
|
||||
void *_vm;
|
||||
addr_t _ds_addr;
|
||||
Dataspace_component _ds;
|
||||
Dataspace_capability _ds_cap;
|
||||
|
||||
static size_t _ds_size() {
|
||||
return align_addr(sizeof(Cpu_state_modes),
|
||||
get_page_size_log2()); }
|
||||
|
||||
addr_t _alloc_ds(size_t *ram_quota)
|
||||
{
|
||||
addr_t addr;
|
||||
if (_ds_size() > *ram_quota ||
|
||||
!_ram_alloc->alloc_aligned(_ds_size(), (void**)&addr,
|
||||
get_page_size_log2()))
|
||||
throw Root::Quota_exceeded();
|
||||
*ram_quota -= _ds_size();
|
||||
return addr;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
Range_allocator *ram_alloc,
|
||||
size_t ram_quota);
|
||||
~Vm_session_component();
|
||||
|
||||
|
||||
/**************************
|
||||
** Vm session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability cpu_state(void) { return _ds_cap; }
|
||||
void exception_handler(Signal_context_capability handler);
|
||||
void run(void);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__VM_SESSION_COMPONENT_H_ */
|
@ -24,6 +24,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/signal.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
#include <util/fifo.h>
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
@ -32,11 +33,11 @@
|
||||
#include <platform_thread.h>
|
||||
#include <assert.h>
|
||||
#include <software_tlb.h>
|
||||
#include <trustzone.h>
|
||||
|
||||
using namespace Kernel;
|
||||
|
||||
/* get core configuration */
|
||||
extern Genode::addr_t _call_after_kernel;
|
||||
extern Genode::Native_utcb * _main_utcb;
|
||||
extern int _kernel_stack_high;
|
||||
extern "C" void CORE_MAIN();
|
||||
@ -45,8 +46,8 @@ extern "C" void CORE_MAIN();
|
||||
extern int _mode_transition_begin;
|
||||
extern int _mode_transition_end;
|
||||
extern int _mt_user_entry_pic;
|
||||
extern int _mt_kernel_entry_pic;
|
||||
extern Genode::addr_t _mt_user_context_ptr;
|
||||
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;
|
||||
|
||||
@ -72,6 +73,7 @@ namespace Kernel
|
||||
MAX_THREADS = 256,
|
||||
MAX_SIGNAL_RECEIVERS = 256,
|
||||
MAX_SIGNAL_CONTEXTS = 256,
|
||||
MAX_VMS = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -710,16 +712,18 @@ namespace Kernel
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Schedule_context;
|
||||
|
||||
/**
|
||||
* Provides the mode transition PIC in a configurable and mappable manner
|
||||
* Controls the mode transition code
|
||||
*
|
||||
* Initially there exists only the code that switches between kernelmode
|
||||
* and usermode. It must be present in a continuous region that is located
|
||||
* at an arbitray RAM address. Its size must not exceed the smallest page
|
||||
* size supported by the MMU. The Code must be position independent. This
|
||||
* control then duplicates the code to an aligned region and declares a
|
||||
* virtual region, where the latter has to be mapped to in every PD, to
|
||||
* ensure appropriate kernel invokation on CPU interrupts.
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
struct Mode_transition_control
|
||||
{
|
||||
@ -731,32 +735,14 @@ namespace Kernel
|
||||
ALIGNM_LOG2 = SIZE_LOG2,
|
||||
};
|
||||
|
||||
/* writeable, page-aligned backing store */
|
||||
char _payload[SIZE] __attribute__((aligned(1 << ALIGNM_LOG2)));
|
||||
|
||||
/* labels within the aligned mode transition PIC */
|
||||
Cpu::Context * * const _user_context_ptr;
|
||||
Cpu::Context * const _kernel_context;
|
||||
addr_t const _virt_user_entry;
|
||||
addr_t const _virt_kernel_entry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Mode_transition_control() :
|
||||
_user_context_ptr((Cpu::Context * *)((addr_t)_payload +
|
||||
((addr_t)&_mt_user_context_ptr -
|
||||
(addr_t)&_mode_transition_begin))),
|
||||
|
||||
_kernel_context((Cpu::Context *)((addr_t)_payload +
|
||||
((addr_t)&_mt_kernel_context_begin -
|
||||
(addr_t)&_mode_transition_begin))),
|
||||
|
||||
_virt_user_entry(VIRT_BASE + ((addr_t)&_mt_user_entry_pic -
|
||||
(addr_t)&_mode_transition_begin)),
|
||||
|
||||
_virt_kernel_entry(VIRT_BASE + ((addr_t)&_mt_kernel_entry_pic -
|
||||
(addr_t)&_mode_transition_begin))
|
||||
(addr_t)&_mode_transition_begin))
|
||||
{
|
||||
/* check if mode transition PIC fits into aligned region */
|
||||
addr_t const pic_begin = (addr_t)&_mode_transition_begin;
|
||||
@ -768,37 +754,28 @@ namespace Kernel
|
||||
addr_t const kc_begin = (addr_t)&_mt_kernel_context_begin;
|
||||
addr_t const kc_end = (addr_t)&_mt_kernel_context_end;
|
||||
size_t const kc_size = kc_end - kc_begin;
|
||||
assert(sizeof(Cpu::Context) <= kc_size)
|
||||
|
||||
/* fetch mode transition PIC */
|
||||
unsigned * dst = (unsigned *)_payload;
|
||||
unsigned * src = (unsigned *)pic_begin;
|
||||
while ((addr_t)src < pic_end) *dst++ = *src++;
|
||||
assert(sizeof(Cpu::Context) <= kc_size);
|
||||
|
||||
/* try to set CPU exception entry accordingly */
|
||||
assert(!Cpu::exception_entry_at(_virt_kernel_entry))
|
||||
assert(!Cpu::exception_entry_at(VIRT_BASE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set next usermode-context pointer
|
||||
*/
|
||||
void user_context(Cpu::Context * const c) { *_user_context_ptr = c; }
|
||||
|
||||
/**
|
||||
* Fetch next kernelmode context
|
||||
*/
|
||||
void fetch_kernel_context(Cpu::Context * const c)
|
||||
{ *_kernel_context = *c; }
|
||||
void fetch_kernel_context(Cpu::Context * const c) {
|
||||
memcpy(&_mt_kernel_context_begin, c, sizeof(Cpu::Context)); }
|
||||
|
||||
/**
|
||||
* Page aligned physical base of the mode transition PIC
|
||||
*/
|
||||
addr_t phys_base() { return (addr_t)_payload; }
|
||||
addr_t phys_base() { return (addr_t)&_mode_transition_begin; }
|
||||
|
||||
/**
|
||||
* Virtual pointer to the usermode entry PIC
|
||||
* Jump to the usermode entry PIC
|
||||
*/
|
||||
addr_t virt_user_entry() { return _virt_user_entry; }
|
||||
void virt_user_entry() {
|
||||
((void(*)(void))_virt_user_entry)(); }
|
||||
};
|
||||
|
||||
|
||||
@ -1093,9 +1070,17 @@ namespace Kernel
|
||||
static Timer * timer() { static Timer _object; return &_object; }
|
||||
|
||||
|
||||
class Thread;
|
||||
class Schedule_context;
|
||||
|
||||
typedef Scheduler<Thread> Cpu_scheduler;
|
||||
typedef Scheduler<Schedule_context> Cpu_scheduler;
|
||||
|
||||
class Schedule_context : public Cpu_scheduler::Entry
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void handle_exception() = 0;
|
||||
virtual void scheduled_next() = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@ -1116,15 +1101,23 @@ namespace Kernel
|
||||
unsigned core_id() { return core()->id(); }
|
||||
|
||||
|
||||
class Thread;
|
||||
|
||||
void handle_pagefault(Thread * const);
|
||||
void handle_syscall(Thread * const);
|
||||
void handle_interrupt(void);
|
||||
void handle_invalid_excpt(void);
|
||||
|
||||
|
||||
/**
|
||||
* Kernel object that represents a Genode thread
|
||||
*/
|
||||
class Thread : public Cpu::User_context,
|
||||
public Object<Thread, MAX_THREADS>,
|
||||
public Cpu_scheduler::Entry,
|
||||
public Schedule_context,
|
||||
public Fifo<Thread>::Element,
|
||||
public Ipc_node,
|
||||
public Irq_owner,
|
||||
public Fifo<Thread>::Element
|
||||
public Irq_owner
|
||||
{
|
||||
enum State { STOPPED, ACTIVE, AWAIT_IPC, AWAIT_RESUMPTION,
|
||||
AWAIT_IRQ, AWAIT_SIGNAL };
|
||||
@ -1132,14 +1125,9 @@ 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 of thread
|
||||
* Resume execution
|
||||
*/
|
||||
void _activate()
|
||||
{
|
||||
@ -1147,6 +1135,12 @@ 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; }
|
||||
@ -1275,6 +1269,32 @@ namespace Kernel
|
||||
_activate();
|
||||
}
|
||||
|
||||
void handle_exception()
|
||||
{
|
||||
switch(cpu_exception) {
|
||||
case SUPERVISOR_CALL:
|
||||
handle_syscall(this);
|
||||
return;
|
||||
case PREFETCH_ABORT:
|
||||
case DATA_ABORT:
|
||||
handle_pagefault(this);
|
||||
return;
|
||||
case INTERRUPT_REQUEST:
|
||||
case FAST_INTERRUPT_REQUEST:
|
||||
handle_interrupt();
|
||||
return;
|
||||
default:
|
||||
handle_invalid_excpt();
|
||||
}
|
||||
}
|
||||
|
||||
void scheduled_next() {
|
||||
/* set context pointer for mode switch */
|
||||
_mt_context_ptr = (addr_t)static_cast<Genode::Cpu_state*>(this);
|
||||
|
||||
/* jump to user entry assembler path */
|
||||
mtc()->virt_user_entry();
|
||||
}
|
||||
|
||||
/***************
|
||||
** Accessors **
|
||||
@ -1324,6 +1344,7 @@ namespace Kernel
|
||||
|
||||
class Signal_receiver;
|
||||
|
||||
|
||||
/**
|
||||
* Specific signal type, owned by a receiver, can be triggered asynchr.
|
||||
*/
|
||||
@ -1410,6 +1431,57 @@ namespace Kernel
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Vm : public Object<Vm, MAX_VMS>,
|
||||
public Schedule_context
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Cpu_state_modes * const _state;
|
||||
Signal_context * const _context;
|
||||
|
||||
public:
|
||||
|
||||
void * operator new (size_t, void * p) { return p; }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Vm(Genode::Cpu_state_modes * const state,
|
||||
Signal_context * const context)
|
||||
: _state(state), _context(context) { }
|
||||
|
||||
void run() {
|
||||
cpu_scheduler()->insert(this); }
|
||||
|
||||
|
||||
/**********************
|
||||
** Schedule_context **
|
||||
**********************/
|
||||
|
||||
void handle_exception()
|
||||
{
|
||||
switch(_state->cpu_exception) {
|
||||
case Genode::Cpu_state::INTERRUPT_REQUEST:
|
||||
case Genode::Cpu_state::FAST_INTERRUPT_REQUEST:
|
||||
handle_interrupt();
|
||||
return;
|
||||
default:
|
||||
cpu_scheduler()->remove(this);
|
||||
_context->trigger_signal(1);
|
||||
}
|
||||
}
|
||||
|
||||
void scheduled_next() {
|
||||
/* set context pointer for mode switch */
|
||||
_mt_context_ptr = (addr_t)_state;
|
||||
|
||||
/* jump to assembler path */
|
||||
((void(*)(void))&_mon_vm_entry)();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Access to static CPU scheduler
|
||||
*/
|
||||
@ -1449,18 +1521,19 @@ namespace Kernel
|
||||
size_t signal_context_size() { return sizeof(Signal_context); }
|
||||
size_t signal_receiver_size() { return sizeof(Signal_receiver); }
|
||||
unsigned pd_alignm_log2() { return Pd::ALIGNM_LOG2; }
|
||||
size_t vm_size() { return sizeof(Vm); }
|
||||
|
||||
|
||||
/**
|
||||
* Handle the occurence of an unknown exception
|
||||
*/
|
||||
void handle_invalid_excpt(Thread * const) { assert(0); }
|
||||
void handle_invalid_excpt() { assert(0); }
|
||||
|
||||
|
||||
/**
|
||||
* Handle an interrupt request
|
||||
*/
|
||||
void handle_interrupt(Thread * const)
|
||||
void handle_interrupt()
|
||||
{
|
||||
/* determine handling for specific interrupt */
|
||||
unsigned irq;
|
||||
@ -1886,7 +1959,48 @@ namespace Kernel
|
||||
assert(c);
|
||||
|
||||
/* trigger signal at context */
|
||||
c->trigger_signal(user->user_arg_2());
|
||||
c->trigger_signal(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for 'user', for details see 'syscall.h'
|
||||
*/
|
||||
void do_new_vm(Thread * const user)
|
||||
{
|
||||
/* check permissions */
|
||||
assert(user->pd_id() == core_id());
|
||||
|
||||
/* dispatch arguments */
|
||||
void * const allocator = (void * const)user->user_arg_1();
|
||||
Genode::Cpu_state_modes * const state =
|
||||
(Genode::Cpu_state_modes * const)user->user_arg_2();
|
||||
Signal_context * const context =
|
||||
Signal_context::pool()->object(user->user_arg_3());
|
||||
assert(context);
|
||||
|
||||
/* create vm */
|
||||
Vm * const vm = new (allocator) Vm(state, context);
|
||||
|
||||
/* return vm id */
|
||||
user->user_arg_0((Syscall_ret)vm->id());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do specific syscall for 'user', for details see 'syscall.h'
|
||||
*/
|
||||
void do_run_vm(Thread * const user)
|
||||
{
|
||||
/* check permissions */
|
||||
assert(user->pd_id() == core_id());
|
||||
|
||||
/* get targeted vm via its id */
|
||||
Vm * const vm = Vm::pool()->object(user->user_arg_1());
|
||||
assert(vm);
|
||||
|
||||
/* run targeted vm */
|
||||
vm->run();
|
||||
}
|
||||
|
||||
|
||||
@ -1928,6 +2042,8 @@ namespace Kernel
|
||||
/* 22 */ do_await_signal,
|
||||
/* 23 */ do_submit_signal,
|
||||
/* 24 */ do_delete_thread,
|
||||
/* 25 */ do_new_vm,
|
||||
/* 26 */ do_run_vm,
|
||||
};
|
||||
enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 };
|
||||
|
||||
@ -1954,30 +2070,12 @@ extern "C" void kernel()
|
||||
/* update how much time the last user has consumed */
|
||||
user_time = timer_value < user_time ? user_time - timer_value : 0;
|
||||
|
||||
/* map exception types to exception-handler functions */
|
||||
typedef void (*Exception_handler)(Thread * const);
|
||||
static Exception_handler const handle_excpt[] =
|
||||
{
|
||||
/* exception ID */ /* handler */
|
||||
/*--------------*/ /*---------*/
|
||||
/* 0 */ handle_invalid_excpt,
|
||||
/* 1 */ handle_interrupt,
|
||||
/* 2 */ handle_pagefault,
|
||||
/* 3 */ handle_syscall
|
||||
};
|
||||
/* handle exception that interrupted the last user */
|
||||
Thread * const user = cpu_scheduler()->current_entry();
|
||||
enum { MAX_EXCPT = sizeof(handle_excpt)/sizeof(handle_excpt[0]) - 1 };
|
||||
unsigned const e = user->exception();
|
||||
if (e > MAX_EXCPT) handle_invalid_excpt(user);
|
||||
else handle_excpt[e](user);
|
||||
cpu_scheduler()->current_entry()->handle_exception();
|
||||
|
||||
/* kernel initialization */
|
||||
} else {
|
||||
|
||||
/* tell the code that called kernel, what to do when kernel returns */
|
||||
_call_after_kernel = mtc()->virt_user_entry();
|
||||
|
||||
/* compose core address space */
|
||||
addr_t a = 0;
|
||||
while (1)
|
||||
@ -2001,7 +2099,6 @@ extern "C" void kernel()
|
||||
/* compose kernel CPU context */
|
||||
static Cpu::Context kernel_context;
|
||||
kernel_context.instruction_ptr((addr_t)kernel);
|
||||
kernel_context.return_ptr(mtc()->virt_user_entry());
|
||||
kernel_context.stack_ptr((addr_t)&_kernel_stack_high);
|
||||
|
||||
/* add kernel to the core PD */
|
||||
@ -2010,6 +2107,9 @@ extern "C" void kernel()
|
||||
/* offer the final kernel context to the mode transition page */
|
||||
mtc()->fetch_kernel_context(&kernel_context);
|
||||
|
||||
/* TrustZone initialization code */
|
||||
trustzone_initialization(pic());
|
||||
|
||||
/* switch to core address space */
|
||||
Cpu::enable_mmu(core(), core_id());
|
||||
|
||||
@ -2028,12 +2128,14 @@ extern "C" void kernel()
|
||||
initial_call = false;
|
||||
}
|
||||
/* offer next user context to the mode transition PIC */
|
||||
Thread * const next = cpu_scheduler()->next_entry(user_time);
|
||||
mtc()->user_context(next);
|
||||
Schedule_context* const next = cpu_scheduler()->next_entry(user_time);
|
||||
|
||||
/* limit user mode execution in time */
|
||||
timer()->start_one_shot(user_time);
|
||||
pic()->unmask(Timer::IRQ);
|
||||
|
||||
/* will jump to the context related mode-switch */
|
||||
next->scheduled_next();
|
||||
}
|
||||
|
||||
|
||||
|
23
base-hw/src/core/kernel_support.cc
Normal file
23
base-hw/src/core/kernel_support.cc
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* \brief Kernel function implementations specific for Cortex A9 CPUs
|
||||
* \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.
|
||||
*/
|
||||
|
||||
#include <kernel_support.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
@ -81,4 +81,3 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
9
base-hw/src/core/panda_a2/target.mk
Normal file
9
base-hw/src/core/panda_a2/target.mk
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# \brief Pandaboard-specific makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
REQUIRES = platform_panda_a2
|
||||
|
||||
include $(REP_DIR)/src/core/target.inc
|
@ -79,4 +79,3 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
9
base-hw/src/core/pbxa9/target.mk
Normal file
9
base-hw/src/core/pbxa9/target.mk
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# \brief PBXA9-specific makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
REQUIRES = platform_pbxa9
|
||||
|
||||
include $(REP_DIR)/src/core/target.inc
|
@ -36,7 +36,6 @@ SRC_CC += _main.cc \
|
||||
platform.cc \
|
||||
platform_pd.cc \
|
||||
platform_thread.cc \
|
||||
platform_services.cc \
|
||||
ram_session_component.cc \
|
||||
ram_session_support.cc \
|
||||
rm_session_component.cc \
|
||||
@ -52,7 +51,6 @@ vpath io_mem_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath io_mem_session_support.cc $(GEN_CORE_DIR)
|
||||
vpath main.cc $(GEN_CORE_DIR)
|
||||
vpath pd_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)
|
||||
vpath ram_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rm_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath rom_session_component.cc $(GEN_CORE_DIR)
|
16
base-hw/src/core/trustzone.cc
Normal file
16
base-hw/src/core/trustzone.cc
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* \brief TrustZone specific functions for non-TZ case
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <trustzone.h>
|
||||
|
||||
void Kernel::trustzone_initialization(Pic *pic) { }
|
@ -80,4 +80,3 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
13
base-hw/src/core/vea9x4/target.mk
Normal file
13
base-hw/src/core/vea9x4/target.mk
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# \brief VEA9x4-specific makefile for core
|
||||
# \author Stefan Kalkowski
|
||||
# \date 2012-10-04
|
||||
#
|
||||
|
||||
REQUIRES = platform_vea9x4
|
||||
|
||||
ifeq ($(filter-out $(SPECS),trustzone),)
|
||||
LD_TEXT_ADDR = 0x48000000
|
||||
endif
|
||||
|
||||
include $(REP_DIR)/src/core/target.inc
|
24
base-hw/src/core/vea9x4/trustzone/kernel_support.cc
Normal file
24
base-hw/src/core/vea9x4/trustzone/kernel_support.cc
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* \brief Kernel-specific implementations for Versatile Express with TZ
|
||||
* \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.
|
||||
*/
|
||||
|
||||
/* Core includes */
|
||||
#include <kernel_support.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
82
base-hw/src/core/vea9x4/trustzone/kernel_support.h
Normal file
82
base-hw/src/core/vea9x4/trustzone/kernel_support.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* \brief Kernel support specific for the Versatile VEA9X4
|
||||
* \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 _SRC__CORE__VEA9X4__TRUSTZONE__KERNEL_SUPPORT_H_
|
||||
#define _SRC__CORE__VEA9X4__TRUSTZONE__KERNEL_SUPPORT_H_
|
||||
|
||||
/* Core includes */
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
#include <pic/pl390_base.h>
|
||||
|
||||
/**
|
||||
* CPU driver
|
||||
*/
|
||||
class Cpu : public Genode::Cortex_a9 { };
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
/* import Genode types */
|
||||
typedef Genode::Cortex_a9 Cortex_a9;
|
||||
typedef Genode::Pl390_base Pl390_base;
|
||||
|
||||
/**
|
||||
* Kernel 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); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Kernel timer
|
||||
*/
|
||||
class Timer : public Cortex_a9::Private_timer { };
|
||||
}
|
||||
|
||||
|
||||
#endif /* _SRC__CORE__VEA9X4__TRUSTZONE__KERNEL_SUPPORT_H_ */
|
||||
|
35
base-hw/src/core/vea9x4/trustzone/platform_services.cc
Normal file
35
base-hw/src/core/vea9x4/trustzone/platform_services.cc
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* \brief Platform specific services for base-hw and VEA9X4 (TrustZone)
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <base/service.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <platform.h>
|
||||
#include <platform_services.h>
|
||||
#include <vm_root.h>
|
||||
|
||||
|
||||
/*
|
||||
* Add TrustZone specific vm service
|
||||
*/
|
||||
void Genode::platform_add_local_services(Genode::Rpc_entrypoint *ep,
|
||||
Genode::Sliced_heap *sh,
|
||||
Genode::Service_registry *ls)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
static Vm_root vm_root(ep, sh, platform()->ram_alloc());
|
||||
static Local_service vm_ls(Vm_session::service_name(), &vm_root);
|
||||
ls->insert(&vm_ls);
|
||||
}
|
88
base-hw/src/core/vea9x4/trustzone/platform_support.cc
Normal file
88
base-hw/src/core/vea9x4/trustzone/platform_support.cc
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* \brief Platform implementations specific for base-hw and VEA9X4
|
||||
* \author Martin Stein
|
||||
* \date 2012-04-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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>
|
||||
|
||||
/* Core includes */
|
||||
#include <platform.h>
|
||||
#include <pic/pl390_base.h>
|
||||
#include <cortex_a9/cpu/core.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Native_region * Platform::_ram_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ Board::SRAM_BASE, Board::SRAM_SIZE }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_irq_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ 0, 34 },
|
||||
{ 37, 3 },
|
||||
{ 46, 1 },
|
||||
{ 49, Pl390_base::MAX_INTERRUPT_ID - 49 }
|
||||
};
|
||||
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 */
|
||||
{ Cortex_a9::PRIVATE_TIMER_IRQ, 1 },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_IRQ, 1 }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
||||
|
||||
|
||||
Native_region * Platform::_mmio_regions(unsigned const i)
|
||||
{
|
||||
static Native_region _regions[] =
|
||||
{
|
||||
{ Board::SMB_CS7_BASE, Board::SMB_CS7_SIZE },
|
||||
{ Board::SMB_CS0_TO_CS6_BASE, Board::SMB_CS0_TO_CS6_SIZE },
|
||||
{ Board::LOCAL_DDR2_BASE, Board::LOCAL_DDR2_SIZE },
|
||||
{ Board::TZASC_MMIO_BASE, Board::TZASC_MMIO_SIZE },
|
||||
{ Board::TZPC_MMIO_BASE, Board::TZPC_MMIO_SIZE },
|
||||
};
|
||||
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 timer and PIC */
|
||||
{ Board::CORTEX_A9_PRIVATE_MEM_BASE,
|
||||
Board::CORTEX_A9_PRIVATE_MEM_SIZE },
|
||||
|
||||
/* Core UART */
|
||||
{ Board::PL011_0_MMIO_BASE, Board::PL011_0_MMIO_SIZE }
|
||||
};
|
||||
return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
|
||||
}
|
42
base-hw/src/core/vea9x4/trustzone/trustzone.cc
Normal file
42
base-hw/src/core/vea9x4/trustzone/trustzone.cc
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* \brief TrustZone specific functions for Versatile Express
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Core includes */
|
||||
#include <trustzone.h>
|
||||
#include <kernel_support.h>
|
||||
|
||||
/* monitor exception vector address */
|
||||
extern int _mon_kernel_entry;
|
||||
|
||||
|
||||
void Kernel::trustzone_initialization(Pic *pic)
|
||||
{
|
||||
/* set exception vector entry */
|
||||
Cpu::mon_exception_entry_at((Genode::addr_t)&_mon_kernel_entry);
|
||||
|
||||
/* enable coprocessor access for TZ VMs */
|
||||
Cpu::allow_coprocessor_nonsecure();
|
||||
|
||||
/* set unsecure IRQs */
|
||||
pic->unsecure(34); //Timer 0/1
|
||||
pic->unsecure(35); //Timer 2/3
|
||||
pic->unsecure(36); //RTC
|
||||
pic->unsecure(40); //UART3
|
||||
pic->unsecure(41); //MCI0
|
||||
pic->unsecure(42); //MCI1
|
||||
pic->unsecure(43); //AACI
|
||||
pic->unsecure(44); //KMI0
|
||||
pic->unsecure(45); //KMI1
|
||||
pic->unsecure(47); //ETHERNET
|
||||
pic->unsecure(48); //USB
|
||||
}
|
70
base-hw/src/core/vm_session_component.cc
Normal file
70
base-hw/src/core/vm_session_component.cc
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* \brief Vm_session_component for base-hw
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2012-10-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <util/string.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <root/root.h>
|
||||
#include <cpu/cpu_state.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <vm_session_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Vm_session_component::exception_handler(Signal_context_capability handler)
|
||||
{
|
||||
if (_vm_id) {
|
||||
PWRN("Cannot register exception_handler repeatedly");
|
||||
return;
|
||||
}
|
||||
|
||||
_vm_id = Kernel::new_vm(_vm, (void*)_ds.core_local_addr(), handler.dst());
|
||||
}
|
||||
|
||||
|
||||
void Vm_session_component::run(void)
|
||||
{
|
||||
if (!_vm_id) {
|
||||
PWRN("No exception handler registered!");
|
||||
return;
|
||||
}
|
||||
Kernel::run_vm(_vm_id);
|
||||
}
|
||||
|
||||
|
||||
Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep,
|
||||
Range_allocator *ram_alloc,
|
||||
size_t ram_quota)
|
||||
: _ds_ep(ds_ep), _ram_alloc(ram_alloc), _vm_id(0),
|
||||
_ds_addr(_alloc_ds(&ram_quota)),
|
||||
_ds(_ds_size(), _ds_addr, _ds_addr, false, true, 0),
|
||||
_ds_cap(static_cap_cast<Dataspace>(_ds_ep->manage(&_ds)))
|
||||
{
|
||||
/* alloc needed memory */
|
||||
if (Kernel::vm_size() > ram_quota ||
|
||||
!_ram_alloc->alloc(Kernel::vm_size(), &_vm))
|
||||
throw Root::Quota_exceeded();
|
||||
}
|
||||
|
||||
|
||||
Vm_session_component::~Vm_session_component()
|
||||
{
|
||||
/* dissolve VM dataspace from service entry point */
|
||||
_ds_ep->dissolve(&_ds);
|
||||
|
||||
/* free region in allocator */
|
||||
_ram_alloc->free((void*)_ds.core_local_addr());
|
||||
_ram_alloc->free(_vm);
|
||||
}
|
@ -25,14 +25,14 @@ namespace Genode {
|
||||
* Native exception types
|
||||
*/
|
||||
enum Cpu_exception {
|
||||
RESET = 1,
|
||||
UNDEFINED_INSTRUCTION = 2,
|
||||
SUPERVISOR_CALL = 3,
|
||||
PREFETCH_ABORT = 4,
|
||||
DATA_ABORT = 5,
|
||||
INTERRUPT_REQUEST = 6,
|
||||
FAST_INTERRUPT_REQUEST = 7,
|
||||
MAX_CPU_EXCEPTION = FAST_INTERRUPT_REQUEST,
|
||||
RESET,
|
||||
UNDEFINED_INSTRUCTION,
|
||||
SUPERVISOR_CALL,
|
||||
PREFETCH_ABORT,
|
||||
DATA_ABORT,
|
||||
INTERRUPT_REQUEST,
|
||||
FAST_INTERRUPT_REQUEST,
|
||||
MAX_CPU_EXCEPTION,
|
||||
};
|
||||
|
||||
enum { MAX_GPR = 13 };
|
||||
@ -62,13 +62,13 @@ namespace Genode {
|
||||
MAX
|
||||
};
|
||||
|
||||
uint32_t sp; /* banked stack pointer */
|
||||
uint32_t lr; /* banked link register */
|
||||
uint32_t spsr; /* saved program status register */
|
||||
addr_t spsr; /* saved program status register */
|
||||
addr_t sp; /* banked stack pointer */
|
||||
addr_t lr; /* banked link register */
|
||||
};
|
||||
|
||||
Mode_state mode[Mode_state::MAX]; /* exception mode registers */
|
||||
uint32_t fiq_r[5]; /* fast-interrupt mode r8-r12 */
|
||||
addr_t fiq_r[5]; /* fast-interrupt mode r8-r12 */
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ namespace Genode
|
||||
enum
|
||||
{
|
||||
/* static memory bus */
|
||||
SMB_CS2_BASE = 0x48000000,
|
||||
SMB_CS7_BASE = 0x10000000,
|
||||
SMB_CS7_SIZE = 0x20000,
|
||||
SMB_CS0_TO_CS6_BASE = 0x40000000,
|
||||
@ -46,6 +47,14 @@ namespace Genode
|
||||
/* clocks */
|
||||
TCREF_CLOCK = 66670*1000,
|
||||
|
||||
/* TrustZone Address Space Controller */
|
||||
TZASC_MMIO_BASE = 0x100ec000,
|
||||
TZASC_MMIO_SIZE = 0x1000,
|
||||
|
||||
/* TrustZone Protection Controller */
|
||||
TZPC_MMIO_BASE = 0x100e6000,
|
||||
TZPC_MMIO_SIZE = 0x1000,
|
||||
|
||||
/* CPU */
|
||||
CORTEX_A9_PRIVATE_MEM_BASE = 0x1e000000,
|
||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000,
|
||||
@ -55,6 +64,10 @@ namespace Genode
|
||||
/* RAM */
|
||||
LOCAL_DDR2_BASE = 0x60000000,
|
||||
LOCAL_DDR2_SIZE = 0x40000000,
|
||||
|
||||
/* SRAM */
|
||||
SRAM_BASE = SMB_CS2_BASE,
|
||||
SRAM_SIZE = 0x01ffffff,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user