Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/panfrost/lib/decode_common.c
4560 views
1
/*
2
* Copyright (C) 2019 Alyssa Rosenzweig
3
* Copyright (C) 2017-2018 Lyude Paul
4
* Copyright (C) 2019 Collabora, Ltd.
5
*
6
* Permission is hereby granted, free of charge, to any person obtaining a
7
* copy of this software and associated documentation files (the "Software"),
8
* to deal in the Software without restriction, including without limitation
9
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
* and/or sell copies of the Software, and to permit persons to whom the
11
* Software is furnished to do so, subject to the following conditions:
12
*
13
* The above copyright notice and this permission notice (including the next
14
* paragraph) shall be included in all copies or substantial portions of the
15
* Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
* SOFTWARE.
24
*/
25
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <assert.h>
29
#include <stdint.h>
30
#include <string.h>
31
#include <sys/mman.h>
32
33
#include "decode.h"
34
#include "util/macros.h"
35
#include "util/u_debug.h"
36
#include "util/u_dynarray.h"
37
#include "util/hash_table.h"
38
39
/* Memory handling */
40
41
static struct hash_table_u64 *mmap_table;
42
43
static struct util_dynarray ro_mappings;
44
45
static struct pandecode_mapped_memory *
46
pandecode_find_mapped_gpu_mem_containing_rw(uint64_t addr)
47
{
48
return _mesa_hash_table_u64_search(mmap_table, addr & ~(4096 - 1));
49
}
50
51
struct pandecode_mapped_memory *
52
pandecode_find_mapped_gpu_mem_containing(uint64_t addr)
53
{
54
struct pandecode_mapped_memory *mem = pandecode_find_mapped_gpu_mem_containing_rw(addr);
55
56
if (mem && mem->addr && !mem->ro) {
57
mprotect(mem->addr, mem->length, PROT_READ);
58
mem->ro = true;
59
util_dynarray_append(&ro_mappings, struct pandecode_mapped_memory *, mem);
60
}
61
62
return mem;
63
}
64
65
void
66
pandecode_map_read_write(void)
67
{
68
util_dynarray_foreach(&ro_mappings, struct pandecode_mapped_memory *, mem) {
69
(*mem)->ro = false;
70
mprotect((*mem)->addr, (*mem)->length, PROT_READ | PROT_WRITE);
71
}
72
util_dynarray_clear(&ro_mappings);
73
}
74
75
static void
76
pandecode_add_name(struct pandecode_mapped_memory *mem, uint64_t gpu_va, const char *name)
77
{
78
if (!name) {
79
/* If we don't have a name, assign one */
80
81
snprintf(mem->name, sizeof(mem->name) - 1,
82
"memory_%" PRIx64, gpu_va);
83
} else {
84
assert((strlen(name) + 1) < sizeof(mem->name));
85
memcpy(mem->name, name, strlen(name) + 1);
86
}
87
}
88
89
void
90
pandecode_inject_mmap(uint64_t gpu_va, void *cpu, unsigned sz, const char *name)
91
{
92
/* First, search if we already mapped this and are just updating an address */
93
94
struct pandecode_mapped_memory *existing =
95
pandecode_find_mapped_gpu_mem_containing_rw(gpu_va);
96
97
if (existing && existing->gpu_va == gpu_va) {
98
existing->length = sz;
99
existing->addr = cpu;
100
pandecode_add_name(existing, gpu_va, name);
101
return;
102
}
103
104
/* Otherwise, add a fresh mapping */
105
struct pandecode_mapped_memory *mapped_mem = NULL;
106
107
mapped_mem = calloc(1, sizeof(*mapped_mem));
108
mapped_mem->gpu_va = gpu_va;
109
mapped_mem->length = sz;
110
mapped_mem->addr = cpu;
111
pandecode_add_name(mapped_mem, gpu_va, name);
112
113
/* Add it to the table */
114
assert((gpu_va & 4095) == 0);
115
116
for (unsigned i = 0; i < sz; i += 4096)
117
_mesa_hash_table_u64_insert(mmap_table, gpu_va + i, mapped_mem);
118
}
119
120
void
121
pandecode_inject_free(uint64_t gpu_va, unsigned sz)
122
{
123
struct pandecode_mapped_memory *mem =
124
pandecode_find_mapped_gpu_mem_containing_rw(gpu_va);
125
126
if (!mem)
127
return;
128
129
assert(mem->gpu_va == gpu_va);
130
assert(mem->length == sz);
131
132
free(mem);
133
134
for (unsigned i = 0; i < sz; i += 4096)
135
_mesa_hash_table_u64_remove(mmap_table, gpu_va + i);
136
}
137
138
char *
139
pointer_as_memory_reference(uint64_t ptr)
140
{
141
struct pandecode_mapped_memory *mapped;
142
char *out = malloc(128);
143
144
/* Try to find the corresponding mapped zone */
145
146
mapped = pandecode_find_mapped_gpu_mem_containing_rw(ptr);
147
148
if (mapped) {
149
snprintf(out, 128, "%s + %d", mapped->name, (int) (ptr - mapped->gpu_va));
150
return out;
151
}
152
153
/* Just use the raw address if other options are exhausted */
154
155
snprintf(out, 128, "0x%" PRIx64, ptr);
156
return out;
157
158
}
159
160
static int pandecode_dump_frame_count = 0;
161
162
static bool force_stderr = false;
163
164
void
165
pandecode_dump_file_open(void)
166
{
167
if (pandecode_dump_stream)
168
return;
169
170
/* This does a getenv every frame, so it is possible to use
171
* setenv to change the base at runtime.
172
*/
173
const char *dump_file_base = debug_get_option("PANDECODE_DUMP_FILE", "pandecode.dump");
174
if (force_stderr || !strcmp(dump_file_base, "stderr"))
175
pandecode_dump_stream = stderr;
176
else {
177
char buffer[1024];
178
snprintf(buffer, sizeof(buffer), "%s.%04d", dump_file_base, pandecode_dump_frame_count);
179
printf("pandecode: dump command stream to file %s\n", buffer);
180
pandecode_dump_stream = fopen(buffer, "w");
181
if (!pandecode_dump_stream)
182
fprintf(stderr,
183
"pandecode: failed to open command stream log file %s\n",
184
buffer);
185
}
186
}
187
188
static void
189
pandecode_dump_file_close(void)
190
{
191
if (pandecode_dump_stream && pandecode_dump_stream != stderr) {
192
if (fclose(pandecode_dump_stream))
193
perror("pandecode: dump file");
194
195
pandecode_dump_stream = NULL;
196
}
197
}
198
199
void
200
pandecode_initialize(bool to_stderr)
201
{
202
force_stderr = to_stderr;
203
mmap_table = _mesa_hash_table_u64_create(NULL);
204
util_dynarray_init(&ro_mappings, NULL);
205
}
206
207
void
208
pandecode_next_frame(void)
209
{
210
pandecode_dump_file_close();
211
pandecode_dump_frame_count++;
212
}
213
214
void
215
pandecode_close(void)
216
{
217
_mesa_hash_table_u64_destroy(mmap_table);
218
util_dynarray_fini(&ro_mappings);
219
pandecode_dump_file_close();
220
}
221
222