1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @file hypercall.h
9  *
10  * @brief public APIs for hypercall
11  */
12 
13 #ifndef HYPERCALL_H
14 #define HYPERCALL_H
15 
16 bool is_hypercall_from_ring0(void);
17 
18 /**
19  * @brief Hypercall
20  *
21  * @addtogroup acrn_hypercall ACRN Hypercall
22  * @{
23  */
24 
25 /**
26  * @brief offline vcpu from Service VM
27  *
28  * The function offline specific vcpu from Service VM.
29  *
30  * @param vcpu Pointer to vCPU that initiates the hypercall
31  * @param target_vm not used
32  * @param param1 lapic id of the vcpu which wants to offline
33  * @param param2 not used
34  *
35  * @pre is_service_vm(vcpu->vm)
36  * @return 0 on success, non-zero on error.
37  */
38 int32_t hcall_service_vm_offline_cpu(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
39 
40 /**
41  * @brief Get hypervisor api version
42  *
43  * The function only return api version information when VM is Service VM.
44  *
45  * @param vcpu Pointer to vCPU that initiates the hypercall
46  * @param target_vm not used
47  * @param param1 guest physical memory address. The api version returned
48  *              will be copied to this gpa
49  * @param param2 not used
50  *
51  * @pre is_service_vm(vcpu->vm)
52  * @return 0 on success, non-zero on error.
53  */
54 int32_t hcall_get_api_version(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
55 
56 
57 /**
58  * @brief create virtual machine
59  *
60  * Create a virtual machine based on parameter, currently there is no
61  * limitation for calling times of this function, will add MAX_VM_NUM
62  * support later.
63  *
64  * @param vcpu Pointer to vCPU that initiates the hypercall
65  * @param target_vm Pointer to target VM data structure
66  * @param param1 guest physical memory address. This gpa points to
67  *              struct acrn_vm_creation
68  * @param param2 not used
69  *
70  * @pre is_service_vm(vcpu->vm)
71  * @return 0 on success, non-zero on error.
72  */
73 int32_t hcall_create_vm(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
74 
75 /**
76  * @brief destroy virtual machine
77  *
78  * Destroy a virtual machine, it will pause target VM then shutdown it.
79  * The function will return -1 if the target VM does not exist.
80  *
81  * @param vcpu not used
82  * @param target_vm Pointer to target VM data structure
83  * @param param1 not used
84  * @param param2 not used
85  *
86  * @return 0 on success, non-zero on error.
87  */
88 int32_t hcall_destroy_vm(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
89 
90 /**
91  * @brief reset virtual machine
92  *
93  * Reset a virtual machine, it will make target VM rerun from
94  * pre-defined entry. Comparing to start vm, this function reset
95  * each vcpu state and do some initialization for guest.
96  * The function will return -1 if the target VM does not exist.
97  *
98  * @param vcpu not used
99  * @param target_vm Pointer to target VM data structure
100  * @param param1 not used
101  * @param param2 not used
102  *
103  * @return 0 on success, non-zero on error.
104  */
105 int32_t hcall_reset_vm(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
106 
107 /**
108  * @brief start virtual machine
109  *
110  * Start a virtual machine, it will schedule target VM's vcpu to run.
111  * The function will return -1 if the target VM does not exist or the
112  * IOReq buffer page for the VM is not ready.
113  *
114  * @param vcpu not used
115  * @param target_vm Pointer to target VM data structure
116  * @param param1 not used
117  * @param param2 not used
118  *
119  * @return 0 on success, non-zero on error.
120  */
121 int32_t hcall_start_vm(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
122 
123 /**
124  * @brief pause virtual machine
125  *
126  * Pause a virtual machine, if the VM is already paused, the function
127  * will return 0 directly for success.
128  * The function will return -1 if the target VM does not exist.
129  *
130  * @param vcpu not used
131  * @param target_vm Pointer to target VM data structure
132  * @param param1 not used
133  * @param param2 not used
134  *
135  * @return 0 on success, non-zero on error.
136  */
137 int32_t hcall_pause_vm(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
138 
139 /**
140  * @brief set vcpu regs
141  *
142  * Set the vcpu regs. It will set the vcpu init regs from DM. Now,
143  * it's only applied to BSP. AP always uses fixed init regs.
144  * The function will return -1 if the targat VM or BSP doesn't exist.
145  *
146  * @param vcpu Pointer to vCPU that initiates the hypercall
147  * @param target_vm Pointer to target VM data structure
148  * @param param1 not used
149  * @param param2 guest physical address. This gpa points to
150  *              struct acrn_vcpu_regs
151  *
152  * @return 0 on success, non-zero on error.
153  */
154 int32_t hcall_set_vcpu_regs(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
155 
156 /**
157  * @brief set or clear IRQ line
158  *
159  * Set or clear a virtual IRQ line for a VM, which could be from ISA
160  * or IOAPIC, normally it triggers an edge IRQ.
161  * The function will return -1 if the target VM does not exist.
162  *
163  * @param vcpu Pointer to vCPU that initiates the hypercall
164  * @param target_vm Pointer to target VM data structure
165  * @param param1 not used
166  * @param param2 info for irqline
167  *
168  * @pre is_service_vm(vcpu->vm)
169  * @return 0 on success, non-zero on error.
170  */
171 int32_t hcall_set_irqline(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
172 
173 /**
174  * @brief inject MSI interrupt
175  *
176  * Inject a MSI interrupt for a VM.
177  * The function will return -1 if the target VM does not exist.
178  *
179  * @param vcpu Pointer to vCPU that initiates the hypercall
180  * @param target_vm Pointer to target VM data structure
181  * @param param1 not used
182  * @param param2 guest physical address. This gpa points to struct acrn_msi_entry
183  *
184  * @pre is_service_vm(vcpu->vm)
185  * @return 0 on success, non-zero on error.
186  */
187 int32_t hcall_inject_msi(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
188 
189 /**
190  * @brief set ioreq shared buffer
191  *
192  * Set the ioreq share buffer for a VM.
193  * The function will return -1 if the target VM does not exist.
194  *
195  * @param vcpu Pointer to vCPU that initiates the hypercall
196  * @param target_vm Pointer to target VM data structure
197  * @param param1 not used
198  * @param param2 guest physical address. This gpa points to buffer address
199  *
200  * @pre is_service_vm(vcpu->vm)
201  * @return 0 on success, non-zero on error.
202  */
203 int32_t hcall_set_ioreq_buffer(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
204 
205 /**
206  * @brief notify request done
207  *
208  * Notify the requestor VCPU for the completion of an ioreq.
209  * The function will return -1 if the target VM does not exist.
210  *
211  * @param vcpu not used
212  * @param target_vm Pointer to target VM data structure
213  * @param param1 not used
214  * @param param2 vcpu ID of the requestor
215  *
216  * @return 0 on success, non-zero on error.
217  */
218 int32_t hcall_notify_ioreq_finish(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
219 
220 /**
221  * @brief setup ept memory mapping for multi regions
222  *
223  * @param vcpu Pointer to vCPU that initiates the hypercall
224  * @param target_vm Pointer to target VM data structure
225  * @param param1 guest physical address. This gpa points to
226  *              struct set_memmaps
227  * @param param2 not used
228  *
229  * @pre is_service_vm(vcpu->vm)
230  * @return 0 on success, non-zero on error.
231  */
232 int32_t hcall_set_vm_memory_regions(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
233 		uint64_t param1, uint64_t param2);
234 
235 /**
236  * @brief change guest memory page write permission
237  *
238  * @param vcpu Pointer to vCPU that initiates the hypercall
239  * @param target_vm Pointer to target VM data structure
240  * @param param1 not used
241  * @param param2 guest physical address. This gpa points to
242  *              struct wp_data
243  *
244  * @pre is_service_vm(vcpu->vm)
245  * @return 0 on success, non-zero on error.
246  */
247 int32_t hcall_write_protect_page(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
248 
249 /**
250  * @brief translate guest physical address to host physical address
251  *
252  * Translate guest physical address to host physical address for a VM.
253  * The function will return -1 if the target VM does not exist.
254  *
255  * @param vcpu Pointer to vCPU that initiates the hypercall
256  * @param target_vm Pointer to target VM data structure
257  * @param param1 not used
258  * @param param2 guest physical address. This gpa points to struct vm_gpa2hpa
259  *
260  * @pre is_service_vm(vcpu->vm)
261  * @return 0 on success, non-zero on error.
262  */
263 int32_t hcall_gpa_to_hpa(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
264 
265 /**
266  * @brief Assign one PCI dev to VM.
267  *
268  * @param vcpu Pointer to vCPU that initiates the hypercall
269  * @param target_vm Pointer to target VM data structure
270  * @param param1 not used
271  * @param param2 guest physical address. This gpa points to data structure of
272  *              acrn_pcidev including assign PCI device info
273  *
274  * @pre is_service_vm(vcpu->vm)
275  * @return 0 on success, non-zero on error.
276  */
277 int32_t hcall_assign_pcidev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
278 
279 /**
280  * @brief Deassign one PCI dev to VM.
281  *
282  * @param vcpu Pointer to vCPU that initiates the hypercall
283  * @param target_vm Pointer to target VM data structure
284  * @param param1 not used
285  * @param param2 guest physical address. This gpa points to data structure of
286  *              acrn_pcidev including deassign PCI device info
287  *
288  * @pre is_service_vm(vcpu->vm)
289  * @return 0 on success, non-zero on error.
290  */
291 int32_t hcall_deassign_pcidev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
292 
293 /**
294  * @brief Assign one MMIO dev to VM.
295  *
296  * @param vcpu Pointer to vCPU that initiates the hypercall
297  * @param target_vm Pointer to target VM data structure
298  * @param param1 not used
299  * @param param2 guest physical address. This gpa points to data structure of
300  *              acrn_mmiodev including assign MMIO device info
301  *
302  * @pre is_service_vm(vcpu->vm)
303  * @return 0 on success, non-zero on error.
304  */
305 int32_t hcall_assign_mmiodev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
306 
307 /**
308  * @brief Deassign one MMIO dev to VM.
309  *
310  * @param vcpu Pointer to vCPU that initiates the hypercall
311  * @param target_vm Pointer to target VM data structure
312  * @param param1 not used
313  * @param param2 guest physical address. This gpa points to data structure of
314  *              acrn_mmiodev including deassign MMIO device info
315  *
316  * @pre is_service_vm(vcpu->vm)
317  * @return 0 on success, non-zero on error.
318  */
319 int32_t hcall_deassign_mmiodev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
320 
321 /**
322  * @brief Add an emulated device in hypervisor.
323  *
324  * @param vcpu Pointer to vCPU that initiates the hypercall
325  * @param target_vm Pointer to target VM data structure
326  * @param param1 not used
327  * @param param2 guest physical address. This gpa points to data structure of
328  *              acrn_vdev including information about PCI or legacy devices
329  *
330  * @pre is_service_vm(vcpu->vm)
331  * @return 0 on success, non-zero on error.
332  */
333 int32_t hcall_add_vdev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
334 
335 /**
336  * @brief Remove an emulated device in hypervisor.
337  *
338  * @param vcpu Pointer to vCPU that initiates the hypercall
339  * @param target_vm Pointer to target VM data structure
340  * @param param1 not used
341  * @param param2 guest physical address. This gpa points to data structure of
342  *              acrn_vdev including information about PCI or legacy devices
343  *
344  * @pre is_service_vm(vcpu->vm)
345  * @return 0 on success, non-zero on error.
346  */
347 int32_t hcall_remove_vdev(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
348 
349 /**
350  * @brief Set interrupt mapping info of ptdev.
351  *
352  * @param vcpu Pointer to vCPU that initiates the hypercall
353  * @param target_vm Pointer to target VM data structure
354  * @param param1 not used
355  * @param param2 guest physical address. This gpa points to data structure of
356  *              hc_ptdev_irq including intr remapping info
357  *
358  * @pre is_service_vm(vcpu->vm)
359  * @return 0 on success, non-zero on error.
360  */
361 int32_t hcall_set_ptdev_intr_info(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
362 
363 /**
364  * @brief Clear interrupt mapping info of ptdev.
365  *
366  * @param vcpu Pointer to vCPU that initiates the hypercall
367  * @param target_vm Pointer to target VM data structure
368  * @param param1 not used
369  * @param param2 guest physical address. This gpa points to data structure of
370  *              hc_ptdev_irq including intr remapping info
371  *
372  * @pre is_service_vm(vcpu->vm)
373  * @return 0 on success, non-zero on error.
374  */
375 int32_t hcall_reset_ptdev_intr_info(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
376 		uint64_t param1, uint64_t param2);
377 
378 /**
379  * @brief Get VCPU Power state.
380  *
381  * @param vcpu Pointer to vCPU that initiates the hypercall
382  * @param target_vm Pointer to target VM data structure
383  * @param param1 cmd to show get which VCPU power state data
384  * @param param2 VCPU power state data
385  *
386  * @pre is_service_vm(vcpu->vm)
387  * @return 0 on success, non-zero on error.
388  */
389 int32_t hcall_get_cpu_pm_state(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
390 
391 /**
392  * @brief Get VCPU a VM's interrupt count data.
393  *
394  * @param vcpu Pointer to vCPU that initiates the hypercall
395  * @param target_vm Pointer to target VM data structure
396  * @param param1 not used
397  * @param param2 guest physical address. This gpa points to data structure of
398  *              acrn_intr_monitor
399  *
400  * @pre is_service_vm(vcpu->vm)
401  * @return 0 on success, non-zero on error.
402  */
403 int32_t hcall_vm_intr_monitor(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
404 
405 /**
406  * @defgroup trusty_hypercall Trusty Hypercalls
407  *
408  * This is a special group that includes all hypercalls
409  * related to Trusty
410  *
411  * @{
412  */
413 
414 /**
415  * @brief Switch vCPU state between Normal/Secure World.
416  *
417  * * The hypervisor uses this hypercall to do the world switch
418  * * The hypervisor needs to:
419  *   * save current world vCPU contexts, and load the next world
420  *     vCPU contexts
421  *   * update ``rdi``, ``rsi``, ``rdx``, ``rbx`` to next world
422  *     vCPU contexts
423  *
424  * @param vcpu Pointer to VCPU data structure
425  * @param target_vm not used
426  * @param param1 not used
427  * @param param2 not used
428  *
429  * @return 0 on success, non-zero on error.
430  */
431 
432 int32_t hcall_world_switch(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
433 
434 /**
435  * @brief Initialize environment for Trusty-OS on a vCPU.
436  *
437  * * It is used by the User VM OS bootloader (``User VM OS Loader``) to request ACRN
438  *   to initialize Trusty
439  * * The Trusty memory region range, entry point must be specified
440  * * The hypervisor needs to save current vCPU contexts (Normal World)
441  *
442  * @param vcpu Pointer to vCPU data structure
443  * @param target_vm not used
444  * @param param1 guest physical address. This gpa points to
445  *               trusty_boot_param structure
446  * @param param2 not used
447  *
448  * @return 0 on success, non-zero on error.
449  */
450 int32_t hcall_initialize_trusty(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
451 
452 /**
453  * @brief Save/Restore Context of Secure World.
454  *
455  * @param vcpu Pointer to VCPU data structure
456  * @param target_vm not used
457  * @param param1 not used
458  * @param param2 not used
459  *
460  * @return 0 on success, non-zero on error.
461  */
462 int32_t hcall_save_restore_sworld_ctx(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
463 		uint64_t param1, uint64_t param2);
464 
465 /**
466  * @brief Handle the TEE boot done signal.
467  *
468  * @param vcpu Pointer to VCPU data structure
469  * @param target_vm not used
470  * @param param1 not used
471  * @param param2 not used
472  *
473  * @return 0 on success, non-zero on error.
474  */
475 int32_t hcall_handle_tee_vcpu_boot_done(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
476 		uint64_t param1, uint64_t param2);
477 
478 /**
479  * @brief Switch the execution environment.
480  *
481  * @param vcpu Pointer to VCPU data structure
482  * @param target_vm not used
483  * @param param1 not used
484  * @param param2 not used
485  *
486  * @return 0 on success, non-zero on error.
487  */
488 int32_t hcall_switch_ee(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
489 		uint64_t param1, uint64_t param2);
490 
491 /**
492  * @}
493  */
494 /* End of trusty_hypercall */
495 
496 /**
497  * @brief set upcall notifier vector
498  *
499  * This is the API that helps to switch the notifer vecotr. If this API is
500  * not called, the hypervisor will use the default notifier vector(0xF7)
501  * to notify the Service VM OS kernel.
502  *
503  * @param vcpu not used
504  * @param target_vm not used
505  * @param param1 the expected notifier vector from guest
506  * @param param2 not used
507  *
508  * @pre is_service_vm(vcpu->vm)
509  * @return 0 on success, non-zero on error.
510  */
511 int32_t hcall_set_callback_vector(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
512 
513 /**
514  * @brief Setup a share buffer for a VM.
515  *
516  * @param vcpu Pointer to vCPU that initiates the hypercall
517  * @param target_vm not used
518  * @param param1 guest physical address. This gpa points to
519  *              struct sbuf_setup_param
520  * @param param2 not used
521  *
522  * @pre is_service_vm(vcpu->vm)
523  * @return 0 on success, non-zero on error.
524  */
525 int32_t hcall_setup_sbuf(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
526 
527 /**
528  * @brief Assign an asyncio to a VM.
529  *
530  * @param vcpu not used
531  * @param target_vm which VM the asyncio belongs.
532  * @param param1 guest physical address. This gpa points to
533  *              struct acrn_asyncio_info
534  * @param param2 not used
535  *
536  * @return 0 on success, non-zero on error.
537  */
538 int32_t hcall_asyncio_assign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
539 		 __unused uint64_t param1, uint64_t param2);
540 /**
541  * @brief Deassign an asyncio from a VM.
542  *
543  * @param vcpu not used
544  * @param target_vm which VM the asyncio belongs.
545  * @param param1 guest physical address. This gpa points to
546  *              struct acrn_asyncio_info
547  * @param param2 not used
548  *
549  * @return 0 on success, non-zero on error.
550  */
551 int32_t hcall_asyncio_deassign(__unused struct acrn_vcpu *vcpu, struct acrn_vm *target_vm,
552 		 __unused uint64_t param1, uint64_t param2);
553 
554 /**
555  * @brief Setup the hypervisor NPK log.
556  *
557  * @param vcpu Pointer to vCPU that initiates the hypercall
558  * @param target_vm not used
559  * @param param1 guest physical address. This gpa points to
560  *              struct hv_npk_log_param
561  * @param param2 not used
562  *
563  * @pre is_service_vm(vcpu->vm)
564  * @return 0 on success, non-zero on error.
565  */
566 int32_t hcall_setup_hv_npk_log(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
567 
568 /**
569  * @brief Get hardware related info
570  *
571  * @param vcpu Pointer to vCPU that initiates the hypercall
572  * @param target_vm not used
573  * @param param1 Guest physical address pointing to struct acrn_hw_info
574  * @param param2 not used
575  *
576  * @pre vm shall point to Service VM
577  * @pre param1 shall be a valid physical address
578  *
579  * @retval 0 on success
580  * @retval -1 in case of error
581  */
582 int32_t hcall_get_hw_info(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
583 
584 /**
585  * @brief Execute profiling operation
586  *
587  * @param vcpu Pointer to vCPU that initiates the hypercall
588  * @param target_vm not used
589  * @param param1 profiling command to be executed
590  * @param param2 guest physical address. This gpa points to
591  *             data structure required by each command
592  *
593  * @pre is_service_vm(vcpu->vm)
594  * @return 0 on success, non-zero on error.
595  */
596 int32_t hcall_profiling_ops(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
597 
598 int32_t hcall_create_vcpu(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm, uint64_t param1, uint64_t param2);
599 /**
600  * @}
601  */
602 /* End of acrn_hypercall */
603 
604 #endif /* HYPERCALL_H*/
605