1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (c) 2020 Google, Inc.
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker *
12*344aa361SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker *
15*344aa361SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker */
23*344aa361SAndroid Build Coastguard Worker
24*344aa361SAndroid Build Coastguard Worker /*
25*344aa361SAndroid Build Coastguard Worker * This module registers smc handlers that are called by tests running in the
26*344aa361SAndroid Build Coastguard Worker * client os. This api is currently only available if lib/sm is enabled.
27*344aa361SAndroid Build Coastguard Worker */
28*344aa361SAndroid Build Coastguard Worker #if WITH_LIB_SM
29*344aa361SAndroid Build Coastguard Worker
30*344aa361SAndroid Build Coastguard Worker #include <arch/arch_ops.h>
31*344aa361SAndroid Build Coastguard Worker #include <arch/ops.h>
32*344aa361SAndroid Build Coastguard Worker #include <err.h>
33*344aa361SAndroid Build Coastguard Worker #include <inttypes.h>
34*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
35*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
36*344aa361SAndroid Build Coastguard Worker #include <lib/sm.h>
37*344aa361SAndroid Build Coastguard Worker #include <lib/sm/sm_err.h>
38*344aa361SAndroid Build Coastguard Worker #include <lib/sm/smcall.h>
39*344aa361SAndroid Build Coastguard Worker #include <lib/smc/smc.h>
40*344aa361SAndroid Build Coastguard Worker #include <limits.h>
41*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
42*344aa361SAndroid Build Coastguard Worker #include <stdatomic.h>
43*344aa361SAndroid Build Coastguard Worker #include <string.h>
44*344aa361SAndroid Build Coastguard Worker #include <trace.h>
45*344aa361SAndroid Build Coastguard Worker
46*344aa361SAndroid Build Coastguard Worker #include "stdcalltest.h"
47*344aa361SAndroid Build Coastguard Worker
args_get_id(struct smc32_args * args)48*344aa361SAndroid Build Coastguard Worker static ext_mem_obj_id_t args_get_id(struct smc32_args* args) {
49*344aa361SAndroid Build Coastguard Worker return (((uint64_t)args->params[1] << 32) | args->params[0]);
50*344aa361SAndroid Build Coastguard Worker }
51*344aa361SAndroid Build Coastguard Worker
args_get_sz(struct smc32_args * args)52*344aa361SAndroid Build Coastguard Worker static size_t args_get_sz(struct smc32_args* args) {
53*344aa361SAndroid Build Coastguard Worker return (size_t)args->params[2];
54*344aa361SAndroid Build Coastguard Worker }
55*344aa361SAndroid Build Coastguard Worker
56*344aa361SAndroid Build Coastguard Worker /**
57*344aa361SAndroid Build Coastguard Worker * stdcalltest_sharedmem_rw - Test shared memory buffer.
58*344aa361SAndroid Build Coastguard Worker * @id: Shared memory id.
59*344aa361SAndroid Build Coastguard Worker * @size: Size.
60*344aa361SAndroid Build Coastguard Worker *
61*344aa361SAndroid Build Coastguard Worker * Check that buffer contains the 64 bit integer sqequnce [0, 1, 2, ...,
62*344aa361SAndroid Build Coastguard Worker * @size / 8 - 1] and modify sequence to [@size, @size - 1, size - 2, ...,
63*344aa361SAndroid Build Coastguard Worker * @size - (@size / 8 - 1)].
64*344aa361SAndroid Build Coastguard Worker *
65*344aa361SAndroid Build Coastguard Worker * Return: 0 on success. SM_ERR_INVALID_PARAMETERS is buffer does not contain
66*344aa361SAndroid Build Coastguard Worker * expected input pattern. SM_ERR_INTERNAL_FAILURE if @id could not be mapped.
67*344aa361SAndroid Build Coastguard Worker */
stdcalltest_sharedmem_rw(ext_mem_client_id_t client_id,ext_mem_obj_id_t mem_obj_id,size_t size)68*344aa361SAndroid Build Coastguard Worker static long stdcalltest_sharedmem_rw(ext_mem_client_id_t client_id,
69*344aa361SAndroid Build Coastguard Worker ext_mem_obj_id_t mem_obj_id,
70*344aa361SAndroid Build Coastguard Worker size_t size) {
71*344aa361SAndroid Build Coastguard Worker struct vmm_aspace* aspace = vmm_get_kernel_aspace();
72*344aa361SAndroid Build Coastguard Worker status_t ret;
73*344aa361SAndroid Build Coastguard Worker long status;
74*344aa361SAndroid Build Coastguard Worker void* va;
75*344aa361SAndroid Build Coastguard Worker uint64_t* va64;
76*344aa361SAndroid Build Coastguard Worker
77*344aa361SAndroid Build Coastguard Worker if (!IS_PAGE_ALIGNED(size)) {
78*344aa361SAndroid Build Coastguard Worker return SM_ERR_INVALID_PARAMETERS;
79*344aa361SAndroid Build Coastguard Worker }
80*344aa361SAndroid Build Coastguard Worker
81*344aa361SAndroid Build Coastguard Worker ret = ext_mem_map_obj_id(aspace, "stdcalltest", client_id, mem_obj_id, 0, 0,
82*344aa361SAndroid Build Coastguard Worker size, &va, PAGE_SIZE_SHIFT, 0,
83*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
84*344aa361SAndroid Build Coastguard Worker if (ret != NO_ERROR) {
85*344aa361SAndroid Build Coastguard Worker status = SM_ERR_INTERNAL_FAILURE;
86*344aa361SAndroid Build Coastguard Worker goto err_map;
87*344aa361SAndroid Build Coastguard Worker }
88*344aa361SAndroid Build Coastguard Worker va64 = va;
89*344aa361SAndroid Build Coastguard Worker
90*344aa361SAndroid Build Coastguard Worker for (size_t i = 0; i < size / sizeof(*va64); i++) {
91*344aa361SAndroid Build Coastguard Worker if (va64[i] != i) {
92*344aa361SAndroid Build Coastguard Worker TRACEF("input mismatch at %zd, got 0x%" PRIx64
93*344aa361SAndroid Build Coastguard Worker " instead of 0x%zx\n",
94*344aa361SAndroid Build Coastguard Worker i, va64[i], i);
95*344aa361SAndroid Build Coastguard Worker status = SM_ERR_INVALID_PARAMETERS;
96*344aa361SAndroid Build Coastguard Worker goto err_input_mismatch;
97*344aa361SAndroid Build Coastguard Worker }
98*344aa361SAndroid Build Coastguard Worker va64[i] = size - i;
99*344aa361SAndroid Build Coastguard Worker }
100*344aa361SAndroid Build Coastguard Worker status = 0;
101*344aa361SAndroid Build Coastguard Worker
102*344aa361SAndroid Build Coastguard Worker err_input_mismatch:
103*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)va);
104*344aa361SAndroid Build Coastguard Worker if (ret) {
105*344aa361SAndroid Build Coastguard Worker status = SM_ERR_INTERNAL_FAILURE;
106*344aa361SAndroid Build Coastguard Worker }
107*344aa361SAndroid Build Coastguard Worker err_map:
108*344aa361SAndroid Build Coastguard Worker return status;
109*344aa361SAndroid Build Coastguard Worker }
110*344aa361SAndroid Build Coastguard Worker
111*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
112*344aa361SAndroid Build Coastguard Worker long clobber_sve_asm(uint32_t byte_clobber);
113*344aa361SAndroid Build Coastguard Worker long load_sve_asm(uint8_t* arr, uint64_t len);
114*344aa361SAndroid Build Coastguard Worker
115*344aa361SAndroid Build Coastguard Worker #define SVE_VEC_LEN_BITS 128
116*344aa361SAndroid Build Coastguard Worker #define SVE_NB_BYTE_VEC_LEN SVE_VEC_LEN_BITS / 8
117*344aa361SAndroid Build Coastguard Worker #define SVE_SVE_REGS_COUNT 32
118*344aa361SAndroid Build Coastguard Worker
119*344aa361SAndroid Build Coastguard Worker #define SMC_FC_TRNG_VERSION SMC_FASTCALL_NR(SMC_ENTITY_STD, 0x50)
120*344aa361SAndroid Build Coastguard Worker
121*344aa361SAndroid Build Coastguard Worker static uint8_t sve_regs[SMP_MAX_CPUS][SVE_SVE_REGS_COUNT * SVE_NB_BYTE_VEC_LEN]
122*344aa361SAndroid Build Coastguard Worker __attribute__((aligned(16)));
123*344aa361SAndroid Build Coastguard Worker
124*344aa361SAndroid Build Coastguard Worker enum clobber_restore_error {
125*344aa361SAndroid Build Coastguard Worker SVE_NO_ERROR = 0,
126*344aa361SAndroid Build Coastguard Worker SVE_GENERIC_ERROR = 1,
127*344aa361SAndroid Build Coastguard Worker SVE_REGISTER_NOT_RESTORED = 2,
128*344aa361SAndroid Build Coastguard Worker SVE_ERROR_LONG_TYPE = LONG_MAX
129*344aa361SAndroid Build Coastguard Worker };
130*344aa361SAndroid Build Coastguard Worker
stdcalltest_clobber_sve(struct smc32_args * args)131*344aa361SAndroid Build Coastguard Worker long stdcalltest_clobber_sve(struct smc32_args* args) {
132*344aa361SAndroid Build Coastguard Worker enum clobber_restore_error ret = SVE_NO_ERROR;
133*344aa361SAndroid Build Coastguard Worker if (!arch_sve_supported()) {
134*344aa361SAndroid Build Coastguard Worker /* test is OK, if there is no SVE there is nothing to assert but this is
135*344aa361SAndroid Build Coastguard Worker * not an ERROR */
136*344aa361SAndroid Build Coastguard Worker return ret;
137*344aa361SAndroid Build Coastguard Worker }
138*344aa361SAndroid Build Coastguard Worker
139*344aa361SAndroid Build Coastguard Worker uint64_t v_cpacr_el1 = arch_enable_sve();
140*344aa361SAndroid Build Coastguard Worker uint cpuid = arch_curr_cpu_num();
141*344aa361SAndroid Build Coastguard Worker long call_nb = args->params[1];
142*344aa361SAndroid Build Coastguard Worker
143*344aa361SAndroid Build Coastguard Worker /* First Call on cpu needs to Clobber ASM registers */
144*344aa361SAndroid Build Coastguard Worker if (call_nb == 1) {
145*344aa361SAndroid Build Coastguard Worker ret = clobber_sve_asm(args->params[0]);
146*344aa361SAndroid Build Coastguard Worker if (ret != SVE_NO_ERROR) {
147*344aa361SAndroid Build Coastguard Worker panic("Failed to Clobber ARM SVE registers: %lx\n", ret);
148*344aa361SAndroid Build Coastguard Worker ret = SVE_GENERIC_ERROR;
149*344aa361SAndroid Build Coastguard Worker goto end_stdcalltest_clobber_sve;
150*344aa361SAndroid Build Coastguard Worker }
151*344aa361SAndroid Build Coastguard Worker }
152*344aa361SAndroid Build Coastguard Worker
153*344aa361SAndroid Build Coastguard Worker /* Make sure registers are as expected */
154*344aa361SAndroid Build Coastguard Worker const uint8_t EXPECTED = (uint8_t)args->params[0];
155*344aa361SAndroid Build Coastguard Worker ret = load_sve_asm(sve_regs[cpuid], SVE_NB_BYTE_VEC_LEN);
156*344aa361SAndroid Build Coastguard Worker if (ret != SVE_NO_ERROR) {
157*344aa361SAndroid Build Coastguard Worker panic("Failed to Load ARM SVE registers: %lx\n", ret);
158*344aa361SAndroid Build Coastguard Worker ret = SVE_GENERIC_ERROR;
159*344aa361SAndroid Build Coastguard Worker goto end_stdcalltest_clobber_sve;
160*344aa361SAndroid Build Coastguard Worker }
161*344aa361SAndroid Build Coastguard Worker
162*344aa361SAndroid Build Coastguard Worker for (size_t idx = 0; idx < countof(sve_regs[cpuid]); ++idx) {
163*344aa361SAndroid Build Coastguard Worker uint8_t val = sve_regs[cpuid][idx];
164*344aa361SAndroid Build Coastguard Worker
165*344aa361SAndroid Build Coastguard Worker if (val != EXPECTED) {
166*344aa361SAndroid Build Coastguard Worker ret = SVE_REGISTER_NOT_RESTORED;
167*344aa361SAndroid Build Coastguard Worker goto end_stdcalltest_clobber_sve;
168*344aa361SAndroid Build Coastguard Worker }
169*344aa361SAndroid Build Coastguard Worker }
170*344aa361SAndroid Build Coastguard Worker
171*344aa361SAndroid Build Coastguard Worker end_stdcalltest_clobber_sve:
172*344aa361SAndroid Build Coastguard Worker ARM64_WRITE_SYSREG(cpacr_el1, v_cpacr_el1);
173*344aa361SAndroid Build Coastguard Worker return ret;
174*344aa361SAndroid Build Coastguard Worker }
175*344aa361SAndroid Build Coastguard Worker
stdcalltest_compute_fpacr(uint64_t * old_cpacr,uint64_t * new_cpacr)176*344aa361SAndroid Build Coastguard Worker static long stdcalltest_compute_fpacr(uint64_t* old_cpacr,
177*344aa361SAndroid Build Coastguard Worker uint64_t* new_cpacr) {
178*344aa361SAndroid Build Coastguard Worker uint64_t cpacr = ARM64_READ_SYSREG(cpacr_el1);
179*344aa361SAndroid Build Coastguard Worker
180*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(old_cpacr);
181*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(new_cpacr);
182*344aa361SAndroid Build Coastguard Worker
183*344aa361SAndroid Build Coastguard Worker if ((cpacr >> 20) & 1) {
184*344aa361SAndroid Build Coastguard Worker return SM_ERR_NOT_ALLOWED;
185*344aa361SAndroid Build Coastguard Worker }
186*344aa361SAndroid Build Coastguard Worker
187*344aa361SAndroid Build Coastguard Worker *old_cpacr = cpacr;
188*344aa361SAndroid Build Coastguard Worker *new_cpacr = cpacr | (3 << 20);
189*344aa361SAndroid Build Coastguard Worker return 0;
190*344aa361SAndroid Build Coastguard Worker }
191*344aa361SAndroid Build Coastguard Worker
stdcalltest_random_u32(void)192*344aa361SAndroid Build Coastguard Worker static uint32_t stdcalltest_random_u32(void) {
193*344aa361SAndroid Build Coastguard Worker /* Initialize the RNG seed to the golden ratio */
194*344aa361SAndroid Build Coastguard Worker static atomic_int hash = 0x9e3779b1U;
195*344aa361SAndroid Build Coastguard Worker int oldh, newh;
196*344aa361SAndroid Build Coastguard Worker
197*344aa361SAndroid Build Coastguard Worker /* Update the RNG with MurmurHash3 */
198*344aa361SAndroid Build Coastguard Worker do {
199*344aa361SAndroid Build Coastguard Worker newh = oldh = atomic_load(&hash);
200*344aa361SAndroid Build Coastguard Worker newh ^= newh >> 16;
201*344aa361SAndroid Build Coastguard Worker __builtin_mul_overflow(newh, 0x85ebca6bU, &newh);
202*344aa361SAndroid Build Coastguard Worker newh ^= newh >> 13;
203*344aa361SAndroid Build Coastguard Worker __builtin_mul_overflow(newh, 0xc2b2ae35U, &newh);
204*344aa361SAndroid Build Coastguard Worker newh ^= newh >> 16;
205*344aa361SAndroid Build Coastguard Worker } while (!atomic_compare_exchange_weak(&hash, &oldh, newh));
206*344aa361SAndroid Build Coastguard Worker
207*344aa361SAndroid Build Coastguard Worker return (uint32_t)oldh;
208*344aa361SAndroid Build Coastguard Worker }
209*344aa361SAndroid Build Coastguard Worker
210*344aa361SAndroid Build Coastguard Worker static struct fpstate stdcalltest_random_fpstate;
211*344aa361SAndroid Build Coastguard Worker
stdcalltest_clobber_fpsimd_clobber(struct smc32_args * args)212*344aa361SAndroid Build Coastguard Worker static long stdcalltest_clobber_fpsimd_clobber(struct smc32_args* args) {
213*344aa361SAndroid Build Coastguard Worker long ret;
214*344aa361SAndroid Build Coastguard Worker uint64_t old_cpacr, new_cpacr;
215*344aa361SAndroid Build Coastguard Worker bool loaded;
216*344aa361SAndroid Build Coastguard Worker
217*344aa361SAndroid Build Coastguard Worker /*
218*344aa361SAndroid Build Coastguard Worker * Check if the FPU at EL1 is already on;
219*344aa361SAndroid Build Coastguard Worker * it shouldn't be, so return an error if it is.
220*344aa361SAndroid Build Coastguard Worker * Otherwise, save the old value and restore it
221*344aa361SAndroid Build Coastguard Worker * after we're done.
222*344aa361SAndroid Build Coastguard Worker */
223*344aa361SAndroid Build Coastguard Worker ret = stdcalltest_compute_fpacr(&old_cpacr, &new_cpacr);
224*344aa361SAndroid Build Coastguard Worker if (ret) {
225*344aa361SAndroid Build Coastguard Worker return ret;
226*344aa361SAndroid Build Coastguard Worker }
227*344aa361SAndroid Build Coastguard Worker
228*344aa361SAndroid Build Coastguard Worker for (size_t i = 0; i < countof(stdcalltest_random_fpstate.regs); i++) {
229*344aa361SAndroid Build Coastguard Worker stdcalltest_random_fpstate.regs[i] =
230*344aa361SAndroid Build Coastguard Worker ((uint64_t)stdcalltest_random_u32() << 32) |
231*344aa361SAndroid Build Coastguard Worker stdcalltest_random_u32();
232*344aa361SAndroid Build Coastguard Worker }
233*344aa361SAndroid Build Coastguard Worker /*
234*344aa361SAndroid Build Coastguard Worker * TODO: set FPCR&FPSR to random values, but they need to be masked
235*344aa361SAndroid Build Coastguard Worker * because many of their bits are MBZ
236*344aa361SAndroid Build Coastguard Worker */
237*344aa361SAndroid Build Coastguard Worker stdcalltest_random_fpstate.fpcr = 0;
238*344aa361SAndroid Build Coastguard Worker stdcalltest_random_fpstate.fpsr = 0;
239*344aa361SAndroid Build Coastguard Worker
240*344aa361SAndroid Build Coastguard Worker ARM64_WRITE_SYSREG(cpacr_el1, new_cpacr);
241*344aa361SAndroid Build Coastguard Worker loaded = arm64_fpu_load_fpstate(&stdcalltest_random_fpstate, true);
242*344aa361SAndroid Build Coastguard Worker ARM64_WRITE_SYSREG(cpacr_el1, old_cpacr);
243*344aa361SAndroid Build Coastguard Worker return loaded ? 0 : SM_ERR_INTERNAL_FAILURE;
244*344aa361SAndroid Build Coastguard Worker }
245*344aa361SAndroid Build Coastguard Worker
stdcalltest_clobber_fpsimd_check(struct smc32_args * args)246*344aa361SAndroid Build Coastguard Worker static long stdcalltest_clobber_fpsimd_check(struct smc32_args* args) {
247*344aa361SAndroid Build Coastguard Worker long ret;
248*344aa361SAndroid Build Coastguard Worker uint64_t old_cpacr, new_cpacr;
249*344aa361SAndroid Build Coastguard Worker struct fpstate new_fpstate;
250*344aa361SAndroid Build Coastguard Worker bool loaded;
251*344aa361SAndroid Build Coastguard Worker
252*344aa361SAndroid Build Coastguard Worker ret = stdcalltest_compute_fpacr(&old_cpacr, &new_cpacr);
253*344aa361SAndroid Build Coastguard Worker if (ret) {
254*344aa361SAndroid Build Coastguard Worker return ret;
255*344aa361SAndroid Build Coastguard Worker }
256*344aa361SAndroid Build Coastguard Worker
257*344aa361SAndroid Build Coastguard Worker ARM64_WRITE_SYSREG(cpacr_el1, new_cpacr);
258*344aa361SAndroid Build Coastguard Worker loaded = arm64_fpu_load_fpstate(&stdcalltest_random_fpstate, false);
259*344aa361SAndroid Build Coastguard Worker arm64_fpu_save_fpstate(&new_fpstate);
260*344aa361SAndroid Build Coastguard Worker ARM64_WRITE_SYSREG(cpacr_el1, old_cpacr);
261*344aa361SAndroid Build Coastguard Worker
262*344aa361SAndroid Build Coastguard Worker if (loaded) {
263*344aa361SAndroid Build Coastguard Worker /*
264*344aa361SAndroid Build Coastguard Worker * Check whether the current fpstate is still the one set
265*344aa361SAndroid Build Coastguard Worker * earlier by the clobber. If not, it means another thread
266*344aa361SAndroid Build Coastguard Worker * ran and overwrote our registers, and we do not want to
267*344aa361SAndroid Build Coastguard Worker * leak them here.
268*344aa361SAndroid Build Coastguard Worker */
269*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_BUSY;
270*344aa361SAndroid Build Coastguard Worker goto err;
271*344aa361SAndroid Build Coastguard Worker }
272*344aa361SAndroid Build Coastguard Worker
273*344aa361SAndroid Build Coastguard Worker for (size_t i = 0; i < countof(new_fpstate.regs); i++) {
274*344aa361SAndroid Build Coastguard Worker if (new_fpstate.regs[i] != stdcalltest_random_fpstate.regs[i]) {
275*344aa361SAndroid Build Coastguard Worker TRACEF("regs[%zu] mismatch: %" PRIx64 " != %" PRIx64 "\n", i,
276*344aa361SAndroid Build Coastguard Worker new_fpstate.regs[i], stdcalltest_random_fpstate.regs[i]);
277*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERNAL_FAILURE;
278*344aa361SAndroid Build Coastguard Worker goto err;
279*344aa361SAndroid Build Coastguard Worker }
280*344aa361SAndroid Build Coastguard Worker }
281*344aa361SAndroid Build Coastguard Worker if (new_fpstate.fpcr != stdcalltest_random_fpstate.fpcr) {
282*344aa361SAndroid Build Coastguard Worker TRACEF("FPCR mismatch: %" PRIx32 " != %" PRIx32 "\n", new_fpstate.fpcr,
283*344aa361SAndroid Build Coastguard Worker stdcalltest_random_fpstate.fpcr);
284*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERNAL_FAILURE;
285*344aa361SAndroid Build Coastguard Worker goto err;
286*344aa361SAndroid Build Coastguard Worker }
287*344aa361SAndroid Build Coastguard Worker if (new_fpstate.fpsr != stdcalltest_random_fpstate.fpsr) {
288*344aa361SAndroid Build Coastguard Worker TRACEF("FPSR mismatch: %" PRIx32 " != %" PRIx32 "\n", new_fpstate.fpsr,
289*344aa361SAndroid Build Coastguard Worker stdcalltest_random_fpstate.fpsr);
290*344aa361SAndroid Build Coastguard Worker ret = SM_ERR_INTERNAL_FAILURE;
291*344aa361SAndroid Build Coastguard Worker goto err;
292*344aa361SAndroid Build Coastguard Worker }
293*344aa361SAndroid Build Coastguard Worker
294*344aa361SAndroid Build Coastguard Worker /* Return 0 on success */
295*344aa361SAndroid Build Coastguard Worker ret = 0;
296*344aa361SAndroid Build Coastguard Worker
297*344aa361SAndroid Build Coastguard Worker err:
298*344aa361SAndroid Build Coastguard Worker return ret;
299*344aa361SAndroid Build Coastguard Worker }
300*344aa361SAndroid Build Coastguard Worker #endif
301*344aa361SAndroid Build Coastguard Worker
stdcalltest_stdcall(struct smc32_args * args)302*344aa361SAndroid Build Coastguard Worker static long stdcalltest_stdcall(struct smc32_args* args) {
303*344aa361SAndroid Build Coastguard Worker switch (args->smc_nr) {
304*344aa361SAndroid Build Coastguard Worker case SMC_SC_TEST_VERSION:
305*344aa361SAndroid Build Coastguard Worker return TRUSTY_STDCALLTEST_API_VERSION;
306*344aa361SAndroid Build Coastguard Worker case SMC_SC_TEST_SHARED_MEM_RW:
307*344aa361SAndroid Build Coastguard Worker return stdcalltest_sharedmem_rw(args->client_id, args_get_id(args),
308*344aa361SAndroid Build Coastguard Worker args_get_sz(args));
309*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
310*344aa361SAndroid Build Coastguard Worker case SMC_SC_TEST_CLOBBER_SVE: {
311*344aa361SAndroid Build Coastguard Worker return stdcalltest_clobber_sve(args);
312*344aa361SAndroid Build Coastguard Worker }
313*344aa361SAndroid Build Coastguard Worker #endif
314*344aa361SAndroid Build Coastguard Worker default:
315*344aa361SAndroid Build Coastguard Worker return SM_ERR_UNDEFINED_SMC;
316*344aa361SAndroid Build Coastguard Worker }
317*344aa361SAndroid Build Coastguard Worker }
318*344aa361SAndroid Build Coastguard Worker
stdcalltest_fastcall(struct smc32_args * args)319*344aa361SAndroid Build Coastguard Worker static long stdcalltest_fastcall(struct smc32_args* args) {
320*344aa361SAndroid Build Coastguard Worker switch (args->smc_nr) {
321*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
322*344aa361SAndroid Build Coastguard Worker case SMC_FC_TEST_CLOBBER_FPSIMD_CLOBBER:
323*344aa361SAndroid Build Coastguard Worker return stdcalltest_clobber_fpsimd_clobber(args);
324*344aa361SAndroid Build Coastguard Worker case SMC_FC_TEST_CLOBBER_FPSIMD_CHECK:
325*344aa361SAndroid Build Coastguard Worker return stdcalltest_clobber_fpsimd_check(args);
326*344aa361SAndroid Build Coastguard Worker #else
327*344aa361SAndroid Build Coastguard Worker /* This test is a no-op on other architectures, e.g., arm32 */
328*344aa361SAndroid Build Coastguard Worker case SMC_FC_TEST_CLOBBER_FPSIMD_CLOBBER:
329*344aa361SAndroid Build Coastguard Worker case SMC_FC_TEST_CLOBBER_FPSIMD_CHECK:
330*344aa361SAndroid Build Coastguard Worker return 0;
331*344aa361SAndroid Build Coastguard Worker #endif
332*344aa361SAndroid Build Coastguard Worker default:
333*344aa361SAndroid Build Coastguard Worker return SM_ERR_UNDEFINED_SMC;
334*344aa361SAndroid Build Coastguard Worker }
335*344aa361SAndroid Build Coastguard Worker }
336*344aa361SAndroid Build Coastguard Worker
337*344aa361SAndroid Build Coastguard Worker static struct smc32_entity stdcalltest_sm_entity = {
338*344aa361SAndroid Build Coastguard Worker .stdcall_handler = stdcalltest_stdcall,
339*344aa361SAndroid Build Coastguard Worker .fastcall_handler = stdcalltest_fastcall,
340*344aa361SAndroid Build Coastguard Worker };
341*344aa361SAndroid Build Coastguard Worker
stdcalltest_init(uint level)342*344aa361SAndroid Build Coastguard Worker static void stdcalltest_init(uint level) {
343*344aa361SAndroid Build Coastguard Worker int err;
344*344aa361SAndroid Build Coastguard Worker
345*344aa361SAndroid Build Coastguard Worker err = sm_register_entity(SMC_ENTITY_TEST, &stdcalltest_sm_entity);
346*344aa361SAndroid Build Coastguard Worker if (err) {
347*344aa361SAndroid Build Coastguard Worker printf("trusty error register entity: %d\n", err);
348*344aa361SAndroid Build Coastguard Worker }
349*344aa361SAndroid Build Coastguard Worker }
350*344aa361SAndroid Build Coastguard Worker LK_INIT_HOOK(stdcalltest, stdcalltest_init, LK_INIT_LEVEL_APPS);
351*344aa361SAndroid Build Coastguard Worker
352*344aa361SAndroid Build Coastguard Worker #endif
353