Skip to content

Commit

Permalink
drm/vmwgfx: Use TTM handles instead of SIDs as user-space surface han…
Browse files Browse the repository at this point in the history
…dles.

Improve the command verifier to catch all occurences of surface handles,
and translate to SIDs.

This way DMA buffers and 3D surfaces share a common handle space,
which makes it possible for the kms code to differentiate.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Thomas Hellstrom authored and Dave Airlie committed Dec 23, 2009
1 parent 3d3a5b3 commit 7a73ba7
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 111 deletions.
10 changes: 6 additions & 4 deletions drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct vmw_sw_context{
uint32_t last_cid;
bool cid_valid;
uint32_t last_sid;
uint32_t sid_translation;
bool sid_valid;
struct ttm_object_file *tfile;
struct list_head validate_nodes;
Expand Down Expand Up @@ -317,9 +318,10 @@ extern void vmw_surface_res_free(struct vmw_resource *res);
extern int vmw_surface_init(struct vmw_private *dev_priv,
struct vmw_surface *srf,
void (*res_free) (struct vmw_resource *res));
extern int vmw_user_surface_lookup(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
int sid, struct vmw_surface **out);
extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
uint32_t handle,
struct vmw_surface **out);
extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
Expand All @@ -328,7 +330,7 @@ extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_surface_check(struct vmw_private *dev_priv,
struct ttm_object_file *tfile,
int id);
uint32_t handle, int *id);
extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo);
extern int vmw_dmabuf_init(struct vmw_private *dev_priv,
struct vmw_dma_buffer *vmw_bo,
Expand Down
153 changes: 129 additions & 24 deletions drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,21 +73,32 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,

static int vmw_cmd_sid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
uint32_t sid)
uint32_t *sid)
{
if (unlikely((!sw_context->sid_valid || sid != sw_context->last_sid) &&
sid != SVGA3D_INVALID_ID)) {
int ret = vmw_surface_check(dev_priv, sw_context->tfile, sid);
if (*sid == SVGA3D_INVALID_ID)
return 0;

if (unlikely((!sw_context->sid_valid ||
*sid != sw_context->last_sid))) {
int real_id;
int ret = vmw_surface_check(dev_priv, sw_context->tfile,
*sid, &real_id);

if (unlikely(ret != 0)) {
DRM_ERROR("Could ot find or use surface %u\n",
(unsigned) sid);
DRM_ERROR("Could ot find or use surface 0x%08x "
"address 0x%08lx\n",
(unsigned int) *sid,
(unsigned long) sid);
return ret;
}

sw_context->last_sid = sid;
sw_context->last_sid = *sid;
sw_context->sid_valid = true;
}
*sid = real_id;
sw_context->sid_translation = real_id;
} else
*sid = sw_context->sid_translation;

return 0;
}

Expand All @@ -107,7 +118,8 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
return ret;

cmd = container_of(header, struct vmw_sid_cmd, header);
return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.target.sid);
ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid);
return ret;
}

static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
Expand All @@ -121,10 +133,10 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
int ret;

cmd = container_of(header, struct vmw_sid_cmd, header);
ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
if (unlikely(ret != 0))
return ret;
return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
}

static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
Expand All @@ -138,10 +150,10 @@ static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv,
int ret;

cmd = container_of(header, struct vmw_sid_cmd, header);
ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid);
ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid);
if (unlikely(ret != 0))
return ret;
return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid);
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid);
}

static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
Expand All @@ -154,7 +166,7 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv,
} *cmd;

cmd = container_of(header, struct vmw_sid_cmd, header);
return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.srcImage.sid);
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid);
}

static int vmw_cmd_present_check(struct vmw_private *dev_priv,
Expand All @@ -167,7 +179,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv,
} *cmd;

cmd = container_of(header, struct vmw_sid_cmd, header);
return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.sid);
return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid);
}

static int vmw_cmd_dma(struct vmw_private *dev_priv,
Expand All @@ -187,12 +199,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
uint32_t cur_validate_node;
struct ttm_validate_buffer *val_buf;


cmd = container_of(header, struct vmw_dma_cmd, header);
ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->dma.host.sid);
if (unlikely(ret != 0))
return ret;

handle = cmd->dma.guest.ptr.gmrId;
ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo);
if (unlikely(ret != 0)) {
Expand Down Expand Up @@ -228,21 +235,114 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
++sw_context->cur_val_buf;
}

ret = vmw_user_surface_lookup(dev_priv, sw_context->tfile,
cmd->dma.host.sid, &srf);
ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile,
cmd->dma.host.sid, &srf);
if (ret) {
DRM_ERROR("could not find surface\n");
goto out_no_reloc;
}

/**
* Patch command stream with device SID.
*/

cmd->dma.host.sid = srf->res.id;
vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header);
/**
* FIXME: May deadlock here when called from the
* command parsing code.
*/
vmw_surface_unreference(&srf);

out_no_reloc:
vmw_dmabuf_unreference(&vmw_bo);
return ret;
}

static int vmw_cmd_draw(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
struct vmw_draw_cmd {
SVGA3dCmdHeader header;
SVGA3dCmdDrawPrimitives body;
} *cmd;
SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)(
(unsigned long)header + sizeof(*cmd));
SVGA3dPrimitiveRange *range;
uint32_t i;
uint32_t maxnum;
int ret;

ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
if (unlikely(ret != 0))
return ret;

cmd = container_of(header, struct vmw_draw_cmd, header);
maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);

if (unlikely(cmd->body.numVertexDecls > maxnum)) {
DRM_ERROR("Illegal number of vertex declarations.\n");
return -EINVAL;
}

for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) {
ret = vmw_cmd_sid_check(dev_priv, sw_context,
&decl->array.surfaceId);
if (unlikely(ret != 0))
return ret;
}

maxnum = (header->size - sizeof(cmd->body) -
cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range);
if (unlikely(cmd->body.numRanges > maxnum)) {
DRM_ERROR("Illegal number of index ranges.\n");
return -EINVAL;
}

range = (SVGA3dPrimitiveRange *) decl;
for (i = 0; i < cmd->body.numRanges; ++i, ++range) {
ret = vmw_cmd_sid_check(dev_priv, sw_context,
&range->indexArray.surfaceId);
if (unlikely(ret != 0))
return ret;
}
return 0;
}


static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
struct vmw_tex_state_cmd {
SVGA3dCmdHeader header;
SVGA3dCmdSetTextureState state;
};

SVGA3dTextureState *last_state = (SVGA3dTextureState *)
((unsigned long) header + header->size + sizeof(header));
SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
int ret;

ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
if (unlikely(ret != 0))
return ret;

for (; cur_state < last_state; ++cur_state) {
if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE))
continue;

ret = vmw_cmd_sid_check(dev_priv, sw_context,
&cur_state->value);
if (unlikely(ret != 0))
return ret;
}

return 0;
}


typedef int (*vmw_cmd_func) (struct vmw_private *,
struct vmw_sw_context *,
Expand All @@ -264,7 +364,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET,
&vmw_cmd_set_render_target_check),
VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state),
VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check),
Expand All @@ -276,7 +376,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = {
VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw),
VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check),
VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_cid_check),
Expand All @@ -291,6 +391,7 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
void *buf, uint32_t *size)
{
uint32_t cmd_id;
uint32_t size_remaining = *size;
SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf;
int ret;

Expand All @@ -304,6 +405,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv,
*size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader);

cmd_id -= SVGA_3D_CMD_BASE;
if (unlikely(*size > size_remaining))
goto out_err;

if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE))
goto out_err;

Expand All @@ -326,6 +430,7 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv,
int ret;

while (cur_size > 0) {
size = cur_size;
ret = vmw_cmd_check(dev_priv, sw_context, buf, &size);
if (unlikely(ret != 0))
return ret;
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
int ret;

if (handle) {
ret = vmw_user_surface_lookup(dev_priv, tfile,
handle, &surface);
ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
handle, &surface);
if (!ret) {
if (!surface->snooper.image) {
DRM_ERROR("surface not suitable for cursor\n");
Expand Down Expand Up @@ -704,8 +704,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
struct vmw_dma_buffer *bo = NULL;
int ret;

ret = vmw_user_surface_lookup(dev_priv, tfile,
mode_cmd->handle, &surface);
ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
mode_cmd->handle, &surface);
if (ret)
goto try_dmabuf;

Expand Down
Loading

0 comments on commit 7a73ba7

Please sign in to comment.