diff options
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | bl1/bl1.ld.S | 4 | ||||
-rw-r--r-- | bl2/bl2.ld.S | 2 | ||||
-rw-r--r-- | bl31/bl31.ld.S | 2 | ||||
-rw-r--r-- | bl31/context_mgmt.c | 5 | ||||
-rw-r--r-- | docs/firmware-design.md | 5 | ||||
-rw-r--r-- | docs/optee-dispatcher.md | 13 | ||||
-rw-r--r-- | docs/porting-guide.md | 28 | ||||
-rw-r--r-- | docs/user-guide.md | 26 | ||||
-rw-r--r-- | include/lib/aarch64/arch.h | 4 | ||||
-rw-r--r-- | include/lib/aarch64/xlat_tables.h | 10 | ||||
-rw-r--r-- | plat/fvp/aarch64/fvp_common.c | 78 | ||||
-rw-r--r-- | plat/fvp/include/plat_macros.S | 38 | ||||
-rw-r--r-- | plat/juno/aarch64/juno_common.c | 71 | ||||
-rw-r--r-- | plat/juno/include/plat_macros.S | 19 | ||||
-rw-r--r-- | services/spd/opteed/opteed.mk | 39 | ||||
-rw-r--r-- | services/spd/opteed/opteed_common.c | 128 | ||||
-rw-r--r-- | services/spd/opteed/opteed_helpers.S | 101 | ||||
-rw-r--r-- | services/spd/opteed/opteed_main.c | 435 | ||||
-rw-r--r-- | services/spd/opteed/opteed_pm.c | 252 | ||||
-rw-r--r-- | services/spd/opteed/opteed_private.h | 181 | ||||
-rw-r--r-- | services/spd/opteed/teesmc_opteed.h | 147 | ||||
-rw-r--r-- | services/spd/opteed/teesmc_opteed_macros.h | 41 |
23 files changed, 1597 insertions, 76 deletions
@@ -150,6 +150,9 @@ endif ifdef BL2_SOURCES NEED_BL2 := yes include bl2/bl2.mk +# Using the ARM Trusted Firmware BL2 implies that a BL3-3 image also need to be supplied for the FIP. +# This flag can be overridden by the platform. +NEED_BL33 ?= yes endif ifdef BL31_SOURCES @@ -168,9 +171,10 @@ ifneq (${SPD},none) $(info Including ${SPD_MAKE}) include ${SPD_MAKE} - # If there's BL32 companion for the chosen SPD, and the SPD wants to build the - # BL2 from source, we expect that the SPD's Makefile would set NEED_BL32 - # variable to "yes" + # If there's BL3-2 companion for the chosen SPD, and the SPD wants to build the + # BL3-2 from source, we expect that the SPD's Makefile would set NEED_BL32 + # variable to "yes". In case the BL3-2 is a binary which needs to be included in + # fip, then the NEED_BL32 needs to be set and BL3-2 would need to point to the bin. endif .PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip @@ -438,39 +442,53 @@ $(eval $(call MAKE_BL,1)) endif ifeq (${NEED_BL2},yes) -$(eval $(call MAKE_BL,2,in_fip)) +$(if ${BL2}, $(eval FIP_DEPS += ${BL2}) $(eval FIP_ARGS += --bl2 ${BL2}),\ + $(eval $(call MAKE_BL,2,in_fip))) endif ifeq (${NEED_BL31},yes) BL31_SOURCES += ${SPD_SOURCES} -$(eval $(call MAKE_BL,31,in_fip)) +$(if ${BL31}, $(eval FIP_DEPS += ${BL31}) $(eval FIP_ARGS += --bl31 ${BL31}),\ + $(eval $(call MAKE_BL,31,in_fip))) endif ifeq (${NEED_BL32},yes) -$(eval $(call MAKE_BL,32,in_fip)) +$(if ${BL32}, $(eval FIP_DEPS += ${BL32}) $(eval FIP_ARGS += --bl32 ${BL32}),\ + $(eval $(call MAKE_BL,32,in_fip))) endif ifeq (${NEED_BL30},yes) -FIP_DEPS += ${BL30} -FIP_ARGS += --bl30 ${BL30} -endif +$(if ${BL30}, $(eval FIP_DEPS += ${BL30}) $(eval FIP_ARGS += --bl30 ${BL30}), ) -ifeq (${NEED_BL30},yes) # If BL3-0 is needed by the platform then 'BL30' variable must be defined. check_bl30: $(if ${BL30},,$(error "To build a FIP for platform ${PLAT}, please set BL30 to point to the SCP firmware")) else + # If BL3-0 is not needed by the platform but the user still specified the path # to a BL3-0 image then warn him that it will be ignored. check_bl30: $(if ${BL30},$(warning "BL3-0 is not supported on platform ${PLAT}, it will just be ignored"),) endif -${BUILD_PLAT}/fip.bin: ${FIP_DEPS} ${BL33} ${FIPTOOL} check_bl30 - $(if ${BL33},,$(error "To build a FIP, please set BL33 to point to the Normal World binary, eg: BL33=../uefi/FVP_AARCH64_EFI.fd")) +ifeq (${NEED_BL33},yes) +$(if ${BL33}, $(eval FIP_DEPS += ${BL33}) $(eval FIP_ARGS += --bl33 ${BL33}), ) + +# If BL3-3 is needed by the platform then 'BL33' variable must be defined. +check_bl33: + $(if ${BL33},,$(error "To build a FIP, please set BL33 to point to the Normal World binary, eg: BL33=../uefi/FVP_AARCH64_EFI.fd")) +else + +# If BL3-3 is not needed by the platform but the user still specified the path +# to a BL3-3 image then warn him that it will be ignored. +check_bl33: + $(if ${BL33},$(warning "BL3-3 is not supported on platform ${PLAT}, it will just be ignored"),) +endif + + +${BUILD_PLAT}/fip.bin: ${FIP_DEPS} ${FIPTOOL} check_bl30 check_bl33 ${Q}${FIPTOOL} --dump \ ${FIP_ARGS} \ - --bl33 ${BL33} \ $@ @echo @echo "Built $@ successfully" diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index 8092396e..007149b5 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -35,8 +35,8 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH) ENTRY(bl1_entrypoint) MEMORY { - ROM (rx): ORIGIN = BL1_RO_BASE, LENGTH = BL1_RO_LIMIT - RAM (rwx): ORIGIN = BL1_RW_BASE, LENGTH = BL1_RW_LIMIT + ROM (rx): ORIGIN = BL1_RO_BASE, LENGTH = BL1_RO_LIMIT - BL1_RO_BASE + RAM (rwx): ORIGIN = BL1_RW_BASE, LENGTH = BL1_RW_LIMIT - BL1_RW_BASE } SECTIONS diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index 1665f5d2..65304de7 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -35,7 +35,7 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH) ENTRY(bl2_entrypoint) MEMORY { - RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE } diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index add65b8d..124be85c 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -36,7 +36,7 @@ ENTRY(bl31_entrypoint) MEMORY { - RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT + RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE } diff --git a/bl31/context_mgmt.c b/bl31/context_mgmt.c index 698fb6fa..6f27176c 100644 --- a/bl31/context_mgmt.c +++ b/bl31/context_mgmt.c @@ -182,7 +182,10 @@ void cm_init_context(uint64_t mpidr, const entry_point_info_t *ep) * against the CPU support, security state, endianess and pc */ sctlr_elx = EP_GET_EE(ep->h.attr) ? SCTLR_EE_BIT : 0; - sctlr_elx |= SCTLR_EL1_RES1; + if (GET_RW(ep->spsr) == MODE_RW_64) + sctlr_elx |= SCTLR_EL1_RES1; + else + sctlr_elx |= SCTLR_AARCH32_EL1_RES1; write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); if ((GET_RW(ep->spsr) == MODE_RW_64 diff --git a/docs/firmware-design.md b/docs/firmware-design.md index 6161b522..e952617b 100644 --- a/docs/firmware-design.md +++ b/docs/firmware-design.md @@ -778,7 +778,10 @@ The ARM Trusted Firmware provides a Test Secure-EL1 Payload (TSP) and a Test Secure-EL1 Payload Dispatcher (TSPD) service as an example of how a Trusted OS is supported on a production system using the Runtime Services Framework. On such a system, the Test BL3-2 image and service are replaced by the Trusted OS -and its dispatcher service. +and its dispatcher service. The ARM Trusted Firmware build system expects that +the dispatcher will define the build flag `NEED_BL32` to enable it to include +the BL3-2 in the build either as a binary or to compile from source depending +on whether the `BL32` build option is specified or not. The TSP runs in Secure-EL1. It is designed to demonstrate synchronous communication with the normal-world software running in EL1/EL2. Communication diff --git a/docs/optee-dispatcher.md b/docs/optee-dispatcher.md new file mode 100644 index 00000000..c154f6b3 --- /dev/null +++ b/docs/optee-dispatcher.md @@ -0,0 +1,13 @@ +OP-TEE Dispatcher +================= + +[OP-TEE OS] is a Trusted OS running as Secure EL1. + +To build and execute [OP-TEE OS] follow the instructions at +[ARM Trusted Firmware with OP-TEE] [OP-TEE OS] + +- - - - - - - - - - - - - - - - - - - - - - - - - - + +_Copyright (c) 2014, ARM Limited and Contributors. All rights reserved._ + +[OP-TEE OS]: http://github.com/OP-TEE/optee_os/tree/master/documentation/arm_trusted_firmware.md diff --git a/docs/porting-guide.md b/docs/porting-guide.md index ae5e7203..7831a278 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -16,8 +16,9 @@ Contents * PSCI implementation (in BL3-1) * Interrupt Management framework (in BL3-1) * Crash Reporting mechanism (in BL3-1) -4. C Library -5. Storage abstraction layer +4. Build flags +5. C Library +6. Storage abstraction layer - - - - - - - - - - - - - - - - - - @@ -1332,7 +1333,26 @@ register x0. The FVP port designates the `PL011_UART0` as the crash console and calls the console_core_putc() to print the character on the console. -4. C Library +4. Build flags +--------------- + +There are some build flags which can be defined by the platform to control +inclusion or exclusion of certain BL stages from the FIP image. These flags +need to be defined in the platform makefile which will get included by the +build system. + +* **NEED_BL30** + This flag if defined by the platform mandates that a BL3-0 binary should + be included in the FIP image. The path to the BL3-0 binary can be specified + by the `BL30` build option (see build options in the [User Guide]). + +* **NEED_BL33** + By default, this flag is defined `yes` by the build system and `BL33` + build option should be supplied as a build option. The platform has the option + of excluding the BL3-3 image in the `fip` image by defining this flag to + `no`. + +5. C Library ------------- To avoid subtle toolchain behavioral dependencies, the header files provided @@ -1369,7 +1389,7 @@ A copy of the [FreeBSD] sources can be downloaded with `git`. git clone git://github.com/freebsd/freebsd.git -b origin/release/9.2.0 -5. Storage abstraction layer +6. Storage abstraction layer ----------------------------- In order to improve platform independence and portability an storage abstraction diff --git a/docs/user-guide.md b/docs/user-guide.md index 5192f9e0..d3a92f9b 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -136,6 +136,16 @@ To build the Trusted Firmware images, follow these steps: make realclean +7. (Optional) Path to binary for certain BL stages (BL2, BL3-1 and BL3-2) can be + provided by specifying the BLx=<path-to>/<blx_image> where BLx is the BL stage. + This will bypass the build of the BL component from source, but will include + the specified binary in the final FIP image. Please note that BL3-2 will be + included in the build, only if the `SPD` build option is specified. + + For example, specifying BL2=<path-to>/<bl2_image> in the build option, will + skip compilation of BL2 source in trusted firmware, but include the BL2 + binary specified in the final FIP image. + ### Summary of build options ARM Trusted Firmware build system supports the following build options. Unless @@ -151,8 +161,20 @@ performed. If a BL3-0 image is present then this option must be passed for the `fip` target. -* `BL33`: Path to BL33 image in the host file system. This is mandatory for - `fip` target. +* `BL33`: Path to BL3-3 image in the host file system. This is mandatory for + `fip` target in case the BL2 from ARM Trusted Firmware is used. + +* `BL2`: This is an optional build option which specifies the path to BL2 + image for the `fip` target. In this case, the BL2 in the ARM Trusted + Firmware will not be built. + +* `BL31`: This is an optional build option which specifies the path to + BL3-1 image for the `fip` target. In this case, the BL3-1 in the ARM + Trusted Firmware will not be built. + +* `BL32`: This is an optional build option which specifies the path to + BL3-2 image for the `fip` target. In this case, the BL3-2 in the ARM + Trusted Firmware will not be built. * `CROSS_COMPILE`: Prefix to toolchain binaries. Please refer to examples in this document for usage. diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 40562607..e5b2bf8c 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -121,6 +121,10 @@ #define SCTLR_EL1_RES1 ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) | \ (1 << 11)) +#define SCTLR_AARCH32_EL1_RES1 \ + ((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \ + (1 << 3)) + #define SCTLR_M_BIT (1 << 0) #define SCTLR_A_BIT (1 << 1) #define SCTLR_C_BIT (1 << 2) diff --git a/include/lib/aarch64/xlat_tables.h b/include/lib/aarch64/xlat_tables.h index 2d4a211b..0b5dbdf2 100644 --- a/include/lib/aarch64/xlat_tables.h +++ b/include/lib/aarch64/xlat_tables.h @@ -41,6 +41,16 @@ #ifndef __ASSEMBLY__ #include <stdint.h> +/* Helper macro to define entries for mmap_region_t. It creates + * identity mappings for each region. + */ +#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr) + +/* Helper macro to define entries for mmap_region_t. It allows to + * re-map address mappings from 'pa' to 'va' for each region. + */ +#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)} + /* * Flags for building up memory mapping attributes. * These are organised so that a clear bit gives a more restrictive mapping diff --git a/plat/fvp/aarch64/fvp_common.c b/plat/fvp/aarch64/fvp_common.c index a25c4f0c..e393ceda 100644 --- a/plat/fvp/aarch64/fvp_common.c +++ b/plat/fvp/aarch64/fvp_common.c @@ -36,6 +36,7 @@ #include <debug.h> #include <mmio.h> #include <platform.h> +#include <platform_def.h> #include <plat_config.h> #include <xlat_tables.h> #include "../fvp_def.h" @@ -49,33 +50,70 @@ ******************************************************************************/ plat_config_t plat_config; +#define MAP_SHARED_RAM MAP_REGION_FLAT(FVP_SHARED_RAM_BASE, \ + FVP_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_FLASH0 MAP_REGION_FLAT(FLASH0_BASE, \ + FLASH0_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DRAM1 MAP_REGION_FLAT(DRAM1_BASE, \ + DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_TSP_SEC_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + /* - * Table of regions to map using the MMU. + * Table of regions for various BL stages to map using the MMU. * This doesn't include TZRAM as the 'mem_layout' argument passed to * configure_mmu_elx() will give the available subset of that, */ +#if IMAGE_BL1 +const mmap_region_t fvp_mmap[] = { + MAP_SHARED_RAM, + MAP_FLASH0, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t fvp_mmap[] = { + MAP_SHARED_RAM, + MAP_FLASH0, + MAP_DEVICE0, + MAP_DEVICE1, + MAP_DRAM1, + MAP_TSP_SEC_MEM, + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t fvp_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif +#if IMAGE_BL32 const mmap_region_t fvp_mmap[] = { - { FVP_SHARED_RAM_BASE, FVP_SHARED_RAM_BASE, FVP_SHARED_RAM_SIZE, - MT_MEMORY | MT_RW | MT_SECURE }, - { FVP_TRUSTED_DRAM_BASE, FVP_TRUSTED_DRAM_BASE, FVP_TRUSTED_DRAM_SIZE, - MT_MEMORY | MT_RW | MT_SECURE }, - { FLASH0_BASE, FLASH0_BASE, FLASH0_SIZE, - MT_MEMORY | MT_RO | MT_SECURE }, - { FLASH1_BASE, FLASH1_BASE, FLASH1_SIZE, - MT_MEMORY | MT_RO | MT_SECURE }, - { VRAM_BASE, VRAM_BASE, VRAM_SIZE, - MT_MEMORY | MT_RW | MT_SECURE }, - { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, - MT_DEVICE | MT_RW | MT_SECURE }, - { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, - MT_DEVICE | MT_RW | MT_SECURE }, - /* 2nd GB as device for now...*/ - { 0x40000000, 0x40000000, 0x40000000, - MT_DEVICE | MT_RW | MT_SECURE }, - { DRAM1_BASE, DRAM1_BASE, DRAM1_SIZE, - MT_MEMORY | MT_RW | MT_NS }, + MAP_DEVICE0, + MAP_DEVICE1, {0} }; +#endif /* Array of secure interrupts to be configured by the gic driver */ const unsigned int irq_sec_array[] = { diff --git a/plat/fvp/include/plat_macros.S b/plat/fvp/include/plat_macros.S index 04199061..f050261f 100644 --- a/plat/fvp/include/plat_macros.S +++ b/plat/fvp/include/plat_macros.S @@ -33,8 +33,8 @@ #include "../fvp_def.h" .section .rodata.gic_reg_name, "aS" -gic_regs: - .asciz "gic_hppir", "gic_ahppir", "gic_ctlr", "" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" gicd_pend_reg: .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" newline: @@ -46,19 +46,33 @@ spacer: * The below macro prints out relevant GIC * registers whenever an unhandled exception is * taken in BL3-1. - * Clobbers: x0 - x10, x16, sp + * Clobbers: x0 - x10, x16, x17, sp * --------------------------------------------- */ .macro plat_print_gic_regs - adr x0, plat_config - ldr w16, [x0, #CONFIG_GICC_BASE_OFFSET] - cbz x16, exit_print_gic_regs - /* gic base address is now in x16 */ - adr x6, gic_regs /* Load the gic reg list to x6 */ - /* Load the gic regs to gp regs used by str_in_crash_buf_print */ - ldr w8, [x16, #GICC_HPPIR] - ldr w9, [x16, #GICC_AHPPIR] - ldr w10, [x16, #GICC_CTLR] + mov_imm x0, (VE_SYSREGS_BASE + V2M_SYS_ID) + ldr w16, [x0] + /* Extract BLD (12th - 15th bits) from the SYS_ID */ + ubfx x16, x16, #SYS_ID_BLD_SHIFT, #4 + /* Check if VE mmap */ + cmp w16, #BLD_GIC_VE_MMAP + b.eq use_ve_mmap + /* Check if Cortex-A53/A57 mmap */ + cmp w16, #BLD_GIC_A53A57_MMAP + b.ne exit_print_gic_regs + mov_imm x17, BASE_GICC_BASE + mov_imm x16, BASE_GICD_BASE + b print_gicc_regs +use_ve_mmap: + mov_imm x17, VE_GICC_BASE + mov_imm x16, VE_GICD_BASE +print_gicc_regs: + /* gicc base address is now in x17 */ + adr x6, gicc_regs /* Load the gicc reg list to x6 */ + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] /* Store to the crash buf and print to console */ bl str_in_crash_buf_print diff --git a/plat/juno/aarch64/juno_common.c b/plat/juno/aarch64/juno_common.c index 5ba38c11..401f5fec 100644 --- a/plat/juno/aarch64/juno_common.c +++ b/plat/juno/aarch64/juno_common.c @@ -38,23 +38,74 @@ #include <xlat_tables.h> #include "../juno_def.h" +#define MAP_MHU_SECURE MAP_REGION_FLAT(MHU_SECURE_BASE, \ + MHU_SECURE_SIZE, \ + (MHU_PAYLOAD_CACHED ? \ + MT_MEMORY : MT_DEVICE) \ + | MT_RW | MT_SECURE) + +#define MAP_FLASH MAP_REGION_FLAT(FLASH_BASE, \ + FLASH_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define MAP_IOFPGA MAP_REGION_FLAT(IOFPGA_BASE, \ + IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DEVICE1 MAP_REGION_FLAT(DEVICE1_BASE, \ + DEVICE1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_DRAM MAP_REGION_FLAT(DRAM_BASE, \ + DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) /* - * Table of regions to map using the MMU. + * Table of regions for different BL stages to map using the MMU. * This doesn't include Trusted RAM as the 'mem_layout' argument passed to * configure_mmu_elx() will give the available subset of that, */ +#if IMAGE_BL1 +static const mmap_region_t juno_mmap[] = { + MAP_MHU_SECURE, + MAP_FLASH, + MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif +#if IMAGE_BL2 +static const mmap_region_t juno_mmap[] = { + MAP_MHU_SECURE, + MAP_FLASH, + MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + MAP_DRAM, + {0} +}; +#endif +#if IMAGE_BL31 +static const mmap_region_t juno_mmap[] = { + MAP_MHU_SECURE, + MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, + {0} +}; +#endif +#if IMAGE_BL32 static const mmap_region_t juno_mmap[] = { - { TZROM_BASE, TZROM_BASE, TZROM_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, - { MHU_SECURE_BASE, MHU_SECURE_BASE, MHU_SECURE_SIZE, (MHU_PAYLOAD_CACHED ? MT_MEMORY : MT_DEVICE) | MT_RW | MT_SECURE }, - { FLASH_BASE, FLASH_BASE, FLASH_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, - { EMMC_BASE, EMMC_BASE, EMMC_SIZE, MT_MEMORY | MT_RO | MT_SECURE }, - { PSRAM_BASE, PSRAM_BASE, PSRAM_SIZE, MT_MEMORY | MT_RW | MT_SECURE }, /* Used for 'TZDRAM' */ - { IOFPGA_BASE, IOFPGA_BASE, IOFPGA_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, - { DEVICE0_BASE, DEVICE0_BASE, DEVICE0_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, - { DEVICE1_BASE, DEVICE1_BASE, DEVICE1_SIZE, MT_DEVICE | MT_RW | MT_SECURE }, - { DRAM_BASE, DRAM_BASE, DRAM_SIZE, MT_MEMORY | MT_RW | MT_NS }, + MAP_IOFPGA, + MAP_DEVICE0, + MAP_DEVICE1, {0} }; +#endif /******************************************************************************* * Macro generating the code for the function setting up the pagetables as per diff --git a/plat/juno/include/plat_macros.S b/plat/juno/include/plat_macros.S index 0e088344..a9d2466b 100644 --- a/plat/juno/include/plat_macros.S +++ b/plat/juno/include/plat_macros.S @@ -34,8 +34,8 @@ #include "../juno_def.h" .section .rodata.gic_reg_name, "aS" -gic_regs: - .asciz "gic_hppir", "gic_ahppir", "gic_ctlr", "" +gicc_regs: + .asciz "gicc_hppir", "gicc_ahppir", "gicc_ctlr", "" gicd_pend_reg: .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n" newline: @@ -52,13 +52,14 @@ spacer: * --------------------------------------------- */ .macro plat_print_gic_regs - ldr x16, =GICC_BASE - /* Load the gic reg list to x6 */ - adr x6, gic_regs - /* Load the gic regs to gp regs used by str_in_crash_buf_print */ - ldr w8, [x16, #GICC_HPPIR] - ldr w9, [x16, #GICC_AHPPIR] - ldr w10, [x16, #GICC_CTLR] + mov_imm x16, GICD_BASE + mov_imm x17, GICC_BASE + /* Load the gicc reg list to x6 */ + adr x6, gicc_regs + /* Load the gicc regs to gp regs used by str_in_crash_buf_print */ + ldr w8, [x17, #GICC_HPPIR] + ldr w9, [x17, #GICC_AHPPIR] + ldr w10, [x17, #GICC_CTLR] /* Store to the crash buf and print to console */ bl str_in_crash_buf_print diff --git a/services/spd/opteed/opteed.mk b/services/spd/opteed/opteed.mk new file mode 100644 index 00000000..8057dcc4 --- /dev/null +++ b/services/spd/opteed/opteed.mk @@ -0,0 +1,39 @@ +# +# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +OPTEED_DIR := services/spd/opteed +SPD_INCLUDES := + +SPD_SOURCES := services/spd/opteed/opteed_common.c \ + services/spd/opteed/opteed_helpers.S \ + services/spd/opteed/opteed_main.c \ + services/spd/opteed/opteed_pm.c + +NEED_BL32 := yes diff --git a/services/spd/opteed/opteed_common.c b/services/spd/opteed/opteed_common.c new file mode 100644 index 00000000..2f20b7ca --- /dev/null +++ b/services/spd/opteed/opteed_common.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <context_mgmt.h> +#include <string.h> +#include "opteed_private.h" + +/******************************************************************************* + * Given a OPTEE entrypoint info pointer, entry point PC, register width, + * cpu id & pointer to a context data structure, this function will + * initialize OPTEE context and entry point info for OPTEE. + ******************************************************************************/ +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, + uint32_t rw, uint64_t pc, + optee_context_t *optee_ctx) +{ + uint32_t ep_attr; + + /* Passing a NULL context is a critical programming error */ + assert(optee_ctx); + assert(optee_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + optee_ctx->mpidr = read_mpidr_el1(); + optee_ctx->state = 0; + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + cm_set_context(&optee_ctx->cpu_ctx, SECURE); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(optee_entry_point, PARAM_EP, VERSION_1, ep_attr); + optee_entry_point->pc = pc; + if (rw == OPTEE_AARCH64) + optee_entry_point->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + else + optee_entry_point->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + memset(&optee_entry_point->args, 0, sizeof(optee_entry_point->args)); +} + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Applies the S-EL1 system register context from optee_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the optee_ctx->cpu_ctx are used to enter the OPTEE image. + ******************************************************************************/ +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx) +{ + uint64_t rc; + + assert(optee_ctx != NULL); + assert(optee_ctx->c_rt_ctx == 0); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = opteed_enter_sp(&optee_ctx->c_rt_ctx); +#if DEBUG + optee_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Saves the S-EL1 system register context tp optee_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using the reference to this state saved in opteed_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret) +{ + assert(optee_ctx != NULL); + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(optee_ctx->c_rt_ctx != 0); + opteed_exit_sp(optee_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/services/spd/opteed/opteed_helpers.S b/services/spd/opteed/opteed_helpers.S new file mode 100644 index 00000000..ef59540b --- /dev/null +++ b/services/spd/opteed/opteed_helpers.S @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <asm_macros.S> +#include "opteed_private.h" + + .global opteed_enter_sp + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func opteed_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #OPTEED_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #OPTEED_C_RT_CTX_X19] + stp x21, x22, [sp, #OPTEED_C_RT_CTX_X21] + stp x23, x24, [sp, #OPTEED_C_RT_CTX_X23] + stp x25, x26, [sp, #OPTEED_C_RT_CTX_X25] + stp x27, x28, [sp, #OPTEED_C_RT_CTX_X27] + stp x29, x30, [sp, #OPTEED_C_RT_CTX_X29] + + /* --------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into OPTEE. + * --------------------------------------------- + */ + b el3_exit + + /* --------------------------------------------- + * This function is called 'x0' pointing to a C + * runtime context saved in opteed_enter_sp(). It + * restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * --------------------------------------------- + */ + .global opteed_exit_sp +func opteed_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(OPTEED_C_RT_CTX_X19 - OPTEED_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(OPTEED_C_RT_CTX_X21 - OPTEED_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(OPTEED_C_RT_CTX_X23 - OPTEED_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(OPTEED_C_RT_CTX_X25 - OPTEED_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(OPTEED_C_RT_CTX_X27 - OPTEED_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(OPTEED_C_RT_CTX_X29 - OPTEED_C_RT_CTX_SIZE)] + + /* --------------------------------------------- + * This should take us back to the instruction + * after the call to the last opteed_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * --------------------------------------------- + */ + mov x0, x1 + ret diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c new file mode 100644 index 00000000..5c5144fb --- /dev/null +++ b/services/spd/opteed/opteed_main.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <bl31.h> +#include <context_mgmt.h> +#include <debug.h> +#include <errno.h> +#include <platform.h> +#include <runtime_svc.h> +#include <stddef.h> +#include <uuid.h> +#include "opteed_private.h" +#include "teesmc_opteed_macros.h" +#include "teesmc_opteed.h" + +/******************************************************************************* + * Address of the entrypoint vector table in OPTEE. It is + * initialised once on the primary core after a cold boot. + ******************************************************************************/ +optee_vectors_t *optee_vectors; + +/******************************************************************************* + * Array to keep track of per-cpu OPTEE state + ******************************************************************************/ +optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +uint32_t opteed_rw; + + + +static int32_t opteed_init(void); + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the + * OPTEED. It validates the interrupt and upon success arranges entry into + * the OPTEE at 'optee_fiq_entry()' for handling the interrupt. + ******************************************************************************/ +static uint64_t opteed_sel1_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + uint32_t linear_id; + uint64_t mpidr; + optee_context_t *optee_ctx; + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + +#if IMF_READ_INTERRUPT_ID + /* Check the security status of the interrupt */ + assert(plat_ic_get_interrupt_type(id) == INTR_TYPE_S_EL1); +#endif + + /* Sanity check the pointer to this cpu's context */ + mpidr = read_mpidr(); + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the OPTEE */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to this cpu's OPTEE context */ + linear_id = platform_get_core_pos(mpidr); + optee_ctx = &opteed_sp_context[linear_id]; + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + cm_set_elr_el3(SECURE, (uint64_t)&optee_vectors->fiq_entry); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* + * Tell the OPTEE that it has to handle an FIQ (synchronously). + * Also the instruction in normal world where the interrupt was + * generated is passed for debugging purposes. It is safe to + * retrieve this address from ELR_EL3 as the secure context will + * not take effect until el3_exit(). + */ + SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3()); +} + +/******************************************************************************* + * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into OPTEE for its initialization. + ******************************************************************************/ +int32_t opteed_setup(void) +{ + entry_point_info_t *optee_ep_info; + uint64_t mpidr = read_mpidr(); + uint32_t linear_id; + + linear_id = platform_get_core_pos(mpidr); + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. TODO: Add support to + * conditionally include the SPD service + */ + optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!optee_ep_info) { + WARN("No OPTEE provided by BL2 boot loader, Booting device" + " without OPTEE initialization. SMC`s destined for OPTEE" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!optee_ep_info->pc) + return 1; + + /* + * We could inspect the SP image and determine it's execution + * state i.e whether AArch32 or AArch64. Assuming it's AArch32 + * for the time being. + */ + opteed_rw = OPTEE_AARCH32; + opteed_init_optee_ep_state(optee_ep_info, + opteed_rw, + optee_ep_info->pc, + &opteed_sp_context[linear_id]); + + /* + * All OPTEED initialization done. Now register our init function with + * BL31 for deferred invocation + */ + bl31_register_bl32_init(&opteed_init); + + return 0; +} + +/******************************************************************************* + * This function passes control to the OPTEE image (BL32) for the first time + * on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by opteed_setup() which can be directly + * used. It also assumes that a valid non-secure context has been + * initialised by PSCI so it does not need to save and restore any + * non-secure state. This function performs a synchronous entry into + * OPTEE. OPTEE passes control back to this routine through a SMC. + ******************************************************************************/ +static int32_t opteed_init(void) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t *optee_entry_point; + uint64_t rc; + + /* + * Get information about the OPTEE (BL32) image. Its + * absence is a critical failure. + */ + optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(optee_entry_point); + + cm_init_context(mpidr, optee_entry_point); + + /* + * Arrange for an entry into OPTEE. It will be returned via + * OPTEE_ENTRY_DONE case + */ + rc = opteed_synchronous_sp_entry(optee_ctx); + assert(rc != 0); + + return rc; +} + + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure + * payload to delegate work and return results back to the non-secure + * state. Lastly it will also return any information that OPTEE needs to do + * the work assigned to it. + ******************************************************************************/ +uint64_t opteed_smc_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + cpu_context_t *ns_cpu_context; + unsigned long mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + uint64_t rc; + + /* + * Determine which security state this SMC originated from + */ + + if (is_caller_non_secure(flags)) { + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * We are done stashing the non-secure context. Ask the + * OPTEE to do the work now. + */ + + /* + * Verify if there is a valid context to use, copy the + * operation type and parameters to the secure context + * and jump to the fast smc entry point in the secure + * payload. Entry into S-EL1 will take place upon exit + * from this function. + */ + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* Set appropriate entry for SMC. + * We expect OPTEE to manage the PSTATE.I and PSTATE.F + * flags as appropriate. + */ + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vectors->fast_smc_entry); + } else { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vectors->std_smc_entry); + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Propagate hypervisor client ID */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X7, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X7)); + + SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3); + } + + /* + * Returning from OPTEE + */ + + switch (smc_fid) { + /* + * OPTEE has finished initialising itself after a cold boot + */ + case TEESMC_OPTEED_RETURN_ENTRY_DONE: + /* + * Stash the OPTEE entry points information. This is done + * only once on the primary cpu + */ + assert(optee_vectors == NULL); + optee_vectors = (optee_vectors_t *) x1; + + if (optee_vectors) { + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); + + /* + * OPTEE has been successfully initialized. + * Register power management hooks with PSCI + */ + psci_register_spd_pm_hook(&opteed_pm); + + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + opteed_sel1_interrupt_handler, + flags); + if (rc) + panic(); + } + + /* + * OPTEE reports completion. The OPTEED must have initiated + * the original request through a synchronous entry into + * OPTEE. Jump back to the original C runtime context. + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + + + /* + * These function IDs is used only by OP-TEE to indicate it has + * finished: + * 1. turning itself on in response to an earlier psci + * cpu_on request + * 2. resuming itself after an earlier psci cpu_suspend + * request. + */ + case TEESMC_OPTEED_RETURN_ON_DONE: + case TEESMC_OPTEED_RETURN_RESUME_DONE: + + + /* + * These function IDs is used only by the SP to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. turning itself off in response to an earlier psci + * cpu_off request. + */ + case TEESMC_OPTEED_RETURN_OFF_DONE: + case TEESMC_OPTEED_RETURN_SUSPEND_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE: + + /* + * OPTEE reports completion. The OPTEED must have initiated the + * original request through a synchronous entry into OPTEE. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + + /* + * OPTEE is returning from a call or being preempted from a call, in + * either case execution should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_CALL_DONE: + /* + * This is the result from the secure client of an + * earlier request. The results are in x0-x3. Copy it + * into the non-secure context, save the secure state + * and return to the non-secure state. + */ + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET4(ns_cpu_context, x1, x2, x3, x4); + + /* + * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution + * should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_FIQ_DONE: + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since OPTEE was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0((uint64_t) ns_cpu_context); + + default: + panic(); + } +} + +/* Define an OPTEED runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + opteed_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + opteed_setup, + opteed_smc_handler +); + +/* Define an OPTEED runtime service descriptor for standard SMC calls */ +DECLARE_RT_SVC( + opteed_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_STD, + NULL, + opteed_smc_handler +); diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c new file mode 100644 index 00000000..552d7a0c --- /dev/null +++ b/services/spd/opteed/opteed_pm.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <context_mgmt.h> +#include <debug.h> +#include <platform.h> +#include "opteed_private.h" + +/******************************************************************************* + * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any + * actions needed. Nothing at the moment. + ******************************************************************************/ +static void opteed_cpu_on_handler(uint64_t target_cpu) +{ +} + +/******************************************************************************* + * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions + * needed + ******************************************************************************/ +static int32_t opteed_cpu_off_handler(uint64_t cookie) +{ + int32_t rc = 0; + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point and enter OPTEE */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_off_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* + * Reset OPTEE's context for a fresh start when this cpu is turned on + * subsequently. + */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + return 0; +} + +/******************************************************************************* + * This cpu is being suspended. S-EL1 state must have been saved in the + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static void opteed_cpu_suspend_handler(uint64_t power_state) +{ + int32_t rc = 0; + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point, power_state parameter and enter OPTEE */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X0, + power_state); + cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND); +} + +/******************************************************************************* + * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits + * before passing control back to the Secure Monitor. Entry in S-El1 is done + * after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void opteed_cpu_on_finish_handler(uint64_t cookie) +{ + int32_t rc = 0; + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t optee_on_entrypoint; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF); + + opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw, + (uint64_t)&optee_vectors->cpu_on_entry, + optee_ctx); + + /* Initialise this cpu's secure context */ + cm_init_context(mpidr, &optee_on_entrypoint); + + /* Enter OPTEE */ + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it + * completed the preceding suspend call. Use that context to program an entry + * into OPTEE to allow it to do any remaining book keeping + ******************************************************************************/ +static void opteed_cpu_suspend_finish_handler(uint64_t suspend_level) +{ + int32_t rc = 0; + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND); + + /* Program the entry point, suspend_level and enter the SP */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X0, + suspend_level); + cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_resume_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * Return the type of OPTEE the OPTEED is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static int32_t opteed_cpu_migrate_info(uint64_t *resident_cpu) +{ + return OPTEE_MIGRATE_INFO; +} + +/******************************************************************************* + * System is about to be switched off. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_off(void) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_off_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the shutdown anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + +/******************************************************************************* + * System is about to be reset. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_reset(void) +{ + uint64_t mpidr = read_mpidr(); + uint32_t linear_id = platform_get_core_pos(mpidr); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vectors); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_reset_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the reset anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + + +/******************************************************************************* + * Structure populated by the OPTEE Dispatcher to be given a chance to + * perform any OPTEE bookkeeping before PSCI executes a power mgmt. + * operation. + ******************************************************************************/ +const spd_pm_ops_t opteed_pm = { + .svc_on = opteed_cpu_on_handler, + .svc_off = opteed_cpu_off_handler, + .svc_suspend = opteed_cpu_suspend_handler, + .svc_on_finish = opteed_cpu_on_finish_handler, + .svc_suspend_finish = opteed_cpu_suspend_finish_handler, + .svc_migrate = NULL, + .svc_migrate_info = opteed_cpu_migrate_info, + .svc_system_off = opteed_system_off, + .svc_system_reset = opteed_system_reset, +}; + diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h new file mode 100644 index 00000000..357c2ecf --- /dev/null +++ b/services/spd/opteed/opteed_private.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OPTEED_PRIVATE_H__ +#define __OPTEED_PRIVATE_H__ + +#include <arch.h> +#include <context.h> +#include <interrupt_mgmt.h> +#include <platform_def.h> +#include <psci.h> + +/******************************************************************************* + * OPTEE PM state information e.g. OPTEE is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags + ******************************************************************************/ +#define OPTEE_PSTATE_OFF 0 +#define OPTEE_PSTATE_ON 1 +#define OPTEE_PSTATE_SUSPEND 2 +#define OPTEE_PSTATE_SHIFT 0 +#define OPTEE_PSTATE_MASK 0x3 +#define get_optee_pstate(state) ((state >> OPTEE_PSTATE_SHIFT) & \ + OPTEE_PSTATE_MASK) +#define clr_optee_pstate(state) (state &= ~(OPTEE_PSTATE_MASK \ + << OPTEE_PSTATE_SHIFT)) +#define set_optee_pstate(st, pst) do { \ + clr_optee_pstate(st); \ + st |= (pst & OPTEE_PSTATE_MASK) << \ + OPTEE_PSTATE_SHIFT; \ + } while (0) + + +/******************************************************************************* + * OPTEE execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define OPTEE_AARCH32 MODE_RW_32 +#define OPTEE_AARCH64 MODE_RW_64 + +/******************************************************************************* + * The OPTEED should know the type of OPTEE + ******************************************************************************/ +#define OPTEE_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP +#define OPTEE_TYPE_UPM PSCI_TOS_UP_MIG_CAP +#define OPTEE_TYPE_MP PSCI_TOS_NOT_PRESENT_MP + +/******************************************************************************* + * OPTEE migrate type information as known to the OPTEED. We assume that + * the OPTEED is dealing with an MP Secure Payload. + ******************************************************************************/ +#define OPTEE_MIGRATE_INFO OPTEE_TYPE_MP + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define OPTEED_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define OPTEED_C_RT_CTX_X19 0x0 +#define OPTEED_C_RT_CTX_X20 0x8 +#define OPTEED_C_RT_CTX_X21 0x10 +#define OPTEED_C_RT_CTX_X22 0x18 +#define OPTEED_C_RT_CTX_X23 0x20 +#define OPTEED_C_RT_CTX_X24 0x28 +#define OPTEED_C_RT_CTX_X25 0x30 +#define OPTEED_C_RT_CTX_X26 0x38 +#define OPTEED_C_RT_CTX_X27 0x40 +#define OPTEED_C_RT_CTX_X28 0x48 +#define OPTEED_C_RT_CTX_X29 0x50 +#define OPTEED_C_RT_CTX_X30 0x58 +#define OPTEED_C_RT_CTX_SIZE 0x60 +#define OPTEED_C_RT_CTX_ENTRIES (OPTEED_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLY__ + +#include <cassert.h> +#include <stdint.h> + +typedef uint32_t optee_vector_isn_t; + +typedef struct optee_vectors { + optee_vector_isn_t std_smc_entry; + optee_vector_isn_t fast_smc_entry; + optee_vector_isn_t cpu_on_entry; + optee_vector_isn_t cpu_off_entry; + optee_vector_isn_t cpu_resume_entry; + optee_vector_isn_t cpu_suspend_entry; + optee_vector_isn_t fiq_entry; + optee_vector_isn_t system_off_entry; + optee_vector_isn_t system_reset_entry; +} optee_vectors_t; + +/* + * The number of arguments to save during a SMC call for OPTEE. + * Currently only x1 and x2 are used by OPTEE. + */ +#define OPTEE_NUM_ARGS 0x2 + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, OPTEED_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(OPTEED_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_spd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the OPTEED to maintain the per-cpu state of OPTEE. + * 'state' - collection of flags to track OPTEE state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into OPTEE. + * 'cpu_ctx' - space to maintain OPTEE architectural state + ******************************************************************************/ +typedef struct optee_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} optee_context_t; + +/* OPTEED power management handlers */ +extern const spd_pm_ops_t opteed_pm; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct optee_vectors; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t opteed_enter_sp(uint64_t *c_rt_ctx); +void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx); +void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret); +void opteed_init_optee_ep_state(struct entry_point_info *optee_ep, + uint32_t rw, + uint64_t pc, + optee_context_t *optee_ctx); + +extern optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +extern uint32_t opteed_rw; +extern struct optee_vectors *optee_vectors; +#endif /*__ASSEMBLY__*/ + +#endif /* __OPTEED_PRIVATE_H__ */ diff --git a/services/spd/opteed/teesmc_opteed.h b/services/spd/opteed/teesmc_opteed.h new file mode 100644 index 00000000..7968d1fe --- /dev/null +++ b/services/spd/opteed/teesmc_opteed.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Copyright (c) 2014, Linaro Limited. All rights reserved. */ + +#ifndef TEESMC_OPTEED_H +#define TEESMC_OPTEED_H + +/* + * This file specify SMC function IDs used when returning from TEE to the + * secure monitor. + * + * All SMC Function IDs indicates SMC32 Calling Convention but will carry + * full 64 bit values in the argument registers if invoked from Aarch64 + * mode. This violates the SMC Calling Convention, but since this + * convention only coveres API towards Normwal World it's something that + * only concerns the OP-TEE Dispatcher in ARM Trusted Firmware and OP-TEE + * OS at Secure EL1. + */ + +/* + * Issued when returning from initial entry. + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE + * r1/x1 Pointer to entry vector + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 +#define TEESMC_OPTEED_RETURN_ENTRY_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE) + + + +/* + * Issued when returning from "cpu_on" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE 1 +#define TEESMC_OPTEED_RETURN_ON_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE) + +/* + * Issued when returning from "cpu_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE 2 +#define TEESMC_OPTEED_RETURN_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE) + +/* + * Issued when returning from "cpu_suspend" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 +#define TEESMC_OPTEED_RETURN_SUSPEND_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE) + +/* + * Issued when returning from "cpu_resume" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE 4 +#define TEESMC_OPTEED_RETURN_RESUME_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE) + +/* + * Issued when returning from "std_smc" or "fast_smc" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE + * r1-4/x1-4 Return value 0-3 which will passed to normal world in + * r0-3/x0-3 + */ +#define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE 5 +#define TEESMC_OPTEED_RETURN_CALL_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE) + +/* + * Issued when returning from "fiq" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE 6 +#define TEESMC_OPTEED_RETURN_FIQ_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE) + +/* + * Issued when returning from "system_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 +#define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) + +/* + * Issued when returning from "system_reset" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 +#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) + +#endif /*TEESMC_OPTEED_H*/ diff --git a/services/spd/opteed/teesmc_opteed_macros.h b/services/spd/opteed/teesmc_opteed_macros.h new file mode 100644 index 00000000..2453c9ae --- /dev/null +++ b/services/spd/opteed/teesmc_opteed_macros.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __TEESMC_OPTEED_MACROS_H__ +#define __TEESMC_OPTEED_MACROS_H__ + +#include <runtime_svc.h> + +#define TEESMC_OPTEED_RV(func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((SMC_32) << FUNCID_CC_SHIFT) | \ + (62 << FUNCID_OEN_SHIFT) | \ + ((func_num) & FUNCID_NUM_MASK)) + +#endif /*__TEESMC_OPTEED_MACROS_H__*/ |