Path: blob/21.2-virgl/src/freedreno/decode/buffers.c
4565 views
/*1* Copyright (c) 2012 Rob Clark <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*/2223/*24* Helper lib to track gpu buffers contents/address, and map between gpu and25* host address while decoding cmdstream/crashdumps26*/2728#include <assert.h>29#include <stdlib.h>3031#include "util/rb_tree.h"32#include "buffers.h"3334struct buffer {35struct rb_node node;36void *hostptr;37unsigned int len;38uint64_t gpuaddr;3940/* for 'once' mode, for buffers containing cmdstream keep track per offset41* into buffer of which modes it has already been dumped;42*/43struct {44unsigned offset;45unsigned dumped_mask;46} offsets[64];47unsigned noffsets;48};4950static struct rb_tree buffers;5152static int53buffer_insert_cmp(const struct rb_node *n1, const struct rb_node *n2)54{55const struct buffer *buf1 = (const struct buffer *)n1;56const struct buffer *buf2 = (const struct buffer *)n2;57return buf1->gpuaddr - buf2->gpuaddr;58}5960static int61buffer_search_cmp(const struct rb_node *node, const void *addrptr)62{63const struct buffer *buf = (const struct buffer *)node;64uint64_t gpuaddr = *(uint64_t *)addrptr;65if (buf->gpuaddr + buf->len <= gpuaddr)66return -1;67else if (buf->gpuaddr > gpuaddr)68return 1;69return 0;70}7172static struct buffer *73get_buffer(uint64_t gpuaddr)74{75if (gpuaddr == 0)76return NULL;77return (struct buffer *)rb_tree_search(&buffers, &gpuaddr,78buffer_search_cmp);79}8081static int82buffer_contains_hostptr(struct buffer *buf, void *hostptr)83{84return (buf->hostptr <= hostptr) && (hostptr < (buf->hostptr + buf->len));85}8687uint64_t88gpuaddr(void *hostptr)89{90rb_tree_foreach(struct buffer, buf, &buffers, node)91{92if (buffer_contains_hostptr(buf, hostptr))93return buf->gpuaddr + (hostptr - buf->hostptr);94}95return 0;96}9798uint64_t99gpubaseaddr(uint64_t gpuaddr)100{101struct buffer *buf = get_buffer(gpuaddr);102if (buf)103return buf->gpuaddr;104else105return 0;106}107108void *109hostptr(uint64_t gpuaddr)110{111struct buffer *buf = get_buffer(gpuaddr);112if (buf)113return buf->hostptr + (gpuaddr - buf->gpuaddr);114else115return 0;116}117118unsigned119hostlen(uint64_t gpuaddr)120{121struct buffer *buf = get_buffer(gpuaddr);122if (buf)123return buf->len + buf->gpuaddr - gpuaddr;124else125return 0;126}127128bool129has_dumped(uint64_t gpuaddr, unsigned enable_mask)130{131if (!gpuaddr)132return false;133134struct buffer *b = get_buffer(gpuaddr);135if (!b)136return false;137138assert(gpuaddr >= b->gpuaddr);139unsigned offset = gpuaddr - b->gpuaddr;140141unsigned n = 0;142while (n < b->noffsets) {143if (offset == b->offsets[n].offset)144break;145n++;146}147148/* if needed, allocate a new offset entry: */149if (n == b->noffsets) {150b->noffsets++;151assert(b->noffsets < ARRAY_SIZE(b->offsets));152b->offsets[n].dumped_mask = 0;153b->offsets[n].offset = offset;154}155156if ((b->offsets[n].dumped_mask & enable_mask) == enable_mask)157return true;158159b->offsets[n].dumped_mask |= enable_mask;160161return false;162}163164void165reset_buffers(void)166{167rb_tree_foreach_safe(struct buffer, buf, &buffers, node)168{169rb_tree_remove(&buffers, &buf->node);170free(buf->hostptr);171free(buf);172}173}174175/**176* Record buffer contents, takes ownership of hostptr (freed in177* reset_buffers())178*/179void180add_buffer(uint64_t gpuaddr, unsigned int len, void *hostptr)181{182struct buffer *buf = get_buffer(gpuaddr);183184if (!buf) {185buf = calloc(sizeof(struct buffer), 1);186buf->gpuaddr = gpuaddr;187rb_tree_insert(&buffers, &buf->node, buffer_insert_cmp);188}189190assert(buf->gpuaddr == gpuaddr);191192buf->hostptr = hostptr;193buf->len = len;194}195196197