drmstat.c revision 1c33c6909546e3b51f36c04bba12cc2275149902
1/* drmstat.c -- DRM device status and testing program 2 * Created: Tue Jan 5 08:19:24 1999 by faith@precisioninsight.com 3 * Revised: Mon Dec 6 10:33:46 1999 by faith@precisioninsight.com 4 * 5 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * $PI: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmstat.c,v 1.28 1999/08/04 18:12:11 faith Exp $ 28 * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmstat.c,v 1.2 1999/12/14 01:33:56 robin Exp $ 29 * 30 */ 31 32#include <stdio.h> 33#include <stdlib.h> 34#include <unistd.h> 35#include <sys/types.h> 36#include <sys/time.h> 37#include <sys/mman.h> 38#include <getopt.h> 39#include <strings.h> 40#include <errno.h> 41#include <signal.h> 42#include <fcntl.h> 43#include "xf86drm.h" 44 45int sigio_fd; 46 47static double usec(struct timeval *end, struct timeval *start) 48{ 49 double e = end->tv_sec * 1000000 + end->tv_usec; 50 double s = start->tv_sec * 1000000 + start->tv_usec; 51 52 return e - s; 53} 54 55static void getversion(int fd) 56{ 57 drmVersionPtr version; 58 59 version = drmGetVersion(fd); 60 if (version) { 61 printf( "Name: %s\n", version->name ? version->name : "?" ); 62 printf( " Version: %d.%d.%d\n", 63 version->version_major, 64 version->version_minor, 65 version->version_patchlevel ); 66 printf( " Date: %s\n", version->date ? version->date : "?" ); 67 printf( " Desc: %s\n", version->desc ? version->desc : "?" ); 68 drmFreeVersion(version); 69 } else { 70 printf( "No driver available\n" ); 71 } 72} 73 74void handler(int fd, void *oldctx, void *newctx) 75{ 76 printf("Got fd %d\n", fd); 77} 78 79void process_sigio(char *device) 80{ 81 int fd; 82 83 if ((fd = open(device, 0)) < 0) { 84 drmError(-errno, __FUNCTION__); 85 exit(1); 86 } 87 88 sigio_fd = fd; 89 drmInstallSIGIOHandler(fd, handler); 90 for (;;) sleep(60); 91} 92 93int main(int argc, char **argv) 94{ 95 int c; 96 int r = 0; 97 int fd = -1; 98 drmHandle handle; 99 void *address; 100 char *pt; 101 unsigned long count; 102 unsigned long offset; 103 unsigned long size; 104 drmContext context; 105 int loops; 106 char buf[1024]; 107 int i; 108 drmBufInfoPtr info; 109 drmBufMapPtr bufs; 110 drmLockPtr lock; 111 int secs; 112 113 while ((c = getopt(argc, argv, 114 "lc:vo:O:f:s:w:W:b:r:R:P:L:C:XS:B:F:")) != EOF) 115 switch (c) { 116 case 'F': 117 count = strtoul(optarg, NULL, 0); 118 if (!fork()) { 119 dup(fd); 120 sleep(count); 121 } 122 close(fd); 123 break; 124 case 'v': getversion(fd); break; 125 case 'X': 126 if ((r = drmCreateContext(fd, &context))) { 127 drmError(r, argv[0]); 128 return 1; 129 } 130 printf( "Got %d\n", context); 131 break; 132 case 'S': 133 process_sigio(optarg); 134 break; 135 case 'C': 136 if ((r = drmSwitchToContext(fd, strtoul(optarg, NULL, 0)))) { 137 drmError(r, argv[0]); 138 return 1; 139 } 140 break; 141 case 'c': 142 if ((r = drmSetBusid(fd,optarg))) { 143 drmError(r, argv[0]); 144 return 1; 145 } 146 break; 147 case 'o': 148 if ((fd = drmOpen(optarg, NULL)) < 0) { 149 drmError(fd, argv[0]); 150 return 1; 151 } 152 break; 153 case 'O': 154 if ((fd = drmOpen(NULL, optarg)) < 0) { 155 drmError(fd, argv[0]); 156 return 1; 157 } 158 break; 159 case 'B': /* Test buffer allocation */ 160 count = strtoul(optarg, &pt, 0); 161 size = strtoul(pt+1, &pt, 0); 162 secs = strtoul(pt+1, NULL, 0); 163 { 164 drmDMAReq dma; 165 int *indices, *sizes; 166 167 indices = alloca(sizeof(*indices) * count); 168 sizes = alloca(sizeof(*sizes) * count); 169 dma.context = context; 170 dma.send_count = 0; 171 dma.request_count = count; 172 dma.request_size = size; 173 dma.request_list = indices; 174 dma.request_sizes = sizes; 175 dma.flags = DRM_DMA_WAIT; 176 if ((r = drmDMA(fd, &dma))) { 177 drmError(r, argv[0]); 178 return 1; 179 } 180 for (i = 0; i < dma.granted_count; i++) { 181 printf("%5d: index = %d, size = %d\n", 182 i, dma.request_list[i], dma.request_sizes[i]); 183 } 184 sleep(secs); 185 drmFreeBufs(fd, dma.granted_count, indices); 186 } 187 break; 188 case 'b': 189 count = strtoul(optarg, &pt, 0); 190 size = strtoul(pt+1, NULL, 0); 191 if ((r = drmAddBufs(fd, count, size, 0)) < 0) { 192 drmError(r, argv[0]); 193 return 1; 194 } 195 if (!(info = drmGetBufInfo(fd))) { 196 drmError(0, argv[0]); 197 return 1; 198 } 199 for (i = 0; i < info->count; i++) { 200 printf("%5d buffers of size %6d (low = %d, high = %d)\n", 201 info->list[i].count, 202 info->list[i].size, 203 info->list[i].low_mark, 204 info->list[i].high_mark); 205 } 206 if ((r = drmMarkBufs(fd, 0.50, 0.80))) { 207 drmError(r, argv[0]); 208 return 1; 209 } 210 if (!(info = drmGetBufInfo(fd))) { 211 drmError(0, argv[0]); 212 return 1; 213 } 214 for (i = 0; i < info->count; i++) { 215 printf("%5d buffers of size %6d (low = %d, high = %d)\n", 216 info->list[i].count, 217 info->list[i].size, 218 info->list[i].low_mark, 219 info->list[i].high_mark); 220 } 221 printf("===== /proc/graphics/0/mem =====\n"); 222 sprintf(buf, "cat /proc/graphics/0/mem"); 223 system(buf); 224#if 1 225 if (!(bufs = drmMapBufs(fd))) { 226 drmError(0, argv[0]); 227 return 1; 228 } 229 printf("===============================\n"); 230 printf( "%d bufs\n", bufs->count); 231 for (i = 0; i < bufs->count; i++) { 232 printf( " %4d: %8d bytes at %p\n", 233 i, 234 bufs->list[i].total, 235 bufs->list[i].address); 236 } 237 printf("===== /proc/graphics/0/vma =====\n"); 238 sprintf(buf, "cat /proc/graphics/0/vma"); 239 system(buf); 240#endif 241 break; 242 case 'f': 243 offset = strtoul(optarg, &pt, 0); 244 size = strtoul(pt+1, NULL, 0); 245 handle = 0; 246 if ((r = drmAddMap(fd, offset, size, 247 DRM_FRAME_BUFFER, 0, &handle))) { 248 drmError(r, argv[0]); 249 return 1; 250 } 251 printf("0x%08lx:0x%04lx added\n", offset, size); 252 printf("===== /proc/graphics/0/mem =====\n"); 253 sprintf(buf, "cat /proc/graphics/0/mem"); 254 system(buf); 255 break; 256 case 'r': 257 case 'R': 258 offset = strtoul(optarg, &pt, 0); 259 size = strtoul(pt+1, NULL, 0); 260 handle = 0; 261 if ((r = drmAddMap(fd, offset, size, 262 DRM_REGISTERS, 263 c == 'R' ? DRM_READ_ONLY : 0, 264 &handle))) { 265 drmError(r, argv[0]); 266 return 1; 267 } 268 printf("0x%08lx:0x%04lx added\n", offset, size); 269 printf("===== /proc/graphics/0/mem =====\n"); 270 sprintf(buf, "cat /proc/graphics/0/mem"); 271 system(buf); 272 break; 273 case 's': 274 size = strtoul(optarg, &pt, 0); 275 handle = 0; 276 if ((r = drmAddMap(fd, 0, size, 277 DRM_SHM, DRM_CONTAINS_LOCK, 278 &handle))) { 279 drmError(r, argv[0]); 280 return 1; 281 } 282 printf("0x%04lx byte shm added at 0x%08lx\n", size, handle); 283 sprintf(buf, "cat /proc/graphics/0/vm"); 284 system(buf); 285 break; 286 case 'P': 287 offset = strtoul(optarg, &pt, 0); 288 size = strtoul(pt+1, NULL, 0); 289 address = NULL; 290 if ((r = drmMap(fd, offset, size, &address))) { 291 drmError(r, argv[0]); 292 return 1; 293 } 294 printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", 295 offset, size, address, getpid()); 296 printf("===== /proc/graphics/0/vma =====\n"); 297 sprintf(buf, "cat /proc/graphics/0/vma"); 298 system(buf); 299 mprotect((void *)offset, size, PROT_READ); 300 printf("===== /proc/graphics/0/vma =====\n"); 301 sprintf(buf, "cat /proc/graphics/0/vma"); 302 system(buf); 303 break; 304 case 'w': 305 case 'W': 306 offset = strtoul(optarg, &pt, 0); 307 size = strtoul(pt+1, NULL, 0); 308 address = NULL; 309 if ((r = drmMap(fd, offset, size, &address))) { 310 drmError(r, argv[0]); 311 return 1; 312 } 313 printf("0x%08lx:0x%04lx mapped at %p for pid %d\n", 314 offset, size, address, getpid()); 315 printf("===== /proc/%d/maps =====\n", getpid()); 316 sprintf(buf, "cat /proc/%d/maps", getpid()); 317 system(buf); 318 printf("===== /proc/grphics/0/mem =====\n"); 319 sprintf(buf, "cat /proc/graphics/0/mem"); 320 system(buf); 321 printf("===== /proc/graphics/0/vma =====\n"); 322 sprintf(buf, "cat /proc/graphics/0/vma"); 323 system(buf); 324 printf("===== READING =====\n"); 325 for (i = 0; i < 0x10; i++) 326 printf("%02x ", (unsigned int)((unsigned char *)address)[i]); 327 printf("\n"); 328 if (c == 'w') { 329 printf("===== WRITING =====\n"); 330 for (i = 0; i < size; i+=2) { 331 ((char *)address)[i] = i & 0xff; 332 ((char *)address)[i+1] = i & 0xff; 333 } 334 } 335 printf("===== READING =====\n"); 336 for (i = 0; i < 0x10; i++) 337 printf("%02x ", (unsigned int)((unsigned char *)address)[i]); 338 printf("\n"); 339 printf("===== /proc/graphics/0/vma =====\n"); 340 sprintf(buf, "cat /proc/graphics/0/vma"); 341 system(buf); 342 break; 343 case 'L': 344 context = strtoul(optarg, &pt, 0); 345 offset = strtoul(pt+1, &pt, 0); 346 size = strtoul(pt+1, &pt, 0); 347 loops = strtoul(pt+1, NULL, 0); 348 address = NULL; 349 if ((r = drmMap(fd, offset, size, &address))) { 350 drmError(r, argv[0]); 351 return 1; 352 } 353 lock = address; 354#if 1 355 { 356 int counter = 0; 357 struct timeval loop_start, loop_end; 358 struct timeval lock_start, lock_end; 359 double wt; 360#define HISTOSIZE 9 361 int histo[HISTOSIZE]; 362 int output = 0; 363 int fast = 0; 364 365 if (loops < 0) { 366 loops = -loops; 367 ++output; 368 } 369 370 for (i = 0; i < HISTOSIZE; i++) histo[i] = 0; 371 372 gettimeofday(&loop_start, NULL); 373 for (i = 0; i < loops; i++) { 374 gettimeofday(&lock_start, NULL); 375 DRM_LIGHT_LOCK_COUNT(fd,lock,context,fast); 376 gettimeofday(&lock_end, NULL); 377 DRM_UNLOCK(fd,lock,context); 378 ++counter; 379 wt = usec(&lock_end, &lock_start); 380 if (wt <= 2.5) ++histo[8]; 381 if (wt < 5.0) ++histo[0]; 382 else if (wt < 50.0) ++histo[1]; 383 else if (wt < 500.0) ++histo[2]; 384 else if (wt < 5000.0) ++histo[3]; 385 else if (wt < 50000.0) ++histo[4]; 386 else if (wt < 500000.0) ++histo[5]; 387 else if (wt < 5000000.0) ++histo[6]; 388 else ++histo[7]; 389 if (output) printf( "%.2f uSec, %d fast\n", wt, fast); 390 } 391 gettimeofday(&loop_end, NULL); 392 printf( "Average wait time = %.2f usec, %d fast\n", 393 usec(&loop_end, &loop_start) / counter, fast); 394 printf( "%9d <= 2.5 uS\n", histo[8]); 395 printf( "%9d < 5 uS\n", histo[0]); 396 printf( "%9d < 50 uS\n", histo[1]); 397 printf( "%9d < 500 uS\n", histo[2]); 398 printf( "%9d < 5000 uS\n", histo[3]); 399 printf( "%9d < 50000 uS\n", histo[4]); 400 printf( "%9d < 500000 uS\n", histo[5]); 401 printf( "%9d < 5000000 uS\n", histo[6]); 402 printf( "%9d >= 5000000 uS\n", histo[7]); 403 } 404#else 405 printf( "before lock: 0x%08x\n", lock->lock); 406 printf( "lock: 0x%08x\n", lock->lock); 407 sleep(5); 408 printf( "unlock: 0x%08x\n", lock->lock); 409#endif 410 break; 411 default: 412 fprintf( stderr, "Usage: drmstat [options]\n" ); 413 return 1; 414 } 415 416 return r; 417} 418