3d157be8创建于 2023年12月27日历史提交
/*
 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */
#include <linux/arm-smccc.h>
#include "smc_call.h"
#include "smc_smp.h"
#include "teek_ns_client.h"
#include "smc_abi.h"

#ifndef CONFIG_ARCH32
void do_smc_transport(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
{
	isb();
	wmb();
	do {
		asm volatile(
			"mov x0, %[fid]\n"
			"mov x1, %[a1]\n"
			"mov x2, %[a2]\n"
			"mov x3, %[a3]\n"
			"mov x4, %[a4]\n"
			"mov x5, %[a5]\n"
			"mov x6, %[a6]\n"
			"mov x7, %[a7]\n"
			SMCCC_SMC_INST"\n"
			"str x0, [%[re0]]\n"
			"str x1, [%[re1]]\n"
			"str x2, [%[re2]]\n"
			"str x3, [%[re3]]\n" :
			[fid] "+r"(in->x0),
			[a1] "+r"(in->x1),
			[a2] "+r"(in->x2),
			[a3] "+r"(in->x3),
			[a4] "+r"(in->x4),
			[a5] "+r"(in->x5),
			[a6] "+r"(in->x6),
			[a7] "+r"(in->x7):
			[re0] "r"(&out->ret),
			[re1] "r"(&out->exit_reason),
			[re2] "r"(&out->ta),
			[re3] "r"(&out->target) :
			"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7");
	} while (out->ret == TSP_REQUEST && wait != 0);
	isb();
	wmb();
}
#else
void do_smc_transport(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
{
	isb();
	wmb();
	do {
		asm volatile(
			"mov r0, %[fid]\n"
			"mov r1, %[a1]\n"
			"mov r2, %[a2]\n"
			"mov r3, %[a3]\n"
			".arch_extension sec\n"
			SMCCC_SMC_INST"\n"
			"str r0, [%[re0]]\n"
			"str r1, [%[re1]]\n"
			"str r2, [%[re2]]\n"
			"str r3, [%[re3]]\n" :
			[fid] "+r"(in->x0),
			[a1] "+r"(in->x1),
			[a2] "+r"(in->x2),
			[a3] "+r"(in->x3):
			[re0] "r"(&out->ret),
			[re1] "r"(&out->exit_reason),
			[re2] "r"(&out->ta),
			[re3] "r"(&out->target) :
			"r0", "r1", "r2", "r3");
	} while (out->ret == TSP_REQUEST && wait != 0);
	isb();
	wmb();
}
#endif

#ifdef CONFIG_THIRDPARTY_COMPATIBLE
static void fix_params_offset(struct smc_out_params *out_param)
{
	out_param->target = out_param->ta;
	out_param->ta = out_param->exit_reason;
	out_param->exit_reason = out_param->ret;
	out_param->ret = TSP_RESPONSE;
	if (out_param->exit_reason == TEE_EXIT_REASON_CRASH) {
		union crash_inf temp_info;
		temp_info.crash_reg[0] = out_param->ta;
		temp_info.crash_reg[1] = 0;
		temp_info.crash_reg[2] = out_param->target;
		temp_info.crash_msg.far = temp_info.crash_msg.elr;
		temp_info.crash_msg.elr = 0;
		out_param->ret = TSP_CRASH;
		out_param->exit_reason = temp_info.crash_reg[0];
		out_param->ta = temp_info.crash_reg[1];
		out_param->target = temp_info.crash_reg[2];
	}
}
#endif

void smc_req(struct smc_in_params *in, struct smc_out_params *out, uint8_t wait)
{
	do_smc_transport(in, out, wait);
#ifdef CONFIG_THIRDPARTY_COMPATIBLE
	fix_params_offset(out);
#endif
}