From patchwork Fri Apr 1 23:54:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 682811 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p31Nvhjt014207 for ; Fri, 1 Apr 2011 23:58:19 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 88F619E8B4 for ; Fri, 1 Apr 2011 16:57:42 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from cloud01.chad-versace.us (184-106-247-128.static.cloud-ips.com [184.106.247.128]) by gabe.freedesktop.org (Postfix) with ESMTP id 1AADC9E793 for ; Fri, 1 Apr 2011 16:56:54 -0700 (PDT) Received: from localhost.localdomain (unknown [67.208.96.87]) by cloud01.chad-versace.us (Postfix) with ESMTPSA id 823E91D4231; Fri, 1 Apr 2011 23:57:37 +0000 (UTC) From: Ben Widawsky To: intel-gfx@lists.freedesktop.org Date: Fri, 1 Apr 2011 16:54:48 -0700 Message-Id: <1301702089-25644-2-git-send-email-ben@bwidawsk.net> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1301621965-23185-1-git-send-email-ben@bwidawsk.net> References: <1301621965-23185-1-git-send-email-ben@bwidawsk.net> Subject: [Intel-gfx] [PATCH v3 1/2] drm/i915: read/write ioctls for userspace X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 01 Apr 2011 23:58:19 +0000 (UTC) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 7273037..30cd576 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1846,6 +1846,174 @@ out_unlock: } EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable); +static struct i915_register_range * +get_register_range(struct drm_device *dev, u32 offset, int mode) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_register_range *range = dev_priv->register_map.map; + u8 align = dev_priv->register_map.alignment_mask; + u32 range_count = dev_priv->register_map.length; + + if (offset & dev_priv->register_map.alignment_mask) + return NULL; + + if (offset >= dev_priv->register_map.top) + return NULL; + + while(range_count--) { + /* list is assumed to be in order */ + if (offset < range->base) + break; + + if ( (offset >= range->base) && + (offset + align) <= (range->base + range->size)) { + /* assume perms ascend in security (ie. rw is > ro) */ + if (mode > range->flags) + return NULL; + else + return range; + } + range++; + } + + return NULL; +} + +static int +i915_read_register_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_intel_write_reg *args = data; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (args->rsvd != 0) + DRM_DEBUG("rsvd field should be zero\n"); + + if (get_register_range(dev, args->offset, I915_RANGE_RO) == NULL) { + args->value = 0xffffffff; + return -EINVAL; + } + + mutex_lock(&dev->struct_mutex); + args->value = (u32)i915_gt_read(dev_priv, args->offset); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + +static int +i915_write_register_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_intel_read_reg *args = data; + struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_register_range *range; + + if (args->rsvd != 0) + DRM_DEBUG("rsvd field should be zero\n"); + + range = get_register_range(dev, args->offset, I915_RANGE_RW); + if (!range) + return -EINVAL; + + mutex_lock(&dev->struct_mutex); + DRM_INFO("User space write %x %x\n", args->offset, (u32)args->value); + range->user_tainted = true; + i915_gt_write(dev_priv, args->offset, (u32)args->value); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + +struct i915_register_range gen_bwcl_register_map[] = { + {0x00000000, 0x00000fff, I915_RANGE_RW}, + {0x00001000, 0x00000fff, I915_RANGE_RSVD}, + {0x00002000, 0x00000fff, I915_RANGE_RW}, + {0x00003000, 0x000001ff, I915_RANGE_RW}, + {0x00003200, 0x00000dff, I915_RANGE_RW}, + {0x00004000, 0x000003ff, I915_RANGE_RSVD}, + {0x00004400, 0x00000bff, I915_RANGE_RSVD}, + {0x00005000, 0x00000fff, I915_RANGE_RW}, + {0x00006000, 0x00000fff, I915_RANGE_RW}, + {0x00007000, 0x000003ff, I915_RANGE_RW}, + {0x00007400, 0x000014ff, I915_RANGE_RW}, + {0x00008900, 0x000006ff, I915_RANGE_RSVD}, + {0x00009000, 0x00000fff, I915_RANGE_RSVD}, + {0x0000a000, 0x00000fff, I915_RANGE_RW}, + {0x0000b000, 0x00004fff, I915_RANGE_RSVD}, + {0x00010000, 0x00003fff, I915_RANGE_RW}, + {0x00014000, 0x0001bfff, I915_RANGE_RSVD}, + {0x00030000, 0x0000ffff, I915_RANGE_RW}, + {0x00040000, 0x0001ffff, I915_RANGE_RSVD}, + {0x00060000, 0x0000ffff, I915_RANGE_RW}, + {0x00070000, 0x00002fff, I915_RANGE_RW}, + {0x00073000, 0x00000fff, I915_RANGE_RW}, + {0x00074000, 0x0000bfff, I915_RANGE_RSVD} +}; + +struct i915_register_range genx_register_map[] = { + {0x00000000, 0x00000fff, I915_RANGE_RW}, + {0x00001000, 0x00000fff, I915_RANGE_RSVD}, + {0x00002000, 0x00000fff, I915_RANGE_RW}, + {0x00003000, 0x000001ff, I915_RANGE_RW}, + {0x00003200, 0x00000dff, I915_RANGE_RW}, + {0x00004000, 0x000003ff, I915_RANGE_RW}, + {0x00004400, 0x00000bff, I915_RANGE_RW}, + {0x00005000, 0x00000fff, I915_RANGE_RW}, + {0x00006000, 0x00000fff, I915_RANGE_RW}, + {0x00007000, 0x000003ff, I915_RANGE_RW}, + {0x00007400, 0x000014ff, I915_RANGE_RW}, + {0x00008900, 0x000006ff, I915_RANGE_RSVD}, + {0x00009000, 0x00000fff, I915_RANGE_RSVD}, + {0x0000a000, 0x00000fff, I915_RANGE_RW}, + {0x0000b000, 0x00004fff, I915_RANGE_RSVD}, + {0x00010000, 0x00003fff, I915_RANGE_RW}, + {0x00014000, 0x0001bfff, I915_RANGE_RSVD}, + {0x00030000, 0x0000ffff, I915_RANGE_RW}, + {0x00040000, 0x0001ffff, I915_RANGE_RSVD}, + {0x00060000, 0x0000ffff, I915_RANGE_RW}, + {0x00070000, 0x00002fff, I915_RANGE_RW}, + {0x00073000, 0x00000fff, I915_RANGE_RW}, + {0x00074000, 0x0000bfff, I915_RANGE_RSVD} +}; + +struct i915_register_range gen6_gt_register_map[] = { + {0x00000000, 0x00000fff, I915_RANGE_RW}, + {0x00001000, 0x00000fff, I915_RANGE_RSVD}, + {0x00002000, 0x00000fff, I915_RANGE_RW}, + {0x00003000, 0x000001ff, I915_RANGE_RW}, + {0x00003200, 0x00000dff, I915_RANGE_RW}, + {0x00004000, 0x00000fff, I915_RANGE_RW}, + {0x00005000, 0x0000017f, I915_RANGE_RW}, + {0x00005180, 0x00000e7f, I915_RANGE_RW}, + {0x00006000, 0x00001fff, I915_RANGE_RW}, + {0x00008000, 0x000007ff, I915_RANGE_RW}, + {0x00008800, 0x000000ff, I915_RANGE_RSVD}, + {0x00008900, 0x000006ff, I915_RANGE_RW}, + {0x00009000, 0x00000fff, I915_RANGE_RSVD}, + {0x0000a000, 0x00000fff, I915_RANGE_RW}, + {0x0000b000, 0x00004fff, I915_RANGE_RSVD}, + {0x00010000, 0x00001fff, I915_RANGE_RW}, + {0x00012000, 0x000003ff, I915_RANGE_RW}, + {0x00012400, 0x00000bff, I915_RANGE_RW}, + {0x00013000, 0x00000fff, I915_RANGE_RW}, + {0x00014000, 0x00000fff, I915_RANGE_RW}, + {0x00015000, 0x0000cfff, I915_RANGE_RW}, + {0x00022000, 0x00000fff, I915_RANGE_RW}, + {0x00023000, 0x00000fff, I915_RANGE_RSVD}, + {0x00024000, 0x00000fff, I915_RANGE_RW}, + {0x00025000, 0x0000afff, I915_RANGE_RSVD}, + {0x00030000, 0x0000ffff, I915_RANGE_RW}, + {0x00040000, 0x0001ffff, I915_RANGE_RSVD}, + {0x00060000, 0x0000ffff, I915_RANGE_RW}, + {0x00070000, 0x00002fff, I915_RANGE_RW}, + {0x00073000, 0x00000fff, I915_RANGE_RW}, + {0x00074000, 0x0008bfff, I915_RANGE_RSVD}, + {0x00100000, 0x00007fff, I915_RANGE_RW}, + {0x00108000, 0x00037fff, I915_RANGE_RSVD}, + {0x00140000, 0x0003ffff, I915_RANGE_RW} +}; + /** * Tells the intel_ips driver that the i915 driver is now loaded, if * IPS got loaded first. @@ -2062,6 +2230,25 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) ips_ping_for_i915_load(); + if (IS_GEN6(dev)) { + dev_priv->register_map.map = gen6_gt_register_map; + dev_priv->register_map.length = + ARRAY_SIZE(gen6_gt_register_map); + dev_priv->register_map.top = 0x180000; + } else if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) { + dev_priv->register_map.map = gen_bwcl_register_map; + dev_priv->register_map.length = + ARRAY_SIZE(gen_bwcl_register_map); + dev_priv->register_map.top = 0x80000; + } else { + dev_priv->register_map.map = genx_register_map; + dev_priv->register_map.length = + ARRAY_SIZE(genx_register_map); + dev_priv->register_map.top = 0x80000; + } + + dev_priv->register_map.alignment_mask = 0x3; + return 0; out_gem_unload: @@ -2276,6 +2463,8 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_READ_REGISTER, i915_read_register_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF_DRV(I915_WRITE_REGISTER, i915_write_register_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5004724..355f008 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -703,6 +703,14 @@ typedef struct drm_i915_private { struct intel_fbdev *fbdev; struct drm_property *broadcast_rgb_property; + + /* User visible register map */ + struct { + struct i915_register_range *map; + u32 length; + u32 top; + u8 alignment_mask; + } register_map; } drm_i915_private_t; struct drm_i915_gem_object { @@ -1385,4 +1393,17 @@ static inline void i915_gt_write(struct drm_i915_private *dev_priv, __gen6_gt_wait_for_fifo(dev_priv); I915_WRITE(reg, val); } + +/* Register range interface */ +struct i915_register_range { + u32 base; + u32 size; + u8 flags; + bool user_tainted; +}; + +#define I915_RANGE_RSVD (0<<0) +#define I915_RANGE_RO (1<<0) +#define I915_RANGE_RW (1<<1) + #endif diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index c4d6dbf..9398cb2 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -198,6 +198,8 @@ typedef struct _drm_i915_sarea { #define DRM_I915_OVERLAY_PUT_IMAGE 0x27 #define DRM_I915_OVERLAY_ATTRS 0x28 #define DRM_I915_GEM_EXECBUFFER2 0x29 +#define DRM_I915_READ_REGISTER 0x2a +#define DRM_I915_WRITE_REGISTER 0x2b #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) @@ -239,6 +241,8 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise) #define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image) #define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs) +#define DRM_IOCTL_I915_READ_REGISTER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_READ_REGISTER, struct drm_intel_read_reg) +#define DRM_IOCTL_I915_WRITE_REGISTER DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_WRITE_REGISTER, struct drm_intel_write_reg) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -844,4 +848,30 @@ struct drm_intel_overlay_attrs { __u32 gamma5; }; +struct drm_intel_read_reg { + /* register offset to read */ + __u32 offset; + + /* register size, RFU */ + __u8 size; + + /* return value, high 4 bytes RFU */ + __u64 value; + + __u64 rsvd; +}; + +struct drm_intel_write_reg { + /* register offset to read */ + __u32 offset; + + /* register size, RFU */ + __u8 size; + + /* value to write, high 4 bytes RFU */ + __u64 value; + + __u64 rsvd; +}; + #endif /* _I915_DRM_H_ */