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