aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2012-11-21 05:36:36 -0500
committerThomas Hellstrom <thellstrom@vmware.com>2014-01-17 01:52:25 -0500
commit58a0c5f036464bd891880b30bde196320e904b81 (patch)
tree263f5d0157cbb4d23df5408881946de0f74f3f86 /drivers/gpu/drm/vmwgfx/vmwgfx_context.c
parentf468911feec94201b4296e3fe7480ebaf278fc4d (diff)
drm/vmwgfx: Hook up guest-backed contexts
Contexts are managed by the kernel only, so disable access to GB context commands from user-space Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Zack Ruzin <zackr@vmware.com>
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_context.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 00ae0925aca8..308e78fdc55e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -38,6 +38,14 @@ static void vmw_user_context_free(struct vmw_resource *res);
38static struct vmw_resource * 38static struct vmw_resource *
39vmw_user_context_base_to_res(struct ttm_base_object *base); 39vmw_user_context_base_to_res(struct ttm_base_object *base);
40 40
41static int vmw_gb_context_create(struct vmw_resource *res);
42static int vmw_gb_context_bind(struct vmw_resource *res,
43 struct ttm_validate_buffer *val_buf);
44static int vmw_gb_context_unbind(struct vmw_resource *res,
45 bool readback,
46 struct ttm_validate_buffer *val_buf);
47static int vmw_gb_context_destroy(struct vmw_resource *res);
48
41static uint64_t vmw_user_context_size; 49static uint64_t vmw_user_context_size;
42 50
43static const struct vmw_user_resource_conv user_context_conv = { 51static const struct vmw_user_resource_conv user_context_conv = {
@@ -62,6 +70,18 @@ static const struct vmw_res_func vmw_legacy_context_func = {
62 .unbind = NULL 70 .unbind = NULL
63}; 71};
64 72
73static const struct vmw_res_func vmw_gb_context_func = {
74 .res_type = vmw_res_context,
75 .needs_backup = true,
76 .may_evict = true,
77 .type_name = "guest backed contexts",
78 .backup_placement = &vmw_mob_placement,
79 .create = vmw_gb_context_create,
80 .destroy = vmw_gb_context_destroy,
81 .bind = vmw_gb_context_bind,
82 .unbind = vmw_gb_context_unbind
83};
84
65/** 85/**
66 * Context management: 86 * Context management:
67 */ 87 */
@@ -76,6 +96,16 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
76 } *cmd; 96 } *cmd;
77 97
78 98
99 if (res->func->destroy == vmw_gb_context_destroy) {
100 mutex_lock(&dev_priv->cmdbuf_mutex);
101 (void) vmw_gb_context_destroy(res);
102 if (dev_priv->pinned_bo != NULL &&
103 !dev_priv->query_cid_valid)
104 __vmw_execbuf_release_pinned_bo(dev_priv, NULL);
105 mutex_unlock(&dev_priv->cmdbuf_mutex);
106 return;
107 }
108
79 vmw_execbuf_release_pinned_bo(dev_priv); 109 vmw_execbuf_release_pinned_bo(dev_priv);
80 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); 110 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
81 if (unlikely(cmd == NULL)) { 111 if (unlikely(cmd == NULL)) {
@@ -92,6 +122,28 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
92 vmw_3d_resource_dec(dev_priv, false); 122 vmw_3d_resource_dec(dev_priv, false);
93} 123}
94 124
125static int vmw_gb_context_init(struct vmw_private *dev_priv,
126 struct vmw_resource *res,
127 void (*res_free) (struct vmw_resource *res))
128{
129 int ret;
130
131 ret = vmw_resource_init(dev_priv, res, true,
132 res_free, &vmw_gb_context_func);
133 res->backup_size = SVGA3D_CONTEXT_DATA_SIZE;
134
135 if (unlikely(ret != 0)) {
136 if (res_free)
137 res_free(res);
138 else
139 kfree(res);
140 return ret;
141 }
142
143 vmw_resource_activate(res, vmw_hw_context_destroy);
144 return 0;
145}
146
95static int vmw_context_init(struct vmw_private *dev_priv, 147static int vmw_context_init(struct vmw_private *dev_priv,
96 struct vmw_resource *res, 148 struct vmw_resource *res,
97 void (*res_free) (struct vmw_resource *res)) 149 void (*res_free) (struct vmw_resource *res))
@@ -103,6 +155,9 @@ static int vmw_context_init(struct vmw_private *dev_priv,
103 SVGA3dCmdDefineContext body; 155 SVGA3dCmdDefineContext body;
104 } *cmd; 156 } *cmd;
105 157
158 if (dev_priv->has_mob)
159 return vmw_gb_context_init(dev_priv, res, res_free);
160
106 ret = vmw_resource_init(dev_priv, res, false, 161 ret = vmw_resource_init(dev_priv, res, false,
107 res_free, &vmw_legacy_context_func); 162 res_free, &vmw_legacy_context_func);
108 163
@@ -154,6 +209,173 @@ struct vmw_resource *vmw_context_alloc(struct vmw_private *dev_priv)
154 return (ret == 0) ? res : NULL; 209 return (ret == 0) ? res : NULL;
155} 210}
156 211
212
213static int vmw_gb_context_create(struct vmw_resource *res)
214{
215 struct vmw_private *dev_priv = res->dev_priv;
216 int ret;
217 struct {
218 SVGA3dCmdHeader header;
219 SVGA3dCmdDefineGBContext body;
220 } *cmd;
221
222 if (likely(res->id != -1))
223 return 0;
224
225 ret = vmw_resource_alloc_id(res);
226 if (unlikely(ret != 0)) {
227 DRM_ERROR("Failed to allocate a context id.\n");
228 goto out_no_id;
229 }
230
231 if (unlikely(res->id >= VMWGFX_NUM_GB_CONTEXT)) {
232 ret = -EBUSY;
233 goto out_no_fifo;
234 }
235
236 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
237 if (unlikely(cmd == NULL)) {
238 DRM_ERROR("Failed reserving FIFO space for context "
239 "creation.\n");
240 ret = -ENOMEM;
241 goto out_no_fifo;
242 }
243
244 cmd->header.id = SVGA_3D_CMD_DEFINE_GB_CONTEXT;
245 cmd->header.size = sizeof(cmd->body);
246 cmd->body.cid = res->id;
247 vmw_fifo_commit(dev_priv, sizeof(*cmd));
248 (void) vmw_3d_resource_inc(dev_priv, false);
249
250 return 0;
251
252out_no_fifo:
253 vmw_resource_release_id(res);
254out_no_id:
255 return ret;
256}
257
258static int vmw_gb_context_bind(struct vmw_resource *res,
259 struct ttm_validate_buffer *val_buf)
260{
261 struct vmw_private *dev_priv = res->dev_priv;
262 struct {
263 SVGA3dCmdHeader header;
264 SVGA3dCmdBindGBContext body;
265 } *cmd;
266 struct ttm_buffer_object *bo = val_buf->bo;
267
268 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
269
270 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
271 if (unlikely(cmd == NULL)) {
272 DRM_ERROR("Failed reserving FIFO space for context "
273 "binding.\n");
274 return -ENOMEM;
275 }
276
277 cmd->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
278 cmd->header.size = sizeof(cmd->body);
279 cmd->body.cid = res->id;
280 cmd->body.mobid = bo->mem.start;
281 cmd->body.validContents = res->backup_dirty;
282 res->backup_dirty = false;
283 vmw_fifo_commit(dev_priv, sizeof(*cmd));
284
285 return 0;
286}
287
288static int vmw_gb_context_unbind(struct vmw_resource *res,
289 bool readback,
290 struct ttm_validate_buffer *val_buf)
291{
292 struct vmw_private *dev_priv = res->dev_priv;
293 struct ttm_buffer_object *bo = val_buf->bo;
294 struct vmw_fence_obj *fence;
295
296 struct {
297 SVGA3dCmdHeader header;
298 SVGA3dCmdReadbackGBContext body;
299 } *cmd1;
300 struct {
301 SVGA3dCmdHeader header;
302 SVGA3dCmdBindGBContext body;
303 } *cmd2;
304 uint32_t submit_size;
305 uint8_t *cmd;
306
307
308 BUG_ON(bo->mem.mem_type != VMW_PL_MOB);
309
310 submit_size = sizeof(*cmd2) + (readback ? sizeof(*cmd1) : 0);
311
312 cmd = vmw_fifo_reserve(dev_priv, submit_size);
313 if (unlikely(cmd == NULL)) {
314 DRM_ERROR("Failed reserving FIFO space for context "
315 "unbinding.\n");
316 return -ENOMEM;
317 }
318
319 cmd2 = (void *) cmd;
320 if (readback) {
321 cmd1 = (void *) cmd;
322 cmd1->header.id = SVGA_3D_CMD_READBACK_GB_CONTEXT;
323 cmd1->header.size = sizeof(cmd1->body);
324 cmd1->body.cid = res->id;
325 cmd2 = (void *) (&cmd1[1]);
326 }
327 cmd2->header.id = SVGA_3D_CMD_BIND_GB_CONTEXT;
328 cmd2->header.size = sizeof(cmd2->body);
329 cmd2->body.cid = res->id;
330 cmd2->body.mobid = SVGA3D_INVALID_ID;
331
332 vmw_fifo_commit(dev_priv, submit_size);
333
334 /*
335 * Create a fence object and fence the backup buffer.
336 */
337
338 (void) vmw_execbuf_fence_commands(NULL, dev_priv,
339 &fence, NULL);
340
341 vmw_fence_single_bo(bo, fence);
342
343 if (likely(fence != NULL))
344 vmw_fence_obj_unreference(&fence);
345
346 return 0;
347}
348
349static int vmw_gb_context_destroy(struct vmw_resource *res)
350{
351 struct vmw_private *dev_priv = res->dev_priv;
352 struct {
353 SVGA3dCmdHeader header;
354 SVGA3dCmdDestroyGBContext body;
355 } *cmd;
356
357 if (likely(res->id == -1))
358 return 0;
359
360 cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
361 if (unlikely(cmd == NULL)) {
362 DRM_ERROR("Failed reserving FIFO space for context "
363 "destruction.\n");
364 return -ENOMEM;
365 }
366
367 cmd->header.id = SVGA_3D_CMD_DESTROY_GB_CONTEXT;
368 cmd->header.size = sizeof(cmd->body);
369 cmd->body.cid = res->id;
370 vmw_fifo_commit(dev_priv, sizeof(*cmd));
371 if (dev_priv->query_cid == res->id)
372 dev_priv->query_cid_valid = false;
373 vmw_resource_release_id(res);
374 vmw_3d_resource_dec(dev_priv, false);
375
376 return 0;
377}
378
157/** 379/**
158 * User-space context management: 380 * User-space context management:
159 */ 381 */