| Antonio Nino Diaz | a1497e3 | 2018-11-08 11:45:13 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (c) 2018, Arm Limited. All rights reserved. |
| 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <arch_helpers.h> |
| 8 | #include <cactus_def.h> |
| 9 | #include <debug.h> |
| 10 | #include <events.h> |
| 11 | #include <ivy_def.h> |
| 12 | #include <plat_topology.h> |
| 13 | #include <platform.h> |
| 14 | #include <power_management.h> |
| 15 | #include <smccc.h> |
| 16 | #include <spci_helpers.h> |
| 17 | #include <spci_svc.h> |
| 18 | #include <test_helpers.h> |
| 19 | #include <tftf_lib.h> |
| 20 | |
| 21 | #define TEST_NUM_ITERATIONS 1000U |
| 22 | |
| 23 | static event_t cpu_has_entered_test[PLATFORM_CORE_COUNT]; |
| 24 | |
| 25 | static test_result_t test_spci_blocking_multicore_fn(void) |
| 26 | { |
| 27 | int ret; |
| 28 | uint16_t handle_cactus, handle_ivy; |
| 29 | u_register_t rx1, rx2, rx3; |
| 30 | test_result_t result = TEST_RESULT_SUCCESS; |
| 31 | |
| 32 | u_register_t cpu_mpid = read_mpidr_el1() & MPID_MASK; |
| 33 | unsigned int core_pos = platform_get_core_pos(cpu_mpid); |
| 34 | |
| 35 | tftf_send_event(&cpu_has_entered_test[core_pos]); |
| 36 | |
| 37 | /* Open handles. */ |
| 38 | |
| 39 | ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_cactus, |
| 40 | CACTUS_SERVICE1_UUID); |
| 41 | if (ret != SPCI_SUCCESS) { |
| 42 | tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: 0x%x\n", |
| 43 | __LINE__, (uint32_t)ret); |
| 44 | result = TEST_RESULT_FAIL; |
| 45 | goto exit_none; |
| 46 | } |
| 47 | |
| 48 | ret = spci_service_handle_open(TFTF_SPCI_CLIENT_ID, &handle_ivy, |
| 49 | IVY_SERVICE1_UUID); |
| 50 | if (ret != SPCI_SUCCESS) { |
| 51 | tftf_testcase_printf("%d: SPM failed to return a valid handle. Returned: 0x%x\n", |
| 52 | __LINE__, (uint32_t)ret); |
| 53 | result = TEST_RESULT_FAIL; |
| 54 | goto exit_cactus; |
| 55 | } |
| 56 | |
| 57 | /* Request services. */ |
| 58 | |
| 59 | for (unsigned int i = 0U; i < TEST_NUM_ITERATIONS; i++) { |
| 60 | |
| 61 | /* Send request to Cactus */ |
| 62 | |
| 63 | ret = spci_service_request_blocking(CACTUS_GET_MAGIC, |
| 64 | 0, 0, 0, 0, 0, |
| 65 | TFTF_SPCI_CLIENT_ID, |
| 66 | handle_cactus, |
| 67 | &rx1, &rx2, &rx3); |
| 68 | |
| 69 | if (ret == SPCI_BUSY) { |
| 70 | /* |
| 71 | * Another CPU is already using Cactus, this is not a |
| 72 | * failure. |
| 73 | */ |
| 74 | } else if (ret == SPCI_SUCCESS) { |
| 75 | if (rx1 != CACTUS_MAGIC_NUMBER) { |
| 76 | tftf_testcase_printf("%d: Cactus returned 0x%x 0x%lx 0x%lx 0x%lx\n", |
| 77 | __LINE__, (uint32_t)ret, rx1, rx2, rx3); |
| 78 | result = TEST_RESULT_FAIL; |
| 79 | break; |
| 80 | } |
| 81 | } else { |
| 82 | tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: 0x%x\n", |
| 83 | __LINE__, (uint32_t)ret); |
| 84 | result = TEST_RESULT_FAIL; |
| 85 | break; |
| 86 | } |
| 87 | |
| 88 | /* Send request to Ivy */ |
| 89 | |
| 90 | ret = spci_service_request_blocking(IVY_GET_MAGIC, |
| 91 | 0, 0, 0, 0, 0, |
| 92 | TFTF_SPCI_CLIENT_ID, |
| 93 | handle_ivy, |
| 94 | &rx1, &rx2, &rx3); |
| 95 | if (ret == SPCI_BUSY) { |
| 96 | /* |
| 97 | * Another CPU is already using Ivy, this is not a |
| 98 | * failure. |
| 99 | */ |
| 100 | } else if (ret == SPCI_SUCCESS) { |
| 101 | if (rx1 != IVY_MAGIC_NUMBER) { |
| 102 | tftf_testcase_printf("%d: Ivy returned 0x%x 0x%lx 0x%lx 0x%lx\n", |
| 103 | __LINE__, (uint32_t)ret, rx1, rx2, rx3); |
| 104 | result = TEST_RESULT_FAIL; |
| 105 | break; |
| 106 | } |
| 107 | } else { |
| 108 | tftf_testcase_printf("%d: SPM should have returned SPCI_SUCCESS. Returned: 0x%x\n", |
| 109 | __LINE__, (uint32_t)ret); |
| 110 | result = TEST_RESULT_FAIL; |
| 111 | break; |
| 112 | } |
| 113 | |
| 114 | } |
| 115 | |
| 116 | /* Close handles. */ |
| 117 | |
| 118 | ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_ivy); |
| 119 | if (ret != SPCI_SUCCESS) { |
| 120 | tftf_testcase_printf("%d: SPM failed to close the handle. Returned: 0x%x\n", |
| 121 | __LINE__, (uint32_t)ret); |
| 122 | result = TEST_RESULT_FAIL; |
| 123 | } |
| 124 | |
| 125 | exit_cactus: |
| 126 | ret = spci_service_handle_close(TFTF_SPCI_CLIENT_ID, handle_cactus); |
| 127 | if (ret != SPCI_SUCCESS) { |
| 128 | tftf_testcase_printf("%d: SPM failed to close the handle. Returned: 0x%x\n", |
| 129 | __LINE__, (uint32_t)ret); |
| 130 | result = TEST_RESULT_FAIL; |
| 131 | } |
| 132 | |
| 133 | /* All tests finished. */ |
| 134 | exit_none: |
| 135 | return result; |
| 136 | } |
| 137 | |
| 138 | /* |
| 139 | * @Test_Aim@ This tests opens a Secure Service handle and performs many simple |
| 140 | * blocking requests to Cactus and Ivy from multiple cores |
| 141 | */ |
| 142 | test_result_t test_spci_blocking_request_multicore(void) |
| 143 | { |
| 144 | unsigned int cpu_node, core_pos; |
| 145 | int psci_ret; |
| 146 | u_register_t cpu_mpid; |
| 147 | u_register_t lead_mpid = read_mpidr_el1() & MPID_MASK; |
| 148 | |
| 149 | SKIP_TEST_IF_SPCI_VERSION_LESS_THAN(0, 1); |
| 150 | |
| 151 | for (int i = 0; i < PLATFORM_CORE_COUNT; i++) { |
| 152 | tftf_init_event(&cpu_has_entered_test[i]); |
| 153 | } |
| 154 | |
| 155 | /* Power on all CPUs */ |
| 156 | for_each_cpu(cpu_node) { |
| 157 | cpu_mpid = tftf_get_mpidr_from_node(cpu_node); |
| 158 | /* Skip lead CPU as it is already powered on */ |
| 159 | if (cpu_mpid == lead_mpid) { |
| 160 | continue; |
| 161 | } |
| 162 | |
| 163 | psci_ret = tftf_cpu_on(cpu_mpid, |
| 164 | (uintptr_t)test_spci_blocking_multicore_fn, 0); |
| 165 | if (psci_ret != PSCI_E_SUCCESS) { |
| 166 | core_pos = platform_get_core_pos(cpu_mpid); |
| 167 | |
| 168 | tftf_testcase_printf( |
| 169 | "Failed to power on CPU %d (rc = %d)\n", |
| 170 | core_pos, psci_ret); |
| 171 | return TEST_RESULT_FAIL; |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | /* Wait until all CPUs have started the test. */ |
| 176 | for_each_cpu(cpu_node) { |
| 177 | cpu_mpid = tftf_get_mpidr_from_node(cpu_node); |
| 178 | /* Skip lead CPU */ |
| 179 | if (cpu_mpid == lead_mpid) { |
| 180 | continue; |
| 181 | } |
| 182 | |
| 183 | core_pos = platform_get_core_pos(cpu_mpid); |
| 184 | tftf_wait_for_event(&cpu_has_entered_test[core_pos]); |
| 185 | } |
| 186 | |
| 187 | /* Enter the test on lead CPU and return the result. */ |
| 188 | return test_spci_blocking_multicore_fn(); |
| 189 | } |