From patchwork Wed Mar 13 09:04:24 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Inki Dae X-Patchwork-Id: 2262481 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 2CFD93FD8C for ; Wed, 13 Mar 2013 09:10:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E5249E601B for ; Wed, 13 Mar 2013 02:10:41 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mailout4.samsung.com (mailout4.samsung.com [203.254.224.34]) by gabe.freedesktop.org (Postfix) with ESMTP id 2F9F0E680D for ; Wed, 13 Mar 2013 02:04:26 -0700 (PDT) Received: from epcpsbgr5.samsung.com (u145.gpu120.samsung.co.kr [203.254.230.145]) by mailout4.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MJL00299D7CS770@mailout4.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 13 Mar 2013 18:04:25 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.41]) by epcpsbgr5.samsung.com (EPCPMTA) with SMTP id 2F.BD.12250.91140415; Wed, 13 Mar 2013 18:04:25 +0900 (KST) X-AuditID: cbfee691-b7f5f6d000002fda-3a-51404119f65c Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 08.71.13494.81140415; Wed, 13 Mar 2013 18:04:25 +0900 (KST) Received: from daeinki-desktop.10.32.193.11 ([10.90.8.53]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MJL00ES9D7CBQ10@mmp1.samsung.com> for dri-devel@lists.freedesktop.org; Wed, 13 Mar 2013 18:04:24 +0900 (KST) From: Inki Dae To: airlied@linux.ie, dri-devel@lists.freedesktop.org Subject: [PATCH 7/7] drm/exynos: Check g2d cmd list for g2d restrictions Date: Wed, 13 Mar 2013 18:04:24 +0900 Message-id: <1363165464-7584-1-git-send-email-inki.dae@samsung.com> X-Mailer: git-send-email 1.7.4.1 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrHLMWRmVeSWpSXmKPExsVy+t8zTV1JR4dAg1VPOC2ufH3P5sDocb/7 OFMAYxSXTUpqTmZZapG+XQJXxumte1kKnrlVnLy9nbWB8Yp5FyMnh4SAiUTHlC9sELaYxIV7 64FsLg4hgWWMEr/2v2SHKZry+CMrRGIRo8SZl+9YIJx1TBK3djxlAaliE1CVmLjiPtgoEQFT iY5JS8GKmAW6GSWeP/jLCpIQFvCQeD9zOTOIzQLUsP3oFqAGDg5eAWeJ7ROVIbYpSCy49xbs DAmBHWwSi95fYYeoF5D4NvkQC0i9hICsxKYDzBD1khIHV9xgmcAouICRYRWjaGpBckFxUnqR qV5xYm5xaV66XnJ+7iZGSFhN3MF4/4D1IcZkoHETmaVEk/OBYZlXEm9obGZkYWpiamxkbmlG mrCSOK96i3WgkEB6YklqdmpqQWpRfFFpTmrxIUYmDk6pBkZ1/zwxE4OOIyabM93XSew7eYr/ GKNka/Smg/qH23yn1/gf2sYZ8POOSbiNSqDp3Z/vMucvVnz8amHMms6osDINttl2L2fOiJac ej37386nO/RXM30MyVzUvKZ0zsP1j697RBlLVzk7KovJTdXqsHsd66D8QWyHn07kt6/HJxxx bZpScnRLbK8SS3FGoqEWc1FxIgC3Z+UGQQIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupikeLIzCtJLcpLzFFi42I5/e+xgK6ko0OgwX5ziytf37M5MHrc7z7O FMAY1cBok5GamJJapJCal5yfkpmXbqvkHRzvHG9qZmCoa2hpYa6kkJeYm2qr5OIToOuWmQM0 VUmhLDGnFCgUkFhcrKRvh2lCaIibrgVMY4Sub0gQXI+RARpIWMeYcXrrXpaCZ24VJ29vZ21g vGLexcjJISFgIjHl8UdWCFtM4sK99WxdjFwcQgKLGCXOvHzHAuGsY5K4teMpC0gVm4CqxMQV 99lAbBEBU4mOSUvBipgFuhklnj/4CzZKWMBD4v3M5cwgNgtQw/ajW4AaODh4BZwltk9Uhtim ILHg3lu2CYzcCxgZVjGKphYkFxQnpeca6RUn5haX5qXrJefnbmIEh+wz6R2MqxosDjEKcDAq 8fBKpNkHCrEmlhVX5h5ilOBgVhLh/WbjECjEm5JYWZValB9fVJqTWnyIMRlo+URmKdHkfGA8 5ZXEGxqbmBlZGpkZm5gbG5MmrCTOe7DVOlBIID2xJDU7NbUgtQhmCxMHp1QDY/3ihum1tluZ XvbKnvq6TeOWpNI3udozGzIZguV3XF/5o7WIbS2jRZiM7tHY3htiFlItt//5vLfQO/mA3y15 /amdyQzlq+aqFdVu3aivkfginPvFwR82Zh3qm+Zq9avaMvJ+XyOftPDnU7n7dzx5dq5Jedv/ o6wzZanrnwcxs/5empR0zaTISImlOCPRUIu5qDgRAEvzIe6dAgAA DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Cc: kyungmin.park@samsung.com, sw0312.kim@samsung.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: YoungJun Cho This patch checks command list from user for g2d restrictions. For now, g2d driver wasn't considered for G2D hardware restrictions properly. The below is the restrictions to G2D hardware and this patch considers them. - width or height value in the command list has to be in valid range (1 to 8000 pixels) - The requested area should be less than buffer size. - right has to be bigger than left. - bottom has to be bigger than top. Signed-off-by: YoungJun Cho Signed-off-by: Inki Dae Signed-off-by: Kyungmin Park --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 183 +++++++++++++++++++++++++++++++ 1 files changed, 183 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index b7be3d4..dbebbb8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -48,8 +48,14 @@ /* registers for base address */ #define G2D_SRC_BASE_ADDR 0x0304 +#define G2D_SRC_COLOR_MODE 0x030C +#define G2D_SRC_LEFT_TOP 0x0310 +#define G2D_SRC_RIGHT_BOTTOM 0x0314 #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 #define G2D_DST_BASE_ADDR 0x0404 +#define G2D_DST_COLOR_MODE 0x040C +#define G2D_DST_LEFT_TOP 0x0410 +#define G2D_DST_RIGHT_BOTTOM 0x0414 #define G2D_DST_PLANE2_BASE_ADDR 0x0418 #define G2D_PAT_BASE_ADDR 0x0500 #define G2D_MSK_BASE_ADDR 0x0520 @@ -91,6 +97,22 @@ #define G2D_START_NHOLT (1 << 1) #define G2D_START_BITBLT (1 << 0) +/* buffer color format */ +#define G2D_FMT_XRGB8888 0 +#define G2D_FMT_ARGB8888 1 +#define G2D_FMT_RGB565 2 +#define G2D_FMT_XRGB1555 3 +#define G2D_FMT_ARGB1555 4 +#define G2D_FMT_XRGB4444 5 +#define G2D_FMT_ARGB4444 6 +#define G2D_FMT_PACKED_RGB888 7 +#define G2D_FMT_A8 11 +#define G2D_FMT_L8 12 + +/* buffer valid length */ +#define G2D_LEN_MIN 1 +#define G2D_LEN_MAX 8000 + #define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) #define G2D_CMDLIST_NUM 64 #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) @@ -123,12 +145,31 @@ struct g2d_cmdlist { }; /* + * A structure of buffer description + * + * @format: color format + * @left_x: the x coordinates of left top corner + * @top_y: the y coordinates of left top corner + * @right_x: the x coordinates of right bottom corner + * @bottom_y: the y coordinates of right bottom corner + * + */ +struct g2d_buf_desc { + unsigned int format; + unsigned int left_x; + unsigned int top_y; + unsigned int right_x; + unsigned int bottom_y; +}; + +/* * A structure of buffer information * * @map_nr: manages the number of mapped buffers * @reg_types: stores regitster type in the order of requested command * @handles: stores buffer handle in its reg_type position * @types: stores buffer type in its reg_type position + * @descs: stores buffer description in its reg_type position * */ struct g2d_buf_info { @@ -136,6 +177,7 @@ struct g2d_buf_info { enum g2d_reg_type reg_types[MAX_REG_TYPE_NR]; unsigned long handles[MAX_REG_TYPE_NR]; unsigned int types[MAX_REG_TYPE_NR]; + struct g2d_buf_desc descs[MAX_REG_TYPE_NR]; }; struct drm_exynos_pending_g2d_event { @@ -540,12 +582,18 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) switch (reg_offset) { case G2D_SRC_BASE_ADDR: + case G2D_SRC_COLOR_MODE: + case G2D_SRC_LEFT_TOP: + case G2D_SRC_RIGHT_BOTTOM: reg_type = REG_TYPE_SRC; break; case G2D_SRC_PLANE2_BASE_ADDR: reg_type = REG_TYPE_SRC_PLANE2; break; case G2D_DST_BASE_ADDR: + case G2D_DST_COLOR_MODE: + case G2D_DST_LEFT_TOP: + case G2D_DST_RIGHT_BOTTOM: reg_type = REG_TYPE_DST; break; case G2D_DST_PLANE2_BASE_ADDR: @@ -566,6 +614,69 @@ static enum g2d_reg_type g2d_get_reg_type(int reg_offset) return reg_type; } +static unsigned long g2d_get_buf_bpp(unsigned int format) +{ + unsigned long bpp; + + switch (format) { + case G2D_FMT_XRGB8888: + case G2D_FMT_ARGB8888: + bpp = 4; + break; + case G2D_FMT_RGB565: + case G2D_FMT_XRGB1555: + case G2D_FMT_ARGB1555: + case G2D_FMT_XRGB4444: + case G2D_FMT_ARGB4444: + bpp = 2; + break; + case G2D_FMT_PACKED_RGB888: + bpp = 3; + break; + default: + bpp = 1; + break; + } + + return bpp; +} + +static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, + enum g2d_reg_type reg_type, + unsigned long size) +{ + unsigned int width, height; + unsigned long area; + + /* + * check source and destination buffers only. + * so the others are always valid. + */ + if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) + return true; + + width = buf_desc->right_x - buf_desc->left_x; + if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { + DRM_ERROR("width[%u] is out of range!\n", width); + return false; + } + + height = buf_desc->bottom_y - buf_desc->top_y; + if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { + DRM_ERROR("height[%u] is out of range!\n", height); + return false; + } + + area = (unsigned long)width * (unsigned long)height * + g2d_get_buf_bpp(buf_desc->format); + if (area > size) { + DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); + return false; + } + + return true; +} + static int g2d_map_cmdlist_gem(struct g2d_data *g2d, struct g2d_cmdlist_node *node, struct drm_device *drm_dev, @@ -576,6 +687,7 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, int ret, i; for (i = 0; i < buf_info->map_nr; i++) { + struct g2d_buf_desc *buf_desc; enum g2d_reg_type reg_type; int reg_pos, reg_offset; unsigned long handle; @@ -592,7 +704,23 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, goto err; } + buf_desc = &buf_info->descs[reg_type]; + if (buf_info->types[reg_type] == BUF_TYPE_GEM) { + unsigned long size; + + size = exynos_drm_gem_get_size(drm_dev, handle, file); + if (!size) { + ret = -EFAULT; + goto err; + } + + if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, + size)) { + ret = -EFAULT; + goto err; + } + addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, file); if (IS_ERR(addr)) { @@ -608,6 +736,12 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, goto err; } + if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, + g2d_userptr.size)) { + ret = -EFAULT; + goto err; + } + addr = g2d_userptr_get_dma_addr(drm_dev, g2d_userptr.userptr, g2d_userptr.size, @@ -640,11 +774,13 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, int i; for (i = 0; i < buf_info->map_nr; i++) { + struct g2d_buf_desc *buf_desc; enum g2d_reg_type reg_type; unsigned long handle; reg_type = buf_info->reg_types[i]; + buf_desc = &buf_info->descs[reg_type]; handle = buf_info->handles[reg_type]; if (buf_info->types[reg_type] == BUF_TYPE_GEM) @@ -657,6 +793,7 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, buf_info->reg_types[i] = REG_TYPE_NONE; buf_info->handles[reg_type] = 0; buf_info->types[reg_type] = 0; + memset(buf_desc, 0x00, sizeof(*buf_desc)); } buf_info->map_nr = 0; @@ -805,8 +942,10 @@ static int g2d_check_reg_offset(struct device *dev, for (i = 0; i < nr; i++) { struct g2d_buf_info *buf_info = &node->buf_info; + struct g2d_buf_desc *buf_desc; enum g2d_reg_type reg_type; int reg_offset; + unsigned long value; reg_pos = cmdlist->last - 2 * (i + 1); @@ -837,6 +976,50 @@ static int g2d_check_reg_offset(struct device *dev, } else buf_info->types[reg_type] = BUF_TYPE_GEM; break; + case G2D_SRC_COLOR_MODE: + case G2D_DST_COLOR_MODE: + if (for_addr) + goto err; + + reg_type = g2d_get_reg_type(reg_offset); + if (reg_type == REG_TYPE_NONE) + goto err; + + buf_desc = &buf_info->descs[reg_type]; + value = cmdlist->data[reg_pos + 1]; + + buf_desc->format = value & 0xf; + break; + case G2D_SRC_LEFT_TOP: + case G2D_DST_LEFT_TOP: + if (for_addr) + goto err; + + reg_type = g2d_get_reg_type(reg_offset); + if (reg_type == REG_TYPE_NONE) + goto err; + + buf_desc = &buf_info->descs[reg_type]; + value = cmdlist->data[reg_pos + 1]; + + buf_desc->left_x = value & 0x1fff; + buf_desc->top_y = (value & 0x1fff0000) >> 16; + break; + case G2D_SRC_RIGHT_BOTTOM: + case G2D_DST_RIGHT_BOTTOM: + if (for_addr) + goto err; + + reg_type = g2d_get_reg_type(reg_offset); + if (reg_type == REG_TYPE_NONE) + goto err; + + buf_desc = &buf_info->descs[reg_type]; + value = cmdlist->data[reg_pos + 1]; + + buf_desc->right_x = value & 0x1fff; + buf_desc->bottom_y = (value & 0x1fff0000) >> 16; + break; default: if (for_addr) goto err;