[Mesa-dev] [PATCH 09/14] intel: tools: split memory management out of aubinator
Rafael Antognolli
rafael.antognolli at intel.com
Sat Aug 4 00:43:38 UTC 2018
This also looks like a harmless and useful refactory.
Reviewed-by: Rafael Antognolli <rafael.antognolli at intel.com>
On Thu, Aug 02, 2018 at 10:39:21AM +0100, Lionel Landwerlin wrote:
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> ---
> src/intel/tools/aub_mem.c | 391 ++++++++++++++++++++++++++++++++++++
> src/intel/tools/aub_mem.h | 72 +++++++
> src/intel/tools/aubinator.c | 379 +++-------------------------------
> src/intel/tools/meson.build | 2 +-
> 4 files changed, 491 insertions(+), 353 deletions(-)
> create mode 100644 src/intel/tools/aub_mem.c
> create mode 100644 src/intel/tools/aub_mem.h
>
> diff --git a/src/intel/tools/aub_mem.c b/src/intel/tools/aub_mem.c
> new file mode 100644
> index 00000000000..788a2461130
> --- /dev/null
> +++ b/src/intel/tools/aub_mem.c
> @@ -0,0 +1,391 @@
> +/*
> + * Copyright © 2016-2018 Intel Corporation
> + *
> + * 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.
> + */
> +
> +#include <string.h>
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/mman.h>
> +
> +#include "aub_mem.h"
> +
> +#ifndef HAVE_MEMFD_CREATE
> +#include <sys/syscall.h>
> +
> +static inline int
> +memfd_create(const char *name, unsigned int flags)
> +{
> + return syscall(SYS_memfd_create, name, flags);
> +}
> +#endif
> +
> +struct bo_map {
> + struct list_head link;
> + struct gen_batch_decode_bo bo;
> + bool unmap_after_use;
> +};
> +
> +struct ggtt_entry {
> + struct rb_node node;
> + uint64_t virt_addr;
> + uint64_t phys_addr;
> +};
> +
> +struct phys_mem {
> + struct rb_node node;
> + uint64_t fd_offset;
> + uint64_t phys_addr;
> + uint8_t *data;
> +};
> +
> +static void
> +add_gtt_bo_map(struct aub_mem *mem, struct gen_batch_decode_bo bo, bool unmap_after_use)
> +{
> + struct bo_map *m = calloc(1, sizeof(*m));
> +
> + m->bo = bo;
> + m->unmap_after_use = unmap_after_use;
> + list_add(&m->link, &mem->maps);
> +}
> +
> +void
> +aub_mem_clear_bo_maps(struct aub_mem *mem)
> +{
> + list_for_each_entry_safe(struct bo_map, i, &mem->maps, link) {
> + if (i->unmap_after_use)
> + munmap((void *)i->bo.map, i->bo.size);
> + list_del(&i->link);
> + free(i);
> + }
> +}
> +
> +static inline struct ggtt_entry *
> +ggtt_entry_next(struct ggtt_entry *entry)
> +{
> + if (!entry)
> + return NULL;
> + struct rb_node *node = rb_node_next(&entry->node);
> + if (!node)
> + return NULL;
> + return rb_node_data(struct ggtt_entry, node, node);
> +}
> +
> +static inline int
> +cmp_uint64(uint64_t a, uint64_t b)
> +{
> + if (a < b)
> + return -1;
> + if (a > b)
> + return 1;
> + return 0;
> +}
> +
> +static inline int
> +cmp_ggtt_entry(const struct rb_node *node, const void *addr)
> +{
> + struct ggtt_entry *entry = rb_node_data(struct ggtt_entry, node, node);
> + return cmp_uint64(entry->virt_addr, *(const uint64_t *)addr);
> +}
> +
> +static struct ggtt_entry *
> +ensure_ggtt_entry(struct aub_mem *mem, uint64_t virt_addr)
> +{
> + struct rb_node *node = rb_tree_search_sloppy(&mem->ggtt, &virt_addr,
> + cmp_ggtt_entry);
> + int cmp = 0;
> + if (!node || (cmp = cmp_ggtt_entry(node, &virt_addr))) {
> + struct ggtt_entry *new_entry = calloc(1, sizeof(*new_entry));
> + new_entry->virt_addr = virt_addr;
> + rb_tree_insert_at(&mem->ggtt, node, &new_entry->node, cmp > 0);
> + node = &new_entry->node;
> + }
> +
> + return rb_node_data(struct ggtt_entry, node, node);
> +}
> +
> +static struct ggtt_entry *
> +search_ggtt_entry(struct aub_mem *mem, uint64_t virt_addr)
> +{
> + virt_addr &= ~0xfff;
> +
> + struct rb_node *node = rb_tree_search(&mem->ggtt, &virt_addr, cmp_ggtt_entry);
> +
> + if (!node)
> + return NULL;
> +
> + return rb_node_data(struct ggtt_entry, node, node);
> +}
> +
> +static inline int
> +cmp_phys_mem(const struct rb_node *node, const void *addr)
> +{
> + struct phys_mem *mem = rb_node_data(struct phys_mem, node, node);
> + return cmp_uint64(mem->phys_addr, *(uint64_t *)addr);
> +}
> +
> +static struct phys_mem *
> +ensure_phys_mem(struct aub_mem *mem, uint64_t phys_addr)
> +{
> + struct rb_node *node = rb_tree_search_sloppy(&mem->mem, &phys_addr, cmp_phys_mem);
> + int cmp = 0;
> + if (!node || (cmp = cmp_phys_mem(node, &phys_addr))) {
> + struct phys_mem *new_mem = calloc(1, sizeof(*new_mem));
> + new_mem->phys_addr = phys_addr;
> + new_mem->fd_offset = mem->mem_fd_len;
> +
> + int ftruncate_res = ftruncate(mem->mem_fd, mem->mem_fd_len += 4096);
> + assert(ftruncate_res == 0);
> +
> + new_mem->data = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED,
> + mem->mem_fd, new_mem->fd_offset);
> + assert(new_mem->data != MAP_FAILED);
> +
> + rb_tree_insert_at(&mem->mem, node, &new_mem->node, cmp > 0);
> + node = &new_mem->node;
> + }
> +
> + return rb_node_data(struct phys_mem, node, node);
> +}
> +
> +static struct phys_mem *
> +search_phys_mem(struct aub_mem *mem, uint64_t phys_addr)
> +{
> + phys_addr &= ~0xfff;
> +
> + struct rb_node *node = rb_tree_search(&mem->mem, &phys_addr, cmp_phys_mem);
> +
> + if (!node)
> + return NULL;
> +
> + return rb_node_data(struct phys_mem, node, node);
> +}
> +
> +void
> +aub_mem_local_write(void *_mem, uint64_t address,
> + const void *data, uint32_t size)
> +{
> + struct aub_mem *mem = _mem;
> + struct gen_batch_decode_bo bo = {
> + .map = data,
> + .addr = address,
> + .size = size,
> + };
> + add_gtt_bo_map(mem, bo, false);
> +}
> +
> +void
> +aub_mem_ggtt_entry_write(void *_mem, uint64_t address,
> + const void *_data, uint32_t _size)
> +{
> + struct aub_mem *mem = _mem;
> + uint64_t virt_addr = (address / sizeof(uint64_t)) << 12;
> + const uint64_t *data = _data;
> + size_t size = _size / sizeof(*data);
> + for (const uint64_t *entry = data;
> + entry < data + size;
> + entry++, virt_addr += 4096) {
> + struct ggtt_entry *pt = ensure_ggtt_entry(mem, virt_addr);
> + pt->phys_addr = *entry;
> + }
> +}
> +
> +void
> +aub_mem_phys_write(void *_mem, uint64_t phys_address,
> + const void *data, uint32_t size)
> +{
> + struct aub_mem *mem = _mem;
> + uint32_t to_write = size;
> + for (uint64_t page = phys_address & ~0xfff; page < phys_address + size; page += 4096) {
> + struct phys_mem *pmem = ensure_phys_mem(mem, page);
> + uint64_t offset = MAX2(page, phys_address) - page;
> + uint32_t size_this_page = MIN2(to_write, 4096 - offset);
> + to_write -= size_this_page;
> + memcpy(pmem->data + offset, data, size_this_page);
> + data = (const uint8_t *)data + size_this_page;
> + }
> +}
> +
> +void
> +aub_mem_ggtt_write(void *_mem, uint64_t virt_address,
> + const void *data, uint32_t size)
> +{
> + struct aub_mem *mem = _mem;
> + uint32_t to_write = size;
> + for (uint64_t page = virt_address & ~0xfff; page < virt_address + size; page += 4096) {
> + struct ggtt_entry *entry = search_ggtt_entry(mem, page);
> + assert(entry && entry->phys_addr & 0x1);
> +
> + uint64_t offset = MAX2(page, virt_address) - page;
> + uint32_t size_this_page = MIN2(to_write, 4096 - offset);
> + to_write -= size_this_page;
> +
> + uint64_t phys_page = entry->phys_addr & ~0xfff; /* Clear the validity bits. */
> + aub_mem_phys_write(mem, phys_page + offset, data, size_this_page);
> + data = (const uint8_t *)data + size_this_page;
> + }
> +}
> +
> +struct gen_batch_decode_bo
> +aub_mem_get_ggtt_bo(void *_mem, uint64_t address)
> +{
> + struct aub_mem *mem = _mem;
> + struct gen_batch_decode_bo bo = {0};
> +
> + list_for_each_entry(struct bo_map, i, &mem->maps, link)
> + if (i->bo.addr <= address && i->bo.addr + i->bo.size > address)
> + return i->bo;
> +
> + address &= ~0xfff;
> +
> + struct ggtt_entry *start =
> + (struct ggtt_entry *)rb_tree_search_sloppy(&mem->ggtt, &address,
> + cmp_ggtt_entry);
> + if (start && start->virt_addr < address)
> + start = ggtt_entry_next(start);
> + if (!start)
> + return bo;
> +
> + struct ggtt_entry *last = start;
> + for (struct ggtt_entry *i = ggtt_entry_next(last);
> + i && last->virt_addr + 4096 == i->virt_addr;
> + last = i, i = ggtt_entry_next(last))
> + ;
> +
> + bo.addr = MIN2(address, start->virt_addr);
> + bo.size = last->virt_addr - bo.addr + 4096;
> + bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> + assert(bo.map != MAP_FAILED);
> +
> + for (struct ggtt_entry *i = start;
> + i;
> + i = i == last ? NULL : ggtt_entry_next(i)) {
> + uint64_t phys_addr = i->phys_addr & ~0xfff;
> + struct phys_mem *phys_mem = search_phys_mem(mem, phys_addr);
> +
> + if (!phys_mem)
> + continue;
> +
> + uint32_t map_offset = i->virt_addr - address;
> + void *res = mmap((uint8_t *)bo.map + map_offset, 4096, PROT_READ,
> + MAP_SHARED | MAP_FIXED, mem->mem_fd, phys_mem->fd_offset);
> + assert(res != MAP_FAILED);
> + }
> +
> + add_gtt_bo_map(mem, bo, true);
> +
> + return bo;
> +}
> +
> +static struct phys_mem *
> +ppgtt_walk(struct aub_mem *mem, uint64_t pml4, uint64_t address)
> +{
> + uint64_t shift = 39;
> + uint64_t addr = pml4;
> + for (int level = 4; level > 0; level--) {
> + struct phys_mem *table = search_phys_mem(mem, addr);
> + if (!table)
> + return NULL;
> + int index = (address >> shift) & 0x1ff;
> + uint64_t entry = ((uint64_t *)table->data)[index];
> + if (!(entry & 1))
> + return NULL;
> + addr = entry & ~0xfff;
> + shift -= 9;
> + }
> + return search_phys_mem(mem, addr);
> +}
> +
> +static bool
> +ppgtt_mapped(struct aub_mem *mem, uint64_t pml4, uint64_t address)
> +{
> + return ppgtt_walk(mem, pml4, address) != NULL;
> +}
> +
> +struct gen_batch_decode_bo
> +aub_mem_get_ppgtt_bo(void *_mem, uint64_t address)
> +{
> + struct aub_mem *mem = _mem;
> + struct gen_batch_decode_bo bo = {0};
> +
> + address &= ~0xfff;
> +
> + if (!ppgtt_mapped(mem, mem->pml4, address))
> + return bo;
> +
> + /* Map everything until the first gap since we don't know how much the
> + * decoder actually needs.
> + */
> + uint64_t end = address;
> + while (ppgtt_mapped(mem, mem->pml4, end))
> + end += 4096;
> +
> + bo.addr = address;
> + bo.size = end - address;
> + bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> + assert(bo.map != MAP_FAILED);
> +
> + for (uint64_t page = address; page < end; page += 4096) {
> + struct phys_mem *phys_mem = ppgtt_walk(mem, mem->pml4, page);
> +
> + void *res = mmap((uint8_t *)bo.map + (page - bo.addr), 4096, PROT_READ,
> + MAP_SHARED | MAP_FIXED, mem->mem_fd, phys_mem->fd_offset);
> + assert(res != MAP_FAILED);
> + }
> +
> + add_gtt_bo_map(mem, bo, true);
> +
> + return bo;
> +}
> +
> +bool
> +aub_mem_init(struct aub_mem *mem)
> +{
> + memset(mem, 0, sizeof(*mem));
> +
> + list_inithead(&mem->maps);
> +
> + mem->mem_fd = memfd_create("phys memory", 0);
> +
> + return mem->mem_fd != -1;
> +}
> +
> +void
> +aub_mem_fini(struct aub_mem *mem)
> +{
> + if (mem->mem_fd == -1)
> + return;
> +
> + aub_mem_clear_bo_maps(mem);
> +
> +
> + rb_tree_foreach_safe(struct ggtt_entry, entry, &mem->ggtt, node) {
> + rb_tree_remove(&mem->ggtt, &entry->node);
> + free(entry);
> + }
> + rb_tree_foreach_safe(struct phys_mem, entry, &mem->mem, node) {
> + rb_tree_remove(&mem->mem, &entry->node);
> + free(entry);
> + }
> +
> + close(mem->mem_fd);
> + mem->mem_fd = -1;
> +}
> diff --git a/src/intel/tools/aub_mem.h b/src/intel/tools/aub_mem.h
> new file mode 100644
> index 00000000000..98e64214b98
> --- /dev/null
> +++ b/src/intel/tools/aub_mem.h
> @@ -0,0 +1,72 @@
> +/*
> + * Copyright © 2018 Intel Corporation
> + *
> + * 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.
> + *
> + */
> +
> +#ifndef INTEL_AUB_MEM
> +#define INTEL_AUB_MEM
> +
> +#include <stdint.h>
> +
> +#include "util/list.h"
> +#include "util/rb_tree.h"
> +
> +#include "dev/gen_device_info.h"
> +#include "common/gen_decoder.h"
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +struct aub_mem {
> + uint64_t pml4;
> +
> + int mem_fd;
> + off_t mem_fd_len;
> +
> + struct list_head maps;
> + struct rb_tree ggtt;
> + struct rb_tree mem;
> +};
> +
> +bool aub_mem_init(struct aub_mem *mem);
> +void aub_mem_fini(struct aub_mem *mem);
> +
> +void aub_mem_clear_bo_maps(struct aub_mem *mem);
> +
> +void aub_mem_phys_write(void *mem, uint64_t virt_address,
> + const void *data, uint32_t size);
> +void aub_mem_ggtt_write(void *mem, uint64_t virt_address,
> + const void *data, uint32_t size);
> +void aub_mem_ggtt_entry_write(void *mem, uint64_t virt_address,
> + const void *data, uint32_t size);
> +void aub_mem_local_write(void *mem, uint64_t virt_address,
> + const void *data, uint32_t size);
> +
> +struct gen_batch_decode_bo aub_mem_get_ggtt_bo(void *mem, uint64_t address);
> +struct gen_batch_decode_bo aub_mem_get_ppgtt_bo(void *mem, uint64_t address);
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* INTEL_AUB_MEM */
> diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c
> index b5622ff9eaa..ae80626b986 100644
> --- a/src/intel/tools/aubinator.c
> +++ b/src/intel/tools/aubinator.c
> @@ -37,29 +37,11 @@
> #include <sys/wait.h>
> #include <sys/mman.h>
>
> -#include "util/list.h"
> #include "util/macros.h"
> -#include "util/rb_tree.h"
>
> #include "common/gen_decoder.h"
> -#include "intel_aub.h"
> #include "aub_read.h"
> -
> -#ifndef HAVE_MEMFD_CREATE
> -#include <sys/syscall.h>
> -
> -static inline int
> -memfd_create(const char *name, unsigned int flags)
> -{
> - return syscall(SYS_memfd_create, name, flags);
> -}
> -#endif
> -
> -/* Below is the only command missing from intel_aub.h in libdrm
> - * So, reuse intel_aub.h from libdrm and #define the
> - * AUB_MI_BATCH_BUFFER_END as below
> - */
> -#define AUB_MI_BATCH_BUFFER_END (0x0500 << 16)
> +#include "aub_mem.h"
>
> #define CSI "\e["
> #define BLUE_HEADER CSI "0;44m"
> @@ -79,326 +61,12 @@ uint16_t pci_id = 0;
> char *input_file = NULL, *xml_path = NULL;
> struct gen_device_info devinfo;
> struct gen_batch_decode_ctx batch_ctx;
> -
> -struct bo_map {
> - struct list_head link;
> - struct gen_batch_decode_bo bo;
> - bool unmap_after_use;
> -};
> -
> -struct ggtt_entry {
> - struct rb_node node;
> - uint64_t virt_addr;
> - uint64_t phys_addr;
> -};
> -
> -struct phys_mem {
> - struct rb_node node;
> - uint64_t fd_offset;
> - uint64_t phys_addr;
> - uint8_t *data;
> -};
> -
> -static struct list_head maps;
> -static struct rb_tree ggtt = {NULL};
> -static struct rb_tree mem = {NULL};
> -int mem_fd = -1;
> -off_t mem_fd_len = 0;
> +struct aub_mem mem;
>
> FILE *outfile;
>
> struct brw_instruction;
>
> -static void
> -add_gtt_bo_map(struct gen_batch_decode_bo bo, bool unmap_after_use)
> -{
> - struct bo_map *m = calloc(1, sizeof(*m));
> -
> - m->bo = bo;
> - m->unmap_after_use = unmap_after_use;
> - list_add(&m->link, &maps);
> -}
> -
> -static void
> -clear_bo_maps(void)
> -{
> - list_for_each_entry_safe(struct bo_map, i, &maps, link) {
> - if (i->unmap_after_use)
> - munmap((void *)i->bo.map, i->bo.size);
> - list_del(&i->link);
> - free(i);
> - }
> -}
> -
> -static inline struct ggtt_entry *
> -ggtt_entry_next(struct ggtt_entry *entry)
> -{
> - if (!entry)
> - return NULL;
> - struct rb_node *node = rb_node_next(&entry->node);
> - if (!node)
> - return NULL;
> - return rb_node_data(struct ggtt_entry, node, node);
> -}
> -
> -static inline int
> -cmp_uint64(uint64_t a, uint64_t b)
> -{
> - if (a < b)
> - return -1;
> - if (a > b)
> - return 1;
> - return 0;
> -}
> -
> -static inline int
> -cmp_ggtt_entry(const struct rb_node *node, const void *addr)
> -{
> - struct ggtt_entry *entry = rb_node_data(struct ggtt_entry, node, node);
> - return cmp_uint64(entry->virt_addr, *(const uint64_t *)addr);
> -}
> -
> -static struct ggtt_entry *
> -ensure_ggtt_entry(struct rb_tree *tree, uint64_t virt_addr)
> -{
> - struct rb_node *node = rb_tree_search_sloppy(&ggtt, &virt_addr,
> - cmp_ggtt_entry);
> - int cmp = 0;
> - if (!node || (cmp = cmp_ggtt_entry(node, &virt_addr))) {
> - struct ggtt_entry *new_entry = calloc(1, sizeof(*new_entry));
> - new_entry->virt_addr = virt_addr;
> - rb_tree_insert_at(&ggtt, node, &new_entry->node, cmp > 0);
> - node = &new_entry->node;
> - }
> -
> - return rb_node_data(struct ggtt_entry, node, node);
> -}
> -
> -static struct ggtt_entry *
> -search_ggtt_entry(uint64_t virt_addr)
> -{
> - virt_addr &= ~0xfff;
> -
> - struct rb_node *node = rb_tree_search(&ggtt, &virt_addr, cmp_ggtt_entry);
> -
> - if (!node)
> - return NULL;
> -
> - return rb_node_data(struct ggtt_entry, node, node);
> -}
> -
> -static inline int
> -cmp_phys_mem(const struct rb_node *node, const void *addr)
> -{
> - struct phys_mem *mem = rb_node_data(struct phys_mem, node, node);
> - return cmp_uint64(mem->phys_addr, *(uint64_t *)addr);
> -}
> -
> -static struct phys_mem *
> -ensure_phys_mem(uint64_t phys_addr)
> -{
> - struct rb_node *node = rb_tree_search_sloppy(&mem, &phys_addr, cmp_phys_mem);
> - int cmp = 0;
> - if (!node || (cmp = cmp_phys_mem(node, &phys_addr))) {
> - struct phys_mem *new_mem = calloc(1, sizeof(*new_mem));
> - new_mem->phys_addr = phys_addr;
> - new_mem->fd_offset = mem_fd_len;
> -
> - int ftruncate_res = ftruncate(mem_fd, mem_fd_len += 4096);
> - assert(ftruncate_res == 0);
> -
> - new_mem->data = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED,
> - mem_fd, new_mem->fd_offset);
> - assert(new_mem->data != MAP_FAILED);
> -
> - rb_tree_insert_at(&mem, node, &new_mem->node, cmp > 0);
> - node = &new_mem->node;
> - }
> -
> - return rb_node_data(struct phys_mem, node, node);
> -}
> -
> -static struct phys_mem *
> -search_phys_mem(uint64_t phys_addr)
> -{
> - phys_addr &= ~0xfff;
> -
> - struct rb_node *node = rb_tree_search(&mem, &phys_addr, cmp_phys_mem);
> -
> - if (!node)
> - return NULL;
> -
> - return rb_node_data(struct phys_mem, node, node);
> -}
> -
> -static void
> -handle_local_write(void *user_data, uint64_t address, const void *data, uint32_t size)
> -{
> - struct gen_batch_decode_bo bo = {
> - .map = data,
> - .addr = address,
> - .size = size,
> - };
> - add_gtt_bo_map(bo, false);
> -}
> -
> -static void
> -handle_ggtt_entry_write(void *user_data, uint64_t address, const void *_data, uint32_t _size)
> -{
> - uint64_t virt_addr = (address / sizeof(uint64_t)) << 12;
> - const uint64_t *data = _data;
> - size_t size = _size / sizeof(*data);
> - for (const uint64_t *entry = data;
> - entry < data + size;
> - entry++, virt_addr += 4096) {
> - struct ggtt_entry *pt = ensure_ggtt_entry(&ggtt, virt_addr);
> - pt->phys_addr = *entry;
> - }
> -}
> -
> -static void
> -handle_physical_write(void *user_data, uint64_t phys_address, const void *data, uint32_t size)
> -{
> - uint32_t to_write = size;
> - for (uint64_t page = phys_address & ~0xfff; page < phys_address + size; page += 4096) {
> - struct phys_mem *mem = ensure_phys_mem(page);
> - uint64_t offset = MAX2(page, phys_address) - page;
> - uint32_t size_this_page = MIN2(to_write, 4096 - offset);
> - to_write -= size_this_page;
> - memcpy(mem->data + offset, data, size_this_page);
> - data = (const uint8_t *)data + size_this_page;
> - }
> -}
> -
> -static void
> -handle_ggtt_write(void *user_data, uint64_t virt_address, const void *data, uint32_t size)
> -{
> - uint32_t to_write = size;
> - for (uint64_t page = virt_address & ~0xfff; page < virt_address + size; page += 4096) {
> - struct ggtt_entry *entry = search_ggtt_entry(page);
> - assert(entry && entry->phys_addr & 0x1);
> -
> - uint64_t offset = MAX2(page, virt_address) - page;
> - uint32_t size_this_page = MIN2(to_write, 4096 - offset);
> - to_write -= size_this_page;
> -
> - uint64_t phys_page = entry->phys_addr & ~0xfff; /* Clear the validity bits. */
> - handle_physical_write(user_data, phys_page + offset, data, size_this_page);
> - data = (const uint8_t *)data + size_this_page;
> - }
> -}
> -
> -static struct gen_batch_decode_bo
> -get_ggtt_batch_bo(void *user_data, uint64_t address)
> -{
> - struct gen_batch_decode_bo bo = {0};
> -
> - list_for_each_entry(struct bo_map, i, &maps, link)
> - if (i->bo.addr <= address && i->bo.addr + i->bo.size > address)
> - return i->bo;
> -
> - address &= ~0xfff;
> -
> - struct ggtt_entry *start =
> - (struct ggtt_entry *)rb_tree_search_sloppy(&ggtt, &address,
> - cmp_ggtt_entry);
> - if (start && start->virt_addr < address)
> - start = ggtt_entry_next(start);
> - if (!start)
> - return bo;
> -
> - struct ggtt_entry *last = start;
> - for (struct ggtt_entry *i = ggtt_entry_next(last);
> - i && last->virt_addr + 4096 == i->virt_addr;
> - last = i, i = ggtt_entry_next(last))
> - ;
> -
> - bo.addr = MIN2(address, start->virt_addr);
> - bo.size = last->virt_addr - bo.addr + 4096;
> - bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> - assert(bo.map != MAP_FAILED);
> -
> - for (struct ggtt_entry *i = start;
> - i;
> - i = i == last ? NULL : ggtt_entry_next(i)) {
> - uint64_t phys_addr = i->phys_addr & ~0xfff;
> - struct phys_mem *phys_mem = search_phys_mem(phys_addr);
> -
> - if (!phys_mem)
> - continue;
> -
> - uint32_t map_offset = i->virt_addr - address;
> - void *res = mmap((uint8_t *)bo.map + map_offset, 4096, PROT_READ,
> - MAP_SHARED | MAP_FIXED, mem_fd, phys_mem->fd_offset);
> - assert(res != MAP_FAILED);
> - }
> -
> - add_gtt_bo_map(bo, true);
> -
> - return bo;
> -}
> -
> -static struct phys_mem *
> -ppgtt_walk(uint64_t pml4, uint64_t address)
> -{
> - uint64_t shift = 39;
> - uint64_t addr = pml4;
> - for (int level = 4; level > 0; level--) {
> - struct phys_mem *table = search_phys_mem(addr);
> - if (!table)
> - return NULL;
> - int index = (address >> shift) & 0x1ff;
> - uint64_t entry = ((uint64_t *)table->data)[index];
> - if (!(entry & 1))
> - return NULL;
> - addr = entry & ~0xfff;
> - shift -= 9;
> - }
> - return search_phys_mem(addr);
> -}
> -
> -static bool
> -ppgtt_mapped(uint64_t pml4, uint64_t address)
> -{
> - return ppgtt_walk(pml4, address) != NULL;
> -}
> -
> -static struct gen_batch_decode_bo
> -get_ppgtt_batch_bo(void *user_data, uint64_t address)
> -{
> - struct gen_batch_decode_bo bo = {0};
> - uint64_t pml4 = *(uint64_t *)user_data;
> -
> - address &= ~0xfff;
> -
> - if (!ppgtt_mapped(pml4, address))
> - return bo;
> -
> - /* Map everything until the first gap since we don't know how much the
> - * decoder actually needs.
> - */
> - uint64_t end = address;
> - while (ppgtt_mapped(pml4, end))
> - end += 4096;
> -
> - bo.addr = address;
> - bo.size = end - address;
> - bo.map = mmap(NULL, bo.size, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> - assert(bo.map != MAP_FAILED);
> -
> - for (uint64_t page = address; page < end; page += 4096) {
> - struct phys_mem *phys_mem = ppgtt_walk(pml4, page);
> -
> - void *res = mmap((uint8_t *)bo.map + (page - bo.addr), 4096, PROT_READ,
> - MAP_SHARED | MAP_FIXED, mem_fd, phys_mem->fd_offset);
> - assert(res != MAP_FAILED);
> - }
> -
> - add_gtt_bo_map(bo, true);
> -
> - return bo;
> -}
> -
> static void
> aubinator_init(void *user_data, int aub_pci_id, const char *app_name)
> {
> @@ -448,7 +116,7 @@ handle_execlist_write(void *user_data, enum gen_engine engine, uint64_t context_
> {
> const uint32_t pphwsp_size = 4096;
> uint32_t pphwsp_addr = context_descriptor & 0xfffff000;
> - struct gen_batch_decode_bo pphwsp_bo = get_ggtt_batch_bo(NULL, pphwsp_addr);
> + struct gen_batch_decode_bo pphwsp_bo = aub_mem_get_ggtt_bo(&mem, pphwsp_addr);
> uint32_t *context = (uint32_t *)((uint8_t *)pphwsp_bo.map +
> (pphwsp_addr - pphwsp_bo.addr) +
> pphwsp_size);
> @@ -456,35 +124,37 @@ handle_execlist_write(void *user_data, enum gen_engine engine, uint64_t context_
> uint32_t ring_buffer_head = context[5];
> uint32_t ring_buffer_tail = context[7];
> uint32_t ring_buffer_start = context[9];
> - uint64_t pml4 = (uint64_t)context[49] << 32 | context[51];
>
> - struct gen_batch_decode_bo ring_bo = get_ggtt_batch_bo(NULL,
> - ring_buffer_start);
> + mem.pml4 = (uint64_t)context[49] << 32 | context[51];
> + batch_ctx.user_data = &mem;
> +
> + struct gen_batch_decode_bo ring_bo = aub_mem_get_ggtt_bo(&mem,
> + ring_buffer_start);
> assert(ring_bo.size > 0);
> void *commands = (uint8_t *)ring_bo.map + (ring_buffer_start - ring_bo.addr);
>
> if (context_descriptor & 0x100 /* ppgtt */) {
> - batch_ctx.get_bo = get_ppgtt_batch_bo;
> - batch_ctx.user_data = &pml4;
> + batch_ctx.get_bo = aub_mem_get_ppgtt_bo;
> } else {
> - batch_ctx.get_bo = get_ggtt_batch_bo;
> + batch_ctx.get_bo = aub_mem_get_ggtt_bo;
> }
>
> (void)engine; /* TODO */
> gen_print_batch(&batch_ctx, commands, ring_buffer_tail - ring_buffer_head,
> 0);
> - clear_bo_maps();
> + aub_mem_clear_bo_maps(&mem);
> }
>
> static void
> handle_ring_write(void *user_data, enum gen_engine engine,
> const void *data, uint32_t data_len)
> {
> - batch_ctx.get_bo = get_ggtt_batch_bo;
> + batch_ctx.user_data = &mem;
> + batch_ctx.get_bo = aub_mem_get_ggtt_bo;
>
> gen_print_batch(&batch_ctx, data, data_len, 0);
>
> - clear_bo_maps();
> + aub_mem_clear_bo_maps(&mem);
> }
>
> struct aub_file {
> @@ -649,19 +319,22 @@ int main(int argc, char *argv[])
> if (isatty(1) && pager)
> setup_pager();
>
> - mem_fd = memfd_create("phys memory", 0);
> -
> - list_inithead(&maps);
> + if (!aub_mem_init(&mem)) {
> + fprintf(stderr, "Unable to create GTT\n");
> + exit(EXIT_FAILURE);
> + }
>
> file = aub_file_open(input_file);
>
> struct aub_read aub_read = {
> - .user_data = NULL,
> + .user_data = &mem,
> .info = aubinator_init,
> - .local_write = handle_local_write,
> - .phys_write = handle_physical_write,
> - .ggtt_write = handle_ggtt_write,
> - .ggtt_entry_write = handle_ggtt_entry_write,
> +
> + .local_write = aub_mem_local_write,
> + .phys_write = aub_mem_phys_write,
> + .ggtt_write = aub_mem_ggtt_write,
> + .ggtt_entry_write = aub_mem_ggtt_entry_write,
> +
> .execlist_write = handle_execlist_write,
> .ring_write = handle_ring_write,
> };
> @@ -672,6 +345,8 @@ int main(int argc, char *argv[])
> file->cursor += consumed;
> }
>
> + aub_mem_fini(&mem);
> +
> fflush(stdout);
> /* close the stdout which is opened to write the output */
> close(1);
> diff --git a/src/intel/tools/meson.build b/src/intel/tools/meson.build
> index 6be9fcf6413..8f9e2bd8e3e 100644
> --- a/src/intel/tools/meson.build
> +++ b/src/intel/tools/meson.build
> @@ -22,7 +22,7 @@ build_intel_tools = with_tools.contains('intel')
>
> aubinator = executable(
> 'aubinator',
> - files('aubinator.c', 'intel_aub.h', 'aub_read.h', 'aub_read.c'),
> + files('aubinator.c', 'intel_aub.h', 'aub_read.h', 'aub_read.c', 'aub_mem.h', 'aub_mem.c'),
> dependencies : [dep_expat, dep_zlib, dep_dl, dep_thread, dep_m],
> include_directories : [inc_common, inc_intel],
> link_with : [libintel_common, libintel_compiler, libintel_dev, libmesa_util],
> --
> 2.18.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list