xref: /openbmc/linux/arch/arm64/kvm/hyp/nvhe/ffa.c (revision 048be5fe)
1*048be5feSWill Deacon // SPDX-License-Identifier: GPL-2.0-only
2*048be5feSWill Deacon /*
3*048be5feSWill Deacon  * FF-A v1.0 proxy to filter out invalid memory-sharing SMC calls issued by
4*048be5feSWill Deacon  * the host. FF-A is a slightly more palatable abbreviation of "Arm Firmware
5*048be5feSWill Deacon  * Framework for Arm A-profile", which is specified by Arm in document
6*048be5feSWill Deacon  * number DEN0077.
7*048be5feSWill Deacon  *
8*048be5feSWill Deacon  * Copyright (C) 2022 - Google LLC
9*048be5feSWill Deacon  * Author: Andrew Walbran <qwandor@google.com>
10*048be5feSWill Deacon  *
11*048be5feSWill Deacon  * This driver hooks into the SMC trapping logic for the host and intercepts
12*048be5feSWill Deacon  * all calls falling within the FF-A range. Each call is either:
13*048be5feSWill Deacon  *
14*048be5feSWill Deacon  *	- Forwarded on unmodified to the SPMD at EL3
15*048be5feSWill Deacon  *	- Rejected as "unsupported"
16*048be5feSWill Deacon  *	- Accompanied by a host stage-2 page-table check/update and reissued
17*048be5feSWill Deacon  *
18*048be5feSWill Deacon  * Consequently, any attempts by the host to make guest memory pages
19*048be5feSWill Deacon  * accessible to the secure world using FF-A will be detected either here
20*048be5feSWill Deacon  * (in the case that the memory is already owned by the guest) or during
21*048be5feSWill Deacon  * donation to the guest (in the case that the memory was previously shared
22*048be5feSWill Deacon  * with the secure world).
23*048be5feSWill Deacon  *
24*048be5feSWill Deacon  * To allow the rolling-back of page-table updates and FF-A calls in the
25*048be5feSWill Deacon  * event of failure, operations involving the RXTX buffers are locked for
26*048be5feSWill Deacon  * the duration and are therefore serialised.
27*048be5feSWill Deacon  */
28*048be5feSWill Deacon 
29*048be5feSWill Deacon #include <linux/arm-smccc.h>
30*048be5feSWill Deacon #include <linux/arm_ffa.h>
31*048be5feSWill Deacon #include <nvhe/ffa.h>
32*048be5feSWill Deacon #include <nvhe/trap_handler.h>
33*048be5feSWill Deacon 
34*048be5feSWill Deacon static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
35*048be5feSWill Deacon {
36*048be5feSWill Deacon 	*res = (struct arm_smccc_res) {
37*048be5feSWill Deacon 		.a0	= FFA_ERROR,
38*048be5feSWill Deacon 		.a2	= ffa_errno,
39*048be5feSWill Deacon 	};
40*048be5feSWill Deacon }
41*048be5feSWill Deacon 
42*048be5feSWill Deacon static void ffa_set_retval(struct kvm_cpu_context *ctxt,
43*048be5feSWill Deacon 			   struct arm_smccc_res *res)
44*048be5feSWill Deacon {
45*048be5feSWill Deacon 	cpu_reg(ctxt, 0) = res->a0;
46*048be5feSWill Deacon 	cpu_reg(ctxt, 1) = res->a1;
47*048be5feSWill Deacon 	cpu_reg(ctxt, 2) = res->a2;
48*048be5feSWill Deacon 	cpu_reg(ctxt, 3) = res->a3;
49*048be5feSWill Deacon }
50*048be5feSWill Deacon 
51*048be5feSWill Deacon static bool is_ffa_call(u64 func_id)
52*048be5feSWill Deacon {
53*048be5feSWill Deacon 	return ARM_SMCCC_IS_FAST_CALL(func_id) &&
54*048be5feSWill Deacon 	       ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD &&
55*048be5feSWill Deacon 	       ARM_SMCCC_FUNC_NUM(func_id) >= FFA_MIN_FUNC_NUM &&
56*048be5feSWill Deacon 	       ARM_SMCCC_FUNC_NUM(func_id) <= FFA_MAX_FUNC_NUM;
57*048be5feSWill Deacon }
58*048be5feSWill Deacon 
59*048be5feSWill Deacon /*
60*048be5feSWill Deacon  * Is a given FFA function supported, either by forwarding on directly
61*048be5feSWill Deacon  * or by handling at EL2?
62*048be5feSWill Deacon  */
63*048be5feSWill Deacon static bool ffa_call_supported(u64 func_id)
64*048be5feSWill Deacon {
65*048be5feSWill Deacon 	switch (func_id) {
66*048be5feSWill Deacon 	/* Unsupported memory management calls */
67*048be5feSWill Deacon 	case FFA_FN64_MEM_RETRIEVE_REQ:
68*048be5feSWill Deacon 	case FFA_MEM_RETRIEVE_RESP:
69*048be5feSWill Deacon 	case FFA_MEM_RELINQUISH:
70*048be5feSWill Deacon 	case FFA_MEM_OP_PAUSE:
71*048be5feSWill Deacon 	case FFA_MEM_OP_RESUME:
72*048be5feSWill Deacon 	case FFA_MEM_FRAG_RX:
73*048be5feSWill Deacon 	case FFA_FN64_MEM_DONATE:
74*048be5feSWill Deacon 	/* Indirect message passing via RX/TX buffers */
75*048be5feSWill Deacon 	case FFA_MSG_SEND:
76*048be5feSWill Deacon 	case FFA_MSG_POLL:
77*048be5feSWill Deacon 	case FFA_MSG_WAIT:
78*048be5feSWill Deacon 	/* 32-bit variants of 64-bit calls */
79*048be5feSWill Deacon 	case FFA_MSG_SEND_DIRECT_REQ:
80*048be5feSWill Deacon 	case FFA_MSG_SEND_DIRECT_RESP:
81*048be5feSWill Deacon 	case FFA_RXTX_MAP:
82*048be5feSWill Deacon 	case FFA_MEM_DONATE:
83*048be5feSWill Deacon 	case FFA_MEM_RETRIEVE_REQ:
84*048be5feSWill Deacon 	/* Don't advertise any features just yet */
85*048be5feSWill Deacon 	case FFA_FEATURES:
86*048be5feSWill Deacon 		return false;
87*048be5feSWill Deacon 	}
88*048be5feSWill Deacon 
89*048be5feSWill Deacon 	return true;
90*048be5feSWill Deacon }
91*048be5feSWill Deacon 
92*048be5feSWill Deacon bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
93*048be5feSWill Deacon {
94*048be5feSWill Deacon 	DECLARE_REG(u64, func_id, host_ctxt, 0);
95*048be5feSWill Deacon 	struct arm_smccc_res res;
96*048be5feSWill Deacon 
97*048be5feSWill Deacon 	/*
98*048be5feSWill Deacon 	 * There's no way we can tell what a non-standard SMC call might
99*048be5feSWill Deacon 	 * be up to. Ideally, we would terminate these here and return
100*048be5feSWill Deacon 	 * an error to the host, but sadly devices make use of custom
101*048be5feSWill Deacon 	 * firmware calls for things like power management, debugging,
102*048be5feSWill Deacon 	 * RNG access and crash reporting.
103*048be5feSWill Deacon 	 *
104*048be5feSWill Deacon 	 * Given that the architecture requires us to trust EL3 anyway,
105*048be5feSWill Deacon 	 * we forward unrecognised calls on under the assumption that
106*048be5feSWill Deacon 	 * the firmware doesn't expose a mechanism to access arbitrary
107*048be5feSWill Deacon 	 * non-secure memory. Short of a per-device table of SMCs, this
108*048be5feSWill Deacon 	 * is the best we can do.
109*048be5feSWill Deacon 	 */
110*048be5feSWill Deacon 	if (!is_ffa_call(func_id))
111*048be5feSWill Deacon 		return false;
112*048be5feSWill Deacon 
113*048be5feSWill Deacon 	if (ffa_call_supported(func_id))
114*048be5feSWill Deacon 		return false; /* Pass through */
115*048be5feSWill Deacon 
116*048be5feSWill Deacon 	ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED);
117*048be5feSWill Deacon 	ffa_set_retval(host_ctxt, &res);
118*048be5feSWill Deacon 	return true;
119*048be5feSWill Deacon }
120