From patchwork Tue Mar 6 23:46:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Roper X-Patchwork-Id: 10263135 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 B3E196016D for ; Tue, 6 Mar 2018 23:47:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A5C9428DCC for ; Tue, 6 Mar 2018 23:47:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A40028E46; Tue, 6 Mar 2018 23:47:58 +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 D9F1F28DCC for ; Tue, 6 Mar 2018 23:47:57 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 18D366E3B9; Tue, 6 Mar 2018 23:47:49 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2BDF16E3B9; Tue, 6 Mar 2018 23:47:48 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Mar 2018 15:47:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,433,1515484800"; d="scan'208";a="39764602" Received: from mdroper-desk.fm.intel.com ([10.1.134.220]) by orsmga002.jf.intel.com with ESMTP; 06 Mar 2018 15:47:47 -0800 From: Matt Roper To: dri-devel@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, cgroups@vger.kernel.org Subject: [PATCH v3 4/6] drm/i915: cgroup integration (v2) Date: Tue, 6 Mar 2018 15:46:58 -0800 Message-Id: <20180306234700.6562-5-matthew.d.roper@intel.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180306234700.6562-1-matthew.d.roper@intel.com> References: <20180306234700.6562-1-matthew.d.roper@intel.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" 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 Signed-off-by: Matt Roper --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_cgroup.c | 167 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.c | 5 ++ drivers/gpu/drm/i915/i915_drv.h | 24 ++++++ include/uapi/drm/i915_drm.h | 12 +++ 5 files changed, 209 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 1bd9bc5b8c5c..5974e32834bf 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..4a46cb167f53 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_cgroup.c @@ -0,0 +1,167 @@ +/* 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 cgroup_priv base; + + struct list_head node; +}; + +static inline struct i915_cgroup_data * +cgrp_to_i915(struct cgroup_priv *priv) +{ + return container_of(priv, struct i915_cgroup_data, base); +} + +static void +i915_cgroup_free(struct cgroup_priv *priv) +{ + struct cgroup *cgrp = priv->cgroup; + struct i915_cgroup_data *ipriv; + + WARN_ON(!mutex_is_locked(&cgrp->privdata_mutex)); + + ipriv = cgrp_to_i915(priv); + + /* + * Remove private data from both cgroup's hashtable and i915's list. + * If this function is being called as a result of cgroup removal + * (as opposed to an i915 unload), it will have already been removed from + * the hashtable, but the hash_del() call here is still safe. + */ + hash_del(&priv->hnode); + list_del(&ipriv->node); + + kfree(ipriv); +} + +void +i915_cgroup_init(struct drm_i915_private *dev_priv) +{ + INIT_LIST_HEAD(&dev_priv->cgroup_list); +} + +void +i915_cgroup_shutdown(struct drm_i915_private *dev_priv) +{ + struct i915_cgroup_data *priv, *tmp; + struct cgroup *cgrp; + + mutex_lock(&cgroup_mutex); + + list_for_each_entry_safe(priv, tmp, &dev_priv->cgroup_list, node) { + cgrp = priv->base.cgroup; + + mutex_lock(&cgrp->privdata_mutex); + i915_cgroup_free(&priv->base); + mutex_unlock(&cgrp->privdata_mutex); + } + + mutex_unlock(&cgroup_mutex); +} + +/* + * Return i915 cgroup private data, creating and registering it if one doesn't + * already exist for this cgroup. + */ +static struct i915_cgroup_data * +get_or_create_cgroup_data(struct drm_i915_private *dev_priv, + struct cgroup *cgrp) +{ + struct cgroup_priv *priv; + struct i915_cgroup_data *ipriv; + + mutex_lock(&cgrp->privdata_mutex); + + priv = cgroup_priv_lookup(cgrp, dev_priv); + if (priv) { + ipriv = cgrp_to_i915(priv); + } else { + ipriv = kzalloc(sizeof *ipriv, GFP_KERNEL); + if (!ipriv) { + ipriv = ERR_PTR(-ENOMEM); + goto out; + } + + ipriv->base.key = dev_priv; + ipriv->base.free = i915_cgroup_free; + list_add(&ipriv->node, &dev_priv->cgroup_list); + + cgroup_priv_install(cgrp, &ipriv->base); + } + +out: + mutex_unlock(&cgrp->privdata_mutex); + + return ipriv; +} + +/** + * 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: The strategy for using cgroups in a given + * environment is generally determined by the system integrator + * and/or OS vendor, so the specific policy about who can/can't + * manipulate them tends to be domain-specific (and may vary + * depending on the location in the cgroup hierarchy). Rather than + * trying to tie permission on this ioctl to a DRM-specific concepts + * like DRM master, we'll allow cgroup parameters to be set by any + * process that has been granted write access on the cgroup's + * virtual file system (i.e., the same permissions that would + * generally be needed to update the virtual files provided by + * cgroup controllers). + */ + ret = cgroup_permission(req->cgroup_fd, MAY_WRITE); + if (ret) + 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 d61b51c0bf0b..a1c7bc9cd173 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1405,6 +1405,8 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_put(dev_priv); + i915_cgroup_init(dev_priv); + i915_welcome_messages(dev_priv); return 0; @@ -1431,6 +1433,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)) @@ -2832,6 +2836,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW), 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_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 7eec99d7fad4..7c38142ee009 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2006,6 +2006,9 @@ struct drm_i915_private { struct intel_ppat ppat; + /* cgroup private data */ + struct list_head cgroup_list; + /* Kernel Modesetting */ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; @@ -2938,6 +2941,27 @@ 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 +void 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 29fa48e4755d..b6651b263838 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -318,6 +318,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_PERF_OPEN 0x36 #define DRM_I915_PERF_ADD_CONFIG 0x37 #define DRM_I915_PERF_REMOVE_CONFIG 0x38 +#define DRM_I915_CGROUP_SETPARAM 0x39 #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) @@ -375,6 +376,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param) #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_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. @@ -1615,6 +1617,16 @@ struct drm_i915_perf_oa_config { __u64 flex_regs_ptr; }; +/** + * 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