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