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 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 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 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 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