From: Alejandro Piñeiro Date: Fri, 29 Nov 2019 10:17:18 +0000 (+0100) Subject: v3d: moving v3d simulator to src/broadcom X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=583d7d3d8d0d14d636340b0f12f72db7b0148ceb;p=mesa.git v3d: moving v3d simulator to src/broadcom So it could be used by both the OpenGL and the Vulkan driver. In addition to the move, some small changes were needed to be made on the API. For example, the simulator was receiving v3d_screen on initialization, and that code setted v3d_screen->sim_file. Now it returns the new sim_file created. Reviewed-by: Eric Anholt Part-of: --- diff --git a/src/broadcom/drm-shim/meson.build b/src/broadcom/drm-shim/meson.build index ab474b648ee..cbad07067c1 100644 --- a/src/broadcom/drm-shim/meson.build +++ b/src/broadcom/drm-shim/meson.build @@ -41,7 +41,7 @@ if dep_v3dv3.found() 'v3dx.c', v3d_xml_pack ], - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_broadcom, inc_gallium_v3d], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_broadcom, inc_gallium_v3d, inc_simulator], c_args : [no_override_init_args, '-DV3D_VERSION=' + ver, v3dv3_c_args], gnu_symbol_visibility : 'hidden', dependencies: [dep_valgrind, dep_thread, dep_v3dv3], @@ -52,11 +52,11 @@ if dep_v3dv3.found() ['v3d_drm_shim'], [ 'v3d.c', - '../../gallium/drivers/v3d/v3d_simulator_wrapper.cpp', + '../simulator/v3d_simulator_wrapper.cpp', ], dependencies: [idep_mesautil, dep_dl, dep_drm_shim, dep_v3dv3], link_with: per_version_libs, - include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_broadcom, inc_gallium_v3d], + include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_broadcom, inc_gallium_v3d, inc_simulator], c_args : [no_override_init_args, '-std=gnu99', v3dv3_c_args], gnu_symbol_visibility : 'hidden', cpp_args : [v3dv3_c_args] diff --git a/src/broadcom/meson.build b/src/broadcom/meson.build index 15177c5f99c..70406b2f1fb 100644 --- a/src/broadcom/meson.build +++ b/src/broadcom/meson.build @@ -28,6 +28,7 @@ v3d_libs = [] if with_gallium_v3d subdir('compiler') subdir('qpu') + subdir('simulator') endif if with_tools.contains('drm-shim') 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 +#include +#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 +#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 + * + * 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 + +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 +#include + +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 +#include +#include + +#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 + * + * 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); diff --git a/src/gallium/drivers/v3d/meson.build b/src/gallium/drivers/v3d/meson.build index 64e6cb0789a..093eb12e01b 100644 --- a/src/gallium/drivers/v3d/meson.build +++ b/src/gallium/drivers/v3d/meson.build @@ -35,8 +35,6 @@ files_libv3d = files( 'v3d_resource.h', 'v3d_screen.c', 'v3d_screen.h', - 'v3d_simulator.c', - 'v3d_simulator_wrapper.cpp', 'v3d_uniforms.c', ) @@ -46,7 +44,6 @@ files_per_version = files( 'v3dx_format_table.c', 'v3dx_job.c', 'v3dx_rcl.c', - 'v3dx_simulator.c', 'v3dx_state.c', ) @@ -111,7 +108,7 @@ libv3d = static_library( ], include_directories : [ inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_broadcom, - inc_gallium_drivers, + inc_simulator, inc_gallium_drivers, ], c_args : [v3d_args], cpp_args : [v3d_args], diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 3a18a0c4fc4..55bc96bed9d 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -40,6 +40,8 @@ #include "v3d_screen.h" #include "broadcom/common/v3d_limits.h" +#include "broadcom/simulator/v3d_simulator.h" + struct v3d_job; struct v3d_bo; void v3d_job_add_bo(struct v3d_job *job, struct v3d_bo *bo); @@ -615,12 +617,6 @@ void v3d_program_init(struct pipe_context *pctx); void v3d_program_fini(struct pipe_context *pctx); void v3d_query_init(struct pipe_context *pctx); -void v3d_simulator_init(struct v3d_screen *screen); -void v3d_simulator_destroy(struct v3d_screen *screen); -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); - static inline int v3d_ioctl(int fd, unsigned long request, void *arg) { diff --git a/src/gallium/drivers/v3d/v3d_screen.c b/src/gallium/drivers/v3d/v3d_screen.c index 503573e36bc..bafe7301266 100644 --- a/src/gallium/drivers/v3d/v3d_screen.c +++ b/src/gallium/drivers/v3d/v3d_screen.c @@ -78,7 +78,7 @@ v3d_screen_destroy(struct pipe_screen *pscreen) free(screen->ro); if (using_v3d_simulator) - v3d_simulator_destroy(screen); + v3d_simulator_destroy(screen->sim_file); v3d_compiler_free(screen->compiler); u_transfer_helper_destroy(pscreen->transfer_helper); @@ -682,7 +682,7 @@ v3d_screen_create(int fd, const struct pipe_screen_config *config, screen->bo_handles = util_hash_table_create_ptr_keys(); #if defined(USE_V3D_SIMULATOR) - v3d_simulator_init(screen); + screen->sim_file = v3d_simulator_init(screen->fd); #endif if (!v3d_get_device_info(screen->fd, &screen->devinfo, &v3d_ioctl)) diff --git a/src/gallium/drivers/v3d/v3d_simulator.c b/src/gallium/drivers/v3d/v3d_simulator.c deleted file mode 100644 index 7b6709887dc..00000000000 --- a/src/gallium/drivers/v3d/v3d_simulator.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * 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 -#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 "drm-uapi/i915_drm.h" -#include "v3d_simulator_wrapper.h" - -#include "v3d_screen.h" -#include "v3d_context.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(const struct v3d_device_info *devinfo) -{ - 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); -} - -void -v3d_simulator_init(struct v3d_screen *screen) -{ - v3d_simulator_init_global(&screen->devinfo); - - screen->sim_file = rzalloc(screen, struct v3d_simulator_file); - struct v3d_simulator_file *sim_file = screen->sim_file; - - drmVersionPtr version = drmGetVersion(screen->fd); - if (version && strncmp(version->name, "i915", version->name_len) == 0) - sim_file->is_i915 = true; - drmFreeVersion(version); - - screen->sim_file->bo_map = - _mesa_hash_table_create(screen->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(screen->fd + 1), - screen->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); -} - -void -v3d_simulator_destroy(struct v3d_screen *screen) -{ - 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); -} - -#endif /* USE_V3D_SIMULATOR */ diff --git a/src/gallium/drivers/v3d/v3d_simulator_wrapper.cpp b/src/gallium/drivers/v3d/v3d_simulator_wrapper.cpp deleted file mode 100644 index 15db767d534..00000000000 --- a/src/gallium/drivers/v3d/v3d_simulator_wrapper.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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/gallium/drivers/v3d/v3d_simulator_wrapper.h b/src/gallium/drivers/v3d/v3d_simulator_wrapper.h deleted file mode 100644 index b20ea2484b4..00000000000 --- a/src/gallium/drivers/v3d/v3d_simulator_wrapper.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 -#include - -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/gallium/drivers/v3d/v3dx_context.h b/src/gallium/drivers/v3d/v3dx_context.h index 64643411b5d..72441e85a20 100644 --- a/src/gallium/drivers/v3d/v3dx_context.h +++ b/src/gallium/drivers/v3d/v3dx_context.h @@ -36,17 +36,6 @@ void v3dX(state_init)(struct pipe_context *pctx); void v3dX(bcl_epilogue)(struct v3d_context *v3d, struct v3d_job *job); -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); const struct v3d_format *v3dX(get_format_desc)(enum pipe_format f); void v3dX(get_internal_type_bpp_for_output_format)(uint32_t format, uint32_t *type, diff --git a/src/gallium/drivers/v3d/v3dx_simulator.c b/src/gallium/drivers/v3d/v3dx_simulator.c deleted file mode 100644 index a9d3d8cd780..00000000000 --- a/src/gallium/drivers/v3d/v3dx_simulator.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * 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_hw.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 "v3d_screen.h" -#include "v3d_context.h" -#include "v3d_simulator_wrapper.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 */