1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4
5 #if defined(HYPERCALLS)
6 #include <assert.h>
7 #include <hyptypes.h>
8
9 #include <hypcall_def.h>
10 #include <hyprights.h>
11
12 #include <atomic.h>
13 #include <compiler.h>
14 #include <cspace.h>
15 #include <cspace_lookup.h>
16 #include <object.h>
17 #include <spinlock.h>
18
19 error_t
hypercall_cspace_delete_cap_from(cap_id_t cspace_cap,cap_id_t cap)20 hypercall_cspace_delete_cap_from(cap_id_t cspace_cap, cap_id_t cap)
21 {
22 error_t ret;
23 cspace_ptr_result_t c;
24 c = cspace_lookup_cspace(cspace_get_self(), cspace_cap,
25 CAP_RIGHTS_CSPACE_CAP_DELETE);
26 if (compiler_unexpected(c.e != OK)) {
27 ret = c.e;
28 goto out;
29 }
30 cspace_t *cspace = c.r;
31
32 ret = cspace_delete_cap(cspace, cap);
33
34 object_put_cspace(cspace);
35 out:
36 return ret;
37 }
38
39 hypercall_cspace_copy_cap_from_result_t
hypercall_cspace_copy_cap_from(cap_id_t src_cspace_cap,cap_id_t src_cap,cap_id_t dest_cspace_cap,cap_rights_t rights_mask)40 hypercall_cspace_copy_cap_from(cap_id_t src_cspace_cap, cap_id_t src_cap,
41 cap_id_t dest_cspace_cap,
42 cap_rights_t rights_mask)
43 {
44 hypercall_cspace_copy_cap_from_result_t ret = { 0 };
45 cspace_ptr_result_t c;
46 c = cspace_lookup_cspace(cspace_get_self(), src_cspace_cap,
47 CAP_RIGHTS_CSPACE_CAP_COPY);
48 if (compiler_unexpected(c.e != OK)) {
49 ret.error = c.e;
50 goto out;
51 }
52 cspace_t *src_cspace = c.r;
53
54 c = cspace_lookup_cspace(cspace_get_self(), dest_cspace_cap,
55 CAP_RIGHTS_CSPACE_CAP_CREATE);
56 if (compiler_unexpected(c.e != OK)) {
57 ret.error = c.e;
58 goto out_src_cspace_release;
59 }
60 cspace_t *dest_cspace = c.r;
61
62 cap_id_result_t new =
63 cspace_copy_cap(dest_cspace, src_cspace, src_cap, rights_mask);
64 if (new.e == OK) {
65 ret.error = OK;
66 ret.new_cap = new.r;
67 } else {
68 ret.error = new.e;
69 }
70
71 object_put_cspace(dest_cspace);
72 out_src_cspace_release:
73 object_put_cspace(src_cspace);
74 out:
75 return ret;
76 }
77
78 error_t
hypercall_cspace_revoke_cap_from(cap_id_t src_cspace,cap_id_t src_cap)79 hypercall_cspace_revoke_cap_from(cap_id_t src_cspace, cap_id_t src_cap)
80 {
81 (void)src_cspace;
82 (void)src_cap;
83 return ERROR_UNIMPLEMENTED;
84 }
85
86 error_t
hypercall_cspace_revoke_caps_from(cap_id_t src_cspace,cap_id_t master_cap)87 hypercall_cspace_revoke_caps_from(cap_id_t src_cspace, cap_id_t master_cap)
88 {
89 error_t ret;
90 cspace_ptr_result_t c;
91 c = cspace_lookup_cspace(cspace_get_self(), src_cspace,
92 CAP_RIGHTS_CSPACE_CAP_REVOKE);
93 if (compiler_unexpected(c.e != OK)) {
94 ret = c.e;
95 goto out;
96 }
97 cspace_t *cspace = c.r;
98
99 ret = cspace_revoke_caps(cspace, master_cap);
100
101 object_put_cspace(cspace);
102 out:
103 return ret;
104 }
105
106 error_t
hypercall_cspace_configure(cap_id_t cspace_cap,count_t max_caps)107 hypercall_cspace_configure(cap_id_t cspace_cap, count_t max_caps)
108 {
109 error_t err;
110 cspace_t *cspace = cspace_get_self();
111 object_type_t type;
112
113 object_ptr_result_t o = cspace_lookup_object_any(
114 cspace, cspace_cap, CAP_RIGHTS_GENERIC_OBJECT_ACTIVATE, &type);
115 if (compiler_unexpected(o.e != OK)) {
116 err = o.e;
117 goto out;
118 }
119 if (type != OBJECT_TYPE_CSPACE) {
120 err = ERROR_CSPACE_WRONG_OBJECT_TYPE;
121 goto out_object_release;
122 }
123
124 cspace_t *target_cspace = o.r.cspace;
125
126 spinlock_acquire(&target_cspace->header.lock);
127
128 if (atomic_load_relaxed(&target_cspace->header.state) ==
129 OBJECT_STATE_INIT) {
130 err = cspace_configure(target_cspace, max_caps);
131 } else {
132 err = ERROR_OBJECT_STATE;
133 }
134
135 spinlock_release(&target_cspace->header.lock);
136 out_object_release:
137 object_put(type, o.r);
138 out:
139 return err;
140 }
141
142 error_t
hypercall_cspace_attach_thread(cap_id_t cspace_cap,cap_id_t thread_cap)143 hypercall_cspace_attach_thread(cap_id_t cspace_cap, cap_id_t thread_cap)
144 {
145 error_t ret;
146 cspace_t *cspace = cspace_get_self();
147 object_type_t type;
148
149 object_ptr_result_t o = cspace_lookup_object_any(
150 cspace, thread_cap, CAP_RIGHTS_GENERIC_OBJECT_ACTIVATE, &type);
151 if (compiler_unexpected(o.e != OK)) {
152 ret = o.e;
153 goto out;
154 }
155
156 if (type != OBJECT_TYPE_THREAD) {
157 ret = ERROR_CSPACE_WRONG_OBJECT_TYPE;
158 goto out_release;
159 }
160
161 thread_t *thread = o.r.thread;
162
163 cspace_ptr_result_t c = cspace_lookup_cspace(cspace, cspace_cap,
164 CAP_RIGHTS_CSPACE_ATTACH);
165 if (compiler_unexpected(c.e != OK)) {
166 ret = c.e;
167 goto out_release;
168 }
169
170 cspace_t *target_cspace = c.r;
171
172 spinlock_acquire(&thread->header.lock);
173
174 if (atomic_load_relaxed(&thread->header.state) == OBJECT_STATE_INIT) {
175 ret = cspace_attach_thread(target_cspace, thread);
176 } else {
177 ret = ERROR_OBJECT_STATE;
178 }
179
180 spinlock_release(&thread->header.lock);
181
182 object_put_cspace(target_cspace);
183
184 out_release:
185 object_put(type, o.r);
186 out:
187 return ret;
188 }
189
190 #else
191 extern int unused;
192 #endif
193