1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2018, Linaro Limited
4 */
5
6 /*
7 * Test lockdep with hypothetical thread and lock objects
8 */
9
10 #include <assert.h>
11 #include <kernel/lockdep.h>
12
13 #include "misc.h"
14
self_test_lockdep1(void)15 static int self_test_lockdep1(void)
16 {
17 TEE_Result res = TEE_ERROR_GENERIC;
18 struct lockdep_node_head graph;
19 struct lockdep_lock_head thread1;
20 int count = 1;
21
22 DMSG("");
23
24 TAILQ_INIT(&thread1);
25 TAILQ_INIT(&graph);
26
27 /* Not locked, expect failure */
28 res = __lockdep_lock_release(&thread1, 1);
29 if (!res)
30 return count;
31 count++;
32
33 res = __lockdep_lock_acquire(&graph, &thread1, 1);
34 if (res)
35 return count;
36 count++;
37
38 res = __lockdep_lock_release(&thread1, 1);
39 if (res)
40 return count;
41 count++;
42
43 res = __lockdep_lock_acquire(&graph, &thread1, 1);
44 if (res)
45 return count;
46 count++;
47
48 res = __lockdep_lock_acquire(&graph, &thread1, 3);
49 if (res)
50 return count;
51 count++;
52
53 res = __lockdep_lock_acquire(&graph, &thread1, 2);
54 if (res)
55 return count;
56 count++;
57
58 res = __lockdep_lock_release(&thread1, 3);
59 if (res)
60 return count;
61 count++;
62
63 /* Already locked */
64 res = __lockdep_lock_acquire(&graph, &thread1, 2);
65 if (!res)
66 return count;
67
68 lockdep_graph_delete(&graph);
69 lockdep_queue_delete(&thread1);
70
71 return 0;
72 }
73
self_test_lockdep2(void)74 static int self_test_lockdep2(void)
75 {
76 TEE_Result res = TEE_ERROR_GENERIC;
77 struct lockdep_node_head graph;
78 struct lockdep_lock_head thread1;
79 struct lockdep_lock_head thread2;
80 struct lockdep_lock_head thread3;
81 int count = 1;
82
83 DMSG("");
84
85 TAILQ_INIT(&thread1);
86 TAILQ_INIT(&thread2);
87 TAILQ_INIT(&thread3);
88 TAILQ_INIT(&graph);
89
90 res = __lockdep_lock_acquire(&graph, &thread1, 1);
91 if (res)
92 return count;
93 count++;
94
95 res = __lockdep_lock_acquire(&graph, &thread2, 2);
96 if (res)
97 return count;
98 count++;
99
100 res = __lockdep_lock_acquire(&graph, &thread1, 2);
101 if (res)
102 return count;
103 count++;
104
105 res = __lockdep_lock_acquire(&graph, &thread3, 3);
106 if (res)
107 return count;
108 count++;
109
110 res = __lockdep_lock_acquire(&graph, &thread2, 3);
111 if (res)
112 return count;
113 count++;
114
115 /* Deadlock 1-2-3 */
116 res = __lockdep_lock_acquire(&graph, &thread3, 1);
117 if (!res)
118 return count;
119
120 lockdep_graph_delete(&graph);
121 lockdep_queue_delete(&thread1);
122 lockdep_queue_delete(&thread2);
123 lockdep_queue_delete(&thread3);
124
125 return 0;
126 }
127
self_test_lockdep3(void)128 static int self_test_lockdep3(void)
129 {
130 TEE_Result res = TEE_ERROR_GENERIC;
131 struct lockdep_node_head graph;
132 struct lockdep_lock_head thread1;
133 struct lockdep_lock_head thread2;
134 int count = 1;
135
136 DMSG("");
137
138 TAILQ_INIT(&thread1);
139 TAILQ_INIT(&thread2);
140 TAILQ_INIT(&graph);
141
142 res = __lockdep_lock_tryacquire(&graph, &thread1, 1);
143 if (res)
144 return count;
145 count++;
146
147 res = __lockdep_lock_release(&thread1, 1);
148 if (res)
149 return count;
150 count++;
151
152 res = __lockdep_lock_tryacquire(&graph, &thread1, 1);
153 if (res)
154 return count;
155 count++;
156
157 res = __lockdep_lock_acquire(&graph, &thread2, 2);
158 if (res)
159 return count;
160 count++;
161
162 res = __lockdep_lock_acquire(&graph, &thread1, 2);
163 if (res)
164 return count;
165 count++;
166
167 /* Deadlock 1-2 */
168 res = __lockdep_lock_acquire(&graph, &thread2, 1);
169 if (!res)
170 return count;
171
172 lockdep_graph_delete(&graph);
173 lockdep_queue_delete(&thread1);
174 lockdep_queue_delete(&thread2);
175
176 return 0;
177 }
178
core_lockdep_tests(uint32_t nParamTypes __unused,TEE_Param pParams[TEE_NUM_PARAMS]__unused)179 TEE_Result core_lockdep_tests(uint32_t nParamTypes __unused,
180 TEE_Param pParams[TEE_NUM_PARAMS] __unused)
181
182 {
183 int count = 0;
184
185 count = self_test_lockdep1();
186 if (count)
187 goto out;
188 count = self_test_lockdep2();
189 if (count)
190 goto out;
191 count = self_test_lockdep3();
192 if (count)
193 goto out;
194 out:
195 if (count) {
196 DMSG("count=%d", count);
197 return TEE_ERROR_GENERIC;
198 }
199
200 return TEE_SUCCESS;
201 }
202