From patchwork Wed Mar 21 23:23:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Roper X-Patchwork-Id: 10300673 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8ED4360349 for ; Wed, 21 Mar 2018 23:25:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 809EC290D7 for ; Wed, 21 Mar 2018 23:25:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 757042990D; Wed, 21 Mar 2018 23:25:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DA35E290D7 for ; Wed, 21 Mar 2018 23:25:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C019A6EB47; Wed, 21 Mar 2018 23:25:18 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by gabe.freedesktop.org (Postfix) with ESMTPS id 131276EB43; Wed, 21 Mar 2018 23:25:17 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 21 Mar 2018 16:25:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,341,1517904000"; d="scan'208";a="210273096" Received: from mdroper-desk.fm.intel.com ([10.1.134.220]) by orsmga005.jf.intel.com with ESMTP; 21 Mar 2018 16:25:16 -0700 From: Matt Roper To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, cgroups@vger.kernel.org Date: Wed, 21 Mar 2018 16:23:41 -0700 Message-Id: <20180321232344.20727-6-matthew.d.roper@intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180321232344.20727-1-matthew.d.roper@intel.com> References: <20180321232344.20727-1-matthew.d.roper@intel.com> Subject: [Intel-gfx] [PATCH v4.5 5/8] drm/i915: cgroup integration (v4) X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Introduce a new DRM_IOCTL_I915_CGROUP_SETPARAM ioctl that will allow userspace to set i915-specific parameters for individual cgroups. i915 cgroup data will be registered and later looked up via the new cgroup_priv infrastructure. v2: - Large rebase/rewrite for new cgroup_priv interface v3: - Another rebase/rewrite for ida-based keys and kref-based storage - Access control no longer follows cgroup filesystem permissions; instead we restrict access to either DRM master or capable(CAP_SYS_RESOURCE). v4: - Fix checkpatch warnings (Intel CI) Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_cgroup.c | 140 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.c | 8 +++ drivers/gpu/drm/i915/i915_drv.h | 32 +++++++++ include/uapi/drm/i915_drm.h | 12 ++++ 5 files changed, 193 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_cgroup.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 552e43e9663f..26031185cf0e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -48,6 +48,7 @@ i915-y := i915_drv.o \ i915-$(CONFIG_COMPAT) += i915_ioc32.o i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o +i915-$(CONFIG_CGROUPS) += i915_cgroup.o # GEM code i915-y += i915_cmd_parser.o \ diff --git a/drivers/gpu/drm/i915/i915_cgroup.c b/drivers/gpu/drm/i915/i915_cgroup.c new file mode 100644 index 000000000000..efe76c2a8915 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_cgroup.c @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: MIT */ +/* + * i915_cgroup.c - Linux cgroups integration for i915 + * + * Copyright (C) 2018 Intel Corporation + */ + +#include + +#include "i915_drv.h" + +struct i915_cgroup_data { + struct kref ref; +}; + +static inline struct i915_cgroup_data * +cgrp_ref_to_i915(struct kref *ref) +{ + return container_of(ref, struct i915_cgroup_data, ref); +} + +static void +i915_cgroup_free(struct kref *ref) +{ + struct i915_cgroup_data *priv; + + priv = cgrp_ref_to_i915(ref); + kfree(priv); +} + +int +i915_cgroup_init(struct drm_i915_private *dev_priv) +{ + int ret = 0; + + dev_priv->cgroup_priv_key = cgroup_priv_getkey(i915_cgroup_free); + if (dev_priv->cgroup_priv_key < 0) { + DRM_DEBUG_DRIVER("Failed to get a cgroup private data key\n"); + ret = dev_priv->cgroup_priv_key; + } + + mutex_init(&dev_priv->cgroup_lock); + + return ret; +} + +void +i915_cgroup_shutdown(struct drm_i915_private *dev_priv) +{ + cgroup_priv_destroykey(dev_priv->cgroup_priv_key); +} + +/* + * Return i915 cgroup private data, creating and registering it if one doesn't + * already exist for this cgroup. + */ +__maybe_unused +static struct i915_cgroup_data * +get_or_create_cgroup_data(struct drm_i915_private *dev_priv, + struct cgroup *cgrp) +{ + struct kref *ref; + struct i915_cgroup_data *priv; + + mutex_lock(&dev_priv->cgroup_lock); + + ref = cgroup_priv_get(cgrp, dev_priv->cgroup_priv_key); + if (ref) { + priv = cgrp_ref_to_i915(ref); + } else { + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + priv = ERR_PTR(-ENOMEM); + goto out; + } + + kref_init(&priv->ref); + cgroup_priv_install(cgrp, dev_priv->cgroup_priv_key, + &priv->ref); + } + +out: + mutex_unlock(&dev_priv->cgroup_lock); + + return priv; +} + +/** + * i915_cgroup_setparam_ioctl - ioctl to alter i915 settings for a cgroup + * @dev: DRM device + * @data: data pointer for the ioctl + * @file_priv: DRM file handle for the ioctl call + * + * Allows i915-specific parameters to be set for a Linux cgroup. + */ +int +i915_cgroup_setparam_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) +{ + struct drm_i915_cgroup_param *req = data; + struct cgroup *cgrp; + int ret; + + /* We don't actually support any flags yet. */ + if (req->flags) { + DRM_DEBUG_DRIVER("Invalid flags\n"); + return -EINVAL; + } + + /* + * Make sure the file descriptor really is a cgroup fd and is on the + * v2 hierarchy. + */ + cgrp = cgroup_get_from_fd(req->cgroup_fd); + if (IS_ERR(cgrp)) { + DRM_DEBUG_DRIVER("Invalid cgroup file descriptor\n"); + return PTR_ERR(cgrp); + } + + /* + * Access control: For now we grant access via CAP_SYS_RESOURCE _or_ + * DRM master status. + */ + if (!capable(CAP_SYS_RESOURCE) && !drm_is_current_master(file)) { + DRM_DEBUG_DRIVER("Insufficient permissions to adjust i915 cgroup settings\n"); + goto out; + } + + switch (req->param) { + default: + DRM_DEBUG_DRIVER("Invalid cgroup parameter %lld\n", req->param); + ret = -EINVAL; + } + +out: + cgroup_put(cgrp); + + return ret; +} diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a7d3275f45d2..ad10fb2a2907 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1407,6 +1407,10 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_put(dev_priv); + ret = i915_cgroup_init(dev_priv); + if (ret < 0) + goto out_cleanup_hw; + i915_welcome_messages(dev_priv); return 0; @@ -1433,6 +1437,8 @@ void i915_driver_unload(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; + i915_cgroup_shutdown(dev_priv); + i915_driver_unregister(dev_priv); if (i915_gem_suspend(dev_priv)) @@ -2833,6 +2839,8 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_CGROUP_SETPARAM, i915_cgroup_setparam_ioctl, + DRM_UNLOCKED | DRM_RENDER_ALLOW), }; static struct drm_driver driver = { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2d7a89fcc0dc..ed365fae1073 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1738,6 +1738,15 @@ struct drm_i915_private { struct intel_ppat ppat; + /* cgroup private data */ + int cgroup_priv_key; + + /* + * protects against concurrent attempts to create private data for a + * cgroup + */ + struct mutex cgroup_lock; + /* Kernel Modesetting */ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; @@ -2678,6 +2687,29 @@ intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *dev_priv) int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, int enable_ppgtt); +/* i915_cgroup.c */ +#ifdef CONFIG_CGROUPS +int i915_cgroup_init(struct drm_i915_private *dev_priv); +int i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file); +void i915_cgroup_shutdown(struct drm_i915_private *dev_priv); +#else +static inline int +i915_cgroup_init(struct drm_i915_private *dev_priv) +{ + return 0; +} + +static inline void i915_cgroup_shutdown(struct drm_i915_private *dev_priv) {} + +static inline int +i915_cgroup_setparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + return -EINVAL; +} +#endif + /* i915_drv.c */ void __printf(3, 4) __i915_printk(struct drm_i915_private *dev_priv, const char *level, diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 7f5634ce8e88..735128fa61de 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -319,6 +319,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_PERF_ADD_CONFIG 0x37 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 #define DRM_I915_QUERY 0x39 +#define DRM_I915_CGROUP_SETPARAM 0x3a #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) @@ -377,6 +378,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config) #define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64) #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) +#define DRM_IOCTL_I915_CGROUP_SETPARAM DRM_IOW(DRM_COMMAND_BASE + DRM_I915_CGROUP_SETPARAM, struct drm_i915_cgroup_param) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -1717,6 +1719,16 @@ struct drm_i915_query_topology_info { __u8 data[]; }; +/** + * Structure to set i915 parameter on a cgroup. + */ +struct drm_i915_cgroup_param { + __s32 cgroup_fd; + __u32 flags; + __u64 param; + __s64 value; +}; + #if defined(__cplusplus) } #endif