Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2013 Jérôme Glisse
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sub license, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16.  * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
  17.  * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  20.  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  21.  *
  22.  * The above copyright notice and this permission notice (including the
  23.  * next paragraph) shall be included in all copies or substantial portions
  24.  * of the Software.
  25.  */
  26. /*
  27.  * Authors:
  28.  *      Jérôme Glisse <jglisse@redhat.com>
  29.  */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <stdint.h>
  33. #include <xf86drm.h>
  34. #include "radeon_drm_cs.h"
  35. #include "radeon_drm_bo.h"
  36.  
  37. #define RADEON_CS_DUMP_AFTER_MS_TIMEOUT         500
  38.  
  39. void radeon_dump_cs_on_lockup(struct radeon_drm_cs *cs, struct radeon_cs_context *csc)
  40. {
  41.     struct drm_radeon_gem_busy args;
  42.     FILE *dump;
  43.     unsigned i, lockup;
  44.     uint32_t *ptr;
  45.     char fname[32];
  46.  
  47.     /* only dump the first cs to cause a lockup */
  48.     if (!csc->crelocs) {
  49.         /* can not determine if there was a lockup if no bo were use by
  50.          * the cs and most likely in such case no lockup occurs
  51.          */
  52.         return;
  53.     }
  54.  
  55.     memset(&args, 0, sizeof(args));
  56.     args.handle = csc->relocs_bo[0]->handle;
  57.     for (i = 0; i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT; i++) {
  58.         usleep(1);
  59.         lockup = drmCommandWriteRead(csc->fd, DRM_RADEON_GEM_BUSY, &args, sizeof(args));
  60.         if (!lockup) {
  61.             break;
  62.         }
  63.     }
  64.     if (!lockup || i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT) {
  65.         return;
  66.     }
  67.  
  68.     ptr = radeon_bo_do_map(cs->trace_buf);
  69.     fprintf(stderr, "timeout on cs lockup likely happen at cs 0x%08x dw 0x%08x\n", ptr[1], ptr[0]);
  70.  
  71.     if (csc->cs_trace_id != ptr[1]) {
  72.         return;
  73.     }
  74.  
  75.     /* ok we are most likely facing a lockup write the standalone replay file */
  76.     snprintf(fname, sizeof(fname), "rlockup_0x%08x.c", csc->cs_trace_id);
  77.     dump = fopen(fname, "w");
  78.     if (dump == NULL) {
  79.         return;
  80.     }
  81.     fprintf(dump, "/* To build this file you will need to copy radeon_ctx.h\n");
  82.     fprintf(dump, " * in same directory. You can find radeon_ctx.h in mesa tree :\n");
  83.     fprintf(dump, " * mesa/src/gallium/winsys/radeon/tools/radeon_ctx.h\n");
  84.     fprintf(dump, " * Build with :\n");
  85.     fprintf(dump, " * gcc -O0 -g %s -ldrm -o rlockup_0x%08x -I/usr/include/libdrm\n", fname, csc->cs_trace_id);
  86.     fprintf(dump, " */\n");
  87.     fprintf(dump, " /* timeout on cs lockup likely happen at cs 0x%08x dw 0x%08x*/\n", ptr[1], ptr[0]);
  88.     fprintf(dump, "#include <stdio.h>\n");
  89.     fprintf(dump, "#include <stdint.h>\n");
  90.     fprintf(dump, "#include \"radeon_ctx.h\"\n");
  91.     fprintf(dump, "\n");
  92.     fprintf(dump, "#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))\n");
  93.     fprintf(dump, "\n");
  94.  
  95.     for (i = 0; i < csc->crelocs; i++) {
  96.         unsigned j, ndw = (csc->relocs_bo[i]->base.size + 3) >> 2;
  97.  
  98.         ptr = radeon_bo_do_map(csc->relocs_bo[i]);
  99.         if (ptr) {
  100.             fprintf(dump, "static uint32_t bo_%04d_data[%d] = {\n   ", i, ndw);
  101.             for (j = 0; j < ndw; j++) {
  102.                 if (j && !(j % 8)) {
  103.                     uint32_t offset = (j - 8) << 2;
  104.                     fprintf(dump, "  /* [0x%08x] va[0x%016lx] */\n   ", offset, offset + csc->relocs_bo[i]->va);
  105.                 }
  106.                 fprintf(dump, " 0x%08x,", ptr[j]);
  107.             }
  108.             fprintf(dump, "};\n\n");
  109.         }
  110.     }
  111.  
  112.     fprintf(dump, "static uint32_t bo_relocs[%d] = {\n", csc->crelocs * 4);
  113.     for (i = 0; i < csc->crelocs; i++) {
  114.         fprintf(dump, "    0x%08x, 0x%08x, 0x%08x, 0x%08x,\n",
  115.                 0, csc->relocs[i].read_domains, csc->relocs[i].write_domain, csc->relocs[i].flags);
  116.     }
  117.     fprintf(dump, "};\n\n");
  118.  
  119.     fprintf(dump, "/* cs %d dw */\n", csc->chunks[0].length_dw);
  120.     fprintf(dump, "static uint32_t cs[] = {\n");
  121.     ptr = csc->buf;
  122.     for (i = 0; i < csc->chunks[0].length_dw; i++) {
  123.         fprintf(dump, "    0x%08x,\n", ptr[i]);
  124.     }
  125.     fprintf(dump, "};\n\n");
  126.  
  127.     fprintf(dump, "static uint32_t cs_flags[2] = {\n");
  128.     fprintf(dump, "    0x%08x,\n", csc->flags[0]);
  129.     fprintf(dump, "    0x%08x,\n", csc->flags[1]);
  130.     fprintf(dump, "};\n\n");
  131.  
  132.     fprintf(dump, "int main(int argc, char *argv[])\n");
  133.     fprintf(dump, "{\n");
  134.     fprintf(dump, "    struct bo *bo[%d];\n", csc->crelocs);
  135.     fprintf(dump, "    struct ctx ctx;\n");
  136.     fprintf(dump, "\n");
  137.     fprintf(dump, "    ctx_init(&ctx);\n");
  138.     fprintf(dump, "\n");
  139.  
  140.     for (i = 0; i < csc->crelocs; i++) {
  141.         unsigned ndw = (csc->relocs_bo[i]->base.size + 3) >> 2;
  142.         uint32_t *ptr;
  143.  
  144.         ptr = radeon_bo_do_map(csc->relocs_bo[i]);
  145.         if (ptr) {
  146.             fprintf(dump, "    bo[%d] = bo_new(&ctx, %d, bo_%04d_data, 0x%016lx, 0x%08x);\n",
  147.                     i, ndw, i, csc->relocs_bo[i]->va, csc->relocs_bo[i]->base.alignment);
  148.         } else {
  149.             fprintf(dump, "    bo[%d] = bo_new(&ctx, %d, NULL, 0x%016lx, 0x%08x);\n",
  150.                     i, ndw, csc->relocs_bo[i]->va, csc->relocs_bo[i]->base.alignment);
  151.         }
  152.     }
  153.     fprintf(dump, "\n");
  154.     fprintf(dump, "    ctx_cs(&ctx, cs, cs_flags, ARRAY_SIZE(cs), bo, bo_relocs, %d);\n", csc->crelocs);
  155.     fprintf(dump, "\n");
  156.     fprintf(dump, "    fprintf(stderr, \"waiting for cs execution to end ....\\n\");\n");
  157.     fprintf(dump, "    bo_wait(&ctx, bo[0]);\n");
  158.     fprintf(dump, "}\n");
  159.     fclose(dump);
  160. }
  161.