1/* 2 * Copyright (C) 2019 Alyssa Rosenzweig 3 * Copyright (C) 2017-2018 Lyude Paul 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <assert.h> 28#include <stdint.h> 29#include <string.h> 30 31#include "mmap.h" 32int pandecode_replay_jc(mali_ptr jc_gpu_va, bool bifrost); 33 34/* Memory handling */ 35 36static struct pandecode_mapped_memory mmaps; 37 38struct pandecode_mapped_memory * 39pandecode_find_mapped_gpu_mem_containing(mali_ptr addr) 40{ 41 list_for_each_entry(struct pandecode_mapped_memory, pos, &mmaps.node, node) { 42 if (addr >= pos->gpu_va && addr < pos->gpu_va + pos->length) 43 return pos; 44 } 45 46 return NULL; 47} 48 49char * 50pointer_as_memory_reference(mali_ptr ptr) 51{ 52 struct pandecode_mapped_memory *mapped; 53 char *out = malloc(128); 54 55 /* Try to find the corresponding mapped zone */ 56 57 mapped = pandecode_find_mapped_gpu_mem_containing(ptr); 58 59 if (mapped) { 60 snprintf(out, 128, "%s + %d", mapped->name, (int) (ptr - mapped->gpu_va)); 61 return out; 62 } 63 64 /* Just use the raw address if other options are exhausted */ 65 66 snprintf(out, 128, MALI_PTR_FMT, ptr); 67 return out; 68 69} 70 71/* Parsing */ 72 73static FILE * 74pandecode_read_filename(const char *base, const char *name) 75{ 76 char *fn = NULL; 77 asprintf(&fn, "%s/%s", base, name); 78 79 FILE *fp = fopen(fn, "rb"); 80 free(fn); 81 82 return fp; 83} 84 85static void 86pandecode_read_memory(const char *base, const char *name, mali_ptr gpu_va) 87{ 88 FILE *fp = pandecode_read_filename(base, name); 89 90 if (!fp) { 91 fprintf(stderr, "Warning: missing %s\n", name); 92 return; 93 } 94 95 fseek(fp, 0, SEEK_END); 96 long sz = ftell(fp); 97 fseek(fp, 0, SEEK_SET); 98 99 char *buf = malloc(sz); 100 assert(buf); 101 fread(buf, 1, sz, fp); 102 fclose(fp); 103 104 /* Now that we have the memory loaded in, create a mmap entry for it so 105 * we remember it later */ 106 107 struct pandecode_mapped_memory *mapped_mem = NULL; 108 109 mapped_mem = malloc(sizeof(*mapped_mem)); 110 list_inithead(&mapped_mem->node); 111 112 mapped_mem->gpu_va = gpu_va; 113 mapped_mem->length = sz; 114 mapped_mem->addr = buf; 115 116 memcpy(mapped_mem->name, name, strlen(name)); 117 118 list_add(&mapped_mem->node, &mmaps.node); 119} 120 121static void 122pandecode_read_mmap(const char *base, const char *line) 123{ 124 assert(strlen(line) < 500); 125 126 mali_ptr addr; 127 char name[512]; 128 129 sscanf(line, "MMAP %" PRIx64 " %s", &addr, name); 130 pandecode_read_memory(base, name, addr); 131} 132 133static void 134pandecode_read_job_submit(const char *base, const char *line) 135{ 136 mali_ptr addr; 137 unsigned core_req; 138 unsigned is_bifrost; 139 140 sscanf(line, "JS %" PRIx64 " %x %x", &addr, &core_req, &is_bifrost); 141 pandecode_replay_jc(addr, is_bifrost); 142} 143 144/* Reads the control file, processing as it goes. */ 145 146static void 147pandecode_read_control(const char *base) 148{ 149 FILE *fp = pandecode_read_filename(base, "control.log"); 150 151 if (!fp) { 152 fprintf(stderr, "Invalid directory path\n"); 153 return; 154 } 155 156 char *line = NULL; 157 size_t len = 0; 158 159 while (getline(&line, &len, fp) != -1) { 160 switch (line[0]) { 161 case 'M': 162 pandecode_read_mmap(base, line); 163 break; 164 165 case 'J': 166 pandecode_read_job_submit(base, line); 167 break; 168 169 default: 170 assert(0); 171 break; 172 } 173 } 174} 175 176int 177main(int argc, char **argv) 178{ 179 if (argc < 2) { 180 fprintf(stderr, "Usage: pandecode [directory]\n"); 181 exit(1); 182 } 183 184 /* Initialize */ 185 list_inithead(&mmaps.node); 186 187 /* Let's go! */ 188 pandecode_read_control(argv[1]); 189} 190