Skip to content

Commit

Permalink
Add Marvell platform with initial support for ARMADA A7K & A8K
Browse files Browse the repository at this point in the history
Only tested 64-bit mode with default configurations:

1. build command
    make PLATFORM=marvell-armada7080 CFG_ARM64_core=y
2. Passed xtest

Signed-off-by: Kevin Peng <[email protected]>
Reviewed-by: Jerome Forissier <[email protected]>
Acked-by: Jens Wiklander <[email protected]>
Acked-by: Etienne Carriere <[email protected]>
  • Loading branch information
Kevin Peng authored and jforissier committed Oct 16, 2017
1 parent ade1412 commit 8ae8c73
Show file tree
Hide file tree
Showing 9 changed files with 585 additions and 0 deletions.
1 change: 1 addition & 0 deletions .shippable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ build:
- _make PLATFORM=rockchip-rk322x
- _make PLATFORM=rockchip-rk322x CFG_TEE_CORE_LOG_LEVEL=4 DEBUG=1
- _make PLATFORM=sam
- _make PLATFORM=marvell-armada7k8k CFG_ARM64_core=y

#
# Regressions tests (QEMU)
Expand Down
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ script:
# Atmel ATSAMA5D2-XULT
- $make PLATFORM=sam

# Marvell ARMADA 7K 8K
- $make PLATFORM=marvell-armada7k8k CFG_ARM64_core=y

# Run regression tests (xtest in QEMU)
- (cd ${HOME}/optee_repo/build && $make check CROSS_COMPILE="ccache arm-linux-gnueabihf-" AARCH32_CROSS_COMPILE=arm-linux-gnueabihf- CFG_TEE_CORE_DEBUG=y DUMP_LOGS_ON_ERROR=1)

Expand Down
2 changes: 2 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ for these platforms.
| HiKey Board (HiSilicon Kirin 620) |`Linaro <[email protected]>`|
| HiKey960 Board (HiSilicon Kirin 960) |`Linaro <[email protected]>`|
| HiSilicon D02 |`Linaro <[email protected]>`|
| Marvell Armada 70x0 |`Kevin Peng <[email protected]>`|
| Marvell Armada 80x0 |`Kevin Peng <[email protected]>`|
| MediaTek MT8173 EVB Board |`Linaro <[email protected]>`|
| QEMU |`Linaro <[email protected]>`|
| Raspberry Pi3 |`Linaro <[email protected]>`|
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ platforms have different sub-maintainers, please refer to the file
| [HiSilicon D02](http://open-estuary.org/d02-2)|`PLATFORM=d02`| No |
| [HiKey Board (HiSilicon Kirin 620)](https://www.96boards.org/product/hikey)|`PLATFORM=hikey` or `PLATFORM=hikey-hikey`| Yes |
| [HiKey960 Board (HiSilicon Kirin 960)](https://www.96boards.org/product/hikey960)|`PLATFORM=hikey-hikey960`| Yes |
| [Marvell ARMADA 7K Family](http://www.marvell.com/embedded-processors/armada-70xx/)|`PLATFORM=marvell-armada7k8k`| No |
| [Marvell ARMADA 8K Family](http://www.marvell.com/embedded-processors/armada-80xx/)|`PLATFORM=marvell-armada7k8k`| No |
| [MediaTek MT8173 EVB Board](https://www.mediatek.com/products/tablets/mt8173)|`PLATFORM=mediatek-mt8173`| No |
| [QEMU](http://wiki.qemu.org/Main_Page) |`PLATFORM=vexpress-qemu_virt`| Yes |
| [QEMUv8](http://wiki.qemu.org/Main_Page) |`PLATFORM=vexpress-qemu_armv8a`| Yes |
Expand Down
296 changes: 296 additions & 0 deletions core/arch/arm/plat-marvell/armada7k8k/hal_sec_perf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
/*
* Copyright (C) 2017 Marvell International Ltd.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 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 <initcall.h>
#include <io.h>
#include <kernel/panic.h>
#include <mm/core_memprot.h>
#include <util.h>

#define PHY_2_VIR(addr) ((vaddr_t)phys_to_virt((addr), MEM_AREA_IO_SEC))

#define MCU_MC_CONTROL_0_REG PHY_2_VIR(MCU_BASE + 0x044)
#define TRUSTZONE_LOCK BIT(31)

#define MCU_TZ_RANGE_HIGH_REG(x) PHY_2_VIR(MCU_BASE + 0x84 + ((x) << 3))
#define MCU_TZ_RANGE_LOW_REG(x) PHY_2_VIR(MCU_BASE + 0x80 + ((x) << 3))

#define RW_PERM 0x0
#define RO_PERM 0x1
#define WO_PERM 0x2
#define ABORT_PERM 0x3

#define MAX_RANGE_NUM 16
#define INVALID_SIZE_CODE 0xff

#ifdef TEE_RES_CFG_16M
#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M)
#elif defined(TEE_RES_CFG_24M)
#define RSVD_SEC_MEM (SIZE_8M + SIZE_8M + SIZE_8M)
#elif defined(TEE_RES_CFG_8M)
#define RSVD_SEC_MEM SIZE_8M
#else
#error "no reserved secure memory defined."
#endif

#define RA_ADDR TZDRAM_BASE
#define RA_SIZE TZDRAM_SIZE
#define RA_PERM ABORT_PERM

#define TZ_IS_VALID(data) ((data) & (0x1))
#define TZ_SET_VALID(data) ((data) |= (0x1))

#define TZ_GET_PERM(data, ret) ((ret) = (((data) & (0x3 << 1)) >> 1))
#define TZ_SET_PERM(data, val) \
do { \
(data) &= (~(0x3 << 1)); \
(data) |= (((val) & 0x3) << 1); \
} while (0)

#define TZ_GET_RZ_EN(data, ret) ((ret) = (((data) & (0x1 << 3)) >> 3))
#define TZ_SET_RZ_EN(data, val) \
do { \
(data) &= (~(0x1 << 3)); \
(data) |= (((val) & 0x1) << 3); \
} while (0)

#define TZ_GET_AREA_LEN_CODE(data, ret) ((ret) = (((data) & (0x1F << 7)) >> 7))

#define TZ_SET_AREA_LEN_CODE(data, val) \
do { \
(data) &= (~(0x1F << 7)); \
(data) |= (((val) & 0x1F) << 7); \
} while (0)

#define TZ_GET_START_ADDR_L(data, ret) \
((ret) = (((data) & 0xFFFFF000)))

#define TZ_SET_START_ADDR_L(data, val) \
do { \
(data) &= (~0xFFFFF000); \
(data) |= (((val) & 0xFFFFF000)); \
} while (0)

#define TZ_GET_UR_PERM(data, val) ((ret) = (((data) & (0x3 << 4)) >> 4))
#define TZ_SET_UR_PERM(data, val) \
do { \
(data) &= (~(0x3 << 4)); \
(data) |= (((val) & 0x3) << 4); \
} while (0)

#define TZ_GET_UR_RZ_EN(data, val) \
((ret) = (((data) & (0x1 << 6)) >> 6))

#define TZ_SET_UR_RZ_EN(data, val) \
do { \
(data) &= (~(0x1 << 6)); \
(data) |= (((val) & 0x1) << 6); \
} while (0)

/* armada mini region size is 1M */
#define RANGE_SIZE_TO_CODE(size, code, i) \
do { \
(code) = INVALID_SIZE_CODE; \
for ((i) = 8; (i) <= 0x1f; (i)++) { \
if (((uint32_t)0x1 << (i)) == ((size) >> 12)) { \
(code) = (i); \
break; \
} \
} \
} while (0)

#define RANGE_CODE_TO_SIZE_K(code, sizek) ((sizek) = ((4) << (code)))

#define TZ_LOCK_MC(x) \
do { \
(x) = read32(MCU_MC_CONTROL_0_REG); \
(x) |= (TRUSTZONE_LOCK); \
write32((x), MCU_MC_CONTROL_0_REG); \
} while (0)

#define _IS_ALIGNED(_addr, _algn) (!((_addr) & ((_algn) - 1)))

register_phys_mem(MEM_AREA_IO_SEC, MCU_BASE, CORE_MMU_DEVICE_SIZE);
register_phys_mem(MEM_AREA_IO_SEC, MC_SCR_REGISTER, CORE_MMU_DEVICE_SIZE);

static int32_t _find_valid_range(void)
{
uint32_t i;
uint32_t tmp;

for (i = 0; i < MAX_RANGE_NUM; i++) {
tmp = read32(MCU_TZ_RANGE_LOW_REG(i));
if (!TZ_IS_VALID(tmp))
return i;
}
return -1;
}

static int32_t set_range(uint32_t addr, uint32_t size, uint32_t perm)
{
uint32_t data;
uint32_t sizecode;
int32_t valid_range;
uint32_t i;

if (!_IS_ALIGNED(addr, SIZE_1M)) {
EMSG("region addr(0x%" PRIx32 ") is not aligned with 1M!",
addr);
return -1;
}

if (!_IS_ALIGNED(size, SIZE_1M)) {
EMSG("region size(0x%" PRIx32 ") is not aligned with 1M!",
size);
return -1;
}

if (!_IS_ALIGNED(addr, size)) {
EMSG("region size(0x%" PRIx32
") not align with addr(0x%" PRIx32 ")",
size, addr);
return -1;
}

RANGE_SIZE_TO_CODE(size, sizecode, i);
if (sizecode == INVALID_SIZE_CODE) {
EMSG("not valid region size(2^n)! size:0x%" PRIx32, size);
return -1;
}

valid_range = _find_valid_range();
if (valid_range == -1) {
EMSG("ERR: can't find valid range!");
return -1;
}

data = read32(MCU_TZ_RANGE_LOW_REG(valid_range));

TZ_SET_VALID(data);
TZ_SET_PERM(data, perm);
TZ_SET_AREA_LEN_CODE(data, sizecode);
TZ_SET_START_ADDR_L(data, addr);

if (!valid_range) {
/* Set Undefine Range RW */
TZ_SET_UR_PERM(data, RW_PERM);
TZ_SET_UR_RZ_EN(data, 0);
}

write32(data, MCU_TZ_RANGE_LOW_REG(valid_range));

return 0;
}

static void _dump_range(void)
{
uint32_t i;
uint32_t tmp;
uint32_t sizek;
uint32_t sizecode_read;
uint32_t __maybe_unused sizem;
uint32_t __maybe_unused addr_read;
uint32_t __maybe_unused perm_read;

for (i = 0; i < MAX_RANGE_NUM; i++) {
tmp = read32(MCU_TZ_RANGE_LOW_REG(i));

if (TZ_IS_VALID(tmp)) {
TZ_GET_PERM(tmp, perm_read);
TZ_GET_AREA_LEN_CODE(tmp, sizecode_read);
TZ_GET_START_ADDR_L(tmp, addr_read);

DMSG("Range Num%" PRIu32
": Reg 0x%" PRIx64 " = 0x%" PRIx32,
i, MCU_TZ_RANGE_LOW_REG(i), tmp);
DMSG("AddrL: 0x%08" PRIx32, addr_read);
RANGE_CODE_TO_SIZE_K(sizecode_read, sizek);
sizem = sizek >> 10;
DMSG("Size: %" PRIu32 "K, %" PRIu32 "M", sizek, sizem);
DMSG("Perm: %" PRIu32, perm_read);
}
}
}

static uint32_t _find_granule(uint32_t addr, uint32_t size)
{
/* max supported granule for armada is 8TB
* but 2GB is far enough here
*/
uint32_t max_granule = SIZE_2G;

while (max_granule >= SIZE_4K) { /* min granule is 4kB */
if (max_granule <= size && _IS_ALIGNED(addr, max_granule))
return max_granule;

max_granule >>= 1;
}

return 0; /* cannot find a valid granule */
}

static void _set_range(uint32_t addr, uint32_t size, uint32_t perm)
{
uint32_t rgn_addr = addr;
uint32_t rgn_size = size;
uint32_t p;

while (rgn_size) {
p = _find_granule(rgn_addr, rgn_size);
if (!p)
panic("cannot find a suitable granule!");
if (set_range(rgn_addr, p, perm))
panic("set_range failed!");

rgn_addr += p;
rgn_size -= p;
}
}

static TEE_Result init_sec_perf(void)
{
uint32_t tmp;

/* MC_SCR config: deny NS access to MC registers */
tmp = read32(PHY_2_VIR(MC_SCR_REGISTER));
tmp |= 0x1;
write32(tmp, PHY_2_VIR(MC_SCR_REGISTER));

/* Set Secure Memory Region */
DMSG("sec-rgn size: ra = 0x%08" PRIx32 ", size = 0x%" PRIx32,
RA_ADDR, RA_SIZE);
_set_range(RA_ADDR, RA_SIZE, RA_PERM);

/* Close TZ register modification */
TZ_LOCK_MC(tmp);

_dump_range();

return TEE_SUCCESS;
}

service_init(init_sec_perf);
36 changes: 36 additions & 0 deletions core/arch/arm/plat-marvell/conf.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
PLATFORM_FLAVOR ?= armada7k8k

# 32-bit flags
core_arm32-platform-aflags += -mfpu=neon

ifeq ($(PLATFORM_FLAVOR),armada7k8k)
include core/arch/arm/cpu/cortex-armv8-0.mk
platform-debugger-arm := 1
endif

ifeq ($(platform-debugger-arm),1)
# ARM debugger needs this
platform-cflags-debug-info = -gdwarf-2
platform-aflags-debug-info = -gdwarf-2
endif

$(call force,CFG_WITH_ARM_TRUSTED_FW,y)

$(call force,CFG_GENERIC_BOOT,y)
$(call force,CFG_GIC,y)
$(call force,CFG_8250_UART,y)
$(call force,CFG_PM_STUBS,y)
$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
$(call force,CFG_CORE_CLUSTER_SHIFT,1)

ta-targets = ta_arm32

ifeq ($(CFG_ARM64_core),y)
$(call force,CFG_WITH_LPAE,y)
ta-targets += ta_arm64
else
$(call force,CFG_ARM32_core,y)
endif

CFG_WITH_STACK_CANARIES ?= y
CFG_WITH_STATS ?= y
Loading

0 comments on commit 8ae8c73

Please sign in to comment.