[PATCH 1/2 v4] drm/exynos: added userptr limit ioctl.

Inki Dae inki.dae at samsung.com
Mon May 14 01:12:44 PDT 2012


ccing linux-mm

> -----Original Message-----
> From: Inki Dae [mailto:inki.dae at samsung.com]
> Sent: Monday, May 14, 2012 3:18 PM
> To: airlied at linux.ie; dri-devel at lists.freedesktop.org
> Cc: j.glisse at gmail.com; minchan at kernel.org; kosaki.motohiro at gmail.com;
> kyungmin.park at samsung.com; sw0312.kim at samsung.com;
jy0922.shim at samsung.com;
> Inki Dae
> Subject: [PATCH 1/2 v4] drm/exynos: added userptr limit ioctl.
> 
> this ioctl is used to limit user-desired userptr size as pre-defined
> and also could be accessed by only root user.
> 
> with userptr feature, unprivileged user can allocate all the pages on
> system,
> so the amount of free physical pages will be very limited. if the VMAs
> within user address space was pinned, the pages couldn't be swapped out so
> it may result in significant degradation of system performance. so this
> feature would be used to avoid such situation.
> 
> Signed-off-by: Inki Dae <inki.dae at samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_drv.c |    6 ++++++
>  drivers/gpu/drm/exynos/exynos_drm_drv.h |    6 ++++++
>  drivers/gpu/drm/exynos/exynos_drm_gem.c |   22 ++++++++++++++++++++++
>  drivers/gpu/drm/exynos/exynos_drm_gem.h |    3 +++
>  include/drm/exynos_drm.h                |   17 +++++++++++++++++
>  5 files changed, 54 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> index 9d3204c..1e68ec2 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
> @@ -64,6 +64,9 @@ static int exynos_drm_load(struct drm_device *dev,
> unsigned long flags)
>  		return -ENOMEM;
>  	}
> 
> +	/* maximum size of userptr is limited to 16MB as default. */
> +	private->userptr_limit = SZ_16M;
> +
>  	INIT_LIST_HEAD(&private->pageflip_event_list);
>  	dev->dev_private = (void *)private;
> 
> @@ -221,6 +224,9 @@ static struct drm_ioctl_desc exynos_ioctls[] = {
>  			exynos_drm_gem_mmap_ioctl, DRM_UNLOCKED | DRM_AUTH),
>  	DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET,
>  			exynos_drm_gem_get_ioctl, DRM_UNLOCKED),
> +	DRM_IOCTL_DEF_DRV(EXYNOS_USER_LIMIT,
> +			exynos_drm_gem_user_limit_ioctl, DRM_MASTER |
> +			DRM_ROOT_ONLY),
>  	DRM_IOCTL_DEF_DRV(EXYNOS_PLANE_SET_ZPOS,
> exynos_plane_set_zpos_ioctl,
>  			DRM_UNLOCKED | DRM_AUTH),
>  	DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION,
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> index c82c90c..b38ed6f 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
> @@ -235,6 +235,12 @@ struct exynos_drm_private {
>  	 * this array is used to be aware of which crtc did it request
> vblank.
>  	 */
>  	struct drm_crtc *crtc[MAX_CRTC];
> +
> +	/*
> +	 * maximum size of allocation by userptr feature.
> +	 * - as default, this has 16MB and only root user can change it.
> +	 */
> +	unsigned long userptr_limit;
>  };
> 
>  /*
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c
> b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> index fc91293..e6abb66 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
> @@ -33,6 +33,8 @@
>  #include "exynos_drm_gem.h"
>  #include "exynos_drm_buf.h"
> 
> +#define USERPTR_MAX_SIZE		SZ_64M
> +
>  static unsigned int convert_to_vm_err_msg(int msg)
>  {
>  	unsigned int out_msg;
> @@ -630,6 +632,26 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev,
> void *data,
>  	return 0;
>  }
> 
> +int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data,
> +				      struct drm_file *filp)
> +{
> +	struct exynos_drm_private *priv = dev->dev_private;
> +	struct drm_exynos_user_limit *limit = data;
> +
> +	if (limit->userptr_limit < PAGE_SIZE ||
> +			limit->userptr_limit > USERPTR_MAX_SIZE) {
> +		DRM_DEBUG_KMS("invalid userptr_limit size.\n");
> +		return -EINVAL;
> +	}
> +
> +	if (priv->userptr_limit == limit->userptr_limit)
> +		return 0;
> +
> +	priv->userptr_limit = limit->userptr_limit;
> +
> +	return 0;
> +}
> +
>  int exynos_drm_gem_init_object(struct drm_gem_object *obj)
>  {
>  	DRM_DEBUG_KMS("%s\n", __FILE__);
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h
> b/drivers/gpu/drm/exynos/exynos_drm_gem.h
> index 14d038b..3334c9f 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
> +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
> @@ -78,6 +78,9 @@ struct exynos_drm_gem_obj {
> 
>  struct page **exynos_gem_get_pages(struct drm_gem_object *obj, gfp_t
> gfpmask);
> 
> +int exynos_drm_gem_user_limit_ioctl(struct drm_device *dev, void *data,
> +				      struct drm_file *filp);
> +
>  /* destroy a buffer with gem object */
>  void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj);
> 
> diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
> index 54c97e8..52465dc 100644
> --- a/include/drm/exynos_drm.h
> +++ b/include/drm/exynos_drm.h
> @@ -92,6 +92,19 @@ struct drm_exynos_gem_info {
>  };
> 
>  /**
> + * A structure to userptr limited information.
> + *
> + * @userptr_limit: maximum size to userptr buffer.
> + *	the buffer could be allocated by unprivileged user using malloc()
> + *	and the size of the buffer would be limited as userptr_limit value.
> + * @pad: just padding to be 64-bit aligned.
> + */
> +struct drm_exynos_user_limit {
> +	unsigned int userptr_limit;
> +	unsigned int pad;
> +};
> +
> +/**
>   * A structure for user connection request of virtual display.
>   *
>   * @connection: indicate whether doing connetion or not by user.
> @@ -162,6 +175,7 @@ struct drm_exynos_g2d_exec {
>  #define DRM_EXYNOS_GEM_MMAP		0x02
>  /* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
>  #define DRM_EXYNOS_GEM_GET		0x04
> +#define DRM_EXYNOS_USER_LIMIT		0x05
>  #define DRM_EXYNOS_PLANE_SET_ZPOS	0x06
>  #define DRM_EXYNOS_VIDI_CONNECTION	0x07
> 
> @@ -182,6 +196,9 @@ struct drm_exynos_g2d_exec {
>  #define DRM_IOCTL_EXYNOS_GEM_GET	DRM_IOWR(DRM_COMMAND_BASE + \
>  		DRM_EXYNOS_GEM_GET,	struct drm_exynos_gem_info)
> 
> +#define DRM_IOCTL_EXYNOS_USER_LIMIT	DRM_IOWR(DRM_COMMAND_BASE + \
> +		DRM_EXYNOS_USER_LIMIT,	struct drm_exynos_user_limit)
> +
>  #define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS	DRM_IOWR(DRM_COMMAND_BASE +
> \
>  		DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos)
> 
> --
> 1.7.4.1



More information about the dri-devel mailing list