drm/radeon/kms: add VM CS checker for SI
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 20 Mar 2012 21:18:15 +0000 (17:18 -0400)
committerDave Airlie <airlied@redhat.com>
Wed, 21 Mar 2012 06:55:53 +0000 (06:55 +0000)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h

index ad91c5fbb61b3acce9bd41b57ce202b65f758a70..30b379e3f3f55d94483a69c947ba56d3e1c5b5eb 100644 (file)
@@ -1882,6 +1882,315 @@ void si_pcie_gart_fini(struct radeon_device *rdev)
        radeon_gart_fini(rdev);
 }
 
+/* vm parser */
+static bool si_vm_reg_valid(u32 reg)
+{
+       /* context regs are fine */
+       if (reg >= 0x28000)
+               return true;
+
+       /* check config regs */
+       switch (reg) {
+       case GRBM_GFX_INDEX:
+       case VGT_VTX_VECT_EJECT_REG:
+       case VGT_CACHE_INVALIDATION:
+       case VGT_ESGS_RING_SIZE:
+       case VGT_GSVS_RING_SIZE:
+       case VGT_GS_VERTEX_REUSE:
+       case VGT_PRIMITIVE_TYPE:
+       case VGT_INDEX_TYPE:
+       case VGT_NUM_INDICES:
+       case VGT_NUM_INSTANCES:
+       case VGT_TF_RING_SIZE:
+       case VGT_HS_OFFCHIP_PARAM:
+       case VGT_TF_MEMORY_BASE:
+       case PA_CL_ENHANCE:
+       case PA_SU_LINE_STIPPLE_VALUE:
+       case PA_SC_LINE_STIPPLE_STATE:
+       case PA_SC_ENHANCE:
+       case SQC_CACHES:
+       case SPI_STATIC_THREAD_MGMT_1:
+       case SPI_STATIC_THREAD_MGMT_2:
+       case SPI_STATIC_THREAD_MGMT_3:
+       case SPI_PS_MAX_WAVE_ID:
+       case SPI_CONFIG_CNTL:
+       case SPI_CONFIG_CNTL_1:
+       case TA_CNTL_AUX:
+               return true;
+       default:
+               DRM_ERROR("Invalid register 0x%x in CS\n", reg);
+               return false;
+       }
+}
+
+static int si_vm_packet3_ce_check(struct radeon_device *rdev,
+                                 u32 *ib, struct radeon_cs_packet *pkt)
+{
+       switch (pkt->opcode) {
+       case PACKET3_NOP:
+       case PACKET3_SET_BASE:
+       case PACKET3_SET_CE_DE_COUNTERS:
+       case PACKET3_LOAD_CONST_RAM:
+       case PACKET3_WRITE_CONST_RAM:
+       case PACKET3_WRITE_CONST_RAM_OFFSET:
+       case PACKET3_DUMP_CONST_RAM:
+       case PACKET3_INCREMENT_CE_COUNTER:
+       case PACKET3_WAIT_ON_DE_COUNTER:
+       case PACKET3_CE_WRITE:
+               break;
+       default:
+               DRM_ERROR("Invalid CE packet3: 0x%x\n", pkt->opcode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int si_vm_packet3_gfx_check(struct radeon_device *rdev,
+                                  u32 *ib, struct radeon_cs_packet *pkt)
+{
+       u32 idx = pkt->idx + 1;
+       u32 idx_value = ib[idx];
+       u32 start_reg, end_reg, reg, i;
+
+       switch (pkt->opcode) {
+       case PACKET3_NOP:
+       case PACKET3_SET_BASE:
+       case PACKET3_CLEAR_STATE:
+       case PACKET3_INDEX_BUFFER_SIZE:
+       case PACKET3_DISPATCH_DIRECT:
+       case PACKET3_DISPATCH_INDIRECT:
+       case PACKET3_ALLOC_GDS:
+       case PACKET3_WRITE_GDS_RAM:
+       case PACKET3_ATOMIC_GDS:
+       case PACKET3_ATOMIC:
+       case PACKET3_OCCLUSION_QUERY:
+       case PACKET3_SET_PREDICATION:
+       case PACKET3_COND_EXEC:
+       case PACKET3_PRED_EXEC:
+       case PACKET3_DRAW_INDIRECT:
+       case PACKET3_DRAW_INDEX_INDIRECT:
+       case PACKET3_INDEX_BASE:
+       case PACKET3_DRAW_INDEX_2:
+       case PACKET3_CONTEXT_CONTROL:
+       case PACKET3_INDEX_TYPE:
+       case PACKET3_DRAW_INDIRECT_MULTI:
+       case PACKET3_DRAW_INDEX_AUTO:
+       case PACKET3_DRAW_INDEX_IMMD:
+       case PACKET3_NUM_INSTANCES:
+       case PACKET3_DRAW_INDEX_MULTI_AUTO:
+       case PACKET3_STRMOUT_BUFFER_UPDATE:
+       case PACKET3_DRAW_INDEX_OFFSET_2:
+       case PACKET3_DRAW_INDEX_MULTI_ELEMENT:
+       case PACKET3_DRAW_INDEX_INDIRECT_MULTI:
+       case PACKET3_MPEG_INDEX:
+       case PACKET3_WAIT_REG_MEM:
+       case PACKET3_MEM_WRITE:
+       case PACKET3_PFP_SYNC_ME:
+       case PACKET3_SURFACE_SYNC:
+       case PACKET3_EVENT_WRITE:
+       case PACKET3_EVENT_WRITE_EOP:
+       case PACKET3_EVENT_WRITE_EOS:
+       case PACKET3_SET_CONTEXT_REG:
+       case PACKET3_SET_CONTEXT_REG_INDIRECT:
+       case PACKET3_SET_SH_REG:
+       case PACKET3_SET_SH_REG_OFFSET:
+       case PACKET3_INCREMENT_DE_COUNTER:
+       case PACKET3_WAIT_ON_CE_COUNTER:
+       case PACKET3_WAIT_ON_AVAIL_BUFFER:
+       case PACKET3_ME_WRITE:
+               break;
+       case PACKET3_COPY_DATA:
+               if ((idx_value & 0xf00) == 0) {
+                       reg = ib[idx + 3] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       case PACKET3_WRITE_DATA:
+               if ((idx_value & 0xf00) == 0) {
+                       start_reg = ib[idx + 1] * 4;
+                       if (idx_value & 0x10000) {
+                               if (!si_vm_reg_valid(start_reg))
+                                       return -EINVAL;
+                       } else {
+                               for (i = 0; i < (pkt->count - 2); i++) {
+                                       reg = start_reg + (4 * i);
+                                       if (!si_vm_reg_valid(reg))
+                                               return -EINVAL;
+                               }
+                       }
+               }
+               break;
+       case PACKET3_COND_WRITE:
+               if (idx_value & 0x100) {
+                       reg = ib[idx + 5] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       case PACKET3_COPY_DW:
+               if (idx_value & 0x2) {
+                       reg = ib[idx + 3] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       case PACKET3_SET_CONFIG_REG:
+               start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START;
+               end_reg = 4 * pkt->count + start_reg - 4;
+               if ((start_reg < PACKET3_SET_CONFIG_REG_START) ||
+                   (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
+                   (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
+                       DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
+                       return -EINVAL;
+               }
+               for (i = 0; i < pkt->count; i++) {
+                       reg = start_reg + (4 * i);
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("Invalid GFX packet3: 0x%x\n", pkt->opcode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int si_vm_packet3_compute_check(struct radeon_device *rdev,
+                                      u32 *ib, struct radeon_cs_packet *pkt)
+{
+       u32 idx = pkt->idx + 1;
+       u32 idx_value = ib[idx];
+       u32 start_reg, reg, i;
+
+       switch (pkt->opcode) {
+       case PACKET3_NOP:
+       case PACKET3_SET_BASE:
+       case PACKET3_CLEAR_STATE:
+       case PACKET3_DISPATCH_DIRECT:
+       case PACKET3_DISPATCH_INDIRECT:
+       case PACKET3_ALLOC_GDS:
+       case PACKET3_WRITE_GDS_RAM:
+       case PACKET3_ATOMIC_GDS:
+       case PACKET3_ATOMIC:
+       case PACKET3_OCCLUSION_QUERY:
+       case PACKET3_SET_PREDICATION:
+       case PACKET3_COND_EXEC:
+       case PACKET3_PRED_EXEC:
+       case PACKET3_CONTEXT_CONTROL:
+       case PACKET3_STRMOUT_BUFFER_UPDATE:
+       case PACKET3_WAIT_REG_MEM:
+       case PACKET3_MEM_WRITE:
+       case PACKET3_PFP_SYNC_ME:
+       case PACKET3_SURFACE_SYNC:
+       case PACKET3_EVENT_WRITE:
+       case PACKET3_EVENT_WRITE_EOP:
+       case PACKET3_EVENT_WRITE_EOS:
+       case PACKET3_SET_CONTEXT_REG:
+       case PACKET3_SET_CONTEXT_REG_INDIRECT:
+       case PACKET3_SET_SH_REG:
+       case PACKET3_SET_SH_REG_OFFSET:
+       case PACKET3_INCREMENT_DE_COUNTER:
+       case PACKET3_WAIT_ON_CE_COUNTER:
+       case PACKET3_WAIT_ON_AVAIL_BUFFER:
+       case PACKET3_ME_WRITE:
+               break;
+       case PACKET3_COPY_DATA:
+               if ((idx_value & 0xf00) == 0) {
+                       reg = ib[idx + 3] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       case PACKET3_WRITE_DATA:
+               if ((idx_value & 0xf00) == 0) {
+                       start_reg = ib[idx + 1] * 4;
+                       if (idx_value & 0x10000) {
+                               if (!si_vm_reg_valid(start_reg))
+                                       return -EINVAL;
+                       } else {
+                               for (i = 0; i < (pkt->count - 2); i++) {
+                                       reg = start_reg + (4 * i);
+                                       if (!si_vm_reg_valid(reg))
+                                               return -EINVAL;
+                               }
+                       }
+               }
+               break;
+       case PACKET3_COND_WRITE:
+               if (idx_value & 0x100) {
+                       reg = ib[idx + 5] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       case PACKET3_COPY_DW:
+               if (idx_value & 0x2) {
+                       reg = ib[idx + 3] * 4;
+                       if (!si_vm_reg_valid(reg))
+                               return -EINVAL;
+               }
+               break;
+       default:
+               DRM_ERROR("Invalid Compute packet3: 0x%x\n", pkt->opcode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+       int ret = 0;
+       u32 idx = 0;
+       struct radeon_cs_packet pkt;
+
+       do {
+               pkt.idx = idx;
+               pkt.type = CP_PACKET_GET_TYPE(ib->ptr[idx]);
+               pkt.count = CP_PACKET_GET_COUNT(ib->ptr[idx]);
+               pkt.one_reg_wr = 0;
+               switch (pkt.type) {
+               case PACKET_TYPE0:
+                       dev_err(rdev->dev, "Packet0 not allowed!\n");
+                       ret = -EINVAL;
+                       break;
+               case PACKET_TYPE2:
+                       idx += 1;
+                       break;
+               case PACKET_TYPE3:
+                       pkt.opcode = CP_PACKET3_GET_OPCODE(ib->ptr[idx]);
+                       if (ib->is_const_ib)
+                               ret = si_vm_packet3_ce_check(rdev, ib->ptr, &pkt);
+                       else {
+                               switch (ib->fence->ring) {
+                               case RADEON_RING_TYPE_GFX_INDEX:
+                                       ret = si_vm_packet3_gfx_check(rdev, ib->ptr, &pkt);
+                                       break;
+                               case CAYMAN_RING_TYPE_CP1_INDEX:
+                               case CAYMAN_RING_TYPE_CP2_INDEX:
+                                       ret = si_vm_packet3_compute_check(rdev, ib->ptr, &pkt);
+                                       break;
+                               default:
+                                       dev_err(rdev->dev, "Non-PM4 ring %d !\n", ib->fence->ring);
+                                       ret = -EINVAL;
+                                       break;
+                               }
+                       }
+                       idx += pkt.count + 2;
+                       break;
+               default:
+                       dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type);
+                       ret = -EINVAL;
+                       break;
+               }
+               if (ret)
+                       break;
+       } while (idx < ib->length_dw);
+
+       return ret;
+}
+
 /*
  * vm
  */
index 4d9cdc813d812b9725272d6f4e8a16885b8ac756..ed1b1e5f5dd57c3b138bd053ed2f9abeb44cd493 100644 (file)
 #define                SOFT_RESET_VGT                                  (1 << 14)
 #define                SOFT_RESET_IA                                   (1 << 15)
 
+#define GRBM_GFX_INDEX                                 0x802C
+
 #define CP_ME_CNTL                                     0x86D8
 #define                CP_CE_HALT                                      (1 << 24)
 #define                CP_PFP_HALT                                     (1 << 26)
 
 #define        CP_PERFMON_CNTL                                 0x87FC
 
+#define        VGT_VTX_VECT_EJECT_REG                          0x88B0
+
 #define        VGT_CACHE_INVALIDATION                          0x88C4
 #define                CACHE_INVALIDATION(x)                           ((x) << 0)
 #define                        VC_ONLY                                         0
 #define                        ES_AUTO                                         1
 #define                        GS_AUTO                                         2
 #define                        ES_AND_GS_AUTO                                  3
+#define        VGT_ESGS_RING_SIZE                              0x88C8
+#define        VGT_GSVS_RING_SIZE                              0x88CC
 
 #define        VGT_GS_VERTEX_REUSE                             0x88D4
 
+#define        VGT_PRIMITIVE_TYPE                              0x8958
+#define        VGT_INDEX_TYPE                                  0x895C
+
+#define        VGT_NUM_INDICES                                 0x8970
 #define        VGT_NUM_INSTANCES                               0x8974
 
+#define        VGT_TF_RING_SIZE                                0x8988
+
+#define        VGT_HS_OFFCHIP_PARAM                            0x89B0
+
+#define        VGT_TF_MEMORY_BASE                              0x89B8
+
 #define CC_GC_SHADER_ARRAY_CONFIG                      0x89bc
 #define GC_USER_SHADER_ARRAY_CONFIG                    0x89c0
 
 #define                CLIP_VTX_REORDER_ENA                            (1 << 0)
 #define                NUM_CLIP_SEQ(x)                                 ((x) << 1)
 
+#define        PA_SU_LINE_STIPPLE_VALUE                        0x8A60
+
 #define        PA_SC_LINE_STIPPLE_STATE                        0x8B10
 
 #define        PA_SC_FORCE_EOV_MAX_CNTS                        0x8B24
 #define                SC_HIZ_TILE_FIFO_SIZE(x)                        ((x) << 15)
 #define                SC_EARLYZ_TILE_FIFO_SIZE(x)                     ((x) << 23)
 
+#define        PA_SC_ENHANCE                                   0x8BF0
+
 #define        SQ_CONFIG                                       0x8C00
 
+#define        SQC_CACHES                                      0x8C08
+
 #define        SX_DEBUG_1                                      0x9060
 
+#define        SPI_STATIC_THREAD_MGMT_1                        0x90E0
+#define        SPI_STATIC_THREAD_MGMT_2                        0x90E4
+#define        SPI_STATIC_THREAD_MGMT_3                        0x90E8
+#define        SPI_PS_MAX_WAVE_ID                              0x90EC
+
+#define        SPI_CONFIG_CNTL                                 0x9100
+
 #define        SPI_CONFIG_CNTL_1                               0x913C
 #define                VTX_DONE_DELAY(x)                               ((x) << 0)
 #define                INTERP_ONE_PRIM_PER_ROW                         (1 << 4)
 #define                TCC_DISABLE_MASK                                0xFFFF0000
 #define                TCC_DISABLE_SHIFT                               16
 
+#define        TA_CNTL_AUX                                     0x9508
+
 #define CC_RB_BACKEND_DISABLE                          0x98F4
 #define                BACKEND_DISABLE(x)                      ((x) << 16)
 #define GB_ADDR_CONFIG                                 0x98F8