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