aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManish Pandey <manish.pandey2@arm.com>2019-12-05 15:29:16 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2019-12-05 15:29:16 +0000
commitcaaa306fe24a503c6fa0eb77b2f9ae718d7335d7 (patch)
treedaa05562daec46c6cb3d1406330636ea3d138033
parent640af3a32b645e1b54003081d93739a6d05527dc (diff)
parentc783c0b82c4803fd666c3e02c1250d8aeca9e378 (diff)
downloadtf-a-tests-master.tar.gz
Merge "Support for extended register usage in SMCCC v1.2 spec"HEADmaster
-rw-r--r--include/lib/tftf_lib.h12
-rw-r--r--lib/smc/aarch32/asm_smc.S6
-rw-r--r--lib/smc/aarch64/asm_smc.S8
-rw-r--r--tftf/tests/runtime_services/generic/generic_smc.c110
4 files changed, 92 insertions, 44 deletions
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h
index 091497a..7f6786a 100644
--- a/include/lib/tftf_lib.h
+++ b/include/lib/tftf_lib.h
@@ -123,9 +123,9 @@ void waitms(uint64_t ms);
void waitus(uint64_t us);
/*
- * SMC calls take a function identifier and up to 6 arguments.
- * Additionally, for SMC calls that originate from EL2, an optional seventh
- * argument can be added. Given that TFTF runs in EL2, we need to be able to
+ * SMC calls take a function identifier and up to 7 arguments.
+ * Additionally, few SMC calls that originate from EL2 leverage the seventh
+ * argument explicitly. Given that TFTF runs in EL2, we need to be able to
* specify it.
*/
typedef struct {
@@ -141,12 +141,16 @@ typedef struct {
u_register_t arg7;
} smc_args;
-/* SMC calls can return up to 4 register values */
+/* SMC calls can return up to 8 register values */
typedef struct {
u_register_t ret0;
u_register_t ret1;
u_register_t ret2;
u_register_t ret3;
+ u_register_t ret4;
+ u_register_t ret5;
+ u_register_t ret6;
+ u_register_t ret7;
} smc_ret_values;
/*
diff --git a/lib/smc/aarch32/asm_smc.S b/lib/smc/aarch32/asm_smc.S
index 908b8d0..1070864 100644
--- a/lib/smc/aarch32/asm_smc.S
+++ b/lib/smc/aarch32/asm_smc.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, Arm Limited. All rights reserved.
+ * Copyright (c) 2016-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,10 +26,10 @@ func asm_tftf_smc32
smc #0
/*
- * The returned values from the SMC are in r0-r3, put them in the
+ * The returned values from the SMC are in r0-r7, put them in the
* 'smc_ret_values' return structure.
*/
- stm r8, {r0 - r3}
+ stm r8, {r0 - r7}
pop {r4 - r9}
bx lr
diff --git a/lib/smc/aarch64/asm_smc.S b/lib/smc/aarch64/asm_smc.S
index 1180f51..c3044a4 100644
--- a/lib/smc/aarch64/asm_smc.S
+++ b/lib/smc/aarch64/asm_smc.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, Arm Limited. All rights reserved.
+ * Copyright (c) 2013-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,17 +34,19 @@ func asm_tftf_smc64
*/
str x8, [sp, #-16]!
- /* SMC arguments are already stored in x0-x6 */
+ /* SMC arguments are already stored in x0-x7 */
smc #0
/* Pop x8 into a caller-saved register */
ldr x9, [sp], #16
/*
- * Return values are stored in x0-x3, put them in the 'smc_ret_values'
+ * Return values are stored in x0-x7, put them in the 'smc_ret_values'
* return structure
*/
stp x0, x1, [x9, #0]
stp x2, x3, [x9, #16]
+ stp x4, x5, [x9, #32]
+ stp x6, x7, [x9, #48]
ret
endfunc asm_tftf_smc64
diff --git a/tftf/tests/runtime_services/generic/generic_smc.c b/tftf/tests/runtime_services/generic/generic_smc.c
index defb843..dc0b102 100644
--- a/tftf/tests/runtime_services/generic/generic_smc.c
+++ b/tftf/tests/runtime_services/generic/generic_smc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -58,9 +58,12 @@ static bool smc_check_eq(const smc_args *args, const smc_ret_values *expect)
return true;
} else {
tftf_testcase_printf(
- "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {0x%lx,0x%lx,0x%lx,0x%lx}.\n",
+ "Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
+ expected {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}.\n",
ret.ret0, ret.ret1, ret.ret2, ret.ret3,
- expect->ret0, expect->ret1, expect->ret2, expect->ret3);
+ ret.ret4, ret.ret5, ret.ret6, ret.ret7,
+ expect->ret0, expect->ret1, expect->ret2, expect->ret3,
+ expect->ret4, expect->ret5, expect->ret6, expect->ret7);
return false;
}
}
@@ -78,7 +81,7 @@ static bool smc_check_eq(const smc_args *args, const smc_ret_values *expect)
* If the values do not match, write an error message in the test report.
*/
static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
- const bool do_check[4], const bool allow_zeros[4])
+ const bool do_check[8], const bool allow_zeros[8])
{
smc_ret_values ret = tftf_smc(args);
@@ -88,14 +91,18 @@ static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
if ((do_check[0] && CHK_RET(ret.ret0, expect->ret0, allow_zeros[0])) ||
(do_check[1] && CHK_RET(ret.ret1, expect->ret1, allow_zeros[1])) ||
(do_check[2] && CHK_RET(ret.ret2, expect->ret2, allow_zeros[2])) ||
- (do_check[3] && CHK_RET(ret.ret3, expect->ret3, allow_zeros[3]))) {
+ (do_check[3] && CHK_RET(ret.ret3, expect->ret3, allow_zeros[3])) ||
+ (do_check[4] && CHK_RET(ret.ret4, expect->ret4, allow_zeros[4])) ||
+ (do_check[5] && CHK_RET(ret.ret5, expect->ret5, allow_zeros[5])) ||
+ (do_check[6] && CHK_RET(ret.ret6, expect->ret6, allow_zeros[6])) ||
+ (do_check[7] && CHK_RET(ret.ret7, expect->ret7, allow_zeros[7]))) {
#undef CHK_RET
/*
* Build an error message where unchecked SMC return values are
* displayed as '*'.
*/
- char expect_str[4][28];
+ char expect_str[8][28];
#define BUILD_STR(_buf, _buf_size, _do_check, _allow_zero, _expect) \
do { \
if (_do_check) { \
@@ -120,11 +127,22 @@ static bool smc_check_match(const smc_args *args, const smc_ret_values *expect,
do_check[2], allow_zeros[2], expect->ret2);
BUILD_STR(expect_str[3], sizeof(expect_str[3]),
do_check[3], allow_zeros[3], expect->ret3);
+ BUILD_STR(expect_str[4], sizeof(expect_str[4]),
+ do_check[4], allow_zeros[4], expect->ret4);
+ BUILD_STR(expect_str[5], sizeof(expect_str[5]),
+ do_check[5], allow_zeros[5], expect->ret5);
+ BUILD_STR(expect_str[6], sizeof(expect_str[6]),
+ do_check[6], allow_zeros[6], expect->ret6);
+ BUILD_STR(expect_str[7], sizeof(expect_str[7]),
+ do_check[7], allow_zeros[7], expect->ret7);
#undef BUILD_STR
tftf_testcase_printf(
- "Got {0x%lx,0x%lx,0x%lx,0x%lx}, expected {%s,%s,%s,%s}.\n",
+ "Got {0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx}, \
+ expected {%s,%s,%s,%s,%s,%s,%s,%s}.\n",
ret.ret0, ret.ret1, ret.ret2, ret.ret3,
- expect_str[0], expect_str[1], expect_str[2], expect_str[3]);
+ ret.ret4, ret.ret5, ret.ret6, ret.ret7,
+ expect_str[0], expect_str[1], expect_str[2], expect_str[3],
+ expect_str[4], expect_str[5], expect_str[6], expect_str[7]);
return false;
} else {
@@ -142,16 +160,20 @@ test_result_t smc32_fast(void)
/* Invalid Fast SMC32. */
const smc_args args2 = {
make_smc_fid(SMC_TYPE_FAST, SMC_32, OEN_ARM_START, INVALID_FN),
- 0x11111111, 0x22222222, 0x33333333 };
+ 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
const smc_ret_values ret2
- = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
FAIL_IF(!smc_check_eq(&args2, &ret2));
/* Valid Fast SMC32 using 1 return value. */
const smc_args args3
- = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666 };
+ = { SMC_PSCI_VERSION, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
const smc_ret_values ret3
- = { psci_version, 0x44444444, 0x55555555, 0x66666666 };
+ = { psci_version, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
FAIL_IF(!smc_check_eq(&args3, &ret3));
return TEST_RESULT_SUCCESS;
@@ -167,9 +189,11 @@ test_result_t smc64_yielding(void)
/* Invalid function number, SMC64 Yielding. */
const smc_args args2 = {
make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_ARM_START, INVALID_FN),
- 0x11111111, 0x22222222, 0x33333333 };
+ 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
const smc_ret_values ret2
- = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
FAIL_IF(!smc_check_eq(&args2, &ret2));
/*
@@ -186,7 +210,8 @@ test_result_t smc64_yielding(void)
*/
const smc_args args3 = {
make_smc_fid(SMC_TYPE_STD, SMC_64, OEN_TOS_START, INVALID_FN),
- 0x44444444, 0x55555555, 0x66666666 };
+ 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
+ 0x99999999, 0xaaaaaaaa };
if (is_trusted_os_present(NULL)) {
/*
@@ -194,14 +219,17 @@ test_result_t smc64_yielding(void)
* should at least preserve or fill by zeroes the values of
* x1-x3.
*/
- const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
- const bool check[4] = { false, true, true, true };
- const bool allow_zeros[4] = { false, true, true, true };
+ const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
+ const bool check[8] = { false, true, true, true, true, true, true, true };
+ const bool allow_zeros[8] = { false, true, true, true,
+ true, true, true, true };
FAIL_IF(!smc_check_match(&args3, &ret3, check, allow_zeros));
} else {
const smc_ret_values ret3
- = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
FAIL_IF(!smc_check_eq(&args3, &ret3));
}
@@ -218,9 +246,11 @@ static test_result_t smc64_fast_caller32(void)
/* Invalid SMC function number, Fast SMC64. */
const smc_args args2 = {
make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
- 0x11111111, 0x22222222, 0x33333333 };
+ 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
const smc_ret_values ret2
- = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333,
+ 0x44444444, 0x55555555, 0x66666666, 0x77777777 };
FAIL_IF(!smc_check_eq(&args2, &ret2));
/*
@@ -228,9 +258,11 @@ static test_result_t smc64_fast_caller32(void)
* forbidden to use the SMC64 calling convention.
*/
const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
- 0x44444444, 0x55555555, 0x66666666 };
+ 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
+ 0x99999999, 0xaaaaaaaa };
const smc_ret_values ret3
- = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
FAIL_IF(!smc_check_eq(&args3, &ret3));
return TEST_RESULT_SUCCESS;
@@ -245,16 +277,20 @@ static test_result_t smc64_fast_caller64(void)
/* Invalid function number, Fast SMC64. */
const smc_args args2 = {
make_smc_fid(SMC_TYPE_FAST, SMC_64, OEN_ARM_START, INVALID_FN),
- 0x11111111, 0x22222222, 0x33333333 };
+ 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555,
+ 0x66666666, 0x77777777 };
const smc_ret_values ret2
- = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
FAIL_IF(!smc_check_eq(&args2, &ret2));
/* Valid Fast SMC64 using 1 return value. */
const smc_args args3 = { SMC_PSCI_AFFINITY_INFO_AARCH64,
- 0x44444444, 0x55555555, 0x66666666 };
+ 0x44444444, 0x55555555, 0x66666666, 0x77777777,
+ 0x88888888, 0x99999999, 0xaaaaaaaa };
const smc_ret_values ret3
- = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666 };
+ = { PSCI_E_INVALID_PARAMS, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
FAIL_IF(!smc_check_eq(&args3, &ret3));
return TEST_RESULT_SUCCESS;
@@ -281,9 +317,11 @@ test_result_t smc32_yielding(void)
/* Invalid function number, SMC32 Yielding. */
const smc_args args2 = {
make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_ARM_START, INVALID_FN),
- 0x11111111, 0x22222222, 0x33333333 };
+ 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
const smc_ret_values ret2
- = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333 };
+ = { SMC_UNKNOWN, 0x11111111, 0x22222222, 0x33333333, 0x44444444,
+ 0x55555555, 0x66666666, 0x77777777 };
FAIL_IF(!smc_check_eq(&args2, &ret2));
/*
@@ -300,7 +338,8 @@ test_result_t smc32_yielding(void)
*/
const smc_args args3 = {
make_smc_fid(SMC_TYPE_STD, SMC_32, OEN_TOS_START, INVALID_FN),
- 0x44444444, 0x55555555, 0x66666666 };
+ 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
+ 0x99999999, 0xaaaaaaaa };
if (is_trusted_os_present(NULL)) {
/*
@@ -308,14 +347,17 @@ test_result_t smc32_yielding(void)
* should at least preserve or fill by zeroes the values of
* x1-x3.
*/
- const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666 };
- const bool check[4] = { false, true, true, true };
- const bool allow_zeros[4] = { false, true, true, true };
+ const smc_ret_values ret3 = { 0, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
+ const bool check[8] = { false, true, true, true, true, true, true, true };
+ const bool allow_zeros[8] = { false, true, true, true,
+ true, true, true, true };
FAIL_IF(!smc_check_match(&args3, &ret3, check, allow_zeros));
} else {
const smc_ret_values ret3
- = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666 };
+ = { SMC_UNKNOWN, 0x44444444, 0x55555555, 0x66666666,
+ 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa };
FAIL_IF(!smc_check_eq(&args3, &ret3));
}