People can start using transform feedback on r6xx with this.
Strict CS checking will be implemented later.
Signed-off-by: Marek Olšák maraeo@gmail.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 104 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 10 +++ drivers/gpu/drm/radeon/r600_cs.c | 105 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 +++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 +++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 +++ 8 files changed, 246 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index cd4590a..3150489 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,19 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +602,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx); + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1451,6 +1487,62 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index e00039e..ebc014e 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -691,6 +692,7 @@ #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 #define PACKET3_MEM_SEMAPHORE 0x39 #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 @@ -918,6 +920,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index cb1acff..ab3f325 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +982,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx); + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1742,6 +1781,62 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c3ef1d2..e977247 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,9 +54,10 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS + * 2.13.0 - r600 streamout */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 12 +#define KMS_DRIVER_MINOR 13 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
On Thu, Jan 5, 2012 at 9:30 PM, Marek Olšák maraeo@gmail.com wrote:
People can start using transform feedback on r6xx with this.
Strict CS checking will be implemented later.
Signed-off-by: Marek Olšák maraeo@gmail.com
drivers/gpu/drm/radeon/evergreen_cs.c | 104 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 10 +++ drivers/gpu/drm/radeon/r600_cs.c | 105 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 +++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 +++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 +++ 8 files changed, 246 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index cd4590a..3150489 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,19 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* XXX fill in */ return 0; } @@ -597,6 +602,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1451,6 +1487,62 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
We need to check the destination reg here to avoid userspace doig something nefarious. Something like: r = evergreen_cs_check_reg(); if (r) return r;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index e00039e..ebc014e 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -691,6 +692,7 @@ #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 #define PACKET3_MEM_SEMAPHORE 0x39 #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 @@ -918,6 +920,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index cb1acff..ab3f325 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +982,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- break;
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1742,6 +1781,62 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
Same as above.
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c3ef1d2..e977247 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,9 +54,10 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - r600 streamout
*/ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 12 +#define KMS_DRIVER_MINOR 13 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.5.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
On Thu, Jan 05, 2012 at 10:21:31PM -0500, Alex Deucher wrote:
On Thu, Jan 5, 2012 at 9:30 PM, Marek Olšák maraeo@gmail.com wrote:
People can start using transform feedback on r6xx with this.
Strict CS checking will be implemented later.
We really need to have checking in the same patch, otherwise someone can claim that the non checking property of what you introduce is part of the API and thus we can't change it. I know it's painful.
Cheers, Jerome
Signed-off-by: Marek Olšák maraeo@gmail.com
drivers/gpu/drm/radeon/evergreen_cs.c | 104 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 10 +++ drivers/gpu/drm/radeon/r600_cs.c | 105 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 +++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 +++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 +++ 8 files changed, 246 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index cd4590a..3150489 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,19 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* XXX fill in */ return 0; } @@ -597,6 +602,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1451,6 +1487,62 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
We need to check the destination reg here to avoid userspace doig something nefarious. Something like: r = evergreen_cs_check_reg(); if (r) return r;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index e00039e..ebc014e 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -691,6 +692,7 @@ #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 #define PACKET3_MEM_SEMAPHORE 0x39 #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 @@ -918,6 +920,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index cb1acff..ab3f325 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +982,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- break;
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1742,6 +1781,62 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
Same as above.
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c3ef1d2..e977247 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,9 +54,10 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - r600 streamout
*/ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 12 +#define KMS_DRIVER_MINOR 13 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.5.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
You're both right. I wanted to put this patch out so that somebody else could try this stuff out. I'll finish it when time allows.
Marek
On Mon, Jan 9, 2012 at 4:26 PM, Jerome Glisse j.glisse@gmail.com wrote:
On Thu, Jan 05, 2012 at 10:21:31PM -0500, Alex Deucher wrote:
On Thu, Jan 5, 2012 at 9:30 PM, Marek Olšák maraeo@gmail.com wrote:
People can start using transform feedback on r6xx with this.
Strict CS checking will be implemented later.
We really need to have checking in the same patch, otherwise someone can claim that the non checking property of what you introduce is part of the API and thus we can't change it. I know it's painful.
Cheers, Jerome
Signed-off-by: Marek Olšák maraeo@gmail.com
drivers/gpu/drm/radeon/evergreen_cs.c | 104 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 10 +++ drivers/gpu/drm/radeon/r600_cs.c | 105 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 +++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 +++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 +++ 8 files changed, 246 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index cd4590a..3150489 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,19 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* XXX fill in */ return 0; } @@ -597,6 +602,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1451,6 +1487,62 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
We need to check the destination reg here to avoid userspace doig something nefarious. Something like: r = evergreen_cs_check_reg(); if (r) return r;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index e00039e..ebc014e 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -691,6 +692,7 @@ #define PACKET3_DRAW_INDEX_MULTI_ELEMENT 0x36 #define PACKET3_MEM_SEMAPHORE 0x39 #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 @@ -918,6 +920,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index cb1acff..ab3f325 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +982,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
- break;
- case CP_COHER_BASE:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- break;
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1742,6 +1781,62 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
Same as above.
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index c3ef1d2..e977247 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,9 +54,10 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - r600 streamout
*/ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 12 +#define KMS_DRIVER_MINOR 13 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.5.4
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 114 +++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 123 ++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 +++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 +++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 +++ 8 files changed, 271 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..1e23c3c 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { - struct evergreen_cs_track *track = p->track; - - /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx); + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1451,6 +1485,70 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + r = evergreen_cs_check_reg(p, reg, idx+1); + if (r) + return r; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + r = evergreen_cs_check_reg(p, reg, idx+3); + if (r) + return r; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..a702f78 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i] == NULL) { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1742,6 +1793,70 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + r = r600_cs_check_reg(p, reg, idx+1); + if (r) + return r; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + r = r600_cs_check_reg(p, reg, idx+3); + if (r) + return r; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 137 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 136 +++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 307 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..7bef5f8 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { - struct evergreen_cs_track *track = p->track; - - /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx); + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1048,31 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + return false; +} + static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1510,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..06f3c2d 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i] == NULL) { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1448,21 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + return false; +} + static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1808,68 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 138 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 137 +++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 309 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..8bc883a 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { - struct evergreen_cs_track *track = p->track; - - /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx); + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1048,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1511,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..030c295 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i] == NULL) { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1448,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1809,68 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 1)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing reloc 2)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
On Tue, Jan 24, 2012 at 05:17:18PM -0500, alexdeucher@gmail.com wrote:
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
NAK
You never check the stream out buffer size and you never check that the memory offset for dw copy is not after the bo end. See comment below. Sorry to not just do a v5 busy with ttm :(
Beside this it looks ok.
Cheers, Jerome
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/evergreen_cs.c | 138 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 137 +++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 309 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..8bc883a 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size;
@@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
track->vgt_strmout_size[i] = 0;
track->vgt_strmout_bo[i] = NULL;
track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) {
- struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
return -EINVAL;
- }
- /* XXX fill in */ return 0;
} @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG "
"0x%04X\n", reg);
return -EINVAL;
}
tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->vgt_strmout_bo[tmp] = reloc->robj;
track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
r6xx path divide this value by 4 but you never check that : track->vgt_strmout_bo_offset[tmp] + track->vgt_strmout_size <= bo.size
break;
- case CP_COHER_BASE:
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
"0x%04X\n", reg);
return -EINVAL;
}
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break;ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
@@ -1014,6 +1048,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 last_reg, m, i;
- if (p->rdev->family >= CHIP_CAYMAN)
last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
- else
last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
- i = (reg >> 7);
- if (i >= last_reg) {
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (p->rdev->family >= CHIP_CAYMAN) {
if (!(cayman_reg_safe_bm[i] & m))
return true;
- } else {
if (!(evergreen_reg_safe_bm[i] & m))
return true;
- }
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1511,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
if (pkt->count != 4) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
return -EINVAL;
}
/* Updating memory at DST_ADDRESS. */
if (idx_value & 0x1) {
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
/* Reading data from SRC_ADDRESS. */
if (((idx_value >> 1) & 0x3) == 2) {
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
return -EINVAL;
}
ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
break;
- case PACKET3_COPY_DW:
if (pkt->count != 4) {
DRM_ERROR("bad COPY_DW (invalid count)\n");
return -EINVAL;
}
if (idx_value & 0x1) {
/* SRC is memory. */
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
The offset is never check against bo size so userspace can write anywhere :( Same for dst below
} else {
/* SRC is a reg. */
reg = radeon_get_ib_value(p, idx+1) << 2;
if (!evergreen_is_safe_reg(p, reg, idx+1))
return -EINVAL;
}
if (idx_value & 0x2) {
/* DST is memory. */
r = evergreen_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
return -EINVAL;
}
ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
} else {
/* DST is a reg. */
reg = radeon_get_ib_value(p, idx+3) << 2;
if (!evergreen_is_safe_reg(p, reg, idx+3))
return -EINVAL;
}
case PACKET3_NOP: break; default:break;
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..030c295 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx;
@@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
track->vgt_strmout_size[i] = 0;
track->vgt_strmout_bo[i] = NULL;
track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
return -EINVAL;
- /* check streamout */
- if (track->vgt_strmout_en) {
for (i = 0; i < 4; i++) {
if (track->vgt_strmout_buffer_en & (1 << i)) {
if (track->vgt_strmout_bo[i] == NULL) {
dev_warn(p->dev, "No buffer for streamout %d\n", i);
return -EINVAL;
}
}
}}
- /* check that we have a cb for each enabled target, we don't check
*/
- shader_mask because it seems mesa isn't always setting it :(
@@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "bad SET_CONTEXT_REG "
"0x%04X\n", reg);
return -EINVAL;
}
tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
track->vgt_strmout_bo[tmp] = reloc->robj;
track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4;
Why /4 here and not in evergreen ?
break;
- case CP_COHER_BASE:
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
"0x%04X\n", reg);
return -EINVAL;
}
ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break;break;
@@ -1397,6 +1448,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 m, i;
- i = (reg >> 7);
- if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (!(r600_reg_safe_bm[i] & m))
return true;
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1809,68 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
if (pkt->count != 4) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
return -EINVAL;
}
/* Updating memory at DST_ADDRESS. */
if (idx_value & 0x1) {
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
/* Reading data from SRC_ADDRESS. */
if (((idx_value >> 1) & 0x3) == 2) {
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
return -EINVAL;
}
ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
}
break;
- case PACKET3_COPY_DW:
if (pkt->count != 4) {
DRM_ERROR("bad COPY_DW (invalid count)\n");
return -EINVAL;
}
if (idx_value & 0x1) {
/* SRC is memory. */
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
return -EINVAL;
}
ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
} else {
/* SRC is a reg. */
reg = radeon_get_ib_value(p, idx+1) << 2;
if (!r600_is_safe_reg(p, reg, idx+1))
return -EINVAL;
}
if (idx_value & 0x2) {
/* DST is memory. */
r = r600_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
return -EINVAL;
}
ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
} else {
/* DST is a reg. */
reg = radeon_get_ib_value(p, idx+3) << 2;
if (!r600_is_safe_reg(p, reg, idx+3))
return -EINVAL;
}
case PACKET3_NOP: break; default:break;
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@
- 2.10.0 - fusion 2D tiling
- 2.11.0 - backend map, initial compute support for the CS checker
- 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - virtual memory support
*/
- 2.13.0 - virtual memory support, streamout
#define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.7.5
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
Sorry Jerome, I didn't have time to properly finish the patch and update the CS checker properly.
Also evergreen_cs_track_check has been a no-op for a long time and this patch doesn't make it any more exploitable.
Marek
On Wed, Jan 25, 2012 at 12:43 AM, Jerome Glisse j.glisse@gmail.com wrote:
On Tue, Jan 24, 2012 at 05:17:18PM -0500, alexdeucher@gmail.com wrote:
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
NAK
You never check the stream out buffer size and you never check that the memory offset for dw copy is not after the bo end. See comment below. Sorry to not just do a v5 busy with ttm :(
Beside this it looks ok.
Cheers, Jerome
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/evergreen_cs.c | 138 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 137 +++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 309 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..8bc883a 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) {
- struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* XXX fill in */ return 0; } @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
r6xx path divide this value by 4 but you never check that : track->vgt_strmout_bo_offset[tmp] + track->vgt_strmout_size <= bo.size
- break;
- case CP_COHER_BASE:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1048,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 last_reg, m, i;
- if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
- else
- last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
- i = (reg >> 7);
- if (i >= last_reg) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (p->rdev->family >= CHIP_CAYMAN) {
- if (!(cayman_reg_safe_bm[i] & m))
- return true;
- } else {
- if (!(evergreen_reg_safe_bm[i] & m))
- return true;
- }
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1511,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
The offset is never check against bo size so userspace can write anywhere :( Same for dst below
- } else {
- /* SRC is a reg. */
- reg = radeon_get_ib_value(p, idx+1) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+1))
- return -EINVAL;
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
- reg = radeon_get_ib_value(p, idx+3) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+3))
- return -EINVAL;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..030c295 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- /* check streamout */
- if (track->vgt_strmout_en) {
- for (i = 0; i < 4; i++) {
- if (track->vgt_strmout_buffer_en & (1 << i)) {
- if (track->vgt_strmout_bo[i] == NULL) {
- dev_warn(p->dev, "No buffer for streamout %d\n", i);
- return -EINVAL;
- }
- }
- }
}
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4;
Why /4 here and not in evergreen ?
- break;
- case CP_COHER_BASE:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- break;
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1448,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 m, i;
- i = (reg >> 7);
- if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (!(r600_reg_safe_bm[i] & m))
- return true;
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1809,68 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- reg = radeon_get_ib_value(p, idx+1) << 2;
- if (!r600_is_safe_reg(p, reg, idx+1))
- return -EINVAL;
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
- reg = radeon_get_ib_value(p, idx+3) << 2;
- if (!r600_is_safe_reg(p, reg, idx+3))
- return -EINVAL;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - virtual memory support
- 2.13.0 - virtual memory support, streamout
*/ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.7.5
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
v5: agd5f: add stricter checking for 6xx/7xx
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 139 +++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 179 ++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 + drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 352 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..30d4a2e 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { - struct evergreen_cs_track *track = p->track; - - /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +600,38 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1049,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1512,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..9f17571 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,28 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[i] + + (u64)track->vgt_strmout_size[i]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", + i, offset, + radeon_bo_size(track->vgt_strmout_bo[i])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +1003,39 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1458,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1819,100 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
v5: agd5f: add stricter checking for 6xx/7xx
v6: agd5f: add range checking for copy_dw on eg+, add sx_surface_sync to safe reg list for 7xx.
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 155 +++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 179 ++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 + drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 11 ++ 8 files changed, 369 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..65d516f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { - struct evergreen_cs_track *track = p->track; - - /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; - } - /* XXX fill in */ return 0; } @@ -597,6 +600,38 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1049,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1512,84 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..9f17571 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,28 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[i] + + (u64)track->vgt_strmout_size[i]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", + i, offset, + radeon_bo_size(track->vgt_strmout_bo[i])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +1003,39 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1458,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1819,100 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..a1fc242 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ @@ -429,6 +439,7 @@ r600 0x9400 0x00028438 SX_ALPHA_REF 0x00028410 SX_ALPHA_TEST_CONTROL 0x00028350 SX_MISC +0x00028354 SX_SURFACE_SYNC 0x00009014 SX_MEMORY_EXPORT_SIZE 0x00009604 TC_INVALIDATE 0x00009400 TD_FILTER4
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
v5: agd5f: add stricter checking for 6xx/7xx
v6: agd5f: add range checking for copy_dw on eg+, add sx_surface_sync to safe reg list for 7xx.
v7: agd5f: add stricter checking for eg+
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/evergreen_cs.c | 189 ++++++++++++++++++++++++++++- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 179 ++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 + drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 11 ++ 8 files changed, 407 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..2c35966 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,16 +163,41 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int evergreen_cs_track_check(struct radeon_cs_parser *p) { struct evergreen_cs_track *track = p->track; + int i, j;
- /* we don't support stream out buffer yet */ - if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + /* check streamout */ + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_config & (1 << i)) { + for (j = 0; j < 4; j++) { + if ((track->vgt_strmout_buffer_config >> (i * 4)) & (1 << j)) { + if (track->vgt_strmout_bo[j]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[j] + + (u64)track->vgt_strmout_size[j]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", + j, offset, + radeon_bo_size(track->vgt_strmout_bo[j])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", j); + return -EINVAL; + } + } + } + } }
/* XXX fill in */ @@ -597,6 +626,38 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1075,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 last_reg, m, i; + + if (p->rdev->family >= CHIP_CAYMAN) + last_reg = ARRAY_SIZE(cayman_reg_safe_bm); + else + last_reg = ARRAY_SIZE(evergreen_reg_safe_bm); + + i = (reg >> 7); + if (i >= last_reg) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (p->rdev->family >= CHIP_CAYMAN) { + if (!(cayman_reg_safe_bm[i] & m)) + return true; + } else { + if (!(evergreen_reg_safe_bm[i] & m)) + return true; + } + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1538,100 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = evergreen_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!evergreen_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..9f17571 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en; + struct radeon_bo *vgt_strmout_bo[4]; + u64 vgt_strmout_bo_mc[4]; + u32 vgt_strmout_bo_offset[4]; + u32 vgt_strmout_size[4]; u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF; + + for (i = 0; i < 4; i++) { + track->vgt_strmout_size[i] = 0; + track->vgt_strmout_bo[i] = NULL; + track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; + track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF; + } }
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,28 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0; - /* we don't support out buffer yet */ - if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) { - dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n"); - return -EINVAL; + + /* check streamout */ + if (track->vgt_strmout_en) { + for (i = 0; i < 4; i++) { + if (track->vgt_strmout_buffer_en & (1 << i)) { + if (track->vgt_strmout_bo[i]) { + u64 offset = (u64)track->vgt_strmout_bo_offset[i] + + (u64)track->vgt_strmout_size[i]; + if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { + DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", + i, offset, + radeon_bo_size(track->vgt_strmout_bo[i])); + return -EINVAL; + } + } else { + dev_warn(p->dev, "No buffer for streamout %d\n", i); + return -EINVAL; + } + } + } } + /* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +1003,39 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break; + case VGT_STRMOUT_BUFFER_BASE_0: + case VGT_STRMOUT_BUFFER_BASE_1: + case VGT_STRMOUT_BUFFER_BASE_2: + case VGT_STRMOUT_BUFFER_BASE_3: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "bad SET_CONTEXT_REG " + "0x%04X\n", reg); + return -EINVAL; + } + tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; + track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + track->vgt_strmout_bo[tmp] = reloc->robj; + track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset; + break; + case VGT_STRMOUT_BUFFER_SIZE_0: + case VGT_STRMOUT_BUFFER_SIZE_1: + case VGT_STRMOUT_BUFFER_SIZE_2: + case VGT_STRMOUT_BUFFER_SIZE_3: + tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; + /* size in register is DWs, convert to bytes */ + track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; + break; + case CP_COHER_BASE: + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + dev_warn(p->dev, "missing reloc for CP_COHER_BASE " + "0x%04X\n", reg); + return -EINVAL; + } + ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); + break; case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1458,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{ + u32 m, i; + + i = (reg >> 7); + if (i >= ARRAY_SIZE(r600_reg_safe_bm)) { + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; + } + m = 1 << ((reg >> 2) & 31); + if (!(r600_reg_safe_bm[i] & m)) + return true; + dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); + return false; +} + static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1819,100 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break; + case PACKET3_STRMOUT_BUFFER_UPDATE: + if (pkt->count != 4) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); + return -EINVAL; + } + /* Updating memory at DST_ADDRESS. */ + if (idx_value & 0x1) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + /* Reading data from SRC_ADDRESS. */ + if (((idx_value >> 1) & 0x3) == 2) { + u64 offset; + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } + break; + case PACKET3_COPY_DW: + if (pkt->count != 4) { + DRM_ERROR("bad COPY_DW (invalid count)\n"); + return -EINVAL; + } + if (idx_value & 0x1) { + u64 offset; + /* SRC is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing src reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+1); + offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* SRC is a reg. */ + reg = radeon_get_ib_value(p, idx+1) << 2; + if (!r600_is_safe_reg(p, reg, idx+1)) + return -EINVAL; + } + if (idx_value & 0x2) { + u64 offset; + /* DST is memory. */ + r = r600_cs_packet_next_reloc(p, &reloc); + if (r) { + DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); + return -EINVAL; + } + offset = radeon_get_ib_value(p, idx+3); + offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; + if ((offset + 4) > radeon_bo_size(reloc->robj)) { + DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", + offset + 4, radeon_bo_size(reloc->robj)); + return -EINVAL; + } + ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); + ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; + } else { + /* DST is a reg. */ + reg = radeon_get_ib_value(p, idx+3) << 2; + if (!r600_is_safe_reg(p, reg, idx+3)) + return -EINVAL; + } + break; case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 + #define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS - * 2.13.0 - virtual memory support + * 2.13.0 - virtual memory support, streamout */ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..a1fc242 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ @@ -429,6 +439,7 @@ r600 0x9400 0x00028438 SX_ALPHA_REF 0x00028410 SX_ALPHA_TEST_CONTROL 0x00028350 SX_MISC +0x00028354 SX_SURFACE_SYNC 0x00009014 SX_MEMORY_EXPORT_SIZE 0x00009604 TC_INVALIDATE 0x00009400 TD_FILTER4
On Tue, Jan 24, 2012 at 6:43 PM, Jerome Glisse j.glisse@gmail.com wrote:
On Tue, Jan 24, 2012 at 05:17:18PM -0500, alexdeucher@gmail.com wrote:
From: Marek Olšák maraeo@gmail.com
v2: agd5f: add strmout CS checking, copy_dw register checking
v3: agd5f: don't use cs_check_reg() for copy_dw checking as it will incorrectly patch the command stream for certain regs.
v4: agd5f: add warning if safe reg check fails for copy_dw
NAK
You never check the stream out buffer size and you never check that the memory offset for dw copy is not after the bo end. See comment below. Sorry to not just do a v5 busy with ttm :(
I just sent out a new version which should address everything. I went ahead and implemented strict checking for 6xx/7xx. I guess my main concern with the strict checking on 6xx/7xx is that we will miss corner cases have to revisit it later. We've already had to revisit the cb, db, and texture code in the cs checker to work around corner cases and userspace problems and we will need to yet again for 2D tiling. I'm not sure the additional overhead and pain actually makes things much safer considering how temperamental GPUs are in general.
Alex
Beside this it looks ok.
Cheers, Jerome
Signed-off-by: Marek Olšák maraeo@gmail.com Signed-off-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/evergreen_cs.c | 138 +++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/evergreend.h | 9 ++ drivers/gpu/drm/radeon/r600_cs.c | 137 +++++++++++++++++++++++++++- drivers/gpu/drm/radeon/r600d.h | 6 ++ drivers/gpu/drm/radeon/radeon_drv.c | 2 +- drivers/gpu/drm/radeon/reg_srcs/cayman | 10 ++ drivers/gpu/drm/radeon/reg_srcs/evergreen | 10 ++ drivers/gpu/drm/radeon/reg_srcs/r600 | 10 ++ 8 files changed, 309 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index f7442e6..8bc883a 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -60,6 +60,10 @@ struct evergreen_cs_track { u32 cb_shader_mask; u32 vgt_strmout_config; u32 vgt_strmout_buffer_config;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_view; u32 db_depth_size; @@ -159,18 +163,17 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->db_s_write_offset = 0xFFFFFFFF; track->db_s_read_bo = NULL; track->db_s_write_bo = NULL;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int evergreen_cs_track_check(struct radeon_cs_parser *p) {
- struct evergreen_cs_track *track = p->track;
- /* we don't support stream out buffer yet */
- if (track->vgt_strmout_config || track->vgt_strmout_buffer_config) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- }
/* XXX fill in */ return 0; } @@ -597,6 +600,37 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case VGT_STRMOUT_BUFFER_CONFIG: track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx);
r6xx path divide this value by 4 but you never check that : track->vgt_strmout_bo_offset[tmp] + track->vgt_strmout_size <= bo.size
- break;
- case CP_COHER_BASE:
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
case CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1014,6 +1048,32 @@ static int evergreen_check_texture_resource(struct radeon_cs_parser *p, u32 idx return 0; }
+static bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 last_reg, m, i;
- if (p->rdev->family >= CHIP_CAYMAN)
- last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
- else
- last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
- i = (reg >> 7);
- if (i >= last_reg) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (p->rdev->family >= CHIP_CAYMAN) {
- if (!(cayman_reg_safe_bm[i] & m))
- return true;
- } else {
- if (!(evergreen_reg_safe_bm[i] & m))
- return true;
- }
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int evergreen_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1451,6 +1511,68 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
The offset is never check against bo size so userspace can write anywhere :( Same for dst below
- } else {
- /* SRC is a reg. */
- reg = radeon_get_ib_value(p, idx+1) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+1))
- return -EINVAL;
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = evergreen_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
- reg = radeon_get_ib_value(p, idx+3) << 2;
- if (!evergreen_is_safe_reg(p, reg, idx+3))
- return -EINVAL;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 74713d4..50d20da 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,7 @@
#define CONFIG_MEMSIZE 0x5428
+#define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) #define CP_PFP_HALT (1 << 26) @@ -948,6 +949,14 @@ #define SQ_PGM_START_HS 0x288b8 #define SQ_PGM_START_LS 0x288d0
+#define VGT_STRMOUT_BUFFER_BASE_0 0x28AD8 +#define VGT_STRMOUT_BUFFER_BASE_1 0x28AE8 +#define VGT_STRMOUT_BUFFER_BASE_2 0x28AF8 +#define VGT_STRMOUT_BUFFER_BASE_3 0x28B08 +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00 #define VGT_STRMOUT_CONFIG 0x28b94 #define VGT_STRMOUT_BUFFER_CONFIG 0x28b98
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 38ce5d0..030c295 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -61,6 +61,10 @@ struct r600_cs_track { u32 cb_color_size[8]; u32 vgt_strmout_en; u32 vgt_strmout_buffer_en;
- struct radeon_bo *vgt_strmout_bo[4];
- u64 vgt_strmout_bo_mc[4];
- u32 vgt_strmout_bo_offset[4];
- u32 vgt_strmout_size[4];
u32 db_depth_control; u32 db_depth_info; u32 db_depth_size_idx; @@ -310,6 +314,13 @@ static void r600_cs_track_init(struct r600_cs_track *track) track->db_depth_size = 0xFFFFFFFF; track->db_depth_size_idx = 0; track->db_depth_control = 0xFFFFFFFF;
- for (i = 0; i < 4; i++) {
- track->vgt_strmout_size[i] = 0;
- track->vgt_strmout_bo[i] = NULL;
- track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
- track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
- }
}
static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) @@ -430,11 +441,19 @@ static int r600_cs_track_check(struct radeon_cs_parser *p) /* on legacy kernel we don't perform advanced check */ if (p->rdev == NULL) return 0;
- /* we don't support out buffer yet */
- if (track->vgt_strmout_en || track->vgt_strmout_buffer_en) {
- dev_warn(p->dev, "this kernel doesn't support SMX output buffer\n");
- return -EINVAL;
- /* check streamout */
- if (track->vgt_strmout_en) {
- for (i = 0; i < 4; i++) {
- if (track->vgt_strmout_buffer_en & (1 << i)) {
- if (track->vgt_strmout_bo[i] == NULL) {
- dev_warn(p->dev, "No buffer for streamout %d\n", i);
- return -EINVAL;
- }
- }
- }
}
/* check that we have a cb for each enabled target, we don't check * shader_mask because it seems mesa isn't always setting it :( */ @@ -975,6 +994,38 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case R_028B20_VGT_STRMOUT_BUFFER_EN: track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx); break;
- case VGT_STRMOUT_BUFFER_BASE_0:
- case VGT_STRMOUT_BUFFER_BASE_1:
- case VGT_STRMOUT_BUFFER_BASE_2:
- case VGT_STRMOUT_BUFFER_BASE_3:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "bad SET_CONTEXT_REG "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
- track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- track->vgt_strmout_bo[tmp] = reloc->robj;
- track->vgt_strmout_bo_mc[tmp] = reloc->lobj.gpu_offset;
- break;
- case VGT_STRMOUT_BUFFER_SIZE_0:
- case VGT_STRMOUT_BUFFER_SIZE_1:
- case VGT_STRMOUT_BUFFER_SIZE_2:
- case VGT_STRMOUT_BUFFER_SIZE_3:
- tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
- track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) / 4;
Why /4 here and not in evergreen ?
should be * 4 since the register value is in dwords. fixed.
- break;
- case CP_COHER_BASE:
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
- "0x%04X\n", reg);
- return -EINVAL;
- }
- ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
- break;
case R_028238_CB_TARGET_MASK: track->cb_target_mask = radeon_get_ib_value(p, idx); break; @@ -1397,6 +1448,22 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, return 0; }
+static bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) +{
- u32 m, i;
- i = (reg >> 7);
- if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
- }
- m = 1 << ((reg >> 2) & 31);
- if (!(r600_reg_safe_bm[i] & m))
- return true;
- dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
- return false;
+}
static int r600_packet3_check(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt) { @@ -1742,6 +1809,68 @@ static int r600_packet3_check(struct radeon_cs_parser *p, return -EINVAL; } break;
- case PACKET3_STRMOUT_BUFFER_UPDATE:
- if (pkt->count != 4) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
- return -EINVAL;
- }
- /* Updating memory at DST_ADDRESS. */
- if (idx_value & 0x1) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- /* Reading data from SRC_ADDRESS. */
- if (((idx_value >> 1) & 0x3) == 2) {
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- }
- break;
- case PACKET3_COPY_DW:
- if (pkt->count != 4) {
- DRM_ERROR("bad COPY_DW (invalid count)\n");
- return -EINVAL;
- }
- if (idx_value & 0x1) {
- /* SRC is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 1)\n");
- return -EINVAL;
- }
- ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* SRC is a reg. */
- reg = radeon_get_ib_value(p, idx+1) << 2;
- if (!r600_is_safe_reg(p, reg, idx+1))
- return -EINVAL;
- }
- if (idx_value & 0x2) {
- /* DST is memory. */
- r = r600_cs_packet_next_reloc(p, &reloc);
- if (r) {
- DRM_ERROR("bad COPY_DW (missing reloc 2)\n");
- return -EINVAL;
- }
- ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
- ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
- } else {
- /* DST is a reg. */
- reg = radeon_get_ib_value(p, idx+3) << 2;
- if (!r600_is_safe_reg(p, reg, idx+3))
- return -EINVAL;
- }
- break;
case PACKET3_NOP: break; default: diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 3ee1fd7..aa9d7c3 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -493,6 +493,11 @@ #define VGT_STRMOUT_BUFFER_OFFSET_1 0x28AEC #define VGT_STRMOUT_BUFFER_OFFSET_2 0x28AFC #define VGT_STRMOUT_BUFFER_OFFSET_3 0x28B0C +#define VGT_STRMOUT_BUFFER_SIZE_0 0x28AD0 +#define VGT_STRMOUT_BUFFER_SIZE_1 0x28AE0 +#define VGT_STRMOUT_BUFFER_SIZE_2 0x28AF0 +#define VGT_STRMOUT_BUFFER_SIZE_3 0x28B00
#define VGT_STRMOUT_EN 0x28AB0 #define VGT_VERTEX_REUSE_BLOCK_CNTL 0x28C58 #define VTX_REUSE_DEPTH_MASK 0x000000FF @@ -834,6 +839,7 @@ # define PACKET3_SEM_SEL_SIGNAL (0x6 << 29) # define PACKET3_SEM_SEL_WAIT (0x7 << 29) #define PACKET3_MPEG_INDEX 0x3A +#define PACKET3_COPY_DW 0x3B #define PACKET3_WAIT_REG_MEM 0x3C #define PACKET3_MEM_WRITE 0x3D #define PACKET3_INDIRECT_BUFFER 0x32 diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 31da622..16ddf3d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -54,7 +54,7 @@ * 2.10.0 - fusion 2D tiling * 2.11.0 - backend map, initial compute support for the CS checker * 2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
- 2.13.0 - virtual memory support
- 2.13.0 - virtual memory support, streamout
*/ #define KMS_DRIVER_MAJOR 2 #define KMS_DRIVER_MINOR 13 diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 2316977..0eac19e 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,8 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -512,6 +515,13 @@ cayman 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen index 161737a..4e3f208 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/evergreen +++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen @@ -4,6 +4,9 @@ evergreen 0x9400 0x00008044 WAIT_UNTIL_POLL_CNTL 0x00008048 WAIT_UNTIL_POLL_MASK 0x0000804c WAIT_UNTIL_POLL_REFDATA +0x000084FC CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088B0 VGT_VTX_VECT_EJECT_REG 0x000088C4 VGT_CACHE_INVALIDATION 0x000088D4 VGT_GS_VERTEX_REUSE @@ -522,6 +525,13 @@ evergreen 0x9400 0x00028AC0 DB_SRESULTS_COMPARE_STATE0 0x00028AC4 DB_SRESULTS_COMPARE_STATE1 0x00028AC8 DB_PRELOAD_CONTROL +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028B38 VGT_GS_MAX_VERT_OUT 0x00028B54 VGT_SHADER_STAGES_EN 0x00028B58 VGT_LS_HS_CONFIG diff --git a/drivers/gpu/drm/radeon/reg_srcs/r600 b/drivers/gpu/drm/radeon/reg_srcs/r600 index 0380c5c..5c33b38 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r600 +++ b/drivers/gpu/drm/radeon/reg_srcs/r600 @@ -3,6 +3,9 @@ r600 0x9400 0x00028230 R7xx_PA_SC_EDGERULE 0x000286C8 R7xx_SPI_THREAD_GROUPING 0x00008D8C R7xx_SQ_DYN_GPR_CNTL_PS_FLUSH_REQ +0x00008490 CP_STRMOUT_CNTL +0x000085F0 CP_COHER_CNTL +0x000085F4 CP_COHER_SIZE 0x000088C4 VGT_CACHE_INVALIDATION 0x00028A50 VGT_ENHANCE 0x000088CC VGT_ES_PER_GS @@ -38,6 +41,13 @@ r600 0x9400 0x00028AB4 VGT_REUSE_OFF 0x00028AB8 VGT_VTX_CNT_EN 0x000088B0 VGT_VTX_VECT_EJECT_REG +0x00028AD4 VGT_STRMOUT_VTX_STRIDE_0 +0x00028AE4 VGT_STRMOUT_VTX_STRIDE_1 +0x00028AF4 VGT_STRMOUT_VTX_STRIDE_2 +0x00028B04 VGT_STRMOUT_VTX_STRIDE_3 +0x00028B28 VGT_STRMOUT_DRAW_OPAQUE_OFFSET +0x00028B2C VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE +0x00028B30 VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0x00028810 PA_CL_CLIP_CNTL 0x00008A14 PA_CL_ENHANCE 0x00028C14 PA_CL_GB_HORZ_CLIP_ADJ -- 1.7.7.5
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org