drm/tgm: tdm_pp: msc: check and adjust src/dest size parameter 98/221198/1 accepted/tizen/unified/20191230.120909 submit/tizen/20191230.065651
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 23 Dec 2019 01:21:38 +0000 (10:21 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Mon, 30 Dec 2019 05:23:00 +0000 (14:23 +0900)
In msc hw, for both src and dest, image x plus image w should be
equal or less than buffer size vsize and image y plus image shou.d
be equal or less than buffer size hsize. Otherwise, hw tries to
access out of buffer boundary and it causes msc sysmmu page fault.
Fix to check and to adjust src/dest size parameter as the hw
constraint.

Change-Id: Ie6e9d431955e0c369164f2b1f46cf9f17e0b1d8b
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/gpu/drm/tgm/tdm_pp_msc.c

index 40eece687dce7d9f6f00487f73612e15b1823759..15e881c2de5375cb4cd6b0f9f042f96d5918f730 100644 (file)
@@ -707,6 +707,22 @@ static int sc_src_set_size(struct device *dev, int swap,
        DRM_DEBUG("%s:x[%d]y[%d]w[%d]h[%d]\n",
                __func__, pos->x, pos->y, pos->w, pos->h);
 
+       if (pos->x + pos->w > sz->hsize) {
+               dev_warn(dev, "wrong src size: pos->x[%d] + pos->w[%d] "
+                             "should be equal or less than sz->hsize[%d], "
+                             "try to adjust pos->w as [%d]\n",
+                       pos->x, pos->w, sz->hsize, sz->hsize - pos->x);
+               pos->w = sz->hsize - pos->x;
+       }
+
+       if (pos->y + pos->h > sz->vsize) {
+               dev_warn(dev, "wrong src size: pos->y[%d] + pos->h[%d] "
+                             "should be equal or less than sz->vsize[%d], "
+                             "try to adjust pos->h as [%d]\n",
+                       pos->y, pos->h, sz->vsize, sz->vsize - pos->y);
+               pos->h = sz->vsize - pos->y;
+       }
+
        /* pixel offset */
        cfg = (SCALER_SRC_YX(pos->x) |
                SCALER_SRC_YY(pos->y));
@@ -1154,6 +1170,22 @@ static int sc_dst_set_size(struct device *dev, int swap,
                img_pos.h = pos->w;
        }
 
+       if (pos->x + pos->w > sz->hsize) {
+               dev_warn(dev, "wrong dst size: pos->x[%d] + pos->w[%d] "
+                             "should be equal or less than sz->hsize[%d], "
+                             "try to adjust pos->w as [%d]\n",
+                       pos->x, pos->w, sz->hsize, sz->hsize - pos->x);
+               pos->w = sz->hsize - pos->x;
+       }
+
+       if (pos->y + pos->h > sz->vsize) {
+               dev_warn(dev, "wrong dst size: pos->y[%d] + pos->h[%d] "
+                             "should be equal or less than sz->vsize[%d], "
+                             "try to adjust pos->h as [%d]\n",
+                       pos->y, pos->h, sz->vsize, sz->vsize - pos->y);
+               pos->h = sz->vsize - pos->y;
+       }
+
        /* pixel offset */
        cfg = (SCALER_DST_X(pos->x) |
                SCALER_DST_Y(pos->y));