1 /* 2 * Copyright 2014 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 <string.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <unistd.h> 28 #include <string.h> 29 #include <ctype.h> 30 #include <fcntl.h> 31 #include <errno.h> 32 #include <signal.h> 33 #include <time.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <sys/ioctl.h> 37 #include <sys/time.h> 38 #include <stdarg.h> 39 #include <stdint.h> 40 41 #include "drm.h" 42 #include "xf86drmMode.h" 43 #include "xf86drm.h" 44 45 #include "CUnit/Basic.h" 46 47 #include "amdgpu_test.h" 48 #include "amdgpu_internal.h" 49 50 /* Test suite names */ 51 #define BASIC_TESTS_STR "Basic Tests" 52 #define BO_TESTS_STR "BO Tests" 53 #define CS_TESTS_STR "CS Tests" 54 #define VCE_TESTS_STR "VCE Tests" 55 #define VCN_TESTS_STR "VCN Tests" 56 #define UVD_ENC_TESTS_STR "UVD ENC Tests" 57 #define DEADLOCK_TESTS_STR "Deadlock Tests" 58 #define VM_TESTS_STR "VM Tests" 59 60 /** 61 * Open handles for amdgpu devices 62 * 63 */ 64 int drm_amdgpu[MAX_CARDS_SUPPORTED]; 65 66 /** Open render node to test */ 67 int open_render_node = 0; /* By default run most tests on primary node */ 68 69 /** The table of all known test suites to run */ 70 static CU_SuiteInfo suites[] = { 71 { 72 .pName = BASIC_TESTS_STR, 73 .pInitFunc = suite_basic_tests_init, 74 .pCleanupFunc = suite_basic_tests_clean, 75 .pTests = basic_tests, 76 }, 77 { 78 .pName = BO_TESTS_STR, 79 .pInitFunc = suite_bo_tests_init, 80 .pCleanupFunc = suite_bo_tests_clean, 81 .pTests = bo_tests, 82 }, 83 { 84 .pName = CS_TESTS_STR, 85 .pInitFunc = suite_cs_tests_init, 86 .pCleanupFunc = suite_cs_tests_clean, 87 .pTests = cs_tests, 88 }, 89 { 90 .pName = VCE_TESTS_STR, 91 .pInitFunc = suite_vce_tests_init, 92 .pCleanupFunc = suite_vce_tests_clean, 93 .pTests = vce_tests, 94 }, 95 { 96 .pName = VCN_TESTS_STR, 97 .pInitFunc = suite_vcn_tests_init, 98 .pCleanupFunc = suite_vcn_tests_clean, 99 .pTests = vcn_tests, 100 }, 101 { 102 .pName = UVD_ENC_TESTS_STR, 103 .pInitFunc = suite_uvd_enc_tests_init, 104 .pCleanupFunc = suite_uvd_enc_tests_clean, 105 .pTests = uvd_enc_tests, 106 }, 107 { 108 .pName = DEADLOCK_TESTS_STR, 109 .pInitFunc = suite_deadlock_tests_init, 110 .pCleanupFunc = suite_deadlock_tests_clean, 111 .pTests = deadlock_tests, 112 }, 113 { 114 .pName = VM_TESTS_STR, 115 .pInitFunc = suite_vm_tests_init, 116 .pCleanupFunc = suite_vm_tests_clean, 117 .pTests = vm_tests, 118 }, 119 120 CU_SUITE_INFO_NULL, 121 }; 122 123 typedef CU_BOOL (*active__stat_func)(void); 124 125 typedef struct Suites_Active_Status { 126 char* pName; 127 active__stat_func pActive; 128 }Suites_Active_Status; 129 130 static CU_BOOL always_active() 131 { 132 return CU_TRUE; 133 } 134 135 static Suites_Active_Status suites_active_stat[] = { 136 { 137 .pName = BASIC_TESTS_STR, 138 .pActive = always_active, 139 }, 140 { 141 .pName = BO_TESTS_STR, 142 .pActive = always_active, 143 }, 144 { 145 .pName = CS_TESTS_STR, 146 .pActive = suite_cs_tests_enable, 147 }, 148 { 149 .pName = VCE_TESTS_STR, 150 .pActive = suite_vce_tests_enable, 151 }, 152 { 153 .pName = VCN_TESTS_STR, 154 .pActive = suite_vcn_tests_enable, 155 }, 156 { 157 .pName = UVD_ENC_TESTS_STR, 158 .pActive = suite_uvd_enc_tests_enable, 159 }, 160 { 161 .pName = DEADLOCK_TESTS_STR, 162 .pActive = suite_deadlock_tests_enable, 163 }, 164 { 165 .pName = VM_TESTS_STR, 166 .pActive = suite_vm_tests_enable, 167 }, 168 }; 169 170 171 /* 172 * Display information about all suites and their tests 173 * 174 * NOTE: Must be run after registry is initialized and suites registered. 175 */ 176 static void display_test_suites(void) 177 { 178 int iSuite; 179 int iTest; 180 CU_pSuite pSuite = NULL; 181 CU_pTest pTest = NULL; 182 183 printf("Suites\n"); 184 185 for (iSuite = 0; suites[iSuite].pName != NULL; iSuite++) { 186 187 pSuite = CU_get_suite_by_index((unsigned int) iSuite + 1, 188 CU_get_registry()); 189 190 if (!pSuite) { 191 fprintf(stderr, "Invalid suite id : %d\n", iSuite + 1); 192 continue; 193 } 194 195 printf("Suite id = %d: Name '%s status: %s'\n", 196 iSuite + 1, suites[iSuite].pName, 197 pSuite->fActive ? "ENABLED" : "DISABLED"); 198 199 200 201 for (iTest = 0; suites[iSuite].pTests[iTest].pName != NULL; 202 iTest++) { 203 204 pTest = CU_get_test_by_index((unsigned int) iTest + 1, 205 pSuite); 206 207 if (!pTest) { 208 fprintf(stderr, "Invalid test id : %d\n", iTest + 1); 209 continue; 210 } 211 212 printf("Test id %d: Name: '%s status: %s'\n", iTest + 1, 213 suites[iSuite].pTests[iTest].pName, 214 pSuite->fActive && pTest->fActive ? 215 "ENABLED" : "DISABLED"); 216 } 217 } 218 } 219 220 221 /** Help string for command line parameters */ 222 static const char usage[] = 223 "Usage: %s [-hlpr] [<-s <suite id>> [-t <test id>] [-f]] " 224 "[-b <pci_bus_id> [-d <pci_device_id>]]\n" 225 "where:\n" 226 " l - Display all suites and their tests\n" 227 " r - Run the tests on render node\n" 228 " b - Specify device's PCI bus id to run tests\n" 229 " d - Specify device's PCI device id to run tests (optional)\n" 230 " p - Display information of AMDGPU devices in system\n" 231 " f - Force executing inactive suite or test\n" 232 " h - Display this help\n"; 233 /** Specified options strings for getopt */ 234 static const char options[] = "hlrps:t:b:d:f"; 235 236 /* Open AMD devices. 237 * Return the number of AMD device openned. 238 */ 239 static int amdgpu_open_devices(int open_render_node) 240 { 241 drmDevicePtr devices[MAX_CARDS_SUPPORTED]; 242 int i; 243 int drm_node; 244 int amd_index = 0; 245 int drm_count; 246 int fd; 247 drmVersionPtr version; 248 249 drm_count = drmGetDevices2(0, devices, MAX_CARDS_SUPPORTED); 250 251 if (drm_count < 0) { 252 fprintf(stderr, 253 "drmGetDevices2() returned an error %d\n", 254 drm_count); 255 return 0; 256 } 257 258 for (i = 0; i < drm_count; i++) { 259 /* If this is not PCI device, skip*/ 260 if (devices[i]->bustype != DRM_BUS_PCI) 261 continue; 262 263 /* If this is not AMD GPU vender ID, skip*/ 264 if (devices[i]->deviceinfo.pci->vendor_id != 0x1002) 265 continue; 266 267 if (open_render_node) 268 drm_node = DRM_NODE_RENDER; 269 else 270 drm_node = DRM_NODE_PRIMARY; 271 272 fd = -1; 273 if (devices[i]->available_nodes & 1 << drm_node) 274 fd = open( 275 devices[i]->nodes[drm_node], 276 O_RDWR | O_CLOEXEC); 277 278 /* This node is not available. */ 279 if (fd < 0) continue; 280 281 version = drmGetVersion(fd); 282 if (!version) { 283 fprintf(stderr, 284 "Warning: Cannot get version for %s." 285 "Error is %s\n", 286 devices[i]->nodes[drm_node], 287 strerror(errno)); 288 close(fd); 289 continue; 290 } 291 292 if (strcmp(version->name, "amdgpu")) { 293 /* This is not AMDGPU driver, skip.*/ 294 drmFreeVersion(version); 295 close(fd); 296 continue; 297 } 298 299 drmFreeVersion(version); 300 301 drm_amdgpu[amd_index] = fd; 302 amd_index++; 303 } 304 305 drmFreeDevices(devices, drm_count); 306 return amd_index; 307 } 308 309 /* Close AMD devices. 310 */ 311 static void amdgpu_close_devices() 312 { 313 int i; 314 for (i = 0; i < MAX_CARDS_SUPPORTED; i++) 315 if (drm_amdgpu[i] >=0) 316 close(drm_amdgpu[i]); 317 } 318 319 /* Print AMD devices information */ 320 static void amdgpu_print_devices() 321 { 322 int i; 323 drmDevicePtr device; 324 325 /* Open the first AMD devcie to print driver information. */ 326 if (drm_amdgpu[0] >=0) { 327 /* Display AMD driver version information.*/ 328 drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]); 329 330 if (retval == NULL) { 331 perror("Cannot get version for AMDGPU device"); 332 return; 333 } 334 335 printf("Driver name: %s, Date: %s, Description: %s.\n", 336 retval->name, retval->date, retval->desc); 337 drmFreeVersion(retval); 338 } 339 340 /* Display information of AMD devices */ 341 printf("Devices:\n"); 342 for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++) 343 if (drmGetDevice2(drm_amdgpu[i], 344 DRM_DEVICE_GET_PCI_REVISION, 345 &device) == 0) { 346 if (device->bustype == DRM_BUS_PCI) { 347 printf("PCI "); 348 printf(" domain:%04x", 349 device->businfo.pci->domain); 350 printf(" bus:%02x", 351 device->businfo.pci->bus); 352 printf(" device:%02x", 353 device->businfo.pci->dev); 354 printf(" function:%01x", 355 device->businfo.pci->func); 356 printf(" vendor_id:%04x", 357 device->deviceinfo.pci->vendor_id); 358 printf(" device_id:%04x", 359 device->deviceinfo.pci->device_id); 360 printf(" subvendor_id:%04x", 361 device->deviceinfo.pci->subvendor_id); 362 printf(" subdevice_id:%04x", 363 device->deviceinfo.pci->subdevice_id); 364 printf(" revision_id:%02x", 365 device->deviceinfo.pci->revision_id); 366 printf("\n"); 367 } 368 drmFreeDevice(&device); 369 } 370 } 371 372 /* Find a match AMD device in PCI bus 373 * Return the index of the device or -1 if not found 374 */ 375 static int amdgpu_find_device(uint8_t bus, uint16_t dev) 376 { 377 int i; 378 drmDevicePtr device; 379 380 for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >= 0; i++) { 381 if (drmGetDevice2(drm_amdgpu[i], 382 DRM_DEVICE_GET_PCI_REVISION, 383 &device) == 0) { 384 if (device->bustype == DRM_BUS_PCI) 385 if ((bus == 0xFF || device->businfo.pci->bus == bus) && 386 device->deviceinfo.pci->device_id == dev) { 387 drmFreeDevice(&device); 388 return i; 389 } 390 391 drmFreeDevice(&device); 392 } 393 } 394 395 return -1; 396 } 397 398 static void amdgpu_disable_suites() 399 { 400 amdgpu_device_handle device_handle; 401 uint32_t major_version, minor_version, family_id; 402 int i; 403 int size = sizeof(suites_active_stat) / sizeof(suites_active_stat[0]); 404 405 if (amdgpu_device_initialize(drm_amdgpu[0], &major_version, 406 &minor_version, &device_handle)) 407 return; 408 409 family_id = device_handle->info.family_id; 410 411 if (amdgpu_device_deinitialize(device_handle)) 412 return; 413 414 /* Set active status for suites based on their policies */ 415 for (i = 0; i < size; ++i) 416 if (amdgpu_set_suite_active(suites_active_stat[i].pName, 417 suites_active_stat[i].pActive())) 418 fprintf(stderr, "suite deactivation failed - %s\n", CU_get_error_msg()); 419 420 /* Explicitly disable specific tests due to known bugs or preferences */ 421 /* 422 * BUG: Compute ring stalls and never recovers when the address is 423 * written after the command already submitted 424 */ 425 if (amdgpu_set_test_active(DEADLOCK_TESTS_STR, "compute ring block test", CU_FALSE)) 426 fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); 427 428 if (amdgpu_set_test_active(BO_TESTS_STR, "Metadata", CU_FALSE)) 429 fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); 430 431 if (amdgpu_set_test_active(BASIC_TESTS_STR, "bo eviction Test", CU_FALSE)) 432 fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); 433 434 /* This test was ran on GFX8 and GFX9 only */ 435 if (family_id < AMDGPU_FAMILY_VI || family_id > AMDGPU_FAMILY_RV) 436 if (amdgpu_set_test_active(BASIC_TESTS_STR, "Sync dependency Test", CU_FALSE)) 437 fprintf(stderr, "test deactivation failed - %s\n", CU_get_error_msg()); 438 } 439 440 /* The main() function for setting up and running the tests. 441 * Returns a CUE_SUCCESS on successful running, another 442 * CUnit error code on failure. 443 */ 444 int main(int argc, char **argv) 445 { 446 int c; /* Character received from getopt */ 447 int i = 0; 448 int suite_id = -1; /* By default run everything */ 449 int test_id = -1; /* By default run all tests in the suite */ 450 int pci_bus_id = -1; /* By default PC bus ID is not specified */ 451 int pci_device_id = 0; /* By default PC device ID is zero */ 452 int display_devices = 0;/* By default not to display devices' info */ 453 CU_pSuite pSuite = NULL; 454 CU_pTest pTest = NULL; 455 int test_device_index; 456 int display_list = 0; 457 int force_run = 0; 458 459 for (i = 0; i < MAX_CARDS_SUPPORTED; i++) 460 drm_amdgpu[i] = -1; 461 462 463 /* Parse command line string */ 464 opterr = 0; /* Do not print error messages from getopt */ 465 while ((c = getopt(argc, argv, options)) != -1) { 466 switch (c) { 467 case 'l': 468 display_list = 1; 469 break; 470 case 's': 471 suite_id = atoi(optarg); 472 break; 473 case 't': 474 test_id = atoi(optarg); 475 break; 476 case 'b': 477 pci_bus_id = atoi(optarg); 478 break; 479 case 'd': 480 sscanf(optarg, "%x", &pci_device_id); 481 break; 482 case 'p': 483 display_devices = 1; 484 break; 485 case 'r': 486 open_render_node = 1; 487 break; 488 case 'f': 489 force_run = 1; 490 break; 491 case '?': 492 case 'h': 493 fprintf(stderr, usage, argv[0]); 494 exit(EXIT_SUCCESS); 495 default: 496 fprintf(stderr, usage, argv[0]); 497 exit(EXIT_FAILURE); 498 } 499 } 500 501 if (amdgpu_open_devices(open_render_node) <= 0) { 502 perror("Cannot open AMDGPU device"); 503 exit(EXIT_FAILURE); 504 } 505 506 if (drm_amdgpu[0] < 0) { 507 perror("Cannot open AMDGPU device"); 508 exit(EXIT_FAILURE); 509 } 510 511 if (display_devices) { 512 amdgpu_print_devices(); 513 amdgpu_close_devices(); 514 exit(EXIT_SUCCESS); 515 } 516 517 if (pci_bus_id > 0 || pci_device_id) { 518 /* A device was specified to run the test */ 519 test_device_index = amdgpu_find_device(pci_bus_id, 520 pci_device_id); 521 522 if (test_device_index >= 0) { 523 /* Most tests run on device of drm_amdgpu[0]. 524 * Swap the chosen device to drm_amdgpu[0]. 525 */ 526 i = drm_amdgpu[0]; 527 drm_amdgpu[0] = drm_amdgpu[test_device_index]; 528 drm_amdgpu[test_device_index] = i; 529 } else { 530 fprintf(stderr, 531 "The specified GPU device does not exist.\n"); 532 exit(EXIT_FAILURE); 533 } 534 } 535 536 /* Initialize test suites to run */ 537 538 /* initialize the CUnit test registry */ 539 if (CUE_SUCCESS != CU_initialize_registry()) { 540 amdgpu_close_devices(); 541 return CU_get_error(); 542 } 543 544 /* Register suites. */ 545 if (CU_register_suites(suites) != CUE_SUCCESS) { 546 fprintf(stderr, "suite registration failed - %s\n", 547 CU_get_error_msg()); 548 CU_cleanup_registry(); 549 amdgpu_close_devices(); 550 exit(EXIT_FAILURE); 551 } 552 553 /* Run tests using the CUnit Basic interface */ 554 CU_basic_set_mode(CU_BRM_VERBOSE); 555 556 /* Disable suites and individual tests based on misc. conditions */ 557 amdgpu_disable_suites(); 558 559 if (display_list) { 560 display_test_suites(); 561 goto end; 562 } 563 564 if (suite_id != -1) { /* If user specify particular suite? */ 565 pSuite = CU_get_suite_by_index((unsigned int) suite_id, 566 CU_get_registry()); 567 568 if (pSuite) { 569 570 if (force_run) 571 CU_set_suite_active(pSuite, CU_TRUE); 572 573 if (test_id != -1) { /* If user specify test id */ 574 pTest = CU_get_test_by_index( 575 (unsigned int) test_id, 576 pSuite); 577 if (pTest) { 578 if (force_run) 579 CU_set_test_active(pTest, CU_TRUE); 580 581 CU_basic_run_test(pSuite, pTest); 582 } 583 else { 584 fprintf(stderr, "Invalid test id: %d\n", 585 test_id); 586 CU_cleanup_registry(); 587 amdgpu_close_devices(); 588 exit(EXIT_FAILURE); 589 } 590 } else 591 CU_basic_run_suite(pSuite); 592 } else { 593 fprintf(stderr, "Invalid suite id : %d\n", 594 suite_id); 595 CU_cleanup_registry(); 596 amdgpu_close_devices(); 597 exit(EXIT_FAILURE); 598 } 599 } else 600 CU_basic_run_tests(); 601 602 end: 603 CU_cleanup_registry(); 604 amdgpu_close_devices(); 605 return CU_get_error(); 606 } 607