aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Jakobi <tjakobi@math.uni-bielefeld.de>2015-08-17 18:51:24 -0400
committerInki Dae <daeinki@gmail.com>2015-09-02 10:10:28 -0400
commit179239a7ae805f7695167c62a97eac3efe52d7af (patch)
tree5228ad4284d25b58c1bd41a75ce41ab46a24570c
parent879a37d00f1882b1e56a66e626af4194d592d257 (diff)
drm/exynos: fix size check in g2d_check_buf_desc_is_valid()
The size check was incomplete. It only computed the size of area of the drawing rectangle and checked if the size still fit inside the buffer. The correct check is to compute the position of the last byte that the G2D engine is going to access and then check if that position is still contained in the buffer. In particular we need the stride information to determine this. Signed-off-by: Tobias Jakobi <tjakobi@math.uni-bielefeld.de> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index ba008391a2fc..85457b33d881 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -48,11 +48,13 @@
48 48
49/* registers for base address */ 49/* registers for base address */
50#define G2D_SRC_BASE_ADDR 0x0304 50#define G2D_SRC_BASE_ADDR 0x0304
51#define G2D_SRC_STRIDE_REG 0x0308
51#define G2D_SRC_COLOR_MODE 0x030C 52#define G2D_SRC_COLOR_MODE 0x030C
52#define G2D_SRC_LEFT_TOP 0x0310 53#define G2D_SRC_LEFT_TOP 0x0310
53#define G2D_SRC_RIGHT_BOTTOM 0x0314 54#define G2D_SRC_RIGHT_BOTTOM 0x0314
54#define G2D_SRC_PLANE2_BASE_ADDR 0x0318 55#define G2D_SRC_PLANE2_BASE_ADDR 0x0318
55#define G2D_DST_BASE_ADDR 0x0404 56#define G2D_DST_BASE_ADDR 0x0404
57#define G2D_DST_STRIDE_REG 0x0408
56#define G2D_DST_COLOR_MODE 0x040C 58#define G2D_DST_COLOR_MODE 0x040C
57#define G2D_DST_LEFT_TOP 0x0410 59#define G2D_DST_LEFT_TOP 0x0410
58#define G2D_DST_RIGHT_BOTTOM 0x0414 60#define G2D_DST_RIGHT_BOTTOM 0x0414
@@ -148,6 +150,7 @@ struct g2d_cmdlist {
148 * A structure of buffer description 150 * A structure of buffer description
149 * 151 *
150 * @format: color format 152 * @format: color format
153 * @stride: buffer stride/pitch in bytes
151 * @left_x: the x coordinates of left top corner 154 * @left_x: the x coordinates of left top corner
152 * @top_y: the y coordinates of left top corner 155 * @top_y: the y coordinates of left top corner
153 * @right_x: the x coordinates of right bottom corner 156 * @right_x: the x coordinates of right bottom corner
@@ -156,6 +159,7 @@ struct g2d_cmdlist {
156 */ 159 */
157struct g2d_buf_desc { 160struct g2d_buf_desc {
158 unsigned int format; 161 unsigned int format;
162 unsigned int stride;
159 unsigned int left_x; 163 unsigned int left_x;
160 unsigned int top_y; 164 unsigned int top_y;
161 unsigned int right_x; 165 unsigned int right_x;
@@ -589,6 +593,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
589 593
590 switch (reg_offset) { 594 switch (reg_offset) {
591 case G2D_SRC_BASE_ADDR: 595 case G2D_SRC_BASE_ADDR:
596 case G2D_SRC_STRIDE_REG:
592 case G2D_SRC_COLOR_MODE: 597 case G2D_SRC_COLOR_MODE:
593 case G2D_SRC_LEFT_TOP: 598 case G2D_SRC_LEFT_TOP:
594 case G2D_SRC_RIGHT_BOTTOM: 599 case G2D_SRC_RIGHT_BOTTOM:
@@ -598,6 +603,7 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
598 reg_type = REG_TYPE_SRC_PLANE2; 603 reg_type = REG_TYPE_SRC_PLANE2;
599 break; 604 break;
600 case G2D_DST_BASE_ADDR: 605 case G2D_DST_BASE_ADDR:
606 case G2D_DST_STRIDE_REG:
601 case G2D_DST_COLOR_MODE: 607 case G2D_DST_COLOR_MODE:
602 case G2D_DST_LEFT_TOP: 608 case G2D_DST_LEFT_TOP:
603 case G2D_DST_RIGHT_BOTTOM: 609 case G2D_DST_RIGHT_BOTTOM:
@@ -652,8 +658,8 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
652 enum g2d_reg_type reg_type, 658 enum g2d_reg_type reg_type,
653 unsigned long size) 659 unsigned long size)
654{ 660{
655 unsigned int width, height; 661 int width, height;
656 unsigned long area; 662 unsigned long bpp, last_pos;
657 663
658 /* 664 /*
659 * check source and destination buffers only. 665 * check source and destination buffers only.
@@ -662,22 +668,37 @@ static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
662 if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) 668 if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST)
663 return true; 669 return true;
664 670
665 width = buf_desc->right_x - buf_desc->left_x; 671 /* This check also makes sure that right_x > left_x. */
672 width = (int)buf_desc->right_x - (int)buf_desc->left_x;
666 if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { 673 if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) {
667 DRM_ERROR("width[%u] is out of range!\n", width); 674 DRM_ERROR("width[%d] is out of range!\n", width);
668 return false; 675 return false;
669 } 676 }
670 677
671 height = buf_desc->bottom_y - buf_desc->top_y; 678 /* This check also makes sure that bottom_y > top_y. */
679 height = (int)buf_desc->bottom_y - (int)buf_desc->top_y;
672 if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { 680 if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) {
673 DRM_ERROR("height[%u] is out of range!\n", height); 681 DRM_ERROR("height[%d] is out of range!\n", height);
674 return false; 682 return false;
675 } 683 }
676 684
677 area = (unsigned long)width * (unsigned long)height * 685 bpp = g2d_get_buf_bpp(buf_desc->format);
678 g2d_get_buf_bpp(buf_desc->format); 686
679 if (area > size) { 687 /* Compute the position of the last byte that the engine accesses. */
680 DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); 688 last_pos = ((unsigned long)buf_desc->bottom_y - 1) *
689 (unsigned long)buf_desc->stride +
690 (unsigned long)buf_desc->right_x * bpp - 1;
691
692 /*
693 * Since right_x > left_x and bottom_y > top_y we already know
694 * that the first_pos < last_pos (first_pos being the position
695 * of the first byte the engine accesses), it just remains to
696 * check if last_pos is smaller then the buffer size.
697 */
698
699 if (last_pos >= size) {
700 DRM_ERROR("last engine access position [%lu] "
701 "is out of range [%lu]!\n", last_pos, size);
681 return false; 702 return false;
682 } 703 }
683 704
@@ -983,6 +1004,16 @@ static int g2d_check_reg_offset(struct device *dev,
983 } else 1004 } else
984 buf_info->types[reg_type] = BUF_TYPE_GEM; 1005 buf_info->types[reg_type] = BUF_TYPE_GEM;
985 break; 1006 break;
1007 case G2D_SRC_STRIDE_REG:
1008 case G2D_DST_STRIDE_REG:
1009 if (for_addr)
1010 goto err;
1011
1012 reg_type = g2d_get_reg_type(reg_offset);
1013
1014 buf_desc = &buf_info->descs[reg_type];
1015 buf_desc->stride = cmdlist->data[index + 1];
1016 break;
986 case G2D_SRC_COLOR_MODE: 1017 case G2D_SRC_COLOR_MODE:
987 case G2D_DST_COLOR_MODE: 1018 case G2D_DST_COLOR_MODE:
988 if (for_addr) 1019 if (for_addr)