1 /* 2 * Copyright 2018 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 #pragma once 10 11 #include <stdatomic.h> 12 13 #include "hf/arch/types.h" 14 15 #include "hf/cpu.h" 16 #include "hf/interrupt_desc.h" 17 #include "hf/list.h" 18 #include "hf/mm.h" 19 #include "hf/mpool.h" 20 21 #include "vmapi/hf/ffa.h" 22 23 #define MAX_SMCS 32 24 #define LOG_BUFFER_SIZE 256 25 #define VM_MANIFEST_MAX_INTERRUPTS 32 26 27 /** 28 * The state of an RX buffer. 29 * 30 * EMPTY is the initial state. The follow state transitions are possible: 31 * * EMPTY => RECEIVED: message sent to the VM. 32 * * RECEIVED => READ: secondary VM receives an RX buffer full notification 33 * or primary VM returns from FFA_RUN with an FFA_MSG_SEND where the receiver 34 * is itself. 35 * * READ => EMPTY: VM called FFA_RX_RELEASE. 36 */ 37 enum mailbox_state { 38 /** There is no message in the mailbox. */ 39 MAILBOX_STATE_EMPTY, 40 41 /** There is a message in the mailbox that is waiting for a reader. */ 42 MAILBOX_STATE_RECEIVED, 43 44 /** There is a message in the mailbox that has been read. */ 45 MAILBOX_STATE_READ, 46 }; 47 48 struct wait_entry { 49 /** The VM that is waiting for a mailbox to become writable. */ 50 struct vm *waiting_vm; 51 52 /** 53 * Links used to add entry to a VM's waiter_list. This is protected by 54 * the notifying VM's lock. 55 */ 56 struct list_entry wait_links; 57 58 /** 59 * Links used to add entry to a VM's ready_list. This is protected by 60 * the waiting VM's lock. 61 */ 62 struct list_entry ready_links; 63 }; 64 65 struct mailbox { 66 enum mailbox_state state; 67 void *recv; 68 const void *send; 69 70 /** The ID of the VM which sent the message currently in `recv`. */ 71 ffa_vm_id_t recv_sender; 72 73 /** The size of the message currently in `recv`. */ 74 uint32_t recv_size; 75 76 /** 77 * The FF-A function ID to use to deliver the message currently in 78 * `recv`. 79 */ 80 uint32_t recv_func; 81 82 /** 83 * List of wait_entry structs representing VMs that want to be notified 84 * when the mailbox becomes writable. Once the mailbox does become 85 * writable, the entry is removed from this list and added to the 86 * waiting VM's ready_list. 87 */ 88 struct list_entry waiter_list; 89 90 /** 91 * List of wait_entry structs representing VMs whose mailboxes became 92 * writable since the owner of the mailbox registers for notification. 93 */ 94 struct list_entry ready_list; 95 }; 96 97 struct notifications_state { 98 /** 99 * To keep track of the notifications pending. 100 * Set on call to FFA_NOTIFICATION_SET, and cleared on call to 101 * FFA_NOTIFICATION_GET. 102 */ 103 ffa_notifications_bitmap_t pending; 104 105 /** 106 * Set on FFA_NOTIFICATION_INFO_GET to keep track of the notifications 107 * whose information has been retrieved by the referred ABI. 108 * Cleared on call to FFA_NOTIFICATION_GET. 109 */ 110 ffa_notifications_bitmap_t info_get_retrieved; 111 }; 112 113 struct notifications { 114 /** 115 * The following array maps the notifications to the bound FF-A 116 * endpoint. 117 * The index in the bindings array relates to the notification 118 * ID, and bit position in 'ffa_notifications_bitmap_t'. 119 */ 120 ffa_vm_id_t bindings_sender_id[MAX_FFA_NOTIFICATIONS]; 121 ffa_notifications_bitmap_t bindings_per_vcpu; 122 123 /* The index of the array below relates to the ID of the VCPU. 124 * This is a dynamically allocated array of struct 125 * notifications_state and has as many entries as vcpu_count. 126 */ 127 struct notifications_state *per_vcpu; 128 struct notifications_state global; 129 }; 130 131 /** 132 * The following enum relates to a state machine to guide the insertion of 133 * IDs in the respective list as a result of a FFA_NOTIFICATION_INFO_GET call. 134 * As per the FF-A v1.1 specification, the return of the interface 135 * FFA_NOTIFICATION_INFO_GET, is a list of 16-bit values, regarding the VM ID 136 * and VCPU IDs of those with pending notifications. 137 * The overall list, is composed of "sub-lists", that starts with the VM ID, and 138 * can follow with up to 3 more VCPU IDs. A VM can have multiple 'sub-lists'. 139 * The states are traversed on a per VM basis, and should help with filling the 140 * list of IDs. 141 * 142 * INIT is the initial state. The following state transitions are possible: 143 * * INIT => INSERTING: no list has been created for the VM prior. There are 144 * notifications pending and VM ID should be inserted first. If it regards to 145 * a per VCPU notification the VCPU ID should follow. Only VCPU IDs should be 146 * inserted from this point, until reaching "sub-list" size limit. 147 * * INIT => FULL: There is no space in the ID list to insert IDs. 148 * * INSERTING => STARTING_NEW: list has been created. Adding only VCPU IDs, 149 * however "sub-list" limit has been reached. If there are more pending per VCPU 150 * notifications pending for the VM, a new list should be created starting with 151 * VM ID. 152 * * INSERTING => FULL: There is no space in the ID list to insert IDs. 153 * * STARTING_NEW => INSERTING: Started a new 'sub-list' for the given VM, for 154 * the remaining pending per VCPU notifications, only the VCPU ID should be 155 * inserted. 156 * * STARTING_NEW => FULL: There is no space in the ID list to insert IDs. 157 */ 158 enum notifications_info_get_state { 159 INIT, 160 INSERTING, 161 STARTING_NEW, 162 FULL, 163 }; 164 165 struct smc_whitelist { 166 uint32_t smcs[MAX_SMCS]; 167 uint16_t smc_count; 168 bool permissive; 169 }; 170 171 struct vm { 172 ffa_vm_id_t id; 173 struct ffa_uuid uuid; 174 uint32_t ffa_version; 175 struct smc_whitelist smc_whitelist; 176 177 /** See api.c for the partial ordering on locks. */ 178 struct spinlock lock; 179 ffa_vcpu_count_t vcpu_count; 180 struct vcpu *vcpus; 181 struct mm_ptable ptable; 182 struct mailbox mailbox; 183 184 struct { 185 /** 186 * State structures for notifications coming from VMs or coming 187 * from SPs. Both fields are maintained by the SPMC. 188 * The hypervisor ignores the 'from_sp' field, given VM 189 * notifications from SPs are managed by the SPMC. 190 */ 191 struct notifications from_vm; 192 struct notifications from_sp; 193 struct notifications_state framework; 194 bool enabled; 195 bool npi_injected; 196 } notifications; 197 198 char log_buffer[LOG_BUFFER_SIZE]; 199 uint16_t log_buffer_length; 200 201 /** 202 * Wait entries to be used when waiting on other VM mailboxes. See 203 * comments on `struct wait_entry` for the lock discipline of these. 204 */ 205 struct wait_entry wait_entries[MAX_VMS]; 206 207 atomic_bool aborting; 208 209 /** 210 * Booting parameters (FF-A SP partitions). 211 */ 212 bool initialized; 213 uint16_t boot_order; 214 215 /** Entries to pass boot data to the VM. */ 216 struct { 217 uint32_t gp_register_num; 218 ipaddr_t blob_addr; 219 } boot_info; 220 221 uint8_t messaging_method; 222 223 /** 224 * Action specified by a Partition through the manifest in response to 225 * non secure interrupt. 226 */ 227 uint8_t ns_interrupts_action; 228 bool me_signal_virq; 229 struct vm *next_boot; 230 231 /** 232 * Secondary entry point supplied by FFA_SECONDARY_EP_REGISTER used 233 * for cold and warm boot of SP execution contexts. 234 */ 235 ipaddr_t secondary_ep; 236 237 /** Arch-specific VM information. */ 238 struct arch_vm arch; 239 bool el0_partition; 240 241 /** Interrupt descriptor */ 242 struct interrupt_descriptor interrupt_desc[VM_MANIFEST_MAX_INTERRUPTS]; 243 }; 244 245 /** Encapsulates a VM whose lock is held. */ 246 struct vm_locked { 247 struct vm *vm; 248 }; 249 250 /** Container for two vm_locked structures */ 251 struct two_vm_locked { 252 struct vm_locked vm1; 253 struct vm_locked vm2; 254 }; 255 256 struct vm *vm_init(ffa_vm_id_t id, ffa_vcpu_count_t vcpu_count, 257 struct mpool *ppool, bool el0_partition); 258 bool vm_init_next(ffa_vcpu_count_t vcpu_count, struct mpool *ppool, 259 struct vm **new_vm, bool el0_partition); 260 ffa_vm_count_t vm_get_count(void); 261 struct vm *vm_find(ffa_vm_id_t id); 262 struct vm_locked vm_find_locked(ffa_vm_id_t id); 263 struct vm *vm_find_index(uint16_t index); 264 struct vm_locked vm_lock(struct vm *vm); 265 struct two_vm_locked vm_lock_both(struct vm *vm1, struct vm *vm2); 266 void vm_unlock(struct vm_locked *locked); 267 struct vcpu *vm_get_vcpu(struct vm *vm, ffa_vcpu_index_t vcpu_index); 268 struct wait_entry *vm_get_wait_entry(struct vm *vm, ffa_vm_id_t for_vm); 269 ffa_vm_id_t vm_id_for_wait_entry(struct vm *vm, struct wait_entry *entry); 270 bool vm_id_is_current_world(ffa_vm_id_t vm_id); 271 272 bool vm_identity_map(struct vm_locked vm_locked, paddr_t begin, paddr_t end, 273 uint32_t mode, struct mpool *ppool, ipaddr_t *ipa); 274 bool vm_identity_prepare(struct vm_locked vm_locked, paddr_t begin, paddr_t end, 275 uint32_t mode, struct mpool *ppool); 276 void vm_identity_commit(struct vm_locked vm_locked, paddr_t begin, paddr_t end, 277 uint32_t mode, struct mpool *ppool, ipaddr_t *ipa); 278 bool vm_unmap(struct vm_locked vm_locked, paddr_t begin, paddr_t end, 279 struct mpool *ppool); 280 void vm_ptable_defrag(struct vm_locked vm_locked, struct mpool *ppool); 281 bool vm_unmap_hypervisor(struct vm_locked vm_locked, struct mpool *ppool); 282 283 void vm_update_boot(struct vm *vm); 284 struct vm *vm_get_first_boot(void); 285 286 bool vm_mem_get_mode(struct vm_locked vm_locked, ipaddr_t begin, ipaddr_t end, 287 uint32_t *mode); 288 289 void vm_notifications_init(struct vm *vm, ffa_vcpu_count_t vcpu_count, 290 struct mpool *ppool); 291 bool vm_are_notifications_pending(struct vm_locked vm_locked, bool from_vm, 292 ffa_notifications_bitmap_t notifications); 293 bool vm_are_global_notifications_pending(struct vm_locked vm_locked); 294 bool vm_are_per_vcpu_notifications_pending(struct vm_locked vm_locked, 295 ffa_vcpu_index_t vcpu_id); 296 bool vm_are_notifications_enabled(struct vm *vm); 297 bool vm_locked_are_notifications_enabled(struct vm_locked vm_locked); 298 bool vm_notifications_validate_per_vcpu(struct vm_locked vm_locked, 299 bool is_from_vm, bool is_per_vcpu, 300 ffa_notifications_bitmap_t notif); 301 bool vm_notifications_validate_bound_sender( 302 struct vm_locked vm_locked, bool is_from_vm, ffa_vm_id_t sender_id, 303 ffa_notifications_bitmap_t notifications); 304 bool vm_notifications_validate_binding(struct vm_locked vm_locked, 305 bool is_from_vm, ffa_vm_id_t sender_id, 306 ffa_notifications_bitmap_t notifications, 307 bool is_per_vcpu); 308 void vm_notifications_update_bindings(struct vm_locked vm_locked, 309 bool is_from_vm, ffa_vm_id_t sender_id, 310 ffa_notifications_bitmap_t notifications, 311 bool is_per_vcpu); 312 void vm_notifications_partition_set_pending( 313 struct vm_locked vm_locked, bool is_from_vm, 314 ffa_notifications_bitmap_t notifications, ffa_vcpu_index_t vcpu_id, 315 bool is_per_vcpu); 316 ffa_notifications_bitmap_t vm_notifications_partition_get_pending( 317 struct vm_locked vm_locked, bool is_from_vm, ffa_vcpu_index_t vcpu_id); 318 void vm_notifications_framework_set_pending( 319 struct vm_locked vm_locked, ffa_notifications_bitmap_t notifications); 320 ffa_notifications_bitmap_t vm_notifications_framework_get_pending( 321 struct vm_locked vm_locked); 322 void vm_notifications_info_get_pending( 323 struct vm_locked vm_locked, bool is_from_vm, uint16_t *ids, 324 uint32_t *ids_count, uint32_t *lists_sizes, uint32_t *lists_count, 325 const uint32_t ids_max_count, 326 enum notifications_info_get_state *info_get_state); 327 bool vm_notifications_pending_not_retrieved_by_scheduler(void); 328 bool vm_is_notifications_pending_count_zero(void); 329 bool vm_notifications_info_get(struct vm_locked vm_locked, uint16_t *ids, 330 uint32_t *ids_count, uint32_t *lists_sizes, 331 uint32_t *lists_count, 332 const uint32_t ids_max_count); 333 bool vm_supports_messaging_method(struct vm *vm, uint8_t messaging_method); 334 void vm_notifications_set_npi_injected(struct vm_locked vm_locked, 335 bool npi_injected); 336 bool vm_notifications_is_npi_injected(struct vm_locked vm_locked); 337 void vm_set_boot_info_gp_reg(struct vm *vm, struct vcpu *vcpu); 338