1 /*
2  * Copyright 2024 The Hafnium Authors.
3  *
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/BSD-3-Clause.
7  */
8 
9 #include "hf/ffa/direct_messaging.h"
10 
11 #include "hf/arch/other_world.h"
12 
13 #include "hf/ffa/init.h"
14 #include "hf/vcpu.h"
15 #include "hf/vm.h"
16 
17 /**
18  * Check validity of a FF-A direct message request.
19  */
ffa_direct_msg_is_direct_request_valid(struct vcpu * current,ffa_id_t sender_vm_id,ffa_id_t receiver_vm_id)20 bool ffa_direct_msg_is_direct_request_valid(struct vcpu *current,
21 					    ffa_id_t sender_vm_id,
22 					    ffa_id_t receiver_vm_id)
23 {
24 	ffa_id_t current_vm_id = current->vm->id;
25 
26 	/*
27 	 * The primary VM can send direct message request to
28 	 * any other VM (but itself) or SP, but can't spoof
29 	 * a different sender.
30 	 */
31 	return sender_vm_id != receiver_vm_id &&
32 	       sender_vm_id == current_vm_id && vm_is_primary(current->vm);
33 }
34 
ffa_direct_msg_is_direct_request_supported(struct vm * sender_vm,struct vm * receiver_vm,uint32_t func)35 bool ffa_direct_msg_is_direct_request_supported(struct vm *sender_vm,
36 						struct vm *receiver_vm,
37 						uint32_t func)
38 {
39 	(void)sender_vm;
40 	(void)receiver_vm;
41 	(void)func;
42 
43 	/*
44 	 * As Hypervisor is only meant to be used as a test artifact, allow
45 	 * direct messaging for all VMs.
46 	 */
47 	return true;
48 }
49 
50 /**
51  * Check validity of a FF-A direct message response.
52  */
ffa_direct_msg_is_direct_response_valid(struct vcpu * current,ffa_id_t sender_vm_id,ffa_id_t receiver_vm_id)53 bool ffa_direct_msg_is_direct_response_valid(struct vcpu *current,
54 					     ffa_id_t sender_vm_id,
55 					     ffa_id_t receiver_vm_id)
56 {
57 	ffa_id_t current_vm_id = current->vm->id;
58 
59 	/*
60 	 * Secondary VMs can send direct message responses to
61 	 * the PVM, but can't spoof a different sender.
62 	 */
63 	return sender_vm_id != receiver_vm_id &&
64 	       sender_vm_id == current_vm_id &&
65 	       receiver_vm_id == HF_PRIMARY_VM_ID;
66 }
67 
ffa_direct_msg_direct_request_forward(ffa_id_t receiver_vm_id,struct ffa_value args,struct ffa_value * ret)68 bool ffa_direct_msg_direct_request_forward(ffa_id_t receiver_vm_id,
69 					   struct ffa_value args,
70 					   struct ffa_value *ret)
71 {
72 	if (!ffa_init_is_tee_enabled()) {
73 		dlog_verbose("Not forwarding: ffa_tee_enabled is false\n");
74 		return false;
75 	}
76 
77 	/*
78 	 * VM's requests should be forwarded to the SPMC, if receiver is an SP.
79 	 */
80 	if (vm_id_is_current_world(receiver_vm_id)) {
81 		dlog_verbose(
82 			"Not forwarding: receiver VM %#x is in the same "
83 			"world\n",
84 			receiver_vm_id);
85 		return false;
86 	}
87 
88 	switch (args.func) {
89 	case FFA_MSG_SEND_DIRECT_REQ_32:
90 	case FFA_MSG_SEND_DIRECT_REQ_64:
91 		*ret = arch_other_world_call(args);
92 		break;
93 	case FFA_MSG_SEND_DIRECT_REQ2_64:
94 		*ret = arch_other_world_call_ext(args);
95 		break;
96 	default:
97 		panic("Invalid direct message function %#x\n", args.func);
98 		break;
99 	}
100 
101 	return true;
102 }
103 
ffa_direct_msg_wind_call_chain_ffa_direct_req(struct vcpu_locked current_locked,struct vcpu_locked receiver_vcpu_locked,ffa_id_t sender_vm_id)104 void ffa_direct_msg_wind_call_chain_ffa_direct_req(
105 	struct vcpu_locked current_locked,
106 	struct vcpu_locked receiver_vcpu_locked, ffa_id_t sender_vm_id)
107 {
108 	/* Calls chains not supported in the Hypervisor/VMs. */
109 	(void)current_locked;
110 	(void)receiver_vcpu_locked;
111 	(void)sender_vm_id;
112 }
113 
ffa_direct_msg_unwind_call_chain_ffa_direct_resp(struct vcpu_locked current_locked,struct vcpu_locked next_locked)114 void ffa_direct_msg_unwind_call_chain_ffa_direct_resp(
115 	struct vcpu_locked current_locked, struct vcpu_locked next_locked)
116 {
117 	/* Calls chains not supported in the Hypervisor/VMs. */
118 	(void)current_locked;
119 	(void)next_locked;
120 }
121 
ffa_direct_msg_handle_framework_msg(struct ffa_value args,struct ffa_value * ret,struct vcpu * current,struct vcpu ** next)122 bool ffa_direct_msg_handle_framework_msg(struct ffa_value args,
123 					 struct ffa_value *ret,
124 					 struct vcpu *current,
125 					 struct vcpu **next)
126 {
127 	(void)args;
128 	(void)ret;
129 	(void)current;
130 	(void)next;
131 
132 	return false;
133 }
134 
ffa_direct_msg_is_spmd_lp_id(ffa_id_t vm_id)135 bool ffa_direct_msg_is_spmd_lp_id(ffa_id_t vm_id)
136 {
137 	(void)vm_id;
138 	return false;
139 }
140 
ffa_direct_msg_handle_framework_msg_resp(struct ffa_value args,struct ffa_value * ret,struct vcpu_locked current_locked,struct vcpu ** next)141 bool ffa_direct_msg_handle_framework_msg_resp(struct ffa_value args,
142 					      struct ffa_value *ret,
143 					      struct vcpu_locked current_locked,
144 					      struct vcpu **next)
145 {
146 	(void)args;
147 	(void)ret;
148 	(void)current_locked;
149 	(void)next;
150 
151 	return false;
152 }
153