aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/gpu/drm/radeon/r100.c76
-rw-r--r--drivers/gpu/drm/radeon/r300.c478
-rw-r--r--drivers/gpu/drm/radeon/r300.h36
-rw-r--r--drivers/gpu/drm/radeon/radeon.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_asic.h15
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c4
-rw-r--r--drivers/gpu/drm/radeon/rv515.c58
7 files changed, 611 insertions, 65 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 64a692c0c31..c550932a108 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -647,7 +647,7 @@ int r100_cp_reset(struct radeon_device *rdev)
647 */ 647 */
648int r100_cs_parse_packet0(struct radeon_cs_parser *p, 648int r100_cs_parse_packet0(struct radeon_cs_parser *p,
649 struct radeon_cs_packet *pkt, 649 struct radeon_cs_packet *pkt,
650 unsigned *auth, unsigned n, 650 const unsigned *auth, unsigned n,
651 radeon_packet0_check_t check) 651 radeon_packet0_check_t check)
652{ 652{
653 unsigned reg; 653 unsigned reg;
@@ -657,6 +657,10 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
657 657
658 idx = pkt->idx + 1; 658 idx = pkt->idx + 1;
659 reg = pkt->reg; 659 reg = pkt->reg;
660 /* Check that register fall into register range
661 * determined by the number of entry (n) in the
662 * safe register bitmap.
663 */
660 if (pkt->one_reg_wr) { 664 if (pkt->one_reg_wr) {
661 if ((reg >> 7) > n) { 665 if ((reg >> 7) > n) {
662 return -EINVAL; 666 return -EINVAL;
@@ -686,24 +690,6 @@ int r100_cs_parse_packet0(struct radeon_cs_parser *p,
686 return 0; 690 return 0;
687} 691}
688 692
689int r100_cs_parse_packet3(struct radeon_cs_parser *p,
690 struct radeon_cs_packet *pkt,
691 unsigned *auth, unsigned n,
692 radeon_packet3_check_t check)
693{
694 unsigned i, m;
695
696 if ((pkt->opcode >> 5) > n) {
697 return -EINVAL;
698 }
699 i = pkt->opcode >> 5;
700 m = 1 << (pkt->opcode & 31);
701 if (auth[i] & m) {
702 return check(p, pkt);
703 }
704 return 0;
705}
706
707void r100_cs_dump_packet(struct radeon_cs_parser *p, 693void r100_cs_dump_packet(struct radeon_cs_parser *p,
708 struct radeon_cs_packet *pkt) 694 struct radeon_cs_packet *pkt)
709{ 695{
@@ -904,6 +890,25 @@ static int r100_packet0_check(struct radeon_cs_parser *p,
904 return 0; 890 return 0;
905} 891}
906 892
893int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
894 struct radeon_cs_packet *pkt,
895 struct radeon_object *robj)
896{
897 struct radeon_cs_chunk *ib_chunk;
898 unsigned idx;
899
900 ib_chunk = &p->chunks[p->chunk_ib_idx];
901 idx = pkt->idx + 1;
902 if ((ib_chunk->kdata[idx+2] + 1) > radeon_object_size(robj)) {
903 DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER "
904 "(need %u have %lu) !\n",
905 ib_chunk->kdata[idx+2] + 1,
906 radeon_object_size(robj));
907 return -EINVAL;
908 }
909 return 0;
910}
911
907static int r100_packet3_check(struct radeon_cs_parser *p, 912static int r100_packet3_check(struct radeon_cs_parser *p,
908 struct radeon_cs_packet *pkt) 913 struct radeon_cs_packet *pkt)
909{ 914{
@@ -957,6 +962,10 @@ static int r100_packet3_check(struct radeon_cs_parser *p,
957 return r; 962 return r;
958 } 963 }
959 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); 964 ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
965 r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
966 if (r) {
967 return r;
968 }
960 break; 969 break;
961 case 0x23: 970 case 0x23:
962 /* FIXME: cleanup */ 971 /* FIXME: cleanup */
@@ -1002,18 +1011,18 @@ int r100_cs_parse(struct radeon_cs_parser *p)
1002 } 1011 }
1003 p->idx += pkt.count + 2; 1012 p->idx += pkt.count + 2;
1004 switch (pkt.type) { 1013 switch (pkt.type) {
1005 case PACKET_TYPE0: 1014 case PACKET_TYPE0:
1006 r = r100_packet0_check(p, &pkt); 1015 r = r100_packet0_check(p, &pkt);
1007 break; 1016 break;
1008 case PACKET_TYPE2: 1017 case PACKET_TYPE2:
1009 break; 1018 break;
1010 case PACKET_TYPE3: 1019 case PACKET_TYPE3:
1011 r = r100_packet3_check(p, &pkt); 1020 r = r100_packet3_check(p, &pkt);
1012 break; 1021 break;
1013 default: 1022 default:
1014 DRM_ERROR("Unknown packet type %d !\n", 1023 DRM_ERROR("Unknown packet type %d !\n",
1015 pkt.type); 1024 pkt.type);
1016 return -EINVAL; 1025 return -EINVAL;
1017 } 1026 }
1018 if (r) { 1027 if (r) {
1019 return r; 1028 return r;
@@ -1349,6 +1358,11 @@ void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
1349 } 1358 }
1350} 1359}
1351 1360
1361int r100_init(struct radeon_device *rdev)
1362{
1363 return 0;
1364}
1365
1352/* 1366/*
1353 * Debugfs info 1367 * Debugfs info
1354 */ 1368 */
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}
diff --git a/drivers/gpu/drm/radeon/r300.h b/drivers/gpu/drm/radeon/r300.h
new file mode 100644
index 00000000000..8486b4da9d6
--- /dev/null
+++ b/drivers/gpu/drm/radeon/r300.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright 2008 Advanced Micro Devices, Inc.
3 * Copyright 2008 Red Hat Inc.
4 * Copyright 2009 Jerome Glisse.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: Dave Airlie
25 * Alex Deucher
26 * Jerome Glisse
27 */
28#ifndef R300_H
29#define R300_H
30
31struct r300_asic {
32 const unsigned *reg_safe_bm;
33 unsigned reg_safe_bm_size;
34};
35
36#endif
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c3f24cc5600..d61f2fc61df 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -51,7 +51,7 @@
51 51
52#include "radeon_mode.h" 52#include "radeon_mode.h"
53#include "radeon_reg.h" 53#include "radeon_reg.h"
54 54#include "r300.h"
55 55
56/* 56/*
57 * Modules parameters. 57 * Modules parameters.
@@ -496,6 +496,7 @@ int r100_debugfs_cp_init(struct radeon_device *rdev);
496 * ASIC specific functions. 496 * ASIC specific functions.
497 */ 497 */
498struct radeon_asic { 498struct radeon_asic {
499 int (*init)(struct radeon_device *rdev);
499 void (*errata)(struct radeon_device *rdev); 500 void (*errata)(struct radeon_device *rdev);
500 void (*vram_info)(struct radeon_device *rdev); 501 void (*vram_info)(struct radeon_device *rdev);
501 int (*gpu_reset)(struct radeon_device *rdev); 502 int (*gpu_reset)(struct radeon_device *rdev);
@@ -536,6 +537,10 @@ struct radeon_asic {
536 void (*set_clock_gating)(struct radeon_device *rdev, int enable); 537 void (*set_clock_gating)(struct radeon_device *rdev, int enable);
537}; 538};
538 539
540union radeon_asic_config {
541 struct r300_asic r300;
542};
543
539 544
540/* 545/*
541 * IOCTL. 546 * IOCTL.
@@ -573,6 +578,7 @@ struct radeon_device {
573 struct drm_device *ddev; 578 struct drm_device *ddev;
574 struct pci_dev *pdev; 579 struct pci_dev *pdev;
575 /* ASIC */ 580 /* ASIC */
581 union radeon_asic_config config;
576 enum radeon_family family; 582 enum radeon_family family;
577 unsigned long flags; 583 unsigned long flags;
578 int usec_timeout; 584 int usec_timeout;
@@ -763,6 +769,7 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
763/* 769/*
764 * ASICs macro. 770 * ASICs macro.
765 */ 771 */
772#define radeon_init(rdev) (rdev)->asic->init((rdev))
766#define radeon_cs_parse(p) rdev->asic->cs_parse((p)) 773#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
767#define radeon_errata(rdev) (rdev)->asic->errata((rdev)) 774#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
768#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev)) 775#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index e57d8a784e9..e2e567395df 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -41,6 +41,7 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable);
41/* 41/*
42 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 42 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
43 */ 43 */
44int r100_init(struct radeon_device *rdev);
44uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); 45uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
45void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 46void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
46void r100_errata(struct radeon_device *rdev); 47void r100_errata(struct radeon_device *rdev);
@@ -72,6 +73,7 @@ int r100_copy_blit(struct radeon_device *rdev,
72 struct radeon_fence *fence); 73 struct radeon_fence *fence);
73 74
74static struct radeon_asic r100_asic = { 75static struct radeon_asic r100_asic = {
76 .init = &r100_init,
75 .errata = &r100_errata, 77 .errata = &r100_errata,
76 .vram_info = &r100_vram_info, 78 .vram_info = &r100_vram_info,
77 .gpu_reset = &r100_gpu_reset, 79 .gpu_reset = &r100_gpu_reset,
@@ -104,6 +106,7 @@ static struct radeon_asic r100_asic = {
104/* 106/*
105 * r300,r350,rv350,rv380 107 * r300,r350,rv350,rv380
106 */ 108 */
109int r300_init(struct radeon_device *rdev);
107void r300_errata(struct radeon_device *rdev); 110void r300_errata(struct radeon_device *rdev);
108void r300_vram_info(struct radeon_device *rdev); 111void r300_vram_info(struct radeon_device *rdev);
109int r300_gpu_reset(struct radeon_device *rdev); 112int r300_gpu_reset(struct radeon_device *rdev);
@@ -126,6 +129,7 @@ int r300_copy_dma(struct radeon_device *rdev,
126 unsigned num_pages, 129 unsigned num_pages,
127 struct radeon_fence *fence); 130 struct radeon_fence *fence);
128static struct radeon_asic r300_asic = { 131static struct radeon_asic r300_asic = {
132 .init = &r300_init,
129 .errata = &r300_errata, 133 .errata = &r300_errata,
130 .vram_info = &r300_vram_info, 134 .vram_info = &r300_vram_info,
131 .gpu_reset = &r300_gpu_reset, 135 .gpu_reset = &r300_gpu_reset,
@@ -162,6 +166,7 @@ void r420_vram_info(struct radeon_device *rdev);
162int r420_mc_init(struct radeon_device *rdev); 166int r420_mc_init(struct radeon_device *rdev);
163void r420_mc_fini(struct radeon_device *rdev); 167void r420_mc_fini(struct radeon_device *rdev);
164static struct radeon_asic r420_asic = { 168static struct radeon_asic r420_asic = {
169 .init = &r300_init,
165 .errata = &r420_errata, 170 .errata = &r420_errata,
166 .vram_info = &r420_vram_info, 171 .vram_info = &r420_vram_info,
167 .gpu_reset = &r300_gpu_reset, 172 .gpu_reset = &r300_gpu_reset,
@@ -205,6 +210,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
205uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); 210uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg);
206void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 211void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
207static struct radeon_asic rs400_asic = { 212static struct radeon_asic rs400_asic = {
213 .init = &r300_init,
208 .errata = &rs400_errata, 214 .errata = &rs400_errata,
209 .vram_info = &rs400_vram_info, 215 .vram_info = &rs400_vram_info,
210 .gpu_reset = &r300_gpu_reset, 216 .gpu_reset = &r300_gpu_reset,
@@ -249,6 +255,7 @@ int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
249uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); 255uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
250void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 256void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
251static struct radeon_asic rs600_asic = { 257static struct radeon_asic rs600_asic = {
258 .init = &r300_init,
252 .errata = &rs600_errata, 259 .errata = &rs600_errata,
253 .vram_info = &rs600_vram_info, 260 .vram_info = &rs600_vram_info,
254 .gpu_reset = &r300_gpu_reset, 261 .gpu_reset = &r300_gpu_reset,
@@ -288,6 +295,7 @@ void rs690_mc_fini(struct radeon_device *rdev);
288uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); 295uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
289void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 296void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
290static struct radeon_asic rs690_asic = { 297static struct radeon_asic rs690_asic = {
298 .init = &r300_init,
291 .errata = &rs690_errata, 299 .errata = &rs690_errata,
292 .vram_info = &rs690_vram_info, 300 .vram_info = &rs690_vram_info,
293 .gpu_reset = &r300_gpu_reset, 301 .gpu_reset = &r300_gpu_reset,
@@ -320,6 +328,7 @@ static struct radeon_asic rs690_asic = {
320/* 328/*
321 * rv515 329 * rv515
322 */ 330 */
331int rv515_init(struct radeon_device *rdev);
323void rv515_errata(struct radeon_device *rdev); 332void rv515_errata(struct radeon_device *rdev);
324void rv515_vram_info(struct radeon_device *rdev); 333void rv515_vram_info(struct radeon_device *rdev);
325int rv515_gpu_reset(struct radeon_device *rdev); 334int rv515_gpu_reset(struct radeon_device *rdev);
@@ -331,6 +340,7 @@ void rv515_ring_start(struct radeon_device *rdev);
331uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); 340uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
332void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); 341void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
333static struct radeon_asic rv515_asic = { 342static struct radeon_asic rv515_asic = {
343 .init = &rv515_init,
334 .errata = &rv515_errata, 344 .errata = &rv515_errata,
335 .vram_info = &rv515_vram_info, 345 .vram_info = &rv515_vram_info,
336 .gpu_reset = &rv515_gpu_reset, 346 .gpu_reset = &rv515_gpu_reset,
@@ -349,7 +359,7 @@ static struct radeon_asic rv515_asic = {
349 .irq_set = &r100_irq_set, 359 .irq_set = &r100_irq_set,
350 .irq_process = &r100_irq_process, 360 .irq_process = &r100_irq_process,
351 .fence_ring_emit = &r300_fence_ring_emit, 361 .fence_ring_emit = &r300_fence_ring_emit,
352 .cs_parse = &r100_cs_parse, 362 .cs_parse = &r300_cs_parse,
353 .copy_blit = &r100_copy_blit, 363 .copy_blit = &r100_copy_blit,
354 .copy_dma = &r300_copy_dma, 364 .copy_dma = &r300_copy_dma,
355 .copy = &r100_copy_blit, 365 .copy = &r100_copy_blit,
@@ -368,6 +378,7 @@ void r520_vram_info(struct radeon_device *rdev);
368int r520_mc_init(struct radeon_device *rdev); 378int r520_mc_init(struct radeon_device *rdev);
369void r520_mc_fini(struct radeon_device *rdev); 379void r520_mc_fini(struct radeon_device *rdev);
370static struct radeon_asic r520_asic = { 380static struct radeon_asic r520_asic = {
381 .init = &rv515_init,
371 .errata = &r520_errata, 382 .errata = &r520_errata,
372 .vram_info = &r520_vram_info, 383 .vram_info = &r520_vram_info,
373 .gpu_reset = &rv515_gpu_reset, 384 .gpu_reset = &rv515_gpu_reset,
@@ -386,7 +397,7 @@ static struct radeon_asic r520_asic = {
386 .irq_set = &r100_irq_set, 397 .irq_set = &r100_irq_set,
387 .irq_process = &r100_irq_process, 398 .irq_process = &r100_irq_process,
388 .fence_ring_emit = &r300_fence_ring_emit, 399 .fence_ring_emit = &r300_fence_ring_emit,
389 .cs_parse = &r100_cs_parse, 400 .cs_parse = &r300_cs_parse,
390 .copy_blit = &r100_copy_blit, 401 .copy_blit = &r100_copy_blit,
391 .copy_dma = &r300_copy_dma, 402 .copy_dma = &r300_copy_dma,
392 .copy = &r100_copy_blit, 403 .copy = &r100_copy_blit,
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 5fd2b639bf6..f30aa7274a5 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -470,6 +470,10 @@ int radeon_device_init(struct radeon_device *rdev,
470 if (r) { 470 if (r) {
471 return r; 471 return r;
472 } 472 }
473 r = radeon_init(rdev);
474 if (r) {
475 return r;
476 }
473 477
474 /* Report DMA addressing limitation */ 478 /* Report DMA addressing limitation */
475 r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); 479 r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 7eab95db58a..ffea37b1b3e 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -225,6 +225,8 @@ void rv515_ring_start(struct radeon_device *rdev)
225 radeon_ring_write(rdev, 225 radeon_ring_write(rdev,
226 R300_GEOMETRY_ROUND_NEAREST | 226 R300_GEOMETRY_ROUND_NEAREST |
227 R300_COLOR_ROUND_NEAREST); 227 R300_COLOR_ROUND_NEAREST);
228 radeon_ring_write(rdev, PACKET0(0x20C8, 0));
229 radeon_ring_write(rdev, 0);
228 radeon_ring_unlock_commit(rdev); 230 radeon_ring_unlock_commit(rdev);
229} 231}
230 232
@@ -502,3 +504,59 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev)
502 return 0; 504 return 0;
503#endif 505#endif
504} 506}
507
508
509/*
510 * Asic initialization
511 */
512static const unsigned r500_reg_safe_bm[159] = {
513 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
514 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
515 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
516 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
517 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
518 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
519 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
520 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
521 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
522 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
523 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
524 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
525 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
526 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
527 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
528 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
529 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
530 0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
531 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
532 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
533 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
534 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
535 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
536 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
537 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
538 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
539 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
540 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
541 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
542 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
543 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
544 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
545 0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF,
546 0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF,
547 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
548 0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF,
549 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
550 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
551 0x00000000, 0x00000000, 0x00000000, 0x00000000,
552 0x0003FC01, 0x3FFFFCF8, 0xFE800B19,
553};
554
555
556
557int rv515_init(struct radeon_device *rdev)
558{
559 rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
560 rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);
561 return 0;
562}