1 /*
2 * Copyright (C) 2018-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <asm/guest/vm.h>
8 #include <hypercall.h>
9 #include <errno.h>
10 #include <logmsg.h>
11
12
13 /**
14 * @brief Switch vCPU state between Normal/Secure World.
15 *
16 * * The hypervisor uses this hypercall to do the world switch
17 * * The hypervisor needs to:
18 * * save current world vCPU contexts, and load the next world
19 * vCPU contexts
20 * * update ``rdi``, ``rsi``, ``rdx``, ``rbx`` to next world
21 * vCPU contexts
22 *
23 * @param vcpu Pointer to VCPU data structure
24 *
25 * @return 0 on success, non-zero on error.
26 */
hcall_world_switch(struct acrn_vcpu * vcpu,__unused struct acrn_vm * target_vm,__unused uint64_t param1,__unused uint64_t param2)27 int32_t hcall_world_switch(struct acrn_vcpu *vcpu, __unused struct acrn_vm *target_vm,
28 __unused uint64_t param1, __unused uint64_t param2)
29 {
30 int32_t next_world_id = !(vcpu->arch.cur_context);
31 int32_t ret = -EPERM;
32
33 if ((vcpu->vm->sworld_control.flag.supported != 0UL) && (next_world_id < NR_WORLD)
34 && (vcpu->vm->sworld_control.flag.active != 0UL)) {
35 switch_world(vcpu, next_world_id);
36 ret = 0;
37 }
38 return ret;
39 }
40
41 /**
42 * @brief Initialize environment for Trusty-OS on a vCPU.
43 *
44 * * It is used by the User VM OS bootloader (``User VM OS Loader``) to request ACRN
45 * to initialize Trusty
46 * * The Trusty memory region range, entry point must be specified
47 * * The hypervisor needs to save current vCPU contexts (Normal World)
48 *
49 * @param vcpu Pointer to vCPU data structure
50 * @param param1 guest physical address. This gpa points to trusty_boot_param structure
51 *
52 * @return 0 on success, non-zero on error.
53 */
hcall_initialize_trusty(struct acrn_vcpu * vcpu,__unused struct acrn_vm * target_vm,uint64_t param1,__unused uint64_t param2)54 int32_t hcall_initialize_trusty(struct acrn_vcpu *vcpu, __unused struct acrn_vm *target_vm,
55 uint64_t param1, __unused uint64_t param2)
56 {
57 int32_t ret = -EFAULT;
58
59 if ((vcpu->vm->sworld_control.flag.supported != 0UL)
60 && (vcpu->vm->sworld_control.flag.active == 0UL)
61 && (vcpu->arch.cur_context == NORMAL_WORLD)) {
62 struct trusty_boot_param boot_param;
63
64 if (copy_from_gpa(vcpu->vm, &boot_param, param1, sizeof(boot_param)) == 0) {
65 if (initialize_trusty(vcpu, &boot_param)) {
66 vcpu->vm->sworld_control.flag.active = 1UL;
67 ret = 0;
68 }
69 }
70 } else {
71 ret = -EPERM;
72 pr_err("%s, context mismatch when initialize trusty.\n", __func__);
73 }
74 return ret;
75 }
76
77 /**
78 * @brief Save/Restore Context of Secure World.
79 *
80 * @param vcpu Pointer to VCPU data structure
81 *
82 * @return 0 on success, non-zero on error.
83 */
hcall_save_restore_sworld_ctx(struct acrn_vcpu * vcpu,__unused struct acrn_vm * target_vm,__unused uint64_t param1,__unused uint64_t param2)84 int32_t hcall_save_restore_sworld_ctx(struct acrn_vcpu *vcpu, __unused struct acrn_vm *target_vm,
85 __unused uint64_t param1, __unused uint64_t param2)
86 {
87 struct acrn_vm *vm = vcpu->vm;
88 int32_t ret = -EINVAL;
89
90 if (is_vcpu_bsp(vcpu) && (vm->sworld_control.flag.supported != 0UL)) {
91 if (vm->sworld_control.flag.active != 0UL) {
92 save_sworld_context(vcpu);
93 vm->sworld_control.flag.ctx_saved = 1UL;
94 ret = 0;
95 } else {
96 if (vm->sworld_control.flag.ctx_saved != 0UL) {
97 restore_sworld_context(vcpu);
98 vm->sworld_control.flag.ctx_saved = 0UL;
99 vm->sworld_control.flag.active = 1UL;
100 ret = 0;
101 }
102 }
103 } else {
104 ret = -EPERM;
105 pr_err("%s, states mismatch when save restore sworld context.\n", __func__);
106 }
107
108 return ret;
109 }
110