aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r300.c
diff options
context:
space:
mode:
authorJerome Glisse <glisse@freedesktop.org>2009-06-17 07:28:30 -0400
committerDave Airlie <airlied@redhat.com>2009-06-18 19:32:27 -0400
commit068a117ca38f27c9641db7642f24fe9270d9424e (patch)
treee1038db118114aa777312a5eae70b512fa13617b /drivers/gpu/drm/radeon/r300.c
parent8b5c744485b75d940ccb1c83c9a358b20eb91346 (diff)
drm/radeon: command stream checker for r3xx-r5xx hardware
For security purpose we want to make sure the userspace process doesn't access memory beyond buffer it owns. To achieve this we need to check states the userspace program. For color buffer and zbuffer we check that the clipping register will discard access beyond buffers set as color or zbuffer. For vertex buffer we check that no vertex fetch will happen beyond buffer end. For texture we check various texture states (number of mipmap level, texture size, texture depth, ...) to compute the amount of memory the texture fetcher might access. The command stream checking impact the performances so far quick benchmark shows an average of 3% decrease in fps of various applications. It can be optimized a bit more by caching result of checking and thus avoid a full recheck if no states changed since last check. Note that this patch is still incomplete on checking side as it doesn't check 2d rendering states. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r300.c')
-rw-r--r--drivers/gpu/drm/radeon/r300.c478
1 files changed, 447 insertions, 31 deletions
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index f5870a099d4..e2ed5bc0817 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -48,14 +48,13 @@ int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
48 struct radeon_cs_reloc **cs_reloc); 48 struct radeon_cs_reloc **cs_reloc);
49int r100_cs_parse_packet0(struct radeon_cs_parser *p, 49int r100_cs_parse_packet0(struct radeon_cs_parser *p,
50 struct radeon_cs_packet *pkt, 50 struct radeon_cs_packet *pkt,
51 unsigned *auth, unsigned n, 51 const unsigned *auth, unsigned n,
52 radeon_packet0_check_t check); 52 radeon_packet0_check_t check);
53int r100_cs_parse_packet3(struct radeon_cs_parser *p,
54 struct radeon_cs_packet *pkt,
55 unsigned *auth, unsigned n,
56 radeon_packet3_check_t check);
57void r100_cs_dump_packet(struct radeon_cs_parser *p, 53void r100_cs_dump_packet(struct radeon_cs_parser *p,
58 struct radeon_cs_packet *pkt); 54 struct radeon_cs_packet *pkt);
55int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
56 struct radeon_cs_packet *pkt,
57 struct radeon_object *robj);
59 58
60/* This files gather functions specifics to: 59/* This files gather functions specifics to:
61 * r300,r350,rv350,rv370,rv380 60 * r300,r350,rv350,rv370,rv380
@@ -288,7 +287,7 @@ int r300_copy_dma(struct radeon_device *rdev,
288 return r; 287 return r;
289 } 288 }
290 /* Must wait for 2D idle & clean before DMA or hangs might happen */ 289 /* Must wait for 2D idle & clean before DMA or hangs might happen */
291 radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); 290 radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0 ));
292 radeon_ring_write(rdev, (1 << 16)); 291 radeon_ring_write(rdev, (1 << 16));
293 for (i = 0; i < num_loops; i++) { 292 for (i = 0; i < num_loops; i++) {
294 cur_size = size; 293 cur_size = size;
@@ -319,7 +318,7 @@ void r300_ring_start(struct radeon_device *rdev)
319 318
320 /* Sub pixel 1/12 so we can have 4K rendering according to doc */ 319 /* Sub pixel 1/12 so we can have 4K rendering according to doc */
321 gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 320 gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
322 switch (rdev->num_gb_pipes) { 321 switch(rdev->num_gb_pipes) {
323 case 2: 322 case 2:
324 gb_tile_config |= R300_PIPE_COUNT_R300; 323 gb_tile_config |= R300_PIPE_COUNT_R300;
325 break; 324 break;
@@ -452,8 +451,8 @@ void r300_gpu_init(struct radeon_device *rdev)
452 case 4: 451 case 4:
453 gb_tile_config |= R300_PIPE_COUNT_R420; 452 gb_tile_config |= R300_PIPE_COUNT_R420;
454 break; 453 break;
455 case 1:
456 default: 454 default:
455 case 1:
457 gb_tile_config |= R300_PIPE_COUNT_RV350; 456 gb_tile_config |= R300_PIPE_COUNT_RV350;
458 break; 457 break;
459 } 458 }
@@ -725,18 +724,120 @@ struct r300_cs_track_cb {
725 unsigned offset; 724 unsigned offset;
726}; 725};
727 726
727struct r300_cs_track_array {
728 struct radeon_object *robj;
729 unsigned esize;
730};
731
732struct r300_cs_track_texture {
733 struct radeon_object *robj;
734 unsigned pitch;
735 unsigned width;
736 unsigned height;
737 unsigned num_levels;
738 unsigned cpp;
739 unsigned tex_coord_type;
740 unsigned txdepth;
741 unsigned width_11;
742 unsigned height_11;
743 bool use_pitch;
744 bool enabled;
745 bool roundup_w;
746 bool roundup_h;
747};
748
728struct r300_cs_track { 749struct r300_cs_track {
729 unsigned num_cb; 750 unsigned num_cb;
730 unsigned maxy; 751 unsigned maxy;
731 struct r300_cs_track_cb cb[4]; 752 unsigned vtx_size;
732 struct r300_cs_track_cb zb; 753 unsigned vap_vf_cntl;
733 bool z_enabled; 754 unsigned immd_dwords;
755 unsigned num_arrays;
756 unsigned max_indx;
757 struct r300_cs_track_array arrays[11];
758 struct r300_cs_track_cb cb[4];
759 struct r300_cs_track_cb zb;
760 struct r300_cs_track_texture textures[16];
761 bool z_enabled;
734}; 762};
735 763
764static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t)
765{
766 DRM_ERROR("pitch %d\n", t->pitch);
767 DRM_ERROR("width %d\n", t->width);
768 DRM_ERROR("height %d\n", t->height);
769 DRM_ERROR("num levels %d\n", t->num_levels);
770 DRM_ERROR("depth %d\n", t->txdepth);
771 DRM_ERROR("bpp %d\n", t->cpp);
772 DRM_ERROR("coordinate type %d\n", t->tex_coord_type);
773 DRM_ERROR("width round to power of 2 %d\n", t->roundup_w);
774 DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
775}
776
777static inline int r300_cs_track_texture_check(struct radeon_device *rdev,
778 struct r300_cs_track *track)
779{
780 struct radeon_object *robj;
781 unsigned long size;
782 unsigned u, i, w, h;
783
784 for (u = 0; u < 16; u++) {
785 if (!track->textures[u].enabled)
786 continue;
787 robj = track->textures[u].robj;
788 if (robj == NULL) {
789 DRM_ERROR("No texture bound to unit %u\n", u);
790 return -EINVAL;
791 }
792 size = 0;
793 for (i = 0; i <= track->textures[u].num_levels; i++) {
794 if (track->textures[u].use_pitch) {
795 w = track->textures[u].pitch / (1 << i);
796 } else {
797 w = track->textures[u].width / (1 << i);
798 if (rdev->family >= CHIP_RV515)
799 w |= track->textures[u].width_11;
800 if (track->textures[u].roundup_w)
801 w = roundup_pow_of_two(w);
802 }
803 h = track->textures[u].height / (1 << i);
804 if (rdev->family >= CHIP_RV515)
805 h |= track->textures[u].height_11;
806 if (track->textures[u].roundup_h)
807 h = roundup_pow_of_two(h);
808 size += w * h;
809 }
810 size *= track->textures[u].cpp;
811 switch (track->textures[u].tex_coord_type) {
812 case 0:
813 break;
814 case 1:
815 size *= (1 << track->textures[u].txdepth);
816 break;
817 case 2:
818 size *= 6;
819 break;
820 default:
821 DRM_ERROR("Invalid texture coordinate type %u for unit "
822 "%u\n", track->textures[u].tex_coord_type, u);
823 return -EINVAL;
824 }
825 if (size > radeon_object_size(robj)) {
826 DRM_ERROR("Texture of unit %u needs %lu bytes but is "
827 "%lu\n", u, size, radeon_object_size(robj));
828 r300_cs_track_texture_print(&track->textures[u]);
829 return -EINVAL;
830 }
831 }
832 return 0;
833}
834
736int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track) 835int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
737{ 836{
738 unsigned i; 837 unsigned i;
739 unsigned long size; 838 unsigned long size;
839 unsigned prim_walk;
840 unsigned nverts;
740 841
741 for (i = 0; i < track->num_cb; i++) { 842 for (i = 0; i < track->num_cb; i++) {
742 if (track->cb[i].robj == NULL) { 843 if (track->cb[i].robj == NULL) {
@@ -769,7 +870,59 @@ int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
769 return -EINVAL; 870 return -EINVAL;
770 } 871 }
771 } 872 }
772 return 0; 873 prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
874 nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
875 switch (prim_walk) {
876 case 1:
877 for (i = 0; i < track->num_arrays; i++) {
878 size = track->arrays[i].esize * track->max_indx * 4;
879 if (track->arrays[i].robj == NULL) {
880 DRM_ERROR("(PW %u) Vertex array %u no buffer "
881 "bound\n", prim_walk, i);
882 return -EINVAL;
883 }
884 if (size > radeon_object_size(track->arrays[i].robj)) {
885 DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
886 "have %lu dwords\n", prim_walk, i,
887 size >> 2,
888 radeon_object_size(track->arrays[i].robj) >> 2);
889 DRM_ERROR("Max indices %u\n", track->max_indx);
890 return -EINVAL;
891 }
892 }
893 break;
894 case 2:
895 for (i = 0; i < track->num_arrays; i++) {
896 size = track->arrays[i].esize * (nverts - 1) * 4;
897 if (track->arrays[i].robj == NULL) {
898 DRM_ERROR("(PW %u) Vertex array %u no buffer "
899 "bound\n", prim_walk, i);
900 return -EINVAL;
901 }
902 if (size > radeon_object_size(track->arrays[i].robj)) {
903 DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
904 "have %lu dwords\n", prim_walk, i, size >> 2,
905 radeon_object_size(track->arrays[i].robj) >> 2);
906 return -EINVAL;
907 }
908 }
909 break;
910 case 3:
911 size = track->vtx_size * nverts;
912 if (size != track->immd_dwords) {
913 DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n",
914 track->immd_dwords, size);
915 DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n",
916 nverts, track->vtx_size);
917 return -EINVAL;
918 }
919 break;
920 default:
921 DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n",
922 prim_walk);
923 return -EINVAL;
924 }
925 return r300_cs_track_texture_check(rdev, track);
773} 926}
774 927
775static inline void r300_cs_track_clear(struct r300_cs_track *track) 928static inline void r300_cs_track_clear(struct r300_cs_track *track)
@@ -789,9 +942,33 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track)
789 track->zb.pitch = 8192; 942 track->zb.pitch = 8192;
790 track->zb.cpp = 4; 943 track->zb.cpp = 4;
791 track->zb.offset = 0; 944 track->zb.offset = 0;
945 track->vtx_size = 0x7F;
946 track->immd_dwords = 0xFFFFFFFFUL;
947 track->num_arrays = 11;
948 track->max_indx = 0x00FFFFFFUL;
949 for (i = 0; i < track->num_arrays; i++) {
950 track->arrays[i].robj = NULL;
951 track->arrays[i].esize = 0x7F;
952 }
953 for (i = 0; i < 16; i++) {
954 track->textures[i].pitch = 16536;
955 track->textures[i].width = 16536;
956 track->textures[i].height = 16536;
957 track->textures[i].width_11 = 1 << 11;
958 track->textures[i].height_11 = 1 << 11;
959 track->textures[i].num_levels = 12;
960 track->textures[i].txdepth = 16;
961 track->textures[i].cpp = 64;
962 track->textures[i].tex_coord_type = 1;
963 track->textures[i].robj = NULL;
964 /* CS IB emission code makes sure texture unit are disabled */
965 track->textures[i].enabled = false;
966 track->textures[i].roundup_w = true;
967 track->textures[i].roundup_h = true;
968 }
792} 969}
793 970
794static unsigned r300_auth_reg[] = { 971static const unsigned r300_reg_safe_bm[159] = {
795 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 972 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
796 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, 973 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
797 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 974 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -808,7 +985,7 @@ static unsigned r300_auth_reg[] = {
808 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 985 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
809 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, 986 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
810 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 987 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
811 0xFFFFFFFF, 0xFFFFCFCC, 0xF00E9FFF, 0x007C0000, 988 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
812 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, 989 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
813 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 990 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
814 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 991 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
@@ -824,9 +1001,9 @@ static unsigned r300_auth_reg[] = {
824 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 1001 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
825 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 1002 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
826 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 1003 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
827 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, 1004 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
828 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, 1005 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
829 0x00000000, 0x00000000, 0xFFFF0000, 0x00000000, 1006 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
830 0x00000000, 0x0000C100, 0x00000000, 0x00000000, 1007 0x00000000, 0x0000C100, 0x00000000, 0x00000000,
831 0x00000000, 0x00000000, 0x00000000, 0x00000000, 1008 0x00000000, 0x00000000, 0x00000000, 0x00000000,
832 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, 1009 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
@@ -848,8 +1025,8 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
848 1025
849 ib = p->ib->ptr; 1026 ib = p->ib->ptr;
850 ib_chunk = &p->chunks[p->chunk_ib_idx]; 1027 ib_chunk = &p->chunks[p->chunk_ib_idx];
851 track = (struct r300_cs_track *)p->track; 1028 track = (struct r300_cs_track*)p->track;
852 switch (reg) { 1029 switch(reg) {
853 case RADEON_DST_PITCH_OFFSET: 1030 case RADEON_DST_PITCH_OFFSET:
854 case RADEON_SRC_PITCH_OFFSET: 1031 case RADEON_SRC_PITCH_OFFSET:
855 r = r100_cs_packet_next_reloc(p, &reloc); 1032 r = r100_cs_packet_next_reloc(p, &reloc);
@@ -907,6 +1084,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
907 case R300_TX_OFFSET_0+52: 1084 case R300_TX_OFFSET_0+52:
908 case R300_TX_OFFSET_0+56: 1085 case R300_TX_OFFSET_0+56:
909 case R300_TX_OFFSET_0+60: 1086 case R300_TX_OFFSET_0+60:
1087 i = (reg - R300_TX_OFFSET_0) >> 2;
910 r = r100_cs_packet_next_reloc(p, &reloc); 1088 r = r100_cs_packet_next_reloc(p, &reloc);
911 if (r) { 1089 if (r) {
912 DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1090 DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
@@ -915,11 +1093,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
915 return r; 1093 return r;
916 } 1094 }
917 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); 1095 ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
1096 track->textures[i].robj = reloc->robj;
918 break; 1097 break;
919 /* Tracked registers */ 1098 /* Tracked registers */
1099 case 0x2084:
1100 /* VAP_VF_CNTL */
1101 track->vap_vf_cntl = ib_chunk->kdata[idx];
1102 break;
1103 case 0x20B4:
1104 /* VAP_VTX_SIZE */
1105 track->vtx_size = ib_chunk->kdata[idx] & 0x7F;
1106 break;
1107 case 0x2134:
1108 /* VAP_VF_MAX_VTX_INDX */
1109 track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
1110 break;
920 case 0x43E4: 1111 case 0x43E4:
921 /* SC_SCISSOR1 */ 1112 /* SC_SCISSOR1 */
922
923 track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1; 1113 track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1;
924 if (p->rdev->family < CHIP_RV515) { 1114 if (p->rdev->family < CHIP_RV515) {
925 track->maxy -= 1440; 1115 track->maxy -= 1440;
@@ -994,8 +1184,166 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
994 /* ZB_DEPTHPITCH */ 1184 /* ZB_DEPTHPITCH */
995 track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; 1185 track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
996 break; 1186 break;
1187 case 0x4104:
1188 for (i = 0; i < 16; i++) {
1189 bool enabled;
1190
1191 enabled = !!(ib_chunk->kdata[idx] & (1 << i));
1192 track->textures[i].enabled = enabled;
1193 }
1194 break;
1195 case 0x44C0:
1196 case 0x44C4:
1197 case 0x44C8:
1198 case 0x44CC:
1199 case 0x44D0:
1200 case 0x44D4:
1201 case 0x44D8:
1202 case 0x44DC:
1203 case 0x44E0:
1204 case 0x44E4:
1205 case 0x44E8:
1206 case 0x44EC:
1207 case 0x44F0:
1208 case 0x44F4:
1209 case 0x44F8:
1210 case 0x44FC:
1211 /* TX_FORMAT1_[0-15] */
1212 i = (reg - 0x44C0) >> 2;
1213 tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
1214 track->textures[i].tex_coord_type = tmp;
1215 switch ((ib_chunk->kdata[idx] & 0x1F)) {
1216 case 0:
1217 case 2:
1218 case 5:
1219 case 18:
1220 case 20:
1221 case 21:
1222 track->textures[i].cpp = 1;
1223 break;
1224 case 1:
1225 case 3:
1226 case 6:
1227 case 7:
1228 case 10:
1229 case 11:
1230 case 19:
1231 case 22:
1232 case 24:
1233 track->textures[i].cpp = 2;
1234 break;
1235 case 4:
1236 case 8:
1237 case 9:
1238 case 12:
1239 case 13:
1240 case 23:
1241 case 25:
1242 case 27:
1243 case 30:
1244 track->textures[i].cpp = 4;
1245 break;
1246 case 14:
1247 case 26:
1248 case 28:
1249 track->textures[i].cpp = 8;
1250 break;
1251 case 29:
1252 track->textures[i].cpp = 16;
1253 break;
1254 default:
1255 DRM_ERROR("Invalid texture format %u\n",
1256 (ib_chunk->kdata[idx] & 0x1F));
1257 return -EINVAL;
1258 break;
1259 }
1260 break;
1261 case 0x4400:
1262 case 0x4404:
1263 case 0x4408:
1264 case 0x440C:
1265 case 0x4410:
1266 case 0x4414:
1267 case 0x4418:
1268 case 0x441C:
1269 case 0x4420:
1270 case 0x4424:
1271 case 0x4428:
1272 case 0x442C:
1273 case 0x4430:
1274 case 0x4434:
1275 case 0x4438:
1276 case 0x443C:
1277 /* TX_FILTER0_[0-15] */
1278 i = (reg - 0x4400) >> 2;
1279 tmp = ib_chunk->kdata[idx] & 0x7;;
1280 if (tmp == 2 || tmp == 4 || tmp == 6) {
1281 track->textures[i].roundup_w = false;
1282 }
1283 tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;;
1284 if (tmp == 2 || tmp == 4 || tmp == 6) {
1285 track->textures[i].roundup_h = false;
1286 }
1287 break;
1288 case 0x4500:
1289 case 0x4504:
1290 case 0x4508:
1291 case 0x450C:
1292 case 0x4510:
1293 case 0x4514:
1294 case 0x4518:
1295 case 0x451C:
1296 case 0x4520:
1297 case 0x4524:
1298 case 0x4528:
1299 case 0x452C:
1300 case 0x4530:
1301 case 0x4534:
1302 case 0x4538:
1303 case 0x453C:
1304 /* TX_FORMAT2_[0-15] */
1305 i = (reg - 0x4500) >> 2;
1306 tmp = ib_chunk->kdata[idx] & 0x3FFF;
1307 track->textures[i].pitch = tmp + 1;
1308 if (p->rdev->family >= CHIP_RV515) {
1309 tmp = ((ib_chunk->kdata[idx] >> 15) & 1) << 11;
1310 track->textures[i].width_11 = tmp;
1311 tmp = ((ib_chunk->kdata[idx] >> 16) & 1) << 11;
1312 track->textures[i].height_11 = tmp;
1313 }
1314 break;
1315 case 0x4480:
1316 case 0x4484:
1317 case 0x4488:
1318 case 0x448C:
1319 case 0x4490:
1320 case 0x4494:
1321 case 0x4498:
1322 case 0x449C:
1323 case 0x44A0:
1324 case 0x44A4:
1325 case 0x44A8:
1326 case 0x44AC:
1327 case 0x44B0:
1328 case 0x44B4:
1329 case 0x44B8:
1330 case 0x44BC:
1331 /* TX_FORMAT0_[0-15] */
1332 i = (reg - 0x4480) >> 2;
1333 tmp = ib_chunk->kdata[idx] & 0x7FF;
1334 track->textures[i].width = tmp + 1;
1335 tmp = (ib_chunk->kdata[idx] >> 11) & 0x7FF;
1336 track->textures[i].height = tmp + 1;
1337 tmp = (ib_chunk->kdata[idx] >> 26) & 0xF;
1338 track->textures[i].num_levels = tmp;
1339 tmp = ib_chunk->kdata[idx] & (1 << 31);
1340 track->textures[i].use_pitch = !!tmp;
1341 tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
1342 track->textures[i].txdepth = tmp;
1343 break;
997 default: 1344 default:
998 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", reg, idx); 1345 printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
1346 reg, idx);
999 return -EINVAL; 1347 return -EINVAL;
1000 } 1348 }
1001 return 0; 1349 return 0;
@@ -1015,11 +1363,12 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
1015 ib = p->ib->ptr; 1363 ib = p->ib->ptr;
1016 ib_chunk = &p->chunks[p->chunk_ib_idx]; 1364 ib_chunk = &p->chunks[p->chunk_ib_idx];
1017 idx = pkt->idx + 1; 1365 idx = pkt->idx + 1;
1018 track = (struct r300_cs_track *)p->track; 1366 track = (struct r300_cs_track*)p->track;
1019 switch (pkt->opcode) { 1367 switch(pkt->opcode) {
1020 case PACKET3_3D_LOAD_VBPNTR: 1368 case PACKET3_3D_LOAD_VBPNTR:
1021 c = ib_chunk->kdata[idx++]; 1369 c = ib_chunk->kdata[idx++] & 0x1F;
1022 for (i = 0; i < (c - 1); i += 2, idx += 3) { 1370 track->num_arrays = c;
1371 for (i = 0; i < (c - 1); i+=2, idx+=3) {
1023 r = r100_cs_packet_next_reloc(p, &reloc); 1372 r = r100_cs_packet_next_reloc(p, &reloc);
1024 if (r) { 1373 if (r) {
1025 DRM_ERROR("No reloc for packet3 %d\n", 1374 DRM_ERROR("No reloc for packet3 %d\n",
@@ -1028,6 +1377,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
1028 return r; 1377 return r;
1029 } 1378 }
1030 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1379 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
1380 track->arrays[i + 0].robj = reloc->robj;
1381 track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
1382 track->arrays[i + 0].esize &= 0x7F;
1031 r = r100_cs_packet_next_reloc(p, &reloc); 1383 r = r100_cs_packet_next_reloc(p, &reloc);
1032 if (r) { 1384 if (r) {
1033 DRM_ERROR("No reloc for packet3 %d\n", 1385 DRM_ERROR("No reloc for packet3 %d\n",
@@ -1036,6 +1388,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
1036 return r; 1388 return r;
1037 } 1389 }
1038 ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); 1390 ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
1391 track->arrays[i + 1].robj = reloc->robj;
1392 track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
1393 track->arrays[i + 1].esize &= 0x7F;
1039 } 1394 }
1040 if (c & 1) { 1395 if (c & 1) {
1041 r = r100_cs_packet_next_reloc(p, &reloc); 1396 r = r100_cs_packet_next_reloc(p, &reloc);
@@ -1046,6 +1401,9 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
1046 return r; 1401 return r;
1047 } 1402 }
1048 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1403 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
1404 track->arrays[i + 0].robj = reloc->robj;
1405 track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
1406 track->arrays[i + 0].esize &= 0x7F;
1049 } 1407 }
1050 break; 1408 break;
1051 case PACKET3_INDX_BUFFER: 1409 case PACKET3_INDX_BUFFER:
@@ -1056,14 +1414,65 @@ static int r300_packet3_check(struct radeon_cs_parser *p,
1056 return r; 1414 return r;
1057 } 1415 }
1058 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 1416 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
1417 r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
1418 if (r) {
1419 return r;
1420 }
1059 break; 1421 break;
1060 /* Draw packet */ 1422 /* Draw packet */
1061 case PACKET3_3D_DRAW_VBUF:
1062 case PACKET3_3D_DRAW_IMMD: 1423 case PACKET3_3D_DRAW_IMMD:
1063 case PACKET3_3D_DRAW_INDX: 1424 /* Number of dwords is vtx_size * (num_vertices - 1)
1064 case PACKET3_3D_DRAW_VBUF_2: 1425 * PRIM_WALK must be equal to 3 vertex data in embedded
1426 * in cmd stream */
1427 if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
1428 DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
1429 return -EINVAL;
1430 }
1431 track->vap_vf_cntl = ib_chunk->kdata[idx+1];
1432 track->immd_dwords = pkt->count - 1;
1433 r = r300_cs_track_check(p->rdev, track);
1434 if (r) {
1435 return r;
1436 }
1437 break;
1065 case PACKET3_3D_DRAW_IMMD_2: 1438 case PACKET3_3D_DRAW_IMMD_2:
1439 /* Number of dwords is vtx_size * (num_vertices - 1)
1440 * PRIM_WALK must be equal to 3 vertex data in embedded
1441 * in cmd stream */
1442 if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
1443 DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
1444 return -EINVAL;
1445 }
1446 track->vap_vf_cntl = ib_chunk->kdata[idx];
1447 track->immd_dwords = pkt->count;
1448 r = r300_cs_track_check(p->rdev, track);
1449 if (r) {
1450 return r;
1451 }
1452 break;
1453 case PACKET3_3D_DRAW_VBUF:
1454 track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
1455 r = r300_cs_track_check(p->rdev, track);
1456 if (r) {
1457 return r;
1458 }
1459 break;
1460 case PACKET3_3D_DRAW_VBUF_2:
1461 track->vap_vf_cntl = ib_chunk->kdata[idx];
1462 r = r300_cs_track_check(p->rdev, track);
1463 if (r) {
1464 return r;
1465 }
1466 break;
1467 case PACKET3_3D_DRAW_INDX:
1468 track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
1469 r = r300_cs_track_check(p->rdev, track);
1470 if (r) {
1471 return r;
1472 }
1473 break;
1066 case PACKET3_3D_DRAW_INDX_2: 1474 case PACKET3_3D_DRAW_INDX_2:
1475 track->vap_vf_cntl = ib_chunk->kdata[idx];
1067 r = r300_cs_track_check(p->rdev, track); 1476 r = r300_cs_track_check(p->rdev, track);
1068 if (r) { 1477 if (r) {
1069 return r; 1478 return r;
@@ -1095,8 +1504,8 @@ int r300_cs_parse(struct radeon_cs_parser *p)
1095 switch (pkt.type) { 1504 switch (pkt.type) {
1096 case PACKET_TYPE0: 1505 case PACKET_TYPE0:
1097 r = r100_cs_parse_packet0(p, &pkt, 1506 r = r100_cs_parse_packet0(p, &pkt,
1098 r300_auth_reg, 1507 p->rdev->config.r300.reg_safe_bm,
1099 ARRAY_SIZE(r300_auth_reg), 1508 p->rdev->config.r300.reg_safe_bm_size,
1100 &r300_packet0_check); 1509 &r300_packet0_check);
1101 break; 1510 break;
1102 case PACKET_TYPE2: 1511 case PACKET_TYPE2:
@@ -1114,3 +1523,10 @@ int r300_cs_parse(struct radeon_cs_parser *p)
1114 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 1523 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
1115 return 0; 1524 return 0;
1116} 1525}
1526
1527int r300_init(struct radeon_device *rdev)
1528{
1529 rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
1530 rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
1531 return 0;
1532}