Subversion Repositories Kolibri OS

Rev

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 <inttypes.h>
  34. #include <xf86drm.h>
  35. #include "radeon_drm_cs.h"
  36. #include "radeon_drm_bo.h"
  37.  
  38. #define RADEON_CS_DUMP_AFTER_MS_TIMEOUT         500
  39.  
  40. void radeon_dump_cs_on_lockup(struct radeon_drm_cs *cs, struct radeon_cs_context *csc)
  41. {
  42.     struct drm_radeon_gem_busy args;
  43.     FILE *dump;
  44.     unsigned i, lockup;
  45.     uint32_t *ptr;
  46.     char fname[32];
  47.  
  48.     /* only dump the first cs to cause a lockup */
  49.     if (!csc->crelocs) {
  50.         /* can not determine if there was a lockup if no bo were use by
  51.          * the cs and most likely in such case no lockup occurs
  52.          */
  53.         return;
  54.     }
  55.  
  56.     memset(&args, 0, sizeof(args));
  57.     args.handle = csc->relocs_bo[0]->handle;
  58.     for (i = 0; i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT; i++) {
  59.         usleep(1);
  60.         lockup = drmCommandWriteRead(csc->fd, DRM_RADEON_GEM_BUSY, &args, sizeof(args));
  61.         if (!lockup) {
  62.             break;
  63.         }
  64.     }
  65.     if (!lockup || i < RADEON_CS_DUMP_AFTER_MS_TIMEOUT) {
  66.         return;
  67.     }
  68.  
  69.     ptr = radeon_bo_do_map(cs->trace_buf);
  70.     fprintf(stderr, "timeout on cs lockup likely happen at cs 0x%08x dw 0x%08x\n", ptr[1], ptr[0]);
  71.  
  72.     if (csc->cs_trace_id != ptr[1]) {
  73.         return;
  74.     }
  75.  
  76.     /* ok we are most likely facing a lockup write the standalone replay file */
  77.     snprintf(fname, sizeof(fname), "rlockup_0x%08x.c", csc->cs_trace_id);
  78.     dump = fopen(fname, "w");
  79.     if (dump == NULL) {
  80.         return;
  81.     }
  82.     fprintf(dump, "/* To build this file you will need to copy radeon_ctx.h\n");
  83.     fprintf(dump, " * in same directory. You can find radeon_ctx.h in mesa tree :\n");
  84.     fprintf(dump, " * mesa/src/gallium/winsys/radeon/drm/radeon_ctx.h\n");
  85.     fprintf(dump, " * Build with :\n");
  86.     fprintf(dump, " * gcc -O0 -g `pkg-config --cflags --libs libdrm` %s -o rlockup_0x%08x \n", fname, csc->cs_trace_id);
  87.     fprintf(dump, " */\n");
  88.     fprintf(dump, " /* timeout on cs lockup likely happen at cs 0x%08x dw 0x%08x*/\n", ptr[1], ptr[0]);
  89.     fprintf(dump, "#include <stdio.h>\n");
  90.     fprintf(dump, "#include <stdint.h>\n");
  91.     fprintf(dump, "#include \"radeon_ctx.h\"\n");
  92.     fprintf(dump, "\n");
  93.     fprintf(dump, "#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))\n");
  94.     fprintf(dump, "\n");
  95.  
  96.     for (i = 0; i < csc->crelocs; i++) {
  97.         unsigned j, ndw = (csc->relocs_bo[i]->base.size + 3) >> 2;
  98.  
  99.         ptr = radeon_bo_do_map(csc->relocs_bo[i]);
  100.         if (ptr) {
  101.             fprintf(dump, "static uint32_t bo_%04d_data[%d] = {\n   ", i, ndw);
  102.             for (j = 0; j < ndw; j++) {
  103.                 if (j && !(j % 8)) {
  104.                     uint32_t offset = (j - 8) << 2;
  105.                     fprintf(dump, "  /* [0x%08x] va[0x%016"PRIx64"] */\n   ", offset, offset + csc->relocs_bo[i]->va);
  106.                 }
  107.                 fprintf(dump, " 0x%08x,", ptr[j]);
  108.             }
  109.             fprintf(dump, "};\n\n");
  110.         }
  111.     }
  112.  
  113.     fprintf(dump, "static uint32_t bo_relocs[%d] = {\n", csc->crelocs * 4);
  114.     for (i = 0; i < csc->crelocs; i++) {
  115.         fprintf(dump, "    0x%08x, 0x%08x, 0x%08x, 0x%08x,\n",
  116.                 0, csc->relocs[i].read_domains, csc->relocs[i].write_domain, csc->relocs[i].flags);
  117.     }
  118.     fprintf(dump, "};\n\n");
  119.  
  120.     fprintf(dump, "/* cs %d dw */\n", csc->chunks[0].length_dw);
  121.     fprintf(dump, "static uint32_t cs[] = {\n");
  122.     ptr = csc->buf;
  123.     for (i = 0; i < csc->chunks[0].length_dw; i++) {
  124.         fprintf(dump, "    0x%08x,\n", ptr[i]);
  125.     }
  126.     fprintf(dump, "};\n\n");
  127.  
  128.     fprintf(dump, "static uint32_t cs_flags[2] = {\n");
  129.     fprintf(dump, "    0x%08x,\n", csc->flags[0]);
  130.     fprintf(dump, "    0x%08x,\n", csc->flags[1]);
  131.     fprintf(dump, "};\n\n");
  132.  
  133.     fprintf(dump, "int main(int argc, char *argv[])\n");
  134.     fprintf(dump, "{\n");
  135.     fprintf(dump, "    struct bo *bo[%d];\n", csc->crelocs);
  136.     fprintf(dump, "    struct ctx ctx;\n");
  137.     fprintf(dump, "\n");
  138.     fprintf(dump, "    ctx_init(&ctx);\n");
  139.     fprintf(dump, "\n");
  140.  
  141.     for (i = 0; i < csc->crelocs; i++) {
  142.         unsigned ndw = (csc->relocs_bo[i]->base.size + 3) >> 2;
  143.         uint32_t *ptr;
  144.  
  145.         ptr = radeon_bo_do_map(csc->relocs_bo[i]);
  146.         if (ptr) {
  147.             fprintf(dump, "    bo[%d] = bo_new(&ctx, %d, bo_%04d_data, 0x%016"PRIx64", 0x%08x);\n",
  148.                     i, ndw, i, csc->relocs_bo[i]->va, csc->relocs_bo[i]->base.alignment);
  149.         } else {
  150.             fprintf(dump, "    bo[%d] = bo_new(&ctx, %d, NULL, 0x%016"PRIx64", 0x%08x);\n",
  151.                     i, ndw, csc->relocs_bo[i]->va, csc->relocs_bo[i]->base.alignment);
  152.         }
  153.     }
  154.     fprintf(dump, "\n");
  155.     fprintf(dump, "    ctx_cs(&ctx, cs, cs_flags, ARRAY_SIZE(cs), bo, bo_relocs, %d);\n", csc->crelocs);
  156.     fprintf(dump, "\n");
  157.     fprintf(dump, "    fprintf(stderr, \"waiting for cs execution to end ....\\n\");\n");
  158.     fprintf(dump, "    bo_wait(&ctx, bo[0]);\n");
  159.     fprintf(dump, "}\n");
  160.     fclose(dump);
  161. }
  162.