diff options
author | Jerome Glisse <glisse@freedesktop.org> | 2009-06-17 07:28:30 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-06-18 19:32:27 -0400 |
commit | 068a117ca38f27c9641db7642f24fe9270d9424e (patch) | |
tree | e1038db118114aa777312a5eae70b512fa13617b /drivers/gpu/drm/radeon/r100.c | |
parent | 8b5c744485b75d940ccb1c83c9a358b20eb91346 (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/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 76 |
1 files changed, 45 insertions, 31 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 64a692c0c319..c550932a108f 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 | */ |
648 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, | 648 | int 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 | ||
689 | int 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 | |||
707 | void r100_cs_dump_packet(struct radeon_cs_parser *p, | 693 | void 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 | ||
893 | int 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 | |||
907 | static int r100_packet3_check(struct radeon_cs_parser *p, | 912 | static 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 | ||
1361 | int r100_init(struct radeon_device *rdev) | ||
1362 | { | ||
1363 | return 0; | ||
1364 | } | ||
1365 | |||
1352 | /* | 1366 | /* |
1353 | * Debugfs info | 1367 | * Debugfs info |
1354 | */ | 1368 | */ |