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