diff options
Diffstat (limited to 'src/broadcom/simulator')
-rw-r--r-- | src/broadcom/simulator/meson.build | 63 | ||||
-rw-r--r-- | src/broadcom/simulator/v3d_simulator.c | 676 | ||||
-rw-r--r-- | src/broadcom/simulator/v3d_simulator.h | 55 | ||||
-rw-r--r-- | src/broadcom/simulator/v3d_simulator_wrapper.cpp | 93 | ||||
-rw-r--r-- | src/broadcom/simulator/v3d_simulator_wrapper.h | 45 | ||||
-rw-r--r-- | src/broadcom/simulator/v3dx_simulator.c | 357 | ||||
-rw-r--r-- | src/broadcom/simulator/v3dx_simulator.h | 46 |
7 files changed, 1335 insertions, 0 deletions
diff --git a/src/broadcom/simulator/meson.build b/src/broadcom/simulator/meson.build new file mode 100644 index 00000000000..51f311bb094 --- /dev/null +++ b/src/broadcom/simulator/meson.build @@ -0,0 +1,63 @@ +# Copyright © 2019 Raspberry Pi +# +# 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 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. +inc_simulator = include_directories('.') + +libbroadcom_simulator_files = files( + 'v3d_simulator.c', + 'v3d_simulator_wrapper.cpp', +) + +files_per_version = files( + 'v3dx_simulator.c', +) + +v3d_args = [] +dep_v3dv3 = dependency('v3dv3', required: false) +if dep_v3dv3.found() + v3d_args += '-DUSE_V3D_SIMULATOR' +endif + +per_version_libs = [] +foreach ver : v3d_versions + per_version_libs += static_library( + 'v3d-simulator-v' + ver, + [files_per_version, v3d_xml_pack], + include_directories : [ + inc_src, inc_include, inc_gallium_aux, inc_broadcom, + ], + c_args : [v3d_args, '-DV3D_VERSION=' + ver], + gnu_symbol_visibility: 'hidden', + dependencies : [dep_v3dv3, dep_libdrm, dep_valgrind], +) +endforeach + +libbroadcom_simulator = static_library( + 'broadcom_simulator', + [libbroadcom_simulator_files], + include_directories : [inc_src, inc_include, inc_gallium, inc_gallium_aux], + c_args : [v3d_args, no_override_init_args], + cpp_args : [v3d_args], + gnu_symbol_visibility : 'hidden', + dependencies : [dep_v3dv3, dep_libdrm, dep_valgrind], + link_with : [per_version_libs], + build_by_default : false, +) + +v3d_libs += libbroadcom_simulator diff --git a/src/broadcom/simulator/v3d_simulator.c b/src/broadcom/simulator/v3d_simulator.c new file mode 100644 index 00000000000..c5d81208d9a --- /dev/null +++ b/src/broadcom/simulator/v3d_simulator.c @@ -0,0 +1,676 @@ +/* + * Copyright © 2014-2017 Broadcom + * + * 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. + */ + +/** + * @file v3d_simulator.c + * + * Implements VC5 simulation on top of a non-VC5 GEM fd. + * + * This file's goal is to emulate the VC5 ioctls' behavior in the kernel on + * top of the simpenrose software simulator. Generally, VC5 driver BOs have a + * GEM-side copy of their contents and a simulator-side memory area that the + * GEM contents get copied into during simulation. Once simulation is done, + * the simulator's data is copied back out to the GEM BOs, so that rendering + * appears on the screen as if actual hardware rendering had been done. + * + * One of the limitations of this code is that we shouldn't really need a + * GEM-side BO for non-window-system BOs. However, do we need unique BO + * handles for each of our GEM bos so that this file can look up its state + * from the handle passed in at submit ioctl time (also, a couple of places + * outside of this file still call ioctls directly on the fd). + * + * Another limitation is that BO import doesn't work unless the underlying + * window system's BO size matches what VC5 is going to use, which of course + * doesn't work out in practice. This means that for now, only DRI3 (VC5 + * makes the winsys BOs) is supported, not DRI2 (window system makes the winys + * BOs). + */ + +#ifdef USE_V3D_SIMULATOR + +#include <stdio.h> +#include <sys/mman.h> +#include "c11/threads.h" +#include "util/hash_table.h" +#include "util/ralloc.h" +#include "util/set.h" +#include "util/u_dynarray.h" +#include "util/u_memory.h" +#include "util/u_mm.h" +#include "util/u_math.h" + +#include <xf86drm.h> +#include "drm-uapi/i915_drm.h" +#include "drm-uapi/v3d_drm.h" + +#include "v3d_simulator.h" +#include "v3d_simulator_wrapper.h" + +/** Global (across GEM fds) state for the simulator */ +static struct v3d_simulator_state { + mtx_t mutex; + mtx_t submit_lock; + + struct v3d_hw *v3d; + int ver; + + /* Base virtual address of the heap. */ + void *mem; + /* Base hardware address of the heap. */ + uint32_t mem_base; + /* Size of the heap. */ + size_t mem_size; + + struct mem_block *heap; + struct mem_block *overflow; + + /** Mapping from GEM fd to struct v3d_simulator_file * */ + struct hash_table *fd_map; + + struct util_dynarray bin_oom; + int refcount; +} sim_state = { + .mutex = _MTX_INITIALIZER_NP, +}; + +/** Per-GEM-fd state for the simulator. */ +struct v3d_simulator_file { + int fd; + + /** Mapping from GEM handle to struct v3d_simulator_bo * */ + struct hash_table *bo_map; + + struct mem_block *gmp; + void *gmp_vaddr; + + /** Actual GEM fd is i915, so we should use their create ioctl. */ + bool is_i915; +}; + +/** Wrapper for drm_v3d_bo tracking the simulator-specific state. */ +struct v3d_simulator_bo { + struct v3d_simulator_file *file; + + /** Area for this BO within sim_state->mem */ + struct mem_block *block; + uint32_t size; + uint64_t mmap_offset; + void *sim_vaddr; + void *gem_vaddr; + + int handle; +}; + +static void * +int_to_key(int key) +{ + return (void *)(uintptr_t)key; +} + +static struct v3d_simulator_file * +v3d_get_simulator_file_for_fd(int fd) +{ + struct hash_entry *entry = _mesa_hash_table_search(sim_state.fd_map, + int_to_key(fd + 1)); + return entry ? entry->data : NULL; +} + +/* A marker placed just after each BO, then checked after rendering to make + * sure it's still there. + */ +#define BO_SENTINEL 0xfedcba98 + +/* 128kb */ +#define GMP_ALIGN2 17 + +/** + * Sets the range of GPU virtual address space to have the given GMP + * permissions (bit 0 = read, bit 1 = write, write-only forbidden). + */ +static void +set_gmp_flags(struct v3d_simulator_file *file, + uint32_t offset, uint32_t size, uint32_t flag) +{ + assert((offset & ((1 << GMP_ALIGN2) - 1)) == 0); + int gmp_offset = offset >> GMP_ALIGN2; + int gmp_count = align(size, 1 << GMP_ALIGN2) >> GMP_ALIGN2; + uint32_t *gmp = file->gmp_vaddr; + + assert(flag <= 0x3); + + for (int i = gmp_offset; i < gmp_offset + gmp_count; i++) { + int32_t bitshift = (i % 16) * 2; + gmp[i / 16] &= ~(0x3 << bitshift); + gmp[i / 16] |= flag << bitshift; + } +} + +/** + * Allocates space in simulator memory and returns a tracking struct for it + * that also contains the drm_gem_cma_object struct. + */ +static struct v3d_simulator_bo * +v3d_create_simulator_bo(int fd, unsigned size) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + struct v3d_simulator_bo *sim_bo = rzalloc(file, + struct v3d_simulator_bo); + size = align(size, 4096); + + sim_bo->file = file; + + mtx_lock(&sim_state.mutex); + sim_bo->block = u_mmAllocMem(sim_state.heap, size + 4, GMP_ALIGN2, 0); + mtx_unlock(&sim_state.mutex); + assert(sim_bo->block); + + set_gmp_flags(file, sim_bo->block->ofs, size, 0x3); + + sim_bo->size = size; + + /* Allocate space for the buffer in simulator memory. */ + sim_bo->sim_vaddr = sim_state.mem + sim_bo->block->ofs - sim_state.mem_base; + memset(sim_bo->sim_vaddr, 0xd0, size); + + *(uint32_t *)(sim_bo->sim_vaddr + sim_bo->size) = BO_SENTINEL; + + return sim_bo; +} + +static struct v3d_simulator_bo * +v3d_create_simulator_bo_for_gem(int fd, int handle, unsigned size) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + struct v3d_simulator_bo *sim_bo = + v3d_create_simulator_bo(fd, size); + + sim_bo->handle = handle; + + /* Map the GEM buffer for copy in/out to the simulator. i915 blocks + * dumb mmap on render nodes, so use their ioctl directly if we're on + * one. + */ + int ret; + if (file->is_i915) { + struct drm_i915_gem_mmap_gtt map = { + .handle = handle, + }; + + /* We could potentially use non-gtt (cached) for LLC systems, + * but the copy-in/out won't be the limiting factor on + * simulation anyway. + */ + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &map); + sim_bo->mmap_offset = map.offset; + } else { + struct drm_mode_map_dumb map = { + .handle = handle, + }; + + ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map); + sim_bo->mmap_offset = map.offset; + } + if (ret) { + fprintf(stderr, "Failed to get MMAP offset: %d\n", ret); + abort(); + } + + sim_bo->gem_vaddr = mmap(NULL, sim_bo->size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, sim_bo->mmap_offset); + if (sim_bo->gem_vaddr == MAP_FAILED) { + fprintf(stderr, "mmap of bo %d (offset 0x%016llx, size %d) failed\n", + handle, (long long)sim_bo->mmap_offset, sim_bo->size); + abort(); + } + + /* A handle of 0 is used for v3d_gem.c internal allocations that + * don't need to go in the lookup table. + */ + if (handle != 0) { + mtx_lock(&sim_state.mutex); + _mesa_hash_table_insert(file->bo_map, int_to_key(handle), + sim_bo); + mtx_unlock(&sim_state.mutex); + } + + return sim_bo; +} + +static int bin_fd; + +uint32_t +v3d_simulator_get_spill(uint32_t spill_size) +{ + struct v3d_simulator_bo *sim_bo = + v3d_create_simulator_bo(bin_fd, spill_size); + + util_dynarray_append(&sim_state.bin_oom, struct v3d_simulator_bo *, + sim_bo); + + return sim_bo->block->ofs; +} + +static void +v3d_free_simulator_bo(struct v3d_simulator_bo *sim_bo) +{ + struct v3d_simulator_file *sim_file = sim_bo->file; + + set_gmp_flags(sim_file, sim_bo->block->ofs, sim_bo->size, 0x0); + + if (sim_bo->gem_vaddr) + munmap(sim_bo->gem_vaddr, sim_bo->size); + + mtx_lock(&sim_state.mutex); + u_mmFreeMem(sim_bo->block); + if (sim_bo->handle) { + _mesa_hash_table_remove_key(sim_file->bo_map, + int_to_key(sim_bo->handle)); + } + mtx_unlock(&sim_state.mutex); + ralloc_free(sim_bo); +} + +static struct v3d_simulator_bo * +v3d_get_simulator_bo(struct v3d_simulator_file *file, int gem_handle) +{ + if (gem_handle == 0) + return NULL; + + mtx_lock(&sim_state.mutex); + struct hash_entry *entry = + _mesa_hash_table_search(file->bo_map, int_to_key(gem_handle)); + mtx_unlock(&sim_state.mutex); + + return entry ? entry->data : NULL; +} + +static void +v3d_simulator_copy_in_handle(struct v3d_simulator_file *file, int handle) +{ + struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle); + + if (!sim_bo) + return; + + memcpy(sim_bo->sim_vaddr, sim_bo->gem_vaddr, sim_bo->size); +} + +static void +v3d_simulator_copy_out_handle(struct v3d_simulator_file *file, int handle) +{ + struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, handle); + + if (!sim_bo) + return; + + memcpy(sim_bo->gem_vaddr, sim_bo->sim_vaddr, sim_bo->size); + + if (*(uint32_t *)(sim_bo->sim_vaddr + + sim_bo->size) != BO_SENTINEL) { + fprintf(stderr, "Buffer overflow in handle %d\n", + handle); + } +} + +static int +v3d_simulator_pin_bos(struct v3d_simulator_file *file, + struct drm_v3d_submit_cl *submit) +{ + uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles; + + for (int i = 0; i < submit->bo_handle_count; i++) + v3d_simulator_copy_in_handle(file, bo_handles[i]); + + return 0; +} + +static int +v3d_simulator_unpin_bos(struct v3d_simulator_file *file, + struct drm_v3d_submit_cl *submit) +{ + uint32_t *bo_handles = (uint32_t *)(uintptr_t)submit->bo_handles; + + for (int i = 0; i < submit->bo_handle_count; i++) + v3d_simulator_copy_out_handle(file, bo_handles[i]); + + return 0; +} + +static int +v3d_simulator_submit_cl_ioctl(int fd, struct drm_v3d_submit_cl *submit) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + int ret; + + ret = v3d_simulator_pin_bos(file, submit); + if (ret) + return ret; + + mtx_lock(&sim_state.submit_lock); + bin_fd = fd; + if (sim_state.ver >= 41) + v3d41_simulator_submit_cl_ioctl(sim_state.v3d, submit, file->gmp->ofs); + else + v3d33_simulator_submit_cl_ioctl(sim_state.v3d, submit, file->gmp->ofs); + + util_dynarray_foreach(&sim_state.bin_oom, struct v3d_simulator_bo *, + sim_bo) { + v3d_free_simulator_bo(*sim_bo); + } + util_dynarray_clear(&sim_state.bin_oom); + + mtx_unlock(&sim_state.submit_lock); + + ret = v3d_simulator_unpin_bos(file, submit); + if (ret) + return ret; + + return 0; +} + +/** + * Do fixups after a BO has been opened from a handle. + * + * This could be done at DRM_IOCTL_GEM_OPEN/DRM_IOCTL_GEM_PRIME_FD_TO_HANDLE + * time, but we're still using drmPrimeFDToHandle() so we have this helper to + * be called afterward instead. + */ +void v3d_simulator_open_from_handle(int fd, int handle, uint32_t size) +{ + v3d_create_simulator_bo_for_gem(fd, handle, size); +} + +/** + * Simulated ioctl(fd, DRM_VC5_CREATE_BO) implementation. + * + * Making a VC5 BO is just a matter of making a corresponding BO on the host. + */ +static int +v3d_simulator_create_bo_ioctl(int fd, struct drm_v3d_create_bo *args) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + + /* i915 bans dumb create on render nodes, so we have to use their + * native ioctl in case we're on a render node. + */ + int ret; + if (file->is_i915) { + struct drm_i915_gem_create create = { + .size = args->size, + }; + ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); + + args->handle = create.handle; + } else { + struct drm_mode_create_dumb create = { + .width = 128, + .bpp = 8, + .height = (args->size + 127) / 128, + }; + + ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create); + assert(ret != 0 || create.size >= args->size); + + args->handle = create.handle; + } + + if (ret == 0) { + struct v3d_simulator_bo *sim_bo = + v3d_create_simulator_bo_for_gem(fd, args->handle, + args->size); + + args->offset = sim_bo->block->ofs; + } + + return ret; +} + +/** + * Simulated ioctl(fd, DRM_VC5_MMAP_BO) implementation. + * + * We've already grabbed the mmap offset when we created the sim bo, so just + * return it. + */ +static int +v3d_simulator_mmap_bo_ioctl(int fd, struct drm_v3d_mmap_bo *args) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, + args->handle); + + args->offset = sim_bo->mmap_offset; + + return 0; +} + +static int +v3d_simulator_get_bo_offset_ioctl(int fd, struct drm_v3d_get_bo_offset *args) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, + args->handle); + + args->offset = sim_bo->block->ofs; + + return 0; +} + +static int +v3d_simulator_gem_close_ioctl(int fd, struct drm_gem_close *args) +{ + /* Free the simulator's internal tracking. */ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + struct v3d_simulator_bo *sim_bo = v3d_get_simulator_bo(file, + args->handle); + + v3d_free_simulator_bo(sim_bo); + + /* Pass the call on down. */ + return drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, args); +} + +static int +v3d_simulator_get_param_ioctl(int fd, struct drm_v3d_get_param *args) +{ + if (sim_state.ver >= 41) + return v3d41_simulator_get_param_ioctl(sim_state.v3d, args); + else + return v3d33_simulator_get_param_ioctl(sim_state.v3d, args); +} + +static int +v3d_simulator_submit_tfu_ioctl(int fd, struct drm_v3d_submit_tfu *args) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + int ret; + + v3d_simulator_copy_in_handle(file, args->bo_handles[0]); + v3d_simulator_copy_in_handle(file, args->bo_handles[1]); + v3d_simulator_copy_in_handle(file, args->bo_handles[2]); + v3d_simulator_copy_in_handle(file, args->bo_handles[3]); + + if (sim_state.ver >= 41) + ret = v3d41_simulator_submit_tfu_ioctl(sim_state.v3d, args); + else + ret = v3d33_simulator_submit_tfu_ioctl(sim_state.v3d, args); + + v3d_simulator_copy_out_handle(file, args->bo_handles[0]); + + return ret; +} + +static int +v3d_simulator_submit_csd_ioctl(int fd, struct drm_v3d_submit_csd *args) +{ + struct v3d_simulator_file *file = v3d_get_simulator_file_for_fd(fd); + uint32_t *bo_handles = (uint32_t *)(uintptr_t)args->bo_handles; + int ret; + + for (int i = 0; i < args->bo_handle_count; i++) + v3d_simulator_copy_in_handle(file, bo_handles[i]); + + if (sim_state.ver >= 41) + ret = v3d41_simulator_submit_csd_ioctl(sim_state.v3d, args, + file->gmp->ofs); + else + ret = -1; + + for (int i = 0; i < args->bo_handle_count; i++) + v3d_simulator_copy_out_handle(file, bo_handles[i]); + + return ret; +} + +int +v3d_simulator_ioctl(int fd, unsigned long request, void *args) +{ + switch (request) { + case DRM_IOCTL_V3D_SUBMIT_CL: + return v3d_simulator_submit_cl_ioctl(fd, args); + case DRM_IOCTL_V3D_CREATE_BO: + return v3d_simulator_create_bo_ioctl(fd, args); + case DRM_IOCTL_V3D_MMAP_BO: + return v3d_simulator_mmap_bo_ioctl(fd, args); + case DRM_IOCTL_V3D_GET_BO_OFFSET: + return v3d_simulator_get_bo_offset_ioctl(fd, args); + + case DRM_IOCTL_V3D_WAIT_BO: + /* We do all of the v3d rendering synchronously, so we just + * return immediately on the wait ioctls. This ignores any + * native rendering to the host BO, so it does mean we race on + * front buffer rendering. + */ + return 0; + + case DRM_IOCTL_V3D_GET_PARAM: + return v3d_simulator_get_param_ioctl(fd, args); + + case DRM_IOCTL_GEM_CLOSE: + return v3d_simulator_gem_close_ioctl(fd, args); + + case DRM_IOCTL_V3D_SUBMIT_TFU: + return v3d_simulator_submit_tfu_ioctl(fd, args); + + case DRM_IOCTL_V3D_SUBMIT_CSD: + return v3d_simulator_submit_csd_ioctl(fd, args); + + case DRM_IOCTL_GEM_OPEN: + case DRM_IOCTL_GEM_FLINK: + return drmIoctl(fd, request, args); + default: + fprintf(stderr, "Unknown ioctl 0x%08x\n", (int)request); + abort(); + } +} + +static void +v3d_simulator_init_global() +{ + mtx_lock(&sim_state.mutex); + if (sim_state.refcount++) { + mtx_unlock(&sim_state.mutex); + return; + } + + sim_state.v3d = v3d_hw_auto_new(NULL); + v3d_hw_alloc_mem(sim_state.v3d, 1024 * 1024 * 1024); + sim_state.mem_base = + v3d_hw_get_mem(sim_state.v3d, &sim_state.mem_size, + &sim_state.mem); + + /* Allocate from anywhere from 4096 up. We don't allocate at 0, + * because for OQs and some other addresses in the HW, 0 means + * disabled. + */ + sim_state.heap = u_mmInit(4096, sim_state.mem_size - 4096); + + /* Make a block of 0xd0 at address 0 to make sure we don't screw up + * and land there. + */ + struct mem_block *b = u_mmAllocMem(sim_state.heap, 4096, GMP_ALIGN2, 0); + memset(sim_state.mem + b->ofs - sim_state.mem_base, 0xd0, 4096); + + sim_state.ver = v3d_hw_get_version(sim_state.v3d); + + mtx_unlock(&sim_state.mutex); + + sim_state.fd_map = + _mesa_hash_table_create(NULL, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + + util_dynarray_init(&sim_state.bin_oom, NULL); + + if (sim_state.ver >= 41) + v3d41_simulator_init_regs(sim_state.v3d); + else + v3d33_simulator_init_regs(sim_state.v3d); +} + +struct v3d_simulator_file * +v3d_simulator_init(int fd) +{ + v3d_simulator_init_global(); + + struct v3d_simulator_file *sim_file = rzalloc(NULL, struct v3d_simulator_file); + + drmVersionPtr version = drmGetVersion(fd); + if (version && strncmp(version->name, "i915", version->name_len) == 0) + sim_file->is_i915 = true; + drmFreeVersion(version); + + sim_file->bo_map = + _mesa_hash_table_create(sim_file, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + + mtx_lock(&sim_state.mutex); + _mesa_hash_table_insert(sim_state.fd_map, int_to_key(fd + 1), + sim_file); + mtx_unlock(&sim_state.mutex); + + sim_file->gmp = u_mmAllocMem(sim_state.heap, 8096, GMP_ALIGN2, 0); + sim_file->gmp_vaddr = (sim_state.mem + sim_file->gmp->ofs - + sim_state.mem_base); + memset(sim_file->gmp_vaddr, 0, 8096); + + return sim_file; +} + +void +v3d_simulator_destroy(struct v3d_simulator_file *sim_file) +{ + mtx_lock(&sim_state.mutex); + if (!--sim_state.refcount) { + _mesa_hash_table_destroy(sim_state.fd_map, NULL); + util_dynarray_fini(&sim_state.bin_oom); + u_mmDestroy(sim_state.heap); + /* No memsetting the struct, because it contains the mutex. */ + sim_state.mem = NULL; + } + mtx_unlock(&sim_state.mutex); + ralloc_free(sim_file); +} + +#endif /* USE_V3D_SIMULATOR */ diff --git a/src/broadcom/simulator/v3d_simulator.h b/src/broadcom/simulator/v3d_simulator.h new file mode 100644 index 00000000000..dfd5b9648f8 --- /dev/null +++ b/src/broadcom/simulator/v3d_simulator.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2019 Raspberry Pi + * Copyright © 2014-2017 Broadcom + * Copyright (C) 2012 Rob Clark <[email protected]> + * + * 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 V3D_SIMULATOR_H +#define V3D_SIMULATOR_H + +#ifdef V3D_VERSION +#include "broadcom/common/v3d_macros.h" +#endif + +#include <stdint.h> + +struct v3d_simulator_file; + +struct v3d_simulator_file* v3d_simulator_init(int fd); +void v3d_simulator_destroy(struct v3d_simulator_file *sim_file); +uint32_t v3d_simulator_get_spill(uint32_t spill_size); +int v3d_simulator_ioctl(int fd, unsigned long request, void *arg); +void v3d_simulator_open_from_handle(int fd, int handle, uint32_t size); + +#ifdef v3dX +# include "v3dx_simulator.h" +#else +# define v3dX(x) v3d33_##x +# include "v3dx_simulator.h" +# undef v3dX + +# define v3dX(x) v3d41_##x +# include "v3dx_simulator.h" +# undef v3dX +#endif + +#endif diff --git a/src/broadcom/simulator/v3d_simulator_wrapper.cpp b/src/broadcom/simulator/v3d_simulator_wrapper.cpp new file mode 100644 index 00000000000..15db767d534 --- /dev/null +++ b/src/broadcom/simulator/v3d_simulator_wrapper.cpp @@ -0,0 +1,93 @@ +/* + * Copyright © 2017 Broadcom + * + * 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. + */ + +/** @file + * + * Wraps bits of the V3D simulator interface in a C interface for the + * v3d_simulator.c code to use. + */ + +#ifdef USE_V3D_SIMULATOR + +#include "v3d_simulator_wrapper.h" + +#define V3D_TECH_VERSION 3 +#define V3D_REVISION 3 +#define V3D_SUB_REV 0 +#define V3D_HIDDEN_REV 0 +#define V3D_COMPAT_REV 0 +#include "v3d_hw_auto.h" + +extern "C" { + +struct v3d_hw *v3d_hw_auto_new(void *in_params) +{ + return v3d_hw_auto_make_unique().release(); +} + + +uint32_t v3d_hw_get_mem(const struct v3d_hw *hw, size_t *size, void **p) +{ + return hw->get_mem(size, p); +} + +bool v3d_hw_alloc_mem(struct v3d_hw *hw, size_t min_size) +{ + return hw->alloc_mem(min_size) == V3D_HW_ALLOC_SUCCESS; +} + +bool v3d_hw_has_gca(struct v3d_hw *hw) +{ + return hw->has_gca(); +} + +uint32_t v3d_hw_read_reg(struct v3d_hw *hw, uint32_t reg) +{ + return hw->read_reg(reg); +} + +void v3d_hw_write_reg(struct v3d_hw *hw, uint32_t reg, uint32_t val) +{ + hw->write_reg(reg, val); +} + +void v3d_hw_tick(struct v3d_hw *hw) +{ + return hw->tick(); +} + +int v3d_hw_get_version(struct v3d_hw *hw) +{ + const V3D_HUB_IDENT_T *ident = hw->get_hub_ident(); + + return ident->tech_version * 10 + ident->revision; +} + +void +v3d_hw_set_isr(struct v3d_hw *hw, void (*isr)(uint32_t status)) +{ + hw->set_isr(isr); +} + +} +#endif /* USE_V3D_SIMULATOR */ diff --git a/src/broadcom/simulator/v3d_simulator_wrapper.h b/src/broadcom/simulator/v3d_simulator_wrapper.h new file mode 100644 index 00000000000..b20ea2484b4 --- /dev/null +++ b/src/broadcom/simulator/v3d_simulator_wrapper.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2017 Broadcom + * + * 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 <stdint.h> +#include <stdlib.h> + +struct v3d_hw; + +#ifdef __cplusplus +extern "C" { +#endif + +struct v3d_hw *v3d_hw_auto_new(void *params); +uint32_t v3d_hw_get_mem(const struct v3d_hw *hw, size_t *size, void **p); +bool v3d_hw_alloc_mem(struct v3d_hw *hw, size_t min_size); +bool v3d_hw_has_gca(struct v3d_hw *hw); +uint32_t v3d_hw_read_reg(struct v3d_hw *hw, uint32_t reg); +void v3d_hw_write_reg(struct v3d_hw *hw, uint32_t reg, uint32_t val); +void v3d_hw_tick(struct v3d_hw *hw); +int v3d_hw_get_version(struct v3d_hw *hw); +void v3d_hw_set_isr(struct v3d_hw *hw, void (*isr)(uint32_t status)); + +#ifdef __cplusplus +} +#endif diff --git a/src/broadcom/simulator/v3dx_simulator.c b/src/broadcom/simulator/v3dx_simulator.c new file mode 100644 index 00000000000..dee3e67992c --- /dev/null +++ b/src/broadcom/simulator/v3dx_simulator.c @@ -0,0 +1,357 @@ +/* + * Copyright © 2014-2017 Broadcom + * + * 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. + */ + +/** + * @file v3dx_simulator.c + * + * Implements the actual HW interaction betweeh the GL driver's VC5 simulator and the simulator. + * + * The register headers between V3D versions will have conflicting defines, so + * all register interactions appear in this file and are compiled per V3D version + * we support. + */ + +#ifdef USE_V3D_SIMULATOR + +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> + +#include "v3d_simulator.h" +#include "v3d_simulator_wrapper.h" + +#include "util/macros.h" +#include "drm-uapi/v3d_drm.h" + +#define HW_REGISTER_RO(x) (x) +#define HW_REGISTER_RW(x) (x) +#if V3D_VERSION >= 41 +#include "libs/core/v3d/registers/4.1.34.0/v3d.h" +#else +#include "libs/core/v3d/registers/3.3.0.0/v3d.h" +#endif + +#define V3D_WRITE(reg, val) v3d_hw_write_reg(v3d, reg, val) +#define V3D_READ(reg) v3d_hw_read_reg(v3d, reg) + +static void +v3d_invalidate_l3(struct v3d_hw *v3d) +{ + if (!v3d_hw_has_gca(v3d)) + return; + +#if V3D_VERSION < 40 + uint32_t gca_ctrl = V3D_READ(V3D_GCA_CACHE_CTRL); + + V3D_WRITE(V3D_GCA_CACHE_CTRL, gca_ctrl | V3D_GCA_CACHE_CTRL_FLUSH_SET); + V3D_WRITE(V3D_GCA_CACHE_CTRL, gca_ctrl & ~V3D_GCA_CACHE_CTRL_FLUSH_SET); +#endif +} + +/* Invalidates the L2C cache. This is a read-only cache for uniforms and instructions. */ +static void +v3d_invalidate_l2c(struct v3d_hw *v3d) +{ + if (V3D_VERSION >= 33) + return; + + V3D_WRITE(V3D_CTL_0_L2CACTL, + V3D_CTL_0_L2CACTL_L2CCLR_SET | + V3D_CTL_0_L2CACTL_L2CENA_SET); +} + +/* Invalidates texture L2 cachelines */ +static void +v3d_invalidate_l2t(struct v3d_hw *v3d) +{ + V3D_WRITE(V3D_CTL_0_L2TFLSTA, 0); + V3D_WRITE(V3D_CTL_0_L2TFLEND, ~0); + V3D_WRITE(V3D_CTL_0_L2TCACTL, + V3D_CTL_0_L2TCACTL_L2TFLS_SET | + (0 << V3D_CTL_0_L2TCACTL_L2TFLM_LSB)); +} + +/* Flushes dirty texture cachelines from the L1 write combiner */ +static void +v3d_flush_l1td(struct v3d_hw *v3d) +{ + V3D_WRITE(V3D_CTL_0_L2TCACTL, + V3D_CTL_0_L2TCACTL_TMUWCF_SET); + + assert(!(V3D_READ(V3D_CTL_0_L2TCACTL) & V3D_CTL_0_L2TCACTL_L2TFLS_SET)); +} + +/* Flushes dirty texture L2 cachelines */ +static void +v3d_flush_l2t(struct v3d_hw *v3d) +{ + V3D_WRITE(V3D_CTL_0_L2TFLSTA, 0); + V3D_WRITE(V3D_CTL_0_L2TFLEND, ~0); + V3D_WRITE(V3D_CTL_0_L2TCACTL, + V3D_CTL_0_L2TCACTL_L2TFLS_SET | + (2 << V3D_CTL_0_L2TCACTL_L2TFLM_LSB)); + + assert(!(V3D_READ(V3D_CTL_0_L2TCACTL) & V3D_CTL_0_L2TCACTL_L2TFLS_SET)); +} + +/* Invalidates the slice caches. These are read-only caches. */ +static void +v3d_invalidate_slices(struct v3d_hw *v3d) +{ + V3D_WRITE(V3D_CTL_0_SLCACTL, ~0); +} + +static void +v3d_invalidate_caches(struct v3d_hw *v3d) +{ + v3d_invalidate_l3(v3d); + v3d_invalidate_l2c(v3d); + v3d_invalidate_l2t(v3d); + v3d_invalidate_slices(v3d); +} + +static uint32_t g_gmp_ofs; +static void +v3d_reload_gmp(struct v3d_hw *v3d) +{ + /* Completely reset the GMP. */ + V3D_WRITE(V3D_GMP_0_CFG, + V3D_GMP_0_CFG_PROTENABLE_SET); + V3D_WRITE(V3D_GMP_0_TABLE_ADDR, g_gmp_ofs); + V3D_WRITE(V3D_GMP_0_CLEAR_LOAD, ~0); + while (V3D_READ(V3D_GMP_0_STATUS) & + V3D_GMP_0_STATUS_CFG_BUSY_SET) { + ; + } +} + +static UNUSED void +v3d_flush_caches(struct v3d_hw *v3d) +{ + v3d_flush_l1td(v3d); + v3d_flush_l2t(v3d); +} + +int +v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_tfu *args) +{ + int last_vtct = V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET; + + V3D_WRITE(V3D_TFU_IIA, args->iia); + V3D_WRITE(V3D_TFU_IIS, args->iis); + V3D_WRITE(V3D_TFU_ICA, args->ica); + V3D_WRITE(V3D_TFU_IUA, args->iua); + V3D_WRITE(V3D_TFU_IOA, args->ioa); + V3D_WRITE(V3D_TFU_IOS, args->ios); + V3D_WRITE(V3D_TFU_COEF0, args->coef[0]); + V3D_WRITE(V3D_TFU_COEF1, args->coef[1]); + V3D_WRITE(V3D_TFU_COEF2, args->coef[2]); + V3D_WRITE(V3D_TFU_COEF3, args->coef[3]); + + V3D_WRITE(V3D_TFU_ICFG, args->icfg); + + while ((V3D_READ(V3D_TFU_CS) & V3D_TFU_CS_CVTCT_SET) == last_vtct) { + v3d_hw_tick(v3d); + } + + return 0; +} + +#if V3D_VERSION >= 41 +int +v3dX(simulator_submit_csd_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_csd *args, + uint32_t gmp_ofs) +{ + g_gmp_ofs = gmp_ofs; + v3d_reload_gmp(v3d); + + v3d_invalidate_caches(v3d); + + V3D_WRITE(V3D_CSD_0_QUEUED_CFG1, args->cfg[1]); + V3D_WRITE(V3D_CSD_0_QUEUED_CFG2, args->cfg[2]); + V3D_WRITE(V3D_CSD_0_QUEUED_CFG3, args->cfg[3]); + V3D_WRITE(V3D_CSD_0_QUEUED_CFG4, args->cfg[4]); + V3D_WRITE(V3D_CSD_0_QUEUED_CFG5, args->cfg[5]); + V3D_WRITE(V3D_CSD_0_QUEUED_CFG6, args->cfg[6]); + /* CFG0 kicks off the job */ + V3D_WRITE(V3D_CSD_0_QUEUED_CFG0, args->cfg[0]); + + while (V3D_READ(V3D_CSD_0_STATUS) & + (V3D_CSD_0_STATUS_HAVE_CURRENT_DISPATCH_SET | + V3D_CSD_0_STATUS_HAVE_QUEUED_DISPATCH_SET)) { + v3d_hw_tick(v3d); + } + + v3d_flush_caches(v3d); + + return 0; +} +#endif + +int +v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_get_param *args) +{ + static const uint32_t reg_map[] = { + [DRM_V3D_PARAM_V3D_UIFCFG] = V3D_HUB_CTL_UIFCFG, + [DRM_V3D_PARAM_V3D_HUB_IDENT1] = V3D_HUB_CTL_IDENT1, + [DRM_V3D_PARAM_V3D_HUB_IDENT2] = V3D_HUB_CTL_IDENT2, + [DRM_V3D_PARAM_V3D_HUB_IDENT3] = V3D_HUB_CTL_IDENT3, + [DRM_V3D_PARAM_V3D_CORE0_IDENT0] = V3D_CTL_0_IDENT0, + [DRM_V3D_PARAM_V3D_CORE0_IDENT1] = V3D_CTL_0_IDENT1, + [DRM_V3D_PARAM_V3D_CORE0_IDENT2] = V3D_CTL_0_IDENT2, + }; + + switch (args->param) { + case DRM_V3D_PARAM_SUPPORTS_TFU: + args->value = 1; + return 0; + case DRM_V3D_PARAM_SUPPORTS_CSD: + args->value = V3D_VERSION >= 41; + return 0; + case DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH: + args->value = 1; + return 0; + } + + if (args->param < ARRAY_SIZE(reg_map) && reg_map[args->param]) { + args->value = V3D_READ(reg_map[args->param]); + return 0; + } + + fprintf(stderr, "Unknown DRM_IOCTL_VC5_GET_PARAM(%lld)\n", + (long long)args->value); + abort(); +} + +static struct v3d_hw *v3d_isr_hw; + +static void +v3d_isr(uint32_t hub_status) +{ + struct v3d_hw *v3d = v3d_isr_hw; + + /* Check the per-core bits */ + if (hub_status & (1 << 0)) { + uint32_t core_status = V3D_READ(V3D_CTL_0_INT_STS); + V3D_WRITE(V3D_CTL_0_INT_CLR, core_status); + + if (core_status & V3D_CTL_0_INT_STS_INT_OUTOMEM_SET) { + uint32_t size = 256 * 1024; + uint32_t offset = v3d_simulator_get_spill(size); + + v3d_reload_gmp(v3d); + + V3D_WRITE(V3D_PTB_0_BPOA, offset); + V3D_WRITE(V3D_PTB_0_BPOS, size); + return; + } + + if (core_status & V3D_CTL_0_INT_STS_INT_GMPV_SET) { + fprintf(stderr, "GMP violation at 0x%08x\n", + V3D_READ(V3D_GMP_0_VIO_ADDR)); + abort(); + } else { + fprintf(stderr, + "Unexpected ISR with core status 0x%08x\n", + core_status); + } + abort(); + } + + return; +} + +void +v3dX(simulator_init_regs)(struct v3d_hw *v3d) +{ +#if V3D_VERSION == 33 + /* Set OVRTMUOUT to match kernel behavior. + * + * This means that the texture sampler uniform configuration's tmu + * output type field is used, instead of using the hardware default + * behavior based on the texture type. If you want the default + * behavior, you can still put "2" in the indirect texture state's + * output_type field. + */ + V3D_WRITE(V3D_CTL_0_MISCCFG, V3D_CTL_1_MISCCFG_OVRTMUOUT_SET); +#endif + + uint32_t core_interrupts = (V3D_CTL_0_INT_STS_INT_GMPV_SET | + V3D_CTL_0_INT_STS_INT_OUTOMEM_SET); + V3D_WRITE(V3D_CTL_0_INT_MSK_SET, ~core_interrupts); + V3D_WRITE(V3D_CTL_0_INT_MSK_CLR, core_interrupts); + + v3d_isr_hw = v3d; + v3d_hw_set_isr(v3d, v3d_isr); +} + +void +v3dX(simulator_submit_cl_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_cl *submit, + uint32_t gmp_ofs) +{ + g_gmp_ofs = gmp_ofs; + v3d_reload_gmp(v3d); + + v3d_invalidate_caches(v3d); + + if (submit->qma) { + V3D_WRITE(V3D_CLE_0_CT0QMA, submit->qma); + V3D_WRITE(V3D_CLE_0_CT0QMS, submit->qms); + } +#if V3D_VERSION >= 41 + if (submit->qts) { + V3D_WRITE(V3D_CLE_0_CT0QTS, + V3D_CLE_0_CT0QTS_CTQTSEN_SET | + submit->qts); + } +#endif + V3D_WRITE(V3D_CLE_0_CT0QBA, submit->bcl_start); + V3D_WRITE(V3D_CLE_0_CT0QEA, submit->bcl_end); + + /* Wait for bin to complete before firing render. The kernel's + * scheduler implements this using the GPU scheduler blocking on the + * bin fence completing. (We don't use HW semaphores). + */ + while (V3D_READ(V3D_CLE_0_CT0CA) != + V3D_READ(V3D_CLE_0_CT0EA)) { + v3d_hw_tick(v3d); + } + + v3d_invalidate_caches(v3d); + + V3D_WRITE(V3D_CLE_0_CT1QBA, submit->rcl_start); + V3D_WRITE(V3D_CLE_0_CT1QEA, submit->rcl_end); + + while (V3D_READ(V3D_CLE_0_CT1CA) != + V3D_READ(V3D_CLE_0_CT1EA) || + V3D_READ(V3D_CLE_1_CT1CA) != + V3D_READ(V3D_CLE_1_CT1EA)) { + v3d_hw_tick(v3d); + } +} + +#endif /* USE_V3D_SIMULATOR */ diff --git a/src/broadcom/simulator/v3dx_simulator.h b/src/broadcom/simulator/v3dx_simulator.h new file mode 100644 index 00000000000..2c623d79a83 --- /dev/null +++ b/src/broadcom/simulator/v3dx_simulator.h @@ -0,0 +1,46 @@ +/* + * Copyright © 2019 Raspberry Pi + * Copyright © 2014-2017 Broadcom + * Copyright (C) 2012 Rob Clark <[email protected]> + * + * 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. + */ + +/* This file generates the per-v3d-version function prototypes. It must only + * be included from v3d_simulator.h. + */ + +struct v3d_hw; +struct drm_v3d_get_param; +struct drm_v3d_submit_cl; +struct drm_v3d_submit_tfu; +struct drm_v3d_submit_csd; + +void v3dX(simulator_init_regs)(struct v3d_hw *v3d); +int v3dX(simulator_get_param_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_get_param *args); +void v3dX(simulator_submit_cl_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_cl *args, + uint32_t gmp_offset); +int v3dX(simulator_submit_tfu_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_tfu *args); +int v3dX(simulator_submit_csd_ioctl)(struct v3d_hw *v3d, + struct drm_v3d_submit_csd *args, + uint32_t gmp_offset); |