summaryrefslogtreecommitdiff
path: root/shared-core/radeon_ms_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/radeon_ms_exec.c')
-rw-r--r--shared-core/radeon_ms_exec.c222
1 files changed, 65 insertions, 157 deletions
diff --git a/shared-core/radeon_ms_exec.c b/shared-core/radeon_ms_exec.c
index 574e5a06..28fcc180 100644
--- a/shared-core/radeon_ms_exec.c
+++ b/shared-core/radeon_ms_exec.c
@@ -25,7 +25,7 @@
* Jerome Glisse <glisse@freedesktop.org>
*/
#include "radeon_ms.h"
-#include "amd_cbuffer.h"
+#include "amd.h"
static void radeon_ms_execbuffer_args_clean(struct drm_device *dev,
struct amd_cbuffer *cbuffer,
@@ -118,175 +118,78 @@ out_err:
return ret;
}
-enum {
- REGISTER_FORBIDDEN = 0,
- REGISTER_SAFE,
- REGISTER_SET_OFFSET,
-};
-static uint8_t _r3xx_register_right[0x5000 >> 2];
-
-static int amd_cbuffer_packet0_set_offset(struct drm_device *dev,
- struct amd_cbuffer *cbuffer,
- uint32_t reg, int dw_id,
- struct amd_cbuffer_arg *arg)
-{
- uint32_t gpu_addr;
- int ret;
-
- ret = radeon_ms_bo_get_gpu_addr(dev, &arg->buffer->mem, &gpu_addr);
- if (ret) {
- return ret;
- }
- switch (reg) {
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static struct amd_cbuffer_arg *
-amd_cbuffer_arg_from_dw_id(struct amd_cbuffer_arg *head, uint32_t dw_id)
+static int cbuffer_packet0_check(struct drm_device *dev,
+ struct amd_cbuffer *cbuffer,
+ int dw_id)
{
- struct amd_cbuffer_arg *arg;
-
- list_for_each_entry(arg, &head->list, list) {
- if (arg->dw_id == dw_id) {
- return arg;
- }
- }
- /* no buffer at this dw index */
- return NULL;
-}
-
-static int amd_cbuffer_packet0_check(struct drm_device *dev,
- struct drm_file *file_priv,
- struct amd_cbuffer *cbuffer,
- int dw_id,
- uint8_t *register_right)
-{
- struct amd_cbuffer_arg *arg;
+ struct drm_radeon_private *dev_priv = dev->dev_private;
uint32_t reg, count, r, i;
int ret;
reg = cbuffer->cbuffer[dw_id] & PACKET0_REG_MASK;
count = (cbuffer->cbuffer[dw_id] & PACKET0_COUNT_MASK) >>
PACKET0_COUNT_SHIFT;
+ if (reg + count > dev_priv->cbuffer_checker.numof_p0_checkers) {
+ return -EINVAL;
+ }
for (r = reg, i = 0; i <= count; i++, r++) {
- switch (register_right[i]) {
- case REGISTER_FORBIDDEN:
+ if (dev_priv->cbuffer_checker.check_p0[r] == NULL) {
+ continue;
+ }
+ if (dev_priv->cbuffer_checker.check_p0[r] == (void *)-1) {
+ DRM_INFO("[radeon_ms] check_f: %d %d -1 checker\n",
+ r, r << 2);
+ return -EINVAL;
+ }
+ ret = dev_priv->cbuffer_checker.check_p0[r](dev, cbuffer,
+ dw_id + i + 1, reg);
+ if (ret) {
+ DRM_INFO("[radeon_ms] check_f: %d %d checker ret=%d\n",
+ r, r << 2, ret);
return -EINVAL;
- case REGISTER_SAFE:
- break;
- case REGISTER_SET_OFFSET:
- arg = amd_cbuffer_arg_from_dw_id(&cbuffer->arg_unused,
- dw_id + i +1);
- if (arg == NULL) {
- return -EINVAL;
- }
- /* remove from unparsed list */
- list_del(&arg->list);
- list_add_tail(&arg->list, &cbuffer->arg_used.list);
- /* set the offset */
- ret = amd_cbuffer_packet0_set_offset(dev, cbuffer,
- r, dw_id + i + 1,
- arg);
- if (ret) {
- return ret;
- }
- break;
}
}
/* header + N + 1 dword passed test */
return count + 2;
}
-static int amd_cbuffer_packet3_check(struct drm_device *dev,
- struct drm_file *file_priv,
- struct amd_cbuffer *cbuffer,
- int dw_id)
+static int cbuffer_packet3_check(struct drm_device *dev,
+ struct amd_cbuffer *cbuffer,
+ int dw_id)
{
- struct amd_cbuffer_arg *arg;
+ struct drm_radeon_private *dev_priv = dev->dev_private;
uint32_t opcode, count;
- uint32_t s_auth, s_mask;
- uint32_t gpu_addr;
int ret;
opcode = (cbuffer->cbuffer[dw_id] & PACKET3_OPCODE_MASK) >>
PACKET3_OPCODE_SHIFT;
+ if (opcode > dev_priv->cbuffer_checker.numof_p3_checkers) {
+ return -EINVAL;
+ }
count = (cbuffer->cbuffer[dw_id] & PACKET3_COUNT_MASK) >>
PACKET3_COUNT_SHIFT;
- switch (opcode) {
- case PACKET3_OPCODE_NOP:
- break;
- case PACKET3_OPCODE_BITBLT:
- case PACKET3_OPCODE_BITBLT_MULTI:
- DRM_INFO("[radeon_ms] exec step - [05][P3]00.00\n");
- /* we only alow simple blit */
- if (count != 5) {
- return -EINVAL;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]01.00\n");
- s_mask = 0xf;
- s_auth = 0x3;
- if ((cbuffer->cbuffer[dw_id + 1] & s_mask) != s_auth) {
- return -EINVAL;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]02.00\n");
- arg = amd_cbuffer_arg_from_dw_id(&cbuffer->arg_unused, dw_id+2);
- if (arg == NULL) {
- return -EINVAL;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]03.00\n");
- ret = radeon_ms_bo_get_gpu_addr(dev, &arg->buffer->mem,
- &gpu_addr);
- if (ret) {
- return ret;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]04.00\n");
- gpu_addr = (gpu_addr >> 10) & 0x003FFFFF;
- cbuffer->cbuffer[dw_id + 2] &= 0xFFC00000;
- cbuffer->cbuffer[dw_id + 2] |= gpu_addr;
- arg = amd_cbuffer_arg_from_dw_id(&cbuffer->arg_unused, dw_id+3);
- if (arg == NULL) {
- return -EINVAL;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]05.00\n");
- ret = radeon_ms_bo_get_gpu_addr(dev, &arg->buffer->mem,
- &gpu_addr);
- if (ret) {
- return ret;
- }
- DRM_INFO("[radeon_ms] exec step - [05][P3]06.00\n");
- gpu_addr = (gpu_addr >> 10) & 0x003FFFFF;
- cbuffer->cbuffer[dw_id + 3] &= 0xFFC00000;
- cbuffer->cbuffer[dw_id + 3] |= gpu_addr;
- DRM_INFO("[radeon_ms] exec step - [05][P3]07.00\n");
- /* FIXME: check that source & destination are big enough
- * for requested blit */
- break;
- default:
+ if (dev_priv->cbuffer_checker.check_p3[opcode] == NULL) {
+ return -EINVAL;
+ }
+ ret = dev_priv->cbuffer_checker.check_p3[opcode](dev, cbuffer,
+ dw_id + 1, opcode,
+ count);
+ if (ret) {
return -EINVAL;
}
- /* header + N + 1 dword passed test */
return count + 2;
}
-static int amd_cbuffer_check(struct drm_device *dev,
- struct drm_file *file_priv,
- struct amd_cbuffer *cbuffer)
+int amd_cbuffer_check(struct drm_device *dev, struct amd_cbuffer *cbuffer)
{
uint32_t i;
int ret;
for (i = 0; i < cbuffer->cbuffer_dw_count;) {
- DRM_INFO("[radeon_ms] exec step - [05]00.00 %d 0x%08X\n",
- i, cbuffer->cbuffer[i]);
switch (PACKET_HEADER_GET(cbuffer->cbuffer[i])) {
case 0:
- ret = amd_cbuffer_packet0_check(dev, file_priv,
- cbuffer, i,
- _r3xx_register_right);
- if (ret) {
+ ret = cbuffer_packet0_check(dev, cbuffer, i);
+ if (ret <= 0) {
return ret;
}
/* advance to next packet */
@@ -296,13 +199,11 @@ static int amd_cbuffer_check(struct drm_device *dev,
/* we don't accept packet 1 */
return -EINVAL;
case 2:
- /* packet 2 */
- i += 1;
- break;
+ /* FIXME: accept packet 2 */
+ return -EINVAL;
case 3:
- ret = amd_cbuffer_packet3_check(dev, file_priv,
- cbuffer, i);
- if (ret) {
+ ret = cbuffer_packet3_check(dev, cbuffer, i);
+ if (ret <= 0) {
return ret;
}
/* advance to next packet */
@@ -313,9 +214,25 @@ static int amd_cbuffer_check(struct drm_device *dev,
return 0;
}
+struct amd_cbuffer_arg *
+amd_cbuffer_arg_from_dw_id(struct amd_cbuffer_arg *head, uint32_t dw_id)
+{
+ struct amd_cbuffer_arg *arg;
+
+ list_for_each_entry(arg, &head->list, list) {
+ if (arg->dw_id == dw_id) {
+ return arg;
+ }
+ }
+ /* no buffer at this dw index */
+ return NULL;
+}
+
+
int radeon_ms_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_radeon_execbuffer *execbuffer = data;
struct drm_fence_arg *fence_arg = &execbuffer->fence_arg;
struct drm_bo_kmap_obj cmd_kmap;
@@ -331,13 +248,11 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
/* FIXME: Lock buffer manager, is this really needed ?
*/
- DRM_INFO("[radeon_ms] exec step - 00.00\n");
ret = drm_bo_read_lock(&dev->bm.bm_lock);
if (ret) {
return ret;
}
- DRM_INFO("[radeon_ms] exec step - 01.00\n");
cbuffer.args = drm_calloc(execbuffer->args_count,
sizeof(struct amd_cbuffer_arg),
DRM_MEM_DRIVER);
@@ -350,7 +265,6 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
INIT_LIST_HEAD(&cbuffer.arg_used.list);
/* process arguments */
- DRM_INFO("[radeon_ms] exec step - 02.00\n");
ret = radeon_ms_execbuffer_args(dev, file_priv, execbuffer, &cbuffer);
if (ret) {
DRM_ERROR("[radeon_ms] execbuffer wrong arguments\n");
@@ -358,14 +272,12 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
}
/* map command buffer */
- DRM_INFO("[radeon_ms] exec step - 03.00\n");
cbuffer.cbuffer_dw_count = (cbuffer.args[0].buffer->mem.num_pages *
PAGE_SIZE) >> 2;
if (execbuffer->cmd_size > cbuffer.cbuffer_dw_count) {
ret = -EINVAL;
goto out_free_release;
}
- DRM_INFO("[radeon_ms] exec step - 04.00\n");
cbuffer.cbuffer_dw_count = execbuffer->cmd_size;
memset(&cmd_kmap, 0, sizeof(struct drm_bo_kmap_obj));
ret = drm_bo_kmap(cbuffer.args[0].buffer, 0,
@@ -374,21 +286,21 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
DRM_ERROR("[radeon_ms] error mapping ring buffer: %d\n", ret);
goto out_free_release;
}
- DRM_INFO("[radeon_ms] exec step - 05.00\n");
cbuffer.cbuffer = drm_bmo_virtual(&cmd_kmap, &cmd_is_iomem);
- DRM_INFO("[radeon_ms] exec step - 05.01\n");
list_del(&cbuffer.args[0].list);
- DRM_INFO("[radeon_ms] exec step - 05.02\n");
list_add_tail(&cbuffer.args[0].list , &cbuffer.arg_used.list);
- DRM_INFO("[radeon_ms] exec step - 05.03\n");
/* do cmd checking & relocations */
- ret = amd_cbuffer_check(dev, file_priv, &cbuffer);
- if (ret) {
+ if (dev_priv->cbuffer_checker.check) {
+ ret = dev_priv->cbuffer_checker.check(dev, &cbuffer);
+ if (ret) {
+ drm_putback_buffer_objects(dev);
+ goto out_free_release;
+ }
+ } else {
drm_putback_buffer_objects(dev);
goto out_free_release;
}
- DRM_INFO("[radeon_ms] exec step - 06.00\n");
ret = radeon_ms_ring_emit(dev, cbuffer.cbuffer,
cbuffer.cbuffer_dw_count);
@@ -396,7 +308,6 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
drm_putback_buffer_objects(dev);
goto out_free_release;
}
- DRM_INFO("[radeon_ms] exec step - 07.00\n");
/* fence */
ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &fence);
@@ -418,16 +329,13 @@ int radeon_ms_execbuffer(struct drm_device *dev, void *data,
}
}
drm_fence_usage_deref_unlocked(&fence);
- DRM_INFO("[radeon_ms] exec step - 08.00\n");
out_free_release:
drm_bo_kunmap(&cmd_kmap);
radeon_ms_execbuffer_args_clean(dev, &cbuffer, execbuffer->args_count);
- DRM_INFO("[radeon_ms] exec step - 09.00\n");
out_free:
drm_free(cbuffer.args,
(execbuffer->args_count * sizeof(struct amd_cbuffer_arg)),
DRM_MEM_DRIVER);
drm_bo_read_unlock(&dev->bm.bm_lock);
- DRM_INFO("[radeon_ms] exec step - 10.00\n");
return ret;
}