diff options
Diffstat (limited to 'src/freedreno/decode/buffers.c')
-rw-r--r-- | src/freedreno/decode/buffers.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/freedreno/decode/buffers.c b/src/freedreno/decode/buffers.c new file mode 100644 index 00000000000..8e696f857df --- /dev/null +++ b/src/freedreno/decode/buffers.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2012 Rob Clark <robdclark@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Helper lib to track gpu buffers contents/address, and map between gpu and + * host address while decoding cmdstream/crashdumps + */ + +#include <assert.h> +#include <stdlib.h> + +#include "buffers.h" + +struct buffer { + void *hostptr; + unsigned int len; + uint64_t gpuaddr; + + /* for 'once' mode, for buffers containing cmdstream keep track per offset + * into buffer of which modes it has already been dumped; + */ + struct { + unsigned offset; + unsigned dumped_mask; + } offsets[64]; + unsigned noffsets; +}; + +static struct buffer buffers[512]; +static int nbuffers; + +static int +buffer_contains_gpuaddr(struct buffer *buf, uint64_t gpuaddr, uint32_t len) +{ + return (buf->gpuaddr <= gpuaddr) && (gpuaddr < (buf->gpuaddr + buf->len)); +} + +static int +buffer_contains_hostptr(struct buffer *buf, void *hostptr) +{ + return (buf->hostptr <= hostptr) && (hostptr < (buf->hostptr + buf->len)); +} + + +uint64_t +gpuaddr(void *hostptr) +{ + int i; + for (i = 0; i < nbuffers; i++) + if (buffer_contains_hostptr(&buffers[i], hostptr)) + return buffers[i].gpuaddr + (hostptr - buffers[i].hostptr); + return 0; +} + +uint64_t +gpubaseaddr(uint64_t gpuaddr) +{ + int i; + if (!gpuaddr) + return 0; + for (i = 0; i < nbuffers; i++) + if (buffer_contains_gpuaddr(&buffers[i], gpuaddr, 0)) + return buffers[i].gpuaddr; + return 0; +} + +void * +hostptr(uint64_t gpuaddr) +{ + int i; + if (!gpuaddr) + return 0; + for (i = 0; i < nbuffers; i++) + if (buffer_contains_gpuaddr(&buffers[i], gpuaddr, 0)) + return buffers[i].hostptr + (gpuaddr - buffers[i].gpuaddr); + return 0; +} + +unsigned +hostlen(uint64_t gpuaddr) +{ + int i; + if (!gpuaddr) + return 0; + for (i = 0; i < nbuffers; i++) + if (buffer_contains_gpuaddr(&buffers[i], gpuaddr, 0)) + return buffers[i].len + buffers[i].gpuaddr - gpuaddr; + return 0; +} + +bool +has_dumped(uint64_t gpuaddr, unsigned enable_mask) +{ + if (!gpuaddr) + return false; + + for (int i = 0; i < nbuffers; i++) { + if (buffer_contains_gpuaddr(&buffers[i], gpuaddr, 0)) { + struct buffer *b = &buffers[i]; + assert(gpuaddr >= b->gpuaddr); + unsigned offset = gpuaddr - b->gpuaddr; + + unsigned n = 0; + while (n < b->noffsets) { + if (offset == b->offsets[n].offset) + break; + n++; + } + + /* if needed, allocate a new offset entry: */ + if (n == b->noffsets) { + b->noffsets++; + assert(b->noffsets < ARRAY_SIZE(b->offsets)); + b->offsets[n].dumped_mask = 0; + b->offsets[n].offset = offset; + } + + if ((b->offsets[n].dumped_mask & enable_mask) == enable_mask) + return true; + + b->offsets[n].dumped_mask |= enable_mask; + + return false; + } + } + + return false; +} + +void +reset_buffers(void) +{ + for (int i = 0; i < nbuffers; i++) { + free(buffers[i].hostptr); + buffers[i].hostptr = NULL; + buffers[i].len = 0; + buffers[i].noffsets = 0; + } + nbuffers = 0; +} + +/** + * Record buffer contents, takes ownership of hostptr (freed in + * reset_buffers()) + */ +void +add_buffer(uint64_t gpuaddr, unsigned int len, void *hostptr) +{ + int i; + + for (i = 0; i < nbuffers; i++) { + if (buffers[i].gpuaddr == gpuaddr) + break; + } + + if (i == nbuffers) { + /* some traces, like test-perf, with some blob versions, + * seem to generate an unreasonable # of gpu buffers (a + * leak?), so just ignore them. + */ + if (nbuffers >= ARRAY_SIZE(buffers)) { + free(hostptr); + return; + } + nbuffers++; + } + + buffers[i].hostptr = hostptr; + buffers[i].len = len; + buffers[i].gpuaddr = gpuaddr; +} |