diff options
author | Manish Pandey <manish.pandey2@arm.com> | 2019-12-05 15:29:16 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2019-12-05 15:29:16 +0000 |
commit | caaa306fe24a503c6fa0eb77b2f9ae718d7335d7 (patch) | |
tree | daa05562daec46c6cb3d1406330636ea3d138033 | |
parent | 640af3a32b645e1b54003081d93739a6d05527dc (diff) | |
parent | c783c0b82c4803fd666c3e02c1250d8aeca9e378 (diff) | |
download | tf-a-tests-caaa306fe24a503c6fa0eb77b2f9ae718d7335d7.tar.gz |
Merge "Support for extended register usage in SMCCC v1.2 spec"
-rw-r--r-- | include/lib/tftf_lib.h | 12 | ||||
-rw-r--r-- | lib/smc/aarch32/asm_smc.S | 6 | ||||
-rw-r--r-- | lib/smc/aarch64/asm_smc.S | 8 | ||||
-rw-r--r-- | tftf/tests/runtime_services/generic/generic_smc.c | 110 |
4 files changed, 92 insertions, 44 deletions
diff --git a/include/lib/tftf_lib.h b/include/lib/tftf_lib.h index 091497a8d..7f6786a0a 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 908b8d075..107086431 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 1180f518e..c3044a42f 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 defb843ec..dc0b10230 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)); } |