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