1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13 #include <linux/arm-smccc.h>
14 #include "smc_call.h"
15 #include "smc_smp.h"
16 #include "teek_ns_client.h"
17 #include "smc_abi.h"
18
19 #ifndef CONFIG_ARCH32
do_smc_transport(struct smc_in_params * in,struct smc_out_params * out,uint8_t wait)20 void do_smc_transport(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
21 {
22 isb();
23 wmb();
24 do {
25 asm volatile(
26 "mov x0, %[fid]\n"
27 "mov x1, %[a1]\n"
28 "mov x2, %[a2]\n"
29 "mov x3, %[a3]\n"
30 "mov x4, %[a4]\n"
31 "mov x5, %[a5]\n"
32 "mov x6, %[a6]\n"
33 "mov x7, %[a7]\n"
34 SMCCC_SMC_INST"\n"
35 "str x0, [%[re0]]\n"
36 "str x1, [%[re1]]\n"
37 "str x2, [%[re2]]\n"
38 "str x3, [%[re3]]\n" :
39 [fid] "+r"(in->x0),
40 [a1] "+r"(in->x1),
41 [a2] "+r"(in->x2),
42 [a3] "+r"(in->x3),
43 [a4] "+r"(in->x4),
44 [a5] "+r"(in->x5),
45 [a6] "+r"(in->x6),
46 [a7] "+r"(in->x7):
47 [re0] "r"(&out->ret),
48 [re1] "r"(&out->exit_reason),
49 [re2] "r"(&out->ta),
50 [re3] "r"(&out->target) :
51 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7");
52 } while (out->ret == TSP_REQUEST && wait != 0);
53 isb();
54 wmb();
55 }
56 #else
do_smc_transport(struct smc_in_params * in,struct smc_out_params * out,uint8_t wait)57 void do_smc_transport(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
58 {
59 isb();
60 wmb();
61 do {
62 asm volatile(
63 "mov r0, %[fid]\n"
64 "mov r1, %[a1]\n"
65 "mov r2, %[a2]\n"
66 "mov r3, %[a3]\n"
67 ".arch_extension sec\n"
68 SMCCC_SMC_INST"\n"
69 "str r0, [%[re0]]\n"
70 "str r1, [%[re1]]\n"
71 "str r2, [%[re2]]\n"
72 "str r3, [%[re3]]\n" :
73 [fid] "+r"(in->x0),
74 [a1] "+r"(in->x1),
75 [a2] "+r"(in->x2),
76 [a3] "+r"(in->x3):
77 [re0] "r"(&out->ret),
78 [re1] "r"(&out->exit_reason),
79 [re2] "r"(&out->ta),
80 [re3] "r"(&out->target) :
81 "r0", "r1", "r2", "r3");
82 } while (out->ret == TSP_REQUEST && wait != 0);
83 isb();
84 wmb();
85 }
86 #endif
87
88 #ifdef CONFIG_THIRDPARTY_COMPATIBLE
fix_params_offset(struct smc_out_params * out_param)89 static void fix_params_offset(struct smc_out_params *out_param)
90 {
91 out_param->target = out_param->ta;
92 out_param->ta = out_param->exit_reason;
93 out_param->exit_reason = out_param->ret;
94 out_param->ret = TSP_RESPONSE;
95 if (out_param->exit_reason == TEE_EXIT_REASON_CRASH) {
96 union crash_inf temp_info;
97 temp_info.crash_reg[0] = out_param->ta;
98 temp_info.crash_reg[1] = 0;
99 temp_info.crash_reg[2] = out_param->target;
100 temp_info.crash_msg.far = temp_info.crash_msg.elr;
101 temp_info.crash_msg.elr = 0;
102 out_param->ret = TSP_CRASH;
103 out_param->exit_reason = temp_info.crash_reg[0];
104 out_param->ta = temp_info.crash_reg[1];
105 out_param->target = temp_info.crash_reg[2];
106 }
107 }
108 #endif
109
smc_req(struct smc_in_params * in,struct smc_out_params * out,uint8_t wait)110 void smc_req(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
111 {
112 do_smc_transport(in, out, wait);
113 #ifdef CONFIG_THIRDPARTY_COMPATIBLE
114 fix_params_offset(out);
115 #endif
116 }
117