1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4
5 #if defined(UNIT_TESTS)
6
7 #include <assert.h>
8 #include <hyptypes.h>
9
10 #include <hyprights.h>
11
12 #include <atomic.h>
13 #include <cpulocal.h>
14 #include <cspace.h>
15 #include <object.h>
16 #include <partition.h>
17 #include <partition_alloc.h>
18 #include <spinlock.h>
19
20 #include <asm/event.h>
21
22 #include "event_handlers.h"
23
24 static cspace_t *test_cspace;
25 static cap_id_t test_cspace_master_cap;
26 static _Atomic count_t test_cspace_wait_count;
27 static _Atomic count_t test_cspace_finish_count;
28 static _Atomic uint8_t test_cspace_revoke_flag;
29
30 #define TEST_CAP_COPIES 20U
31 #define TEST_CSPACE_MAX_CAPS ((PLATFORM_MAX_CORES * TEST_CAP_COPIES) + 1U)
32
33 CPULOCAL_DECLARE_STATIC(cap_id_t, test_caps)[TEST_CAP_COPIES];
34
35 void
tests_cspace_init(void)36 tests_cspace_init(void)
37 {
38 cspace_ptr_result_t cspace_ret;
39 object_ptr_t obj;
40 cap_id_result_t cap_ret;
41 error_t err;
42
43 cspace_create_t params = { NULL };
44
45 cspace_ret = partition_allocate_cspace(partition_get_private(), params);
46 assert(cspace_ret.e == OK);
47 test_cspace = cspace_ret.r;
48 spinlock_acquire(&test_cspace->header.lock);
49 err = cspace_configure(test_cspace, TEST_CSPACE_MAX_CAPS);
50 spinlock_release(&test_cspace->header.lock);
51 assert(err == OK);
52 err = object_activate_cspace(test_cspace);
53 assert(err == OK);
54
55 obj.cspace = test_cspace;
56 cap_ret =
57 cspace_create_master_cap(test_cspace, obj, OBJECT_TYPE_CSPACE);
58 assert(cap_ret.e == OK);
59 test_cspace_master_cap = cap_ret.r;
60
61 atomic_init(&test_cspace_wait_count, 0U);
62 atomic_init(&test_cspace_finish_count, PLATFORM_MAX_CORES);
63 atomic_init(&test_cspace_revoke_flag, 0U);
64 }
65
66 static error_t
tests_cspace_cap_lookup(cap_id_t cap,cap_rights_t rights)67 tests_cspace_cap_lookup(cap_id_t cap, cap_rights_t rights)
68 {
69 object_ptr_result_t ret = cspace_lookup_object(
70 test_cspace, cap, OBJECT_TYPE_CSPACE, rights, true);
71
72 if (ret.e == OK) {
73 assert(ret.r.cspace == test_cspace);
74 object_put_cspace(ret.r.cspace);
75 }
76
77 return ret.e;
78 }
79
80 bool
tests_cspace_start(void)81 tests_cspace_start(void)
82 {
83 cap_id_result_t cap_ret;
84 cap_id_t *cap = CPULOCAL(test_caps);
85 cap_rights_cspace_t cspace_rights = cap_rights_cspace_default();
86 cap_rights_t rights;
87 error_t err;
88 const count_t num_delete = TEST_CAP_COPIES / 2U;
89
90 object_get_cspace_additional(test_cspace);
91
92 cap_rights_cspace_set_test(&cspace_rights, true);
93 rights = cap_rights_cspace_raw(cspace_rights);
94
95 // Sync with other cores to maximise concurrent accesses
96 (void)atomic_fetch_add_explicit(&test_cspace_wait_count, 1U,
97 memory_order_relaxed);
98 while (asm_event_load_before_wait(&test_cspace_wait_count) !=
99 PLATFORM_MAX_CORES) {
100 asm_event_wait(&test_cspace_wait_count);
101 }
102
103 for (count_t i = 0U; i < TEST_CAP_COPIES; i++) {
104 cap_ret = cspace_copy_cap(test_cspace, test_cspace,
105 test_cspace_master_cap, rights);
106 assert(cap_ret.e == OK);
107 cap[i] = cap_ret.r;
108 }
109
110 err = tests_cspace_cap_lookup(test_cspace_master_cap, rights);
111 assert(err == OK);
112
113 for (count_t i = 0U; i < TEST_CAP_COPIES; i++) {
114 err = tests_cspace_cap_lookup(cap[i], rights);
115 assert(err == OK);
116 }
117
118 cspace_rights = CAP_RIGHTS_CSPACE_ALL;
119 rights = cap_rights_cspace_raw(cspace_rights);
120
121 err = tests_cspace_cap_lookup(test_cspace_master_cap, rights);
122 assert(err == OK);
123
124 for (count_t i = 0U; i < TEST_CAP_COPIES; i++) {
125 err = tests_cspace_cap_lookup(cap[i], rights);
126 assert(err == ERROR_CSPACE_INSUFFICIENT_RIGHTS);
127 }
128
129 for (count_t i = 0U; i < num_delete; i++) {
130 err = cspace_delete_cap(test_cspace, cap[i]);
131 assert(err == OK);
132 }
133
134 if (atomic_fetch_sub_explicit(&test_cspace_finish_count, 1U,
135 memory_order_release) == 1U) {
136 err = cspace_revoke_caps(test_cspace, test_cspace_master_cap);
137 assert(err == OK);
138
139 err = cspace_delete_cap(test_cspace, test_cspace_master_cap);
140 assert(err == OK);
141
142 asm_event_store_and_wake(&test_cspace_revoke_flag, 1U);
143 } else {
144 while (asm_event_load_before_wait(&test_cspace_revoke_flag) ==
145 0U) {
146 asm_event_wait(&test_cspace_revoke_flag);
147 }
148 }
149
150 // Delete the revoked caps
151 for (count_t i = num_delete; i < TEST_CAP_COPIES; i++) {
152 err = cspace_delete_cap(test_cspace, cap[i]);
153 assert(err == OK);
154 }
155
156 object_put_cspace(test_cspace);
157
158 return false;
159 }
160 #else
161
162 extern char unused;
163
164 #endif
165