deadlock_tests.c revision 7cdc0497
1/* 2 * Copyright 2017 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22*/ 23 24#include <stdio.h> 25#include <stdlib.h> 26#include <unistd.h> 27#ifdef HAVE_ALLOCA_H 28# include <alloca.h> 29#endif 30 31#include "CUnit/Basic.h" 32 33#include "amdgpu_test.h" 34#include "amdgpu_drm.h" 35#include "amdgpu_internal.h" 36 37#include <pthread.h> 38 39 40/* 41 * This defines the delay in MS after which memory location designated for 42 * compression against reference value is written to, unblocking command 43 * processor 44 */ 45#define WRITE_MEM_ADDRESS_DELAY_MS 100 46 47#define PACKET_TYPE3 3 48 49#define PACKET3(op, n) ((PACKET_TYPE3 << 30) | \ 50 (((op) & 0xFF) << 8) | \ 51 ((n) & 0x3FFF) << 16) 52 53#define PACKET3_WAIT_REG_MEM 0x3C 54#define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) 55 /* 0 - always 56 * 1 - < 57 * 2 - <= 58 * 3 - == 59 * 4 - != 60 * 5 - >= 61 * 6 - > 62 */ 63#define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) 64 /* 0 - reg 65 * 1 - mem 66 */ 67#define WAIT_REG_MEM_OPERATION(x) ((x) << 6) 68 /* 0 - wait_reg_mem 69 * 1 - wr_wait_wr_reg 70 */ 71#define WAIT_REG_MEM_ENGINE(x) ((x) << 8) 72 /* 0 - me 73 * 1 - pfp 74 */ 75 76static amdgpu_device_handle device_handle; 77static uint32_t major_version; 78static uint32_t minor_version; 79 80static pthread_t stress_thread; 81static uint32_t *ptr; 82 83int use_uc_mtype = 0; 84 85static void amdgpu_deadlock_helper(unsigned ip_type); 86static void amdgpu_deadlock_gfx(void); 87static void amdgpu_deadlock_compute(void); 88 89CU_BOOL suite_deadlock_tests_enable(void) 90{ 91 CU_BOOL enable = CU_TRUE; 92 93 if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, 94 &minor_version, &device_handle)) 95 return CU_FALSE; 96 97 if (device_handle->info.family_id == AMDGPU_FAMILY_SI) { 98 printf("\n\nCurrently hangs the CP on this ASIC, deadlock suite disabled\n"); 99 enable = CU_FALSE; 100 } 101 102 if (device_handle->info.family_id >= AMDGPU_FAMILY_AI) 103 use_uc_mtype = 1; 104 105 if (amdgpu_device_deinitialize(device_handle)) 106 return CU_FALSE; 107 108 return enable; 109} 110 111int suite_deadlock_tests_init(void) 112{ 113 int r; 114 115 r = amdgpu_device_initialize(drm_amdgpu[0], &major_version, 116 &minor_version, &device_handle); 117 118 if (r) { 119 if ((r == -EACCES) && (errno == EACCES)) 120 printf("\n\nError:%s. " 121 "Hint:Try to run this test program as root.", 122 strerror(errno)); 123 return CUE_SINIT_FAILED; 124 } 125 126 return CUE_SUCCESS; 127} 128 129int suite_deadlock_tests_clean(void) 130{ 131 int r = amdgpu_device_deinitialize(device_handle); 132 133 if (r == 0) 134 return CUE_SUCCESS; 135 else 136 return CUE_SCLEAN_FAILED; 137} 138 139 140CU_TestInfo deadlock_tests[] = { 141 { "gfx ring block test", amdgpu_deadlock_gfx }, 142 { "compute ring block test", amdgpu_deadlock_compute }, 143 CU_TEST_INFO_NULL, 144}; 145 146static void *write_mem_address(void *data) 147{ 148 int i; 149 150 /* useconds_t range is [0, 1,000,000] so use loop for waits > 1s */ 151 for (i = 0; i < WRITE_MEM_ADDRESS_DELAY_MS; i++) 152 usleep(1000); 153 154 ptr[256] = 0x1; 155 156 return 0; 157} 158 159static void amdgpu_deadlock_gfx(void) 160{ 161 amdgpu_deadlock_helper(AMDGPU_HW_IP_GFX); 162} 163 164static void amdgpu_deadlock_compute(void) 165{ 166 amdgpu_deadlock_helper(AMDGPU_HW_IP_COMPUTE); 167} 168 169static void amdgpu_deadlock_helper(unsigned ip_type) 170{ 171 amdgpu_context_handle context_handle; 172 amdgpu_bo_handle ib_result_handle; 173 void *ib_result_cpu; 174 uint64_t ib_result_mc_address; 175 struct amdgpu_cs_request ibs_request; 176 struct amdgpu_cs_ib_info ib_info; 177 struct amdgpu_cs_fence fence_status; 178 uint32_t expired; 179 int i, r; 180 amdgpu_bo_list_handle bo_list; 181 amdgpu_va_handle va_handle; 182 183 r = pthread_create(&stress_thread, NULL, write_mem_address, NULL); 184 CU_ASSERT_EQUAL(r, 0); 185 186 r = amdgpu_cs_ctx_create(device_handle, &context_handle); 187 CU_ASSERT_EQUAL(r, 0); 188 189 r = amdgpu_bo_alloc_and_map_raw(device_handle, 4096, 4096, 190 AMDGPU_GEM_DOMAIN_GTT, 0, use_uc_mtype ? AMDGPU_VM_MTYPE_UC : 0, 191 &ib_result_handle, &ib_result_cpu, 192 &ib_result_mc_address, &va_handle); 193 CU_ASSERT_EQUAL(r, 0); 194 195 r = amdgpu_get_bo_list(device_handle, ib_result_handle, NULL, 196 &bo_list); 197 CU_ASSERT_EQUAL(r, 0); 198 199 ptr = ib_result_cpu; 200 201 ptr[0] = PACKET3(PACKET3_WAIT_REG_MEM, 5); 202 ptr[1] = (WAIT_REG_MEM_MEM_SPACE(1) | /* memory */ 203 WAIT_REG_MEM_FUNCTION(4) | /* != */ 204 WAIT_REG_MEM_ENGINE(0)); /* me */ 205 ptr[2] = (ib_result_mc_address + 256*4) & 0xfffffffc; 206 ptr[3] = ((ib_result_mc_address + 256*4) >> 32) & 0xffffffff; 207 ptr[4] = 0x00000000; /* reference value */ 208 ptr[5] = 0xffffffff; /* and mask */ 209 ptr[6] = 0x00000004; /* poll interval */ 210 211 for (i = 7; i < 16; ++i) 212 ptr[i] = 0xffff1000; 213 214 215 ptr[256] = 0x0; /* the memory we wait on to change */ 216 217 218 219 memset(&ib_info, 0, sizeof(struct amdgpu_cs_ib_info)); 220 ib_info.ib_mc_address = ib_result_mc_address; 221 ib_info.size = 16; 222 223 memset(&ibs_request, 0, sizeof(struct amdgpu_cs_request)); 224 ibs_request.ip_type = ip_type; 225 ibs_request.ring = 0; 226 ibs_request.number_of_ibs = 1; 227 ibs_request.ibs = &ib_info; 228 ibs_request.resources = bo_list; 229 ibs_request.fence_info.handle = NULL; 230 231 for (i = 0; i < 200; i++) { 232 r = amdgpu_cs_submit(context_handle, 0,&ibs_request, 1); 233 CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); 234 235 } 236 237 memset(&fence_status, 0, sizeof(struct amdgpu_cs_fence)); 238 fence_status.context = context_handle; 239 fence_status.ip_type = ip_type; 240 fence_status.ip_instance = 0; 241 fence_status.ring = 0; 242 fence_status.fence = ibs_request.seq_no; 243 244 r = amdgpu_cs_query_fence_status(&fence_status, 245 AMDGPU_TIMEOUT_INFINITE,0, &expired); 246 CU_ASSERT_EQUAL((r == 0 || r == -ECANCELED), 1); 247 248 pthread_join(stress_thread, NULL); 249 250 r = amdgpu_bo_list_destroy(bo_list); 251 CU_ASSERT_EQUAL(r, 0); 252 253 r = amdgpu_bo_unmap_and_free(ib_result_handle, va_handle, 254 ib_result_mc_address, 4096); 255 CU_ASSERT_EQUAL(r, 0); 256 257 r = amdgpu_cs_ctx_free(context_handle); 258 CU_ASSERT_EQUAL(r, 0); 259} 260