vc4: Switch simulator to using kernel validator
[mesa.git] / src / gallium / drivers / vc4 / vc4_simulator.c
1 /*
2 * Copyright © 2014 Broadcom
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #ifdef USE_VC4_SIMULATOR
25
26 #include <stdio.h>
27
28 #include "util/u_memory.h"
29
30 #include "vc4_screen.h"
31 #include "vc4_context.h"
32 #include "vc4_simulator_validate.h"
33 #include "simpenrose/simpenrose.h"
34
35 static struct drm_gem_cma_object *
36 vc4_wrap_bo_with_cma(struct drm_device *dev, struct vc4_bo *bo)
37 {
38 struct vc4_context *vc4 = dev->vc4;
39 struct vc4_screen *screen = vc4->screen;
40 struct drm_gem_cma_object *obj = CALLOC_STRUCT(drm_gem_cma_object);
41 uint32_t size = align(bo->size, 4096);
42
43 obj->bo = bo;
44 obj->base.size = size;
45 obj->vaddr = screen->simulator_mem_base + dev->simulator_mem_next;
46 obj->paddr = simpenrose_hw_addr(obj->vaddr);
47
48 dev->simulator_mem_next += size;
49 dev->simulator_mem_next = align(dev->simulator_mem_next, 4096);
50 assert(dev->simulator_mem_next <= screen->simulator_mem_size);
51
52 return obj;
53 }
54
55 static struct drm_gem_cma_object *
56 drm_gem_cma_create(struct drm_device *dev, size_t size)
57 {
58 struct vc4_context *vc4 = dev->vc4;
59 struct vc4_screen *screen = vc4->screen;
60
61 struct vc4_bo *bo = vc4_bo_alloc(screen, size, "simulator validate");
62 return vc4_wrap_bo_with_cma(dev, bo);
63 }
64
65 static int
66 vc4_simulator_pin_bos(struct drm_device *dev, struct drm_vc4_submit_cl *args,
67 struct exec_info *exec)
68 {
69 struct vc4_context *vc4 = dev->vc4;
70 struct vc4_bo **bos = vc4->bo_pointers.base;
71
72 exec->bo_count = args->bo_handle_count;
73 exec->bo = calloc(exec->bo_count, sizeof(void *));
74 for (int i = 0; i < exec->bo_count; i++) {
75 struct vc4_bo *bo = bos[i];
76 struct drm_gem_cma_object *obj = vc4_wrap_bo_with_cma(dev, bo);
77
78 memcpy(obj->vaddr, bo->map, bo->size);
79
80 exec->bo[i] = obj;
81 }
82
83 return 0;
84 }
85
86 static int
87 vc4_simulator_unpin_bos(struct drm_vc4_submit_cl *args,
88 struct exec_info *exec)
89 {
90 for (int i = 0; i < exec->bo_count; i++) {
91 struct drm_gem_cma_object *obj = exec->bo[i];
92 struct vc4_bo *bo = obj->bo;
93
94 memcpy(bo->map, obj->vaddr, bo->size);
95
96 free(obj);
97 }
98
99 free(exec->bo);
100
101 return 0;
102 }
103
104 static int
105 vc4_cl_validate(struct drm_device *dev, struct drm_vc4_submit_cl *args,
106 struct exec_info *exec)
107 {
108 void *temp = NULL;
109 void *bin, *render, *shader_rec;
110 int ret = 0;
111 uint32_t bin_offset = 0;
112 uint32_t render_offset = bin_offset + args->bin_cl_len;
113 uint32_t shader_rec_offset = roundup(render_offset +
114 args->render_cl_len, 16);
115 uint32_t exec_size = shader_rec_offset + args->shader_record_len;
116 uint32_t temp_size = exec_size + (sizeof(struct vc4_shader_state) *
117 args->shader_record_count);
118
119 if (shader_rec_offset < render_offset ||
120 exec_size < shader_rec_offset ||
121 args->shader_record_count >= (UINT_MAX /
122 sizeof(struct vc4_shader_state)) ||
123 temp_size < exec_size) {
124 DRM_ERROR("overflow in exec arguments\n");
125 goto fail;
126 }
127
128 /* Allocate space where we'll store the copied in user command lists
129 * and shader records.
130 *
131 * We don't just copy directly into the BOs because we need to
132 * read the contents back for validation, and I think the
133 * bo->vaddr is uncached access.
134 */
135 temp = kmalloc(temp_size, GFP_KERNEL);
136 if (!temp) {
137 DRM_ERROR("Failed to allocate storage for copying "
138 "in bin/render CLs.\n");
139 ret = -ENOMEM;
140 goto fail;
141 }
142 bin = temp + bin_offset;
143 render = temp + render_offset;
144 shader_rec = temp + shader_rec_offset;
145 exec->shader_state = temp + exec_size;
146 exec->shader_state_size = args->shader_record_count;
147
148 ret = copy_from_user(bin, args->bin_cl, args->bin_cl_len);
149 if (ret) {
150 DRM_ERROR("Failed to copy in bin cl\n");
151 goto fail;
152 }
153
154 ret = copy_from_user(render, args->render_cl, args->render_cl_len);
155 if (ret) {
156 DRM_ERROR("Failed to copy in render cl\n");
157 goto fail;
158 }
159
160 ret = copy_from_user(shader_rec, args->shader_records,
161 args->shader_record_len);
162 if (ret) {
163 DRM_ERROR("Failed to copy in shader recs\n");
164 goto fail;
165 }
166
167 exec->exec_bo = drm_gem_cma_create(dev, exec_size);
168 #if 0
169 if (IS_ERR(exec->exec_bo)) {
170 DRM_ERROR("Couldn't allocate BO for exec\n");
171 ret = PTR_ERR(exec->exec_bo);
172 exec->exec_bo = NULL;
173 goto fail;
174 }
175 #endif
176
177 exec->ct0ca = exec->exec_bo->paddr + bin_offset;
178 exec->ct0ea = exec->ct0ca + args->bin_cl_len;
179 exec->ct1ca = exec->exec_bo->paddr + render_offset;
180 exec->ct1ea = exec->ct1ca + args->render_cl_len;
181 exec->shader_paddr = exec->exec_bo->paddr + shader_rec_offset;
182
183 ret = vc4_validate_cl(dev,
184 exec->exec_bo->vaddr + bin_offset,
185 bin,
186 args->bin_cl_len,
187 true,
188 exec);
189 if (ret)
190 goto fail;
191
192 ret = vc4_validate_cl(dev,
193 exec->exec_bo->vaddr + render_offset,
194 render,
195 args->render_cl_len,
196 false,
197 exec);
198 if (ret)
199 goto fail;
200
201 ret = vc4_validate_shader_recs(dev,
202 exec->exec_bo->vaddr + shader_rec_offset,
203 shader_rec,
204 args->shader_record_len,
205 exec);
206
207 fail:
208 kfree(temp);
209 return ret;
210 }
211
212 int
213 vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args,
214 struct vc4_surface *csurf)
215 {
216 struct vc4_resource *ctex = vc4_resource(csurf->base.texture);
217 uint32_t winsys_stride = ctex->bo->simulator_winsys_stride;
218 uint32_t sim_stride = ctex->slices[0].stride;
219 uint32_t row_len = MIN2(sim_stride, winsys_stride);
220 struct exec_info exec;
221 struct drm_device local_dev = {
222 .vc4 = vc4,
223 .simulator_mem_next = 0,
224 };
225 struct drm_device *dev = &local_dev;
226 int ret;
227
228 memset(&exec, 0, sizeof(exec));
229
230 if (ctex->bo->simulator_winsys_map) {
231 #if 0
232 fprintf(stderr, "%dx%d %d %d %d\n",
233 ctex->base.b.width0, ctex->base.b.height0,
234 winsys_stride,
235 sim_stride,
236 ctex->bo->size);
237 #endif
238
239 for (int y = 0; y < ctex->base.b.height0; y++) {
240 memcpy(ctex->bo->map + y * sim_stride,
241 ctex->bo->simulator_winsys_map + y * winsys_stride,
242 row_len);
243 }
244 }
245
246 ret = vc4_simulator_pin_bos(dev, args, &exec);
247 if (ret)
248 return ret;
249
250 ret = vc4_cl_validate(dev, args, &exec);
251 if (ret)
252 return ret;
253
254 simpenrose_do_binning(exec.ct0ca, exec.ct0ea);
255 simpenrose_do_rendering(exec.ct1ca, exec.ct1ea);
256
257 ret = vc4_simulator_unpin_bos(args, &exec);
258 if (ret)
259 return ret;
260
261 free(exec.exec_bo);
262
263 if (ctex->bo->simulator_winsys_map) {
264 for (int y = 0; y < ctex->base.b.height0; y++) {
265 memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride,
266 ctex->bo->map + y * sim_stride,
267 row_len);
268 }
269 }
270
271 return 0;
272 }
273
274 void
275 vc4_simulator_init(struct vc4_screen *screen)
276 {
277 simpenrose_init_hardware();
278 screen->simulator_mem_base = simpenrose_get_mem_start();
279 screen->simulator_mem_size = simpenrose_get_mem_size();
280 }
281
282 #endif /* USE_VC4_SIMULATOR */