From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4BCC0C6FD1C for ; Tue, 14 Mar 2023 14:19:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230190AbjCNOTn (ORCPT ); Tue, 14 Mar 2023 10:19:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229946AbjCNOTb (ORCPT ); Tue, 14 Mar 2023 10:19:31 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F13F022DC7; Tue, 14 Mar 2023 07:19:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803562; x=1710339562; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=jDLp2/3Yl14dmLvreY8sfPyvQKizzKWroDIsTYa9bwY=; b=jFij9oumtXklZlImqaBqqiCEja5l8Fu07CW54NTNZ9yX/4FcHO3ysF1d ve+U/BvkfR0czm6/9CDduSG3FH68eFMinjREjCB0D1AbxWsddnFXBD4ys M6qiwBpr6wqajqJBVA1XCyOxv3jgfiC/y7A5t81oYHHRUw+u5622spcpk VIAsfSy1sl6Ly8eD5IA89n7H+RdAyGHLWw9hTsWn5UoVpBCUvGn9iMlSv RvQCfQJtfg+0Gnjb9eg8z1PopdafZ1r+tR0BW6bmZnR8jzo5FZ1c19nnD fj78gCdnPpFB4mKvzMpRCW0mifHjXg8Sfu2D5oGzqj/QPHZ5Vxxl7SocP g==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284650" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284650" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363203" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363203" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:16 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin , Zack Rusin , linux-graphics-maintainer@vmware.com, Alex Deucher Subject: [RFC 01/10] drm: Track clients by tgid and not tid Date: Tue, 14 Mar 2023 14:18:55 +0000 Message-Id: <20230314141904.1210824-2-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin Thread group id (aka pid from userspace point of view) is a more interesting thing to show as an owner of a DRM fd, so track and show that instead of the thread id. In the next patch we will make the owner updated post file descriptor handover, which will also be tgid based to avoid ping-pong when multiple threads access the fd. Signed-off-by: Tvrtko Ursulin Cc: Zack Rusin Cc: linux-graphics-maintainer@vmware.com Cc: Alex Deucher Cc: "Christian K=C3=B6nig" Reviewed-by: Zack Rusin Reviewed-by: Christian K=C3=B6nig --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/drm_debugfs.c | 4 ++-- drivers/gpu/drm/drm_file.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_gem.c index d8e683688daa..863cb668e000 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -969,7 +969,7 @@ static int amdgpu_debugfs_gem_info_show(struct seq_file= *m, void *unused) * Therefore, we need to protect this ->comm access using RCU. */ rcu_read_lock(); - task =3D pid_task(file->pid, PIDTYPE_PID); + task =3D pid_task(file->pid, PIDTYPE_TGID); seq_printf(m, "pid %8d command %s:\n", pid_nr(file->pid), task ? task->comm : ""); rcu_read_unlock(); diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 4f643a490dc3..4855230ba2c6 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -80,7 +80,7 @@ static int drm_clients_info(struct seq_file *m, void *dat= a) seq_printf(m, "%20s %5s %3s master a %5s %10s\n", "command", - "pid", + "tgid", "dev", "uid", "magic"); @@ -94,7 +94,7 @@ static int drm_clients_info(struct seq_file *m, void *dat= a) bool is_current_master =3D drm_is_current_master(priv); =20 rcu_read_lock(); /* locks pid_task()->comm */ - task =3D pid_task(priv->pid, PIDTYPE_PID); + task =3D pid_task(priv->pid, PIDTYPE_TGID); uid =3D task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", task ? task->comm : "", diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index a51ff8cee049..c1018c470047 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -156,7 +156,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) if (!file) return ERR_PTR(-ENOMEM); =20 - file->pid =3D get_pid(task_pid(current)); + file->pid =3D get_pid(task_tgid(current)); file->minor =3D minor; =20 /* for compatibility root is always authenticated */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/v= mwgfx_gem.c index d6baf73a6458..c0da89e16e6f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -241,7 +241,7 @@ static int vmw_debugfs_gem_info_show(struct seq_file *m= , void *unused) * Therefore, we need to protect this ->comm access using RCU. */ rcu_read_lock(); - task =3D pid_task(file->pid, PIDTYPE_PID); + task =3D pid_task(file->pid, PIDTYPE_TGID); seq_printf(m, "pid %8d command %s:\n", pid_nr(file->pid), task ? task->comm : ""); rcu_read_unlock(); --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 46A36C6FD1D for ; Tue, 14 Mar 2023 14:20:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230031AbjCNOUW (ORCPT ); Tue, 14 Mar 2023 10:20:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230152AbjCNOTn (ORCPT ); Tue, 14 Mar 2023 10:19:43 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 76F5016337; Tue, 14 Mar 2023 07:19:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803566; x=1710339566; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1SxLjl6qhTMi8K6jcf0bH0P37z8ztwqynXPKYwnqmlg=; b=IN0rU4kHKRotaLYli9ew55SpzUI5sdkNvl5HbOs2cAPX4Da5owIWN8Z1 zBWUN6CoNz0SkF899cIKKR7SCjIqjXyECKUObwZHSZpe5M258Za8WFUZR XWCBUbK9OqdxFzbb5ASQ6JqB6hvq6DxECytu1qeGh84eSoZqL9cprh9up dSYulOKUEG8FnUU21XSia8syz4MntzDCH+z23Qz9VVwAUoMP/zy0Rp1Kl fyqbkkngw2giJ6Sx0h+8Ex4uZ/YVcYWxarmJns7CJUjgREuoTQhdCB/D2 3ZsAWx1XdeDGccGA3QKHu4rkP515v2HadlCSQIAQOaQS/SRdmQprZSNAY g==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284682" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284682" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:25 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363215" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363215" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:21 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin , Daniel Vetter Subject: [RFC 02/10] drm: Update file owner during use Date: Tue, 14 Mar 2023 14:18:56 +0000 Message-Id: <20230314141904.1210824-3-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin With the typical model where the display server opends the file descriptor and then hands it over to the client we were showing stale data in debugfs. Fix it by updating the drm_file->pid on ioctl access from a different process. The field is also made RCU protected to allow for lockless readers. Update side is protected with dev->filelist_mutex. Before: $ cat /sys/kernel/debug/dri/0/clients command pid dev master a uid magic Xorg 2344 0 y y 0 0 Xorg 2344 0 n y 0 2 Xorg 2344 0 n y 0 3 Xorg 2344 0 n y 0 4 After: $ cat /sys/kernel/debug/dri/0/clients command tgid dev master a uid magic Xorg 830 0 y y 0 0 xfce4-session 880 0 n y 0 1 xfwm4 943 0 n y 0 2 neverball 1095 0 n y 0 3 Signed-off-by: Tvrtko Ursulin Cc: "Christian K=C3=B6nig" Cc: Daniel Vetter Reviewed-by: Emil Velikov --- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 6 ++-- drivers/gpu/drm/drm_auth.c | 3 +- drivers/gpu/drm/drm_debugfs.c | 10 ++++--- drivers/gpu/drm/drm_file.c | 40 +++++++++++++++++++++++-- drivers/gpu/drm/drm_ioctl.c | 3 ++ drivers/gpu/drm/nouveau/nouveau_drm.c | 5 +++- drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 6 ++-- include/drm/drm_file.h | 13 ++++++-- 8 files changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_gem.c index 863cb668e000..67ce634992f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -960,6 +960,7 @@ static int amdgpu_debugfs_gem_info_show(struct seq_file= *m, void *unused) list_for_each_entry(file, &dev->filelist, lhead) { struct task_struct *task; struct drm_gem_object *gobj; + struct pid *pid; int id; =20 /* @@ -969,8 +970,9 @@ static int amdgpu_debugfs_gem_info_show(struct seq_file= *m, void *unused) * Therefore, we need to protect this ->comm access using RCU. */ rcu_read_lock(); - task =3D pid_task(file->pid, PIDTYPE_TGID); - seq_printf(m, "pid %8d command %s:\n", pid_nr(file->pid), + pid =3D rcu_dereference(file->pid); + task =3D pid_task(pid, PIDTYPE_TGID); + seq_printf(m, "pid %8d command %s:\n", pid_nr(pid), task ? task->comm : ""); rcu_read_unlock(); =20 diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index cf92a9ae8034..2ed2585ded37 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -235,7 +235,8 @@ static int drm_new_set_master(struct drm_device *dev, s= truct drm_file *fpriv) static int drm_master_check_perm(struct drm_device *dev, struct drm_file *file_priv) { - if (file_priv->pid =3D=3D task_pid(current) && file_priv->was_master) + if (file_priv->was_master && + rcu_access_pointer(file_priv->pid) =3D=3D task_pid(current)) return 0; =20 if (!capable(CAP_SYS_ADMIN)) diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 4855230ba2c6..b46f5ceb24c6 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -90,15 +90,17 @@ static int drm_clients_info(struct seq_file *m, void *d= ata) */ mutex_lock(&dev->filelist_mutex); list_for_each_entry_reverse(priv, &dev->filelist, lhead) { - struct task_struct *task; bool is_current_master =3D drm_is_current_master(priv); + struct task_struct *task; + struct pid *pid; =20 - rcu_read_lock(); /* locks pid_task()->comm */ - task =3D pid_task(priv->pid, PIDTYPE_TGID); + rcu_read_lock(); /* Locks priv->pid and pid_task()->comm! */ + pid =3D rcu_dereference(priv->pid); + task =3D pid_task(pid, PIDTYPE_TGID); uid =3D task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", task ? task->comm : "", - pid_vnr(priv->pid), + pid_vnr(pid), priv->minor->index, is_current_master ? 'y' : 'n', priv->authenticated ? 'y' : 'n', diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index c1018c470047..f2f8175ece15 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -156,7 +156,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) if (!file) return ERR_PTR(-ENOMEM); =20 - file->pid =3D get_pid(task_tgid(current)); + rcu_assign_pointer(file->pid, get_pid(task_tgid(current))); file->minor =3D minor; =20 /* for compatibility root is always authenticated */ @@ -196,7 +196,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) drm_syncobj_release(file); if (drm_core_check_feature(dev, DRIVER_GEM)) drm_gem_release(dev, file); - put_pid(file->pid); + put_pid(rcu_access_pointer(file->pid)); kfree(file); =20 return ERR_PTR(ret); @@ -287,7 +287,7 @@ void drm_file_free(struct drm_file *file) =20 WARN_ON(!list_empty(&file->event_list)); =20 - put_pid(file->pid); + put_pid(rcu_access_pointer(file->pid)); kfree(file); } =20 @@ -501,6 +501,40 @@ int drm_release(struct inode *inode, struct file *filp) } EXPORT_SYMBOL(drm_release); =20 +void drm_file_update_pid(struct drm_file *filp) +{ + struct drm_device *dev; + struct pid *pid, *old; + + /* + * Master nodes need to keep the original ownership in order for + * drm_master_check_perm to keep working correctly. (See comment in + * drm_auth.c.) + */ + if (filp->was_master) + return; + + pid =3D task_tgid(current); + + /* + * Quick unlocked check since the model is a single handover followed by + * exclusive repeated use. + */ + if (pid =3D=3D rcu_access_pointer(filp->pid)) + return; + + dev =3D filp->minor->dev; + mutex_lock(&dev->filelist_mutex); + old =3D rcu_replace_pointer(filp->pid, pid, 1); + mutex_unlock(&dev->filelist_mutex); + + if (pid !=3D old) { + get_pid(pid); + synchronize_rcu(); + put_pid(old); + } +} + /** * drm_release_noglobal - release method for DRM file * @inode: device inode diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 7c9d66ee917d..305b18d9d7b6 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -775,6 +775,9 @@ long drm_ioctl_kernel(struct file *file, drm_ioctl_t *f= unc, void *kdata, struct drm_device *dev =3D file_priv->minor->dev; int retcode; =20 + /* Update drm_file owner if fd was passed along. */ + drm_file_update_pid(file_priv); + if (drm_dev_is_unplugged(dev)) return -ENODEV; =20 diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouvea= u/nouveau_drm.c index cc7c5b4a05fd..57aeaf7af613 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1095,7 +1095,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_= file *fpriv) } =20 get_task_comm(tmpname, current); - snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); + rcu_read_lock(); + snprintf(name, sizeof(name), "%s[%d]", + tmpname, pid_nr(rcu_dereference(fpriv->pid))); + rcu_read_unlock(); =20 if (!(cli =3D kzalloc(sizeof(*cli), GFP_KERNEL))) { ret =3D -ENOMEM; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/v= mwgfx_gem.c index c0da89e16e6f..a07e5b7e2f2f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -232,6 +232,7 @@ static int vmw_debugfs_gem_info_show(struct seq_file *m= , void *unused) list_for_each_entry(file, &dev->filelist, lhead) { struct task_struct *task; struct drm_gem_object *gobj; + struct pid *pid; int id; =20 /* @@ -241,8 +242,9 @@ static int vmw_debugfs_gem_info_show(struct seq_file *m= , void *unused) * Therefore, we need to protect this ->comm access using RCU. */ rcu_read_lock(); - task =3D pid_task(file->pid, PIDTYPE_TGID); - seq_printf(m, "pid %8d command %s:\n", pid_nr(file->pid), + pid =3D rcu_dereference(file->pid); + task =3D pid_task(pid, PIDTYPE_TGID); + seq_printf(m, "pid %8d command %s:\n", pid_nr(pid), task ? task->comm : ""); rcu_read_unlock(); =20 diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 0d1f853092ab..27d545131d4a 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -255,8 +255,15 @@ struct drm_file { /** @master_lookup_lock: Serializes @master. */ spinlock_t master_lookup_lock; =20 - /** @pid: Process that opened this file. */ - struct pid *pid; + /** + * @pid: Process that is using this file. + * + * Must only be dereferenced under a rcu_read_lock or equivalent. + * + * Updates are guarded with dev->filelist_mutex and reference must be + * dropped after a RCU grace period to accommodate lockless readers. + */ + struct pid __rcu *pid; =20 /** @magic: Authentication magic, see @authenticated. */ drm_magic_t magic; @@ -415,6 +422,8 @@ static inline bool drm_is_accel_client(const struct drm= _file *file_priv) return file_priv->minor->type =3D=3D DRM_MINOR_ACCEL; } =20 +void drm_file_update_pid(struct drm_file *); + int drm_open(struct inode *inode, struct file *filp); int drm_open_helper(struct file *filp, struct drm_minor *minor); ssize_t drm_read(struct file *filp, char __user *buffer, --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D7A86C6FD1C for ; Tue, 14 Mar 2023 14:20:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230152AbjCNOU0 (ORCPT ); Tue, 14 Mar 2023 10:20:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45102 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230043AbjCNOTo (ORCPT ); Tue, 14 Mar 2023 10:19:44 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 67B36A1892; Tue, 14 Mar 2023 07:19:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803570; x=1710339570; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=33+0P00oKCPT59EPr+zGQB3p4qKmhGdsGjDhazkuHW8=; b=LwKf/IbgSxTXkut+aJmrJGKpc8OC2wv83+Gu7i1SNCvFo1yoQSWcgDpN 8Y1/TdmzLbR6mDJ79DUhPm7GLTum4+VaZp3p47ey4LO1gI+lkV0woj7ec bkxdo4j/tuuKIB7Av7VgGA8FU/E/PsoErt4uo1qEMBW6hIEmEnBksLFWe XBL1FbiGj9fFQcbI/hZ++avjXj4ZqDFfT5e2hZf3eC1hhkP/v/brRXr+z bg5pZgWDwAdFsJTXnhAZbNQEO8SfPTkGfhO+PAz4JJbH3VzJ5D3Fm2FcA 9BuSeIbqXq80e2xKqIatLdiVrULsX68mx7zeI8iZ46m/YN/Mxf01MWGav A==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284719" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284719" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363227" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363227" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:25 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 03/10] cgroup: Add the DRM cgroup controller Date: Tue, 14 Mar 2023 14:18:57 +0000 Message-Id: <20230314141904.1210824-4-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin Skeleton controller without any functionality. Signed-off-by: Tvrtko Ursulin --- include/linux/cgroup_drm.h | 9 ++++++ include/linux/cgroup_subsys.h | 4 +++ init/Kconfig | 7 ++++ kernel/cgroup/Makefile | 1 + kernel/cgroup/drm.c | 60 +++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 include/linux/cgroup_drm.h create mode 100644 kernel/cgroup/drm.c diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h new file mode 100644 index 000000000000..8ef66a47619f --- /dev/null +++ b/include/linux/cgroup_drm.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright =C2=A9 2023 Intel Corporation + */ + +#ifndef _CGROUP_DRM_H +#define _CGROUP_DRM_H + +#endif /* _CGROUP_DRM_H */ diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 445235487230..49460494a010 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -65,6 +65,10 @@ SUBSYS(rdma) SUBSYS(misc) #endif =20 +#if IS_ENABLED(CONFIG_CGROUP_DRM) +SUBSYS(drm) +#endif + /* * The following subsystems are not supported on the default hierarchy. */ diff --git a/init/Kconfig b/init/Kconfig index 1fb5f313d18f..1679229143c0 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1093,6 +1093,13 @@ config CGROUP_RDMA Attaching processes with active RDMA resources to the cgroup hierarchy is allowed even if can cross the hierarchy's limit. =20 +config CGROUP_DRM + bool "DRM controller" + help + Provides the DRM subsystem controller. + + ... + config CGROUP_FREEZER bool "Freezer controller" help diff --git a/kernel/cgroup/Makefile b/kernel/cgroup/Makefile index 12f8457ad1f9..849bd2917477 100644 --- a/kernel/cgroup/Makefile +++ b/kernel/cgroup/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_CGROUP_PIDS) +=3D pids.o obj-$(CONFIG_CGROUP_RDMA) +=3D rdma.o obj-$(CONFIG_CPUSETS) +=3D cpuset.o obj-$(CONFIG_CGROUP_MISC) +=3D misc.o +obj-$(CONFIG_CGROUP_DRM) +=3D drm.o obj-$(CONFIG_CGROUP_DEBUG) +=3D debug.o diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c new file mode 100644 index 000000000000..02c8eaa633d3 --- /dev/null +++ b/kernel/cgroup/drm.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright =C2=A9 2023 Intel Corporation + */ + +#include +#include +#include + +struct drm_cgroup_state { + struct cgroup_subsys_state css; +}; + +struct drm_root_cgroup_state { + struct drm_cgroup_state drmcs; +}; + +static struct drm_root_cgroup_state root_drmcs; + +static inline struct drm_cgroup_state * +css_to_drmcs(struct cgroup_subsys_state *css) +{ + return container_of(css, struct drm_cgroup_state, css); +} + +static void drmcs_free(struct cgroup_subsys_state *css) +{ + struct drm_cgroup_state *drmcs =3D css_to_drmcs(css); + + if (drmcs !=3D &root_drmcs.drmcs) + kfree(drmcs); +} + +static struct cgroup_subsys_state * +drmcs_alloc(struct cgroup_subsys_state *parent_css) +{ + struct drm_cgroup_state *drmcs; + + if (!parent_css) { + drmcs =3D &root_drmcs.drmcs; + } else { + drmcs =3D kzalloc(sizeof(*drmcs), GFP_KERNEL); + if (!drmcs) + return ERR_PTR(-ENOMEM); + } + + return &drmcs->css; +} + +struct cftype files[] =3D { + { } /* Zero entry terminates. */ +}; + +struct cgroup_subsys drm_cgrp_subsys =3D { + .css_alloc =3D drmcs_alloc, + .css_free =3D drmcs_free, + .early_init =3D false, + .legacy_cftypes =3D files, + .dfl_cftypes =3D files, +}; --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B26EC74A5B for ; Tue, 14 Mar 2023 14:20:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230280AbjCNOU3 (ORCPT ); Tue, 14 Mar 2023 10:20:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45332 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230510AbjCNOTy (ORCPT ); Tue, 14 Mar 2023 10:19:54 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 865F6BDCE; Tue, 14 Mar 2023 07:19:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803579; x=1710339579; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=raKUxSv4ojFNFa7oNu8geuj7x2x6g9Q1/OIQOduxzss=; b=lJZRhVbSWbUp74XRygoicxcDUULcrQA3Hvzs9aqWjWX5iiRvNnmVishw wv6IGpY2wFPIRyTUiSfCYNAf9VpsyTQ7ObYqcyIG5+76kfxJUdnhNcD2B aaI9tBFWigluoks0M3oDORJO/VYNqLOukbUw3N3O7d8J+2OI/XQe9fiGV 8aO7o/Jn6oNj5o3iyRFuuVz6wGUp2U8txcu38xiqw0olxc0qeyp31xzcP 4G3aJYiI68wPTHhk0BOz+NXfXfIDgpxAWyjZ4KufYH2UJS2Gd1my5gLFM ylVtGr87emT59lENRxvnuFWIucgfAlD+Bopo8cQnfd9wkLCybHYcEsA+h w==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284751" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284751" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363242" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363242" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:29 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 04/10] drm/cgroup: Track DRM clients per cgroup Date: Tue, 14 Mar 2023 14:18:58 +0000 Message-Id: <20230314141904.1210824-5-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tvrtko Ursulin To enable propagation of settings from the cgroup DRM controller to DRM and vice-versa, we need to start tracking to which cgroups DRM clients belong. Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/drm_file.c | 6 ++++ include/drm/drm_file.h | 6 ++++ include/linux/cgroup_drm.h | 20 ++++++++++++ kernel/cgroup/drm.c | 62 +++++++++++++++++++++++++++++++++++++- 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index f2f8175ece15..f6bad820b7ee 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -32,6 +32,7 @@ */ =20 #include +#include #include #include #include @@ -300,6 +301,8 @@ static void drm_close_helper(struct file *filp) list_del(&file_priv->lhead); mutex_unlock(&dev->filelist_mutex); =20 + drmcgroup_client_close(file_priv); + drm_file_free(file_priv); } =20 @@ -363,6 +366,8 @@ int drm_open_helper(struct file *filp, struct drm_minor= *minor) list_add(&priv->lhead, &dev->filelist); mutex_unlock(&dev->filelist_mutex); =20 + drmcgroup_client_open(priv); + #ifdef CONFIG_DRM_LEGACY #ifdef __alpha__ /* @@ -529,6 +534,7 @@ void drm_file_update_pid(struct drm_file *filp) mutex_unlock(&dev->filelist_mutex); =20 if (pid !=3D old) { + drmcgroup_client_migrate(filp); get_pid(pid); synchronize_rcu(); put_pid(old); diff --git a/include/drm/drm_file.h b/include/drm/drm_file.h index 27d545131d4a..e3e0de0a8ec4 100644 --- a/include/drm/drm_file.h +++ b/include/drm/drm_file.h @@ -30,6 +30,7 @@ #ifndef _DRM_FILE_H_ #define _DRM_FILE_H_ =20 +#include #include #include #include @@ -279,6 +280,11 @@ struct drm_file { /** @minor: &struct drm_minor for this file. */ struct drm_minor *minor; =20 +#if IS_ENABLED(CONFIG_CGROUP_DRM) + struct cgroup_subsys_state *__css; + struct list_head clink; +#endif + /** * @object_idr: * diff --git a/include/linux/cgroup_drm.h b/include/linux/cgroup_drm.h index 8ef66a47619f..176431842d8e 100644 --- a/include/linux/cgroup_drm.h +++ b/include/linux/cgroup_drm.h @@ -6,4 +6,24 @@ #ifndef _CGROUP_DRM_H #define _CGROUP_DRM_H =20 +#include + +#if IS_ENABLED(CONFIG_CGROUP_DRM) +void drmcgroup_client_open(struct drm_file *file_priv); +void drmcgroup_client_close(struct drm_file *file_priv); +void drmcgroup_client_migrate(struct drm_file *file_priv); +#else +static inline void drmcgroup_client_open(struct drm_file *file_priv) +{ +} + +static inline void drmcgroup_client_close(struct drm_file *file_priv) +{ +} + +static void drmcgroup_client_migrate(struct drm_file *file_priv) +{ +} +#endif + #endif /* _CGROUP_DRM_H */ diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 02c8eaa633d3..d702be1b441f 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -5,17 +5,25 @@ =20 #include #include +#include +#include #include =20 struct drm_cgroup_state { struct cgroup_subsys_state css; + + struct list_head clients; }; =20 struct drm_root_cgroup_state { struct drm_cgroup_state drmcs; }; =20 -static struct drm_root_cgroup_state root_drmcs; +static struct drm_root_cgroup_state root_drmcs =3D { + .drmcs.clients =3D LIST_HEAD_INIT(root_drmcs.drmcs.clients), +}; + +static DEFINE_MUTEX(drmcg_mutex); =20 static inline struct drm_cgroup_state * css_to_drmcs(struct cgroup_subsys_state *css) @@ -42,11 +50,63 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css) drmcs =3D kzalloc(sizeof(*drmcs), GFP_KERNEL); if (!drmcs) return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&drmcs->clients); } =20 return &drmcs->css; } =20 +void drmcgroup_client_open(struct drm_file *file_priv) +{ + struct drm_cgroup_state *drmcs; + + drmcs =3D css_to_drmcs(task_get_css(current, drm_cgrp_id)); + + mutex_lock(&drmcg_mutex); + file_priv->__css =3D &drmcs->css; /* Keeps the reference. */ + list_add_tail(&file_priv->clink, &drmcs->clients); + mutex_unlock(&drmcg_mutex); +} +EXPORT_SYMBOL_GPL(drmcgroup_client_open); + +void drmcgroup_client_close(struct drm_file *file_priv) +{ + struct drm_cgroup_state *drmcs; + + drmcs =3D css_to_drmcs(file_priv->__css); + + mutex_lock(&drmcg_mutex); + list_del(&file_priv->clink); + file_priv->__css =3D NULL; + mutex_unlock(&drmcg_mutex); + + css_put(&drmcs->css); +} +EXPORT_SYMBOL_GPL(drmcgroup_client_close); + +void drmcgroup_client_migrate(struct drm_file *file_priv) +{ + struct drm_cgroup_state *src, *dst; + struct cgroup_subsys_state *old; + + mutex_lock(&drmcg_mutex); + + old =3D file_priv->__css; + src =3D css_to_drmcs(old); + dst =3D css_to_drmcs(task_get_css(current, drm_cgrp_id)); + + if (src !=3D dst) { + file_priv->__css =3D &dst->css; /* Keeps the reference. */ + list_move_tail(&file_priv->clink, &dst->clients); + } + + mutex_unlock(&drmcg_mutex); + + css_put(old); +} +EXPORT_SYMBOL_GPL(drmcgroup_client_migrate); + struct cftype files[] =3D { { } /* Zero entry terminates. */ }; --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04773C6FD1C for ; Tue, 14 Mar 2023 14:20:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230359AbjCNOUc (ORCPT ); Tue, 14 Mar 2023 10:20:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45116 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231175AbjCNOTz (ORCPT ); Tue, 14 Mar 2023 10:19:55 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA91B23137; Tue, 14 Mar 2023 07:19:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803581; x=1710339581; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YOLueewwuDNMLLryD+HA+AYOg+k/XFD1PEr0h2uYLdE=; b=H+/QS/FqWU7eF8AE9qMGRWyqfr1Q7qgHXJyZTD/X+1C9oO2iaVMaT9k0 clmzkEnpLMebKQSyPt/Xbu1E2XVii7HzKmHJJMHpGTyx5YRjYCU9MWvQd kV/I4ZlyFrweIiaMmSN5Zjtf7FiJ36zWRi+bZRQ4octJ1EM6ciZqJ6tUU kPgp0lQq9/OnqK404KkchWZCUz5HlenxgBiEvJgqYZLZ6Pf/vulavITNJ GMdlNTMobNLSl4jk2WSEuVv/Ls1bDNOjRBRwqzNM/HHkrARou4zT+Im0q AczhDSXaMG3QIlgtEYxq1f/6f9kfqW+xoS35+0mf7qMOJWDy1CFfH45Ut w==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284768" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284768" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:37 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363256" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363256" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:33 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 05/10] drm/cgroup: Add ability to query drm cgroup GPU time Date: Tue, 14 Mar 2023 14:18:59 +0000 Message-Id: <20230314141904.1210824-6-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tvrtko Ursulin Add a driver callback and core helper which allow querying the time spent on GPUs for processes belonging to a group. Signed-off-by: Tvrtko Ursulin --- include/drm/drm_drv.h | 28 ++++++++++++++++++++++++++++ kernel/cgroup/drm.c | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 5b86bb7603e7..01953d6b98d6 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -151,6 +151,24 @@ enum drm_driver_feature { DRIVER_HAVE_IRQ =3D BIT(30), }; =20 +/** + * struct drm_cgroup_ops + * + * This structure contains a number of callbacks that drivers can provide = if + * they are able to support one or more of the functionalities implemented= by + * the DRM cgroup controller. + */ +struct drm_cgroup_ops { + /** + * @active_time_us: + * + * Optional callback for reporting the GPU time consumed by this client. + * + * Used by the DRM core when queried by the DRM cgroup controller. + */ + u64 (*active_time_us) (struct drm_file *); +}; + /** * struct drm_driver - DRM driver structure * @@ -443,6 +461,16 @@ struct drm_driver { */ const struct file_operations *fops; =20 +#ifdef CONFIG_CGROUP_DRM + /** + * @cg_ops: + * + * Optional pointer to driver callbacks facilitating integration with + * the DRM cgroup controller. + */ + const struct drm_cgroup_ops *cg_ops; +#endif + #ifdef CONFIG_DRM_LEGACY /* Everything below here is for legacy driver, never use! */ /* private: */ diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index d702be1b441f..acdb76635b60 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -9,6 +9,8 @@ #include #include =20 +#include + struct drm_cgroup_state { struct cgroup_subsys_state css; =20 @@ -31,6 +33,24 @@ css_to_drmcs(struct cgroup_subsys_state *css) return container_of(css, struct drm_cgroup_state, css); } =20 +static u64 drmcs_get_active_time_us(struct drm_cgroup_state *drmcs) +{ + struct drm_file *fpriv; + u64 total =3D 0; + + lockdep_assert_held(&drmcg_mutex); + + list_for_each_entry(fpriv, &drmcs->clients, clink) { + const struct drm_cgroup_ops *cg_ops =3D + fpriv->minor->dev->driver->cg_ops; + + if (cg_ops && cg_ops->active_time_us) + total +=3D cg_ops->active_time_us(fpriv); + } + + return total; +} + static void drmcs_free(struct cgroup_subsys_state *css) { struct drm_cgroup_state *drmcs =3D css_to_drmcs(css); --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05AFAC6FD1C for ; Tue, 14 Mar 2023 14:20:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230493AbjCNOUf (ORCPT ); Tue, 14 Mar 2023 10:20:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44490 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231370AbjCNOUE (ORCPT ); Tue, 14 Mar 2023 10:20:04 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE0DFA6746; Tue, 14 Mar 2023 07:19:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803585; x=1710339585; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Q3d9NzbFoh1gANUnCkXfWtCqiIz1wYgVTln49cPWTPw=; b=jOGhGv+CY4mQtTuf9A7xfgkU8AAnpQz/FZZDdNTlOMJ5k2/V5NyqfAMU 5QOzESZ4vx/scn7upeyDnDjvnYFXFm+Tsat4knUCmKyUH3/UVY/6/GCcD fNsdUZO2HpYW3Tq+tzuijrqDn3ezQe7PubTUEqGcqcbe7kWfbYr9vnWaV 6eYESsjKyeqAp55r6tjUP6DyvoqNyV5pf+OJJUThw7/vRUBsCCXZDYh9/ SnmQjFrOC2ikhpcfipxgeh4k2OP18HSRoAhxxcykvFCNF94qiV8m3KU81 QJcryanuZ7vTalT+ZRZS2Khp3JCA8SJypeEtc1Lts/59OBkOzZtg9/Bbl Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284829" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284829" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363275" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363275" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:37 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 06/10] drm/cgroup: Add over budget signalling callback Date: Tue, 14 Mar 2023 14:19:00 +0000 Message-Id: <20230314141904.1210824-7-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tvrtko Ursulin Add a new callback via which the drm cgroup controller is notifying the drm core that a certain process is above its allotted GPU time. Signed-off-by: Tvrtko Ursulin --- include/drm/drm_drv.h | 8 ++++++++ kernel/cgroup/drm.c | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 01953d6b98d6..d8386b64eab5 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -167,6 +167,14 @@ struct drm_cgroup_ops { * Used by the DRM core when queried by the DRM cgroup controller. */ u64 (*active_time_us) (struct drm_file *); + + /** + * @signal_budget: + * + * Optional callback used by the DRM core to forward over/under GPU time + * messages sent by the DRM cgroup controller. + */ + int (*signal_budget) (struct drm_file *, u64 used, u64 budget); }; =20 /** diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index acdb76635b60..68f31797c4f0 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -51,6 +51,22 @@ static u64 drmcs_get_active_time_us(struct drm_cgroup_st= ate *drmcs) return total; } =20 +static void +drmcs_signal_budget(struct drm_cgroup_state *drmcs, u64 usage, u64 budget) +{ + struct drm_file *fpriv; + + lockdep_assert_held(&drmcg_mutex); + + list_for_each_entry(fpriv, &drmcs->clients, clink) { + const struct drm_cgroup_ops *cg_ops =3D + fpriv->minor->dev->driver->cg_ops; + + if (cg_ops && cg_ops->signal_budget) + cg_ops->signal_budget(fpriv, usage, budget); + } +} + static void drmcs_free(struct cgroup_subsys_state *css) { struct drm_cgroup_state *drmcs =3D css_to_drmcs(css); --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1814C74A5B for ; Tue, 14 Mar 2023 14:20:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231145AbjCNOUj (ORCPT ); Tue, 14 Mar 2023 10:20:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46530 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231695AbjCNOUS (ORCPT ); Tue, 14 Mar 2023 10:20:18 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6FEBB53721; Tue, 14 Mar 2023 07:19:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803595; x=1710339595; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=cSI6Q6EbGTpwkXN6+Xoa9wbEHqsQK4X+xOn9dT9cmLs=; b=RJZgE8fJ6adhFntv3Z5ImfYt2WRiEPkaPdojM6fnMn/nEv0t0/hxYPvp FIL7EvAMujkt15iFDsKWz9MY3vaIxLdhxvsNb/pd9u1b1Mf5z1qwsJaXW wzAhbbTNCRXqAeFZGjAa8SewnHJHMzafSD0wcCkubxgtANuWvdhS9reAo 8XmEbitEP4ynT4FD8SXiY4xaoNil9VIwekk/CMnPLBhlh6IEB6vQhpsAQ RK7sWjWrj1a5vNaJovkXAAC0KrR5cHtHluEw3IMvJwz6dnlUQPUZy1irD MScB7VLBsEORDhuHZYXu5p+T1A2vAxHJJEEi7hrz5jza+P/Cod58/mP+P w==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284861" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284861" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:45 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363286" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363286" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:41 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 07/10] drm/cgroup: Only track clients which are providing drm_cgroup_ops Date: Tue, 14 Mar 2023 14:19:01 +0000 Message-Id: <20230314141904.1210824-8-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tvrtko Ursulin To reduce the number of tracking going on, especially with drivers which will not support any sort of control from the drm cgroup controller side, lets express the funcionality as opt-in and use the presence of drm_cgroup_ops as activation criteria. Signed-off-by: Tvrtko Ursulin --- kernel/cgroup/drm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 68f31797c4f0..60e1f3861576 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -97,6 +97,9 @@ void drmcgroup_client_open(struct drm_file *file_priv) { struct drm_cgroup_state *drmcs; =20 + if (!file_priv->minor->dev->driver->cg_ops) + return; + drmcs =3D css_to_drmcs(task_get_css(current, drm_cgrp_id)); =20 mutex_lock(&drmcg_mutex); @@ -112,6 +115,9 @@ void drmcgroup_client_close(struct drm_file *file_priv) =20 drmcs =3D css_to_drmcs(file_priv->__css); =20 + if (!file_priv->minor->dev->driver->cg_ops) + return; + mutex_lock(&drmcg_mutex); list_del(&file_priv->clink); file_priv->__css =3D NULL; @@ -126,6 +132,9 @@ void drmcgroup_client_migrate(struct drm_file *file_pri= v) struct drm_cgroup_state *src, *dst; struct cgroup_subsys_state *old; =20 + if (!file_priv->minor->dev->driver->cg_ops) + return; + mutex_lock(&drmcg_mutex); =20 old =3D file_priv->__css; --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A287C6FD1C for ; Tue, 14 Mar 2023 14:20:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231245AbjCNOUl (ORCPT ); Tue, 14 Mar 2023 10:20:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229730AbjCNOUV (ORCPT ); Tue, 14 Mar 2023 10:20:21 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F84B3D936; Tue, 14 Mar 2023 07:19:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803596; x=1710339596; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Lz4KHqLFh7pnuonBnFmsRzri9N472KLS0VZ+xVXNm7w=; b=k++CDjktbzYrt6JsGkC+eqTUhFsKTSFgIj1P6l3OnyB5c/6kwHXU/YKI hnYQrbQoPL1AeA8w24q8KthGJgW6SHSZZNzm28WCs6rrRU+V1NXOs/OzU MBcJuqiPHHESm6uCCgAmZWBNWLjGr+m30TJq1jxnYPxrdwzfKODqRepz7 uX7OqIpSe/C9bHHCAYQVqWbIjuzEbucrZHc/BhFxwJ2XDZZfNFAMfrD9g 2p0cCcLzTPVml4anX6Iud856AOgPK+pLnvjF1sP4+sHkG8DuJcDIo8onF ODOJtpeW96eESftgwyfJgZn3vgTUw7w5sbzWSyu0VZm/Z1lqIz54rtmHD w==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284901" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284901" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363297" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363297" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:46 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin , =?UTF-8?q?Michal=20Koutn=C3=BD?= Subject: [RFC 08/10] cgroup/drm: Introduce weight based drm cgroup control Date: Tue, 14 Mar 2023 14:19:02 +0000 Message-Id: <20230314141904.1210824-9-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin Similar to CPU scheduling, implement a concept of weight in the drm cgroup controller. Uses the same range and default as the CPU controller - CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_DFL and CGROUP_WEIGHT_MAX. Later each cgroup is assigned a time budget proportionaly based on the relative weights of it's siblings. This time budget is in turn split by the group's children and so on. This will be used to implement a soft, or best effort signal from drm cgroup to drm core notifying about groups which are over their allotted budget. No guarantees that the limit can be enforced are provided or implied. Checking of GPU usage is done periodically by the controller which can be configured via drmcg_period_ms kernel boot parameter and which defaults to 2s. Signed-off-by: Tvrtko Ursulin Cc: Michal Koutn=C3=BD Cc: Tejun Heo --- Documentation/admin-guide/cgroup-v2.rst | 31 ++ kernel/cgroup/drm.c | 409 +++++++++++++++++++++++- 2 files changed, 437 insertions(+), 3 deletions(-) diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-= guide/cgroup-v2.rst index f67c0829350b..8906fdf5c8d6 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst @@ -2407,6 +2407,37 @@ HugeTLB Interface Files hugetlb pages of in this cgroup. Only active in use hugetlb pages are included. The per-node values are in bytes. =20 +DRM +--- + +The DRM controller allows configuring scheduling soft limits. + +DRM scheduling soft limits +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Because of the heterogenous hardware and driver DRM capabilities, soft lim= its +are implemented as a loose co-operative (bi-directional) interface between= the +controller and DRM core. + +The controller configures the GPU time allowed per group and periodically = scans +the belonging tasks to detect the over budget condition, at which point it +invokes a callback notifying the DRM core of the condition. + +DRM core provides an API to query per process GPU utilization and 2nd API = to +receive notification from the cgroup controller when the group enters or e= xits +the over budget condition. + +Individual DRM drivers which implement the interface are expected to act o= n this +in the best-effort manner only. There are no guarantees that the soft limi= ts +will be respected. + +DRM scheduling soft limits interface files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + drm.weight + Standard cgroup weight based control [1, 10000] used to configure the + relative distributing of GPU time between the sibling groups. + Misc ---- =20 diff --git a/kernel/cgroup/drm.c b/kernel/cgroup/drm.c index 60e1f3861576..b244e3d828cc 100644 --- a/kernel/cgroup/drm.c +++ b/kernel/cgroup/drm.c @@ -6,7 +6,9 @@ #include #include #include +#include #include +#include #include =20 #include @@ -15,10 +17,28 @@ struct drm_cgroup_state { struct cgroup_subsys_state css; =20 struct list_head clients; + + unsigned int weight; + + unsigned int sum_children_weights; + + bool over; + bool over_budget; + + u64 per_s_budget_us; + u64 prev_active_us; + u64 active_us; }; =20 struct drm_root_cgroup_state { struct drm_cgroup_state drmcs; + + unsigned int period_us; + + unsigned int last_scan_duration_us; + ktime_t prev_timestamp; + + struct delayed_work scan_work; }; =20 static struct drm_root_cgroup_state root_drmcs =3D { @@ -27,6 +47,9 @@ static struct drm_root_cgroup_state root_drmcs =3D { =20 static DEFINE_MUTEX(drmcg_mutex); =20 +static int drmcg_period_ms =3D 2000; +module_param(drmcg_period_ms, int, 0644); + static inline struct drm_cgroup_state * css_to_drmcs(struct cgroup_subsys_state *css) { @@ -67,12 +90,263 @@ drmcs_signal_budget(struct drm_cgroup_state *drmcs, u6= 4 usage, u64 budget) } } =20 -static void drmcs_free(struct cgroup_subsys_state *css) +static u64 +drmcs_read_weight(struct cgroup_subsys_state *css, struct cftype *cft) +{ + struct drm_cgroup_state *drmcs =3D css_to_drmcs(css); + + return drmcs->weight; +} + +static int +drmcs_write_weight(struct cgroup_subsys_state *css, struct cftype *cftype, + u64 weight) { struct drm_cgroup_state *drmcs =3D css_to_drmcs(css); + int ret; + + if (weight < CGROUP_WEIGHT_MIN || weight > CGROUP_WEIGHT_MAX) + return -ERANGE; + + ret =3D mutex_lock_interruptible(&drmcg_mutex); + if (ret) + return ret; + drmcs->weight =3D weight; + mutex_unlock(&drmcg_mutex); + + return 0; +} + +static bool __start_scanning(unsigned int period_us) +{ + struct drm_cgroup_state *root =3D &root_drmcs.drmcs; + struct cgroup_subsys_state *node; + ktime_t start, now; + bool ok =3D false; + + lockdep_assert_held(&drmcg_mutex); + + start =3D ktime_get(); + if (period_us > root_drmcs.last_scan_duration_us) + period_us -=3D root_drmcs.last_scan_duration_us; + + rcu_read_lock(); + + css_for_each_descendant_post(node, &root->css) { + struct drm_cgroup_state *drmcs =3D css_to_drmcs(node); + + if (!css_tryget_online(node)) + goto out; =20 - if (drmcs !=3D &root_drmcs.drmcs) - kfree(drmcs); + drmcs->active_us =3D 0; + drmcs->sum_children_weights =3D 0; + + if (period_us && node =3D=3D &root->css) + drmcs->per_s_budget_us =3D + DIV_ROUND_UP_ULL((u64)period_us * USEC_PER_SEC, + USEC_PER_SEC); + else + drmcs->per_s_budget_us =3D 0; + + css_put(node); + } + + css_for_each_descendant_post(node, &root->css) { + struct drm_cgroup_state *drmcs =3D css_to_drmcs(node); + struct drm_cgroup_state *parent; + u64 active; + + if (!css_tryget_online(node)) + goto out; + if (!node->parent) { + css_put(node); + continue; + } + if (!css_tryget_online(node->parent)) { + css_put(node); + goto out; + } + parent =3D css_to_drmcs(node->parent); + + active =3D drmcs_get_active_time_us(drmcs); + if (period_us && active > drmcs->prev_active_us) + drmcs->active_us +=3D active - drmcs->prev_active_us; + drmcs->prev_active_us =3D active; + + parent->active_us +=3D drmcs->active_us; + parent->sum_children_weights +=3D drmcs->weight; + + css_put(node); + css_put(&parent->css); + } + + ok =3D true; + now =3D ktime_get(); + root_drmcs.last_scan_duration_us =3D ktime_to_us(ktime_sub(now, start)); + root_drmcs.prev_timestamp =3D now; + +out: + rcu_read_unlock(); + + return ok; +} + +static void scan_worker(struct work_struct *work) +{ + struct drm_cgroup_state *root =3D &root_drmcs.drmcs; + struct cgroup_subsys_state *node; + unsigned int period_us; + + mutex_lock(&drmcg_mutex); + + rcu_read_lock(); + + if (WARN_ON_ONCE(!css_tryget_online(&root->css))) { + rcu_read_unlock(); + mutex_unlock(&drmcg_mutex); + return; + } + + period_us =3D ktime_to_us(ktime_sub(ktime_get(), + root_drmcs.prev_timestamp)); + + /* + * 1st pass - reset working values and update hierarchical weights and + * GPU utilisation. + */ + if (!__start_scanning(period_us)) + goto out_retry; /* + * Always come back later if scanner races with + * core cgroup management. (Repeated pattern.) + */ + + css_for_each_descendant_pre(node, &root->css) { + struct drm_cgroup_state *drmcs =3D css_to_drmcs(node); + struct cgroup_subsys_state *css; + u64 reused_us =3D 0, unused_us =3D 0; + unsigned int over_weights =3D 0; + + if (!css_tryget_online(node)) + goto out_retry; + + /* + * 2nd pass - calculate initial budgets, mark over budget + * siblings and add up unused budget for the group. + */ + css_for_each_child(css, &drmcs->css) { + struct drm_cgroup_state *sibling =3D css_to_drmcs(css); + + if (!css_tryget_online(css)) { + css_put(node); + goto out_retry; + } + + sibling->per_s_budget_us =3D + DIV_ROUND_UP_ULL(drmcs->per_s_budget_us * + sibling->weight, + drmcs->sum_children_weights); + + sibling->over =3D sibling->active_us > + sibling->per_s_budget_us; + if (sibling->over) + over_weights +=3D sibling->weight; + else + unused_us +=3D sibling->per_s_budget_us - + sibling->active_us; + + css_put(css); + } + + /* + * 3rd pass - spread unused budget according to relative weights + * of over budget siblings. + */ + while (over_weights && reused_us < unused_us) { + unsigned int under =3D 0; + + unused_us -=3D reused_us; + reused_us =3D 0; + + css_for_each_child(css, &drmcs->css) { + struct drm_cgroup_state *sibling; + u64 extra_us, max_us, need_us; + + if (!css_tryget_online(css)) { + css_put(node); + goto out_retry; + } + + sibling =3D css_to_drmcs(css); + if (!sibling->over) { + css_put(css); + continue; + } + + extra_us =3D DIV_ROUND_UP_ULL(unused_us * + sibling->weight, + over_weights); + max_us =3D sibling->per_s_budget_us + extra_us; + if (max_us > sibling->active_us) + need_us =3D sibling->active_us - + sibling->per_s_budget_us; + else + need_us =3D extra_us; + reused_us +=3D need_us; + sibling->per_s_budget_us +=3D need_us; + sibling->over =3D sibling->active_us > + sibling->per_s_budget_us; + if (!sibling->over) + under +=3D sibling->weight; + + css_put(css); + } + + over_weights -=3D under; + } + + css_put(node); + } + + /* + * 4th pass - send out over/under budget notifications. + */ + css_for_each_descendant_post(node, &root->css) { + struct drm_cgroup_state *drmcs =3D css_to_drmcs(node); + + if (!css_tryget_online(node)) + goto out_retry; + + if (drmcs->over || drmcs->over_budget) + drmcs_signal_budget(drmcs, + drmcs->active_us, + drmcs->per_s_budget_us); + drmcs->over_budget =3D drmcs->over; + + css_put(node); + } + +out_retry: + rcu_read_unlock(); + mutex_unlock(&drmcg_mutex); + + period_us =3D READ_ONCE(root_drmcs.period_us); + if (period_us) + schedule_delayed_work(&root_drmcs.scan_work, + usecs_to_jiffies(period_us)); + + css_put(&root->css); +} + +static void drmcs_free(struct cgroup_subsys_state *css) +{ + if (css !=3D &root_drmcs.drmcs.css) + kfree(css_to_drmcs(css)); +} + +static void record_baseline_utilisation(void) +{ + /* Re-capture baseline group GPU times to avoid downward jumps. */ + WARN_ON_ONCE(!__start_scanning(0)); /* QQQ Retry if it fails? */ } =20 static struct cgroup_subsys_state * @@ -82,6 +356,7 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css) =20 if (!parent_css) { drmcs =3D &root_drmcs.drmcs; + INIT_DELAYED_WORK(&root_drmcs.scan_work, scan_worker); } else { drmcs =3D kzalloc(sizeof(*drmcs), GFP_KERNEL); if (!drmcs) @@ -90,9 +365,124 @@ drmcs_alloc(struct cgroup_subsys_state *parent_css) INIT_LIST_HEAD(&drmcs->clients); } =20 + drmcs->weight =3D CGROUP_WEIGHT_DFL; + return &drmcs->css; } =20 +static int drmcs_online(struct cgroup_subsys_state *css) +{ + if (css =3D=3D &root_drmcs.drmcs.css && drmcg_period_ms) { + mutex_lock(&drmcg_mutex); + record_baseline_utilisation(); + root_drmcs.period_us =3D max(500, drmcg_period_ms) * 1000; + mod_delayed_work(system_wq, + &root_drmcs.scan_work, + usecs_to_jiffies(root_drmcs.period_us)); + mutex_unlock(&drmcg_mutex); + } + + return 0; +} + +static void drmcs_offline(struct cgroup_subsys_state *css) +{ + bool flush =3D false; + + if (css !=3D &root_drmcs.drmcs.css) + return; + + mutex_lock(&drmcg_mutex); + if (root_drmcs.period_us) { + root_drmcs.period_us =3D 0; + cancel_delayed_work(&root_drmcs.scan_work); + flush =3D true; + } + mutex_unlock(&drmcg_mutex); + + if (flush) + flush_delayed_work(&root_drmcs.scan_work); +} + +static struct drm_cgroup_state *old_drmcs; + +static int drmcs_can_attach(struct cgroup_taskset *tset) +{ + struct cgroup_subsys_state *css; + struct task_struct *task; + + /* + * QQQ + * Same passing of state via global as cpuset_can_attach to + * cpuset_attach. Always serialized? + */ + + task =3D cgroup_taskset_first(tset, &css); + old_drmcs =3D css_to_drmcs(task_css(task, drm_cgrp_id)); + + return 0; +} + +static void drmcs_attach(struct cgroup_taskset *tset) +{ + struct drm_cgroup_state *old =3D old_drmcs; + struct cgroup_subsys_state *css; + struct drm_file *fpriv, *next; + struct drm_cgroup_state *new; + struct task_struct *task; + bool migrated =3D false; + + if (!old) + return; + + task =3D cgroup_taskset_first(tset, &css); + new =3D css_to_drmcs(task_css(task, drm_cgrp_id)); + if (new =3D=3D old) + return; + + mutex_lock(&drmcg_mutex); + + list_for_each_entry_safe(fpriv, next, &old->clients, clink) { + cgroup_taskset_for_each(task, css, tset) { + struct cgroup_subsys_state *old_css; + + if (task->flags & PF_KTHREAD) + continue; + if (!thread_group_leader(task)) + continue; + + new =3D css_to_drmcs(task_css(task, drm_cgrp_id)); + if (WARN_ON_ONCE(new =3D=3D old)) + continue; + + if (rcu_access_pointer(fpriv->pid) !=3D task_tgid(task)) + continue; + + if (WARN_ON_ONCE(fpriv->__css !=3D &old->css)) + continue; + + old_css =3D fpriv->__css; + fpriv->__css =3D &new->css; + css_get(fpriv->__css); + list_move_tail(&fpriv->clink, &new->clients); + css_put(old_css); + migrated =3D true; + } + } + + if (migrated) + record_baseline_utilisation(); + + mutex_unlock(&drmcg_mutex); + + old_drmcs =3D NULL; +} + +static void drmcs_cancel_attach(struct cgroup_taskset *tset) +{ + old_drmcs =3D NULL; +} + void drmcgroup_client_open(struct drm_file *file_priv) { struct drm_cgroup_state *drmcs; @@ -121,6 +511,7 @@ void drmcgroup_client_close(struct drm_file *file_priv) mutex_lock(&drmcg_mutex); list_del(&file_priv->clink); file_priv->__css =3D NULL; + record_baseline_utilisation(); mutex_unlock(&drmcg_mutex); =20 css_put(&drmcs->css); @@ -144,6 +535,7 @@ void drmcgroup_client_migrate(struct drm_file *file_pri= v) if (src !=3D dst) { file_priv->__css =3D &dst->css; /* Keeps the reference. */ list_move_tail(&file_priv->clink, &dst->clients); + record_baseline_utilisation(); } =20 mutex_unlock(&drmcg_mutex); @@ -153,12 +545,23 @@ void drmcgroup_client_migrate(struct drm_file *file_p= riv) EXPORT_SYMBOL_GPL(drmcgroup_client_migrate); =20 struct cftype files[] =3D { + { + .name =3D "weight", + .flags =3D CFTYPE_NOT_ON_ROOT, + .read_u64 =3D drmcs_read_weight, + .write_u64 =3D drmcs_write_weight, + }, { } /* Zero entry terminates. */ }; =20 struct cgroup_subsys drm_cgrp_subsys =3D { .css_alloc =3D drmcs_alloc, .css_free =3D drmcs_free, + .css_online =3D drmcs_online, + .css_offline =3D drmcs_offline, + .can_attach =3D drmcs_can_attach, + .attach =3D drmcs_attach, + .cancel_attach =3D drmcs_cancel_attach, .early_init =3D false, .legacy_cftypes =3D files, .dfl_cftypes =3D files, --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 253F2C6FD1D for ; Tue, 14 Mar 2023 14:20:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231335AbjCNOUz (ORCPT ); Tue, 14 Mar 2023 10:20:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47110 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231299AbjCNOUt (ORCPT ); Tue, 14 Mar 2023 10:20:49 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7FF9922DC7; Tue, 14 Mar 2023 07:20:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803605; x=1710339605; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=zyvw01nw5i24yTZdtQNlFxRGIqb6RB7teXa+DHhFniw=; b=LJ+oQ+wESioxWs56yTTdhwVacYRot7rZ2+q6Hp/5GF9jeMlyCugpn7hZ maF8kuqmxWaKQW0rWUy7n15aY2ApyM+HsTjrSMybWZ2m1G8++cAPRGqzq FxRVPkKIxeUkzHXtntErfkjHagDaC9tpZeeAuzdOZ4Uztdr54OAYIouyZ 2GVoItSjxSGreiaTeTw1CTomufLIP8C6dtWtox1eFlQ3alfYq2e3w2mSR fAtN6kLYKxYUFNCLg/EiI+Ms8evDsHrLZJ+a3XIATDKsrFrDkj2iUrpmK kvr3zH6c0YKW/r7seyb7mMLU/cKdgDjQdhVfuiR+qKQ0aGog/djaCXSsg Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284940" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284940" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:54 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363306" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363306" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:50 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 09/10] drm/i915: Wire up with drm controller GPU time query Date: Tue, 14 Mar 2023 14:19:03 +0000 Message-Id: <20230314141904.1210824-10-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Tvrtko Ursulin Implement the drm_cgroup_ops->active_time_us callback. Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/i915_driver.c | 10 ++++ drivers/gpu/drm/i915/i915_drm_client.c | 76 ++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_drm_client.h | 2 + 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915= _driver.c index da249337c23b..e956990a9870 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1777,6 +1777,12 @@ static const struct drm_ioctl_desc i915_ioctls[] =3D= { DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_REN= DER_ALLOW), }; =20 +#ifdef CONFIG_CGROUP_DRM +static const struct drm_cgroup_ops i915_drm_cgroup_ops =3D { + .active_time_us =3D i915_drm_cgroup_get_active_time_us, +}; +#endif + /* * Interface history: * @@ -1805,6 +1811,10 @@ static const struct drm_driver i915_drm_driver =3D { .lastclose =3D i915_driver_lastclose, .postclose =3D i915_driver_postclose, =20 +#ifdef CONFIG_CGROUP_DRM + .cg_ops =3D &i915_drm_cgroup_ops, +#endif + .prime_handle_to_fd =3D drm_gem_prime_handle_to_fd, .prime_fd_to_handle =3D drm_gem_prime_fd_to_handle, .gem_prime_import =3D i915_gem_prime_import, diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/= i915_drm_client.c index b09d1d386574..c9754cb0277f 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.c +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -75,7 +75,7 @@ void i915_drm_clients_fini(struct i915_drm_clients *clien= ts) xa_destroy(&clients->xarray); } =20 -#ifdef CONFIG_PROC_FS +#if defined(CONFIG_PROC_FS) || defined(CONFIG_CGROUP_DRM) static const char * const uabi_class_names[] =3D { [I915_ENGINE_CLASS_RENDER] =3D "render", [I915_ENGINE_CLASS_COPY] =3D "copy", @@ -100,22 +100,78 @@ static u64 busy_add(struct i915_gem_context *ctx, uns= igned int class) return total; } =20 -static void -show_client_class(struct seq_file *m, - struct i915_drm_client *client, - unsigned int class) +static u64 get_class_active_ns(struct i915_drm_client *client, + unsigned int class, + unsigned int *capacity) { - const struct list_head *list =3D &client->ctx_list; - u64 total =3D atomic64_read(&client->past_runtime[class]); - const unsigned int capacity =3D - client->clients->i915->engine_uabi_class_count[class]; struct i915_gem_context *ctx; + u64 total; + + *capacity =3D + client->clients->i915->engine_uabi_class_count[class]; + if (!*capacity) + return 0; + + total =3D atomic64_read(&client->past_runtime[class]); =20 rcu_read_lock(); - list_for_each_entry_rcu(ctx, list, client_link) + list_for_each_entry_rcu(ctx, &client->ctx_list, client_link) total +=3D busy_add(ctx, class); rcu_read_unlock(); =20 + return total; +} +#endif + +#ifdef CONFIG_CGROUP_DRM +static bool supports_stats(struct drm_i915_private *i915) +{ + if (GRAPHICS_VER(i915) < 8) + return false; + + /* temporary... */ + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + return false; + + return true; +} + +u64 i915_drm_cgroup_get_active_time_us(struct drm_file *file) +{ + struct drm_i915_file_private *fpriv =3D file->driver_priv; + struct i915_drm_client *client =3D fpriv->client; + unsigned int i; + u64 busy =3D 0; + + if (!supports_stats(client->clients->i915)) + return 0; + + for (i =3D 0; i < ARRAY_SIZE(uabi_class_names); i++) { + unsigned int capacity; + u64 b; + + b =3D get_class_active_ns(client, i, &capacity); + if (capacity) { + b =3D DIV_ROUND_UP_ULL(b, capacity * 1000); + busy +=3D b; + } + } + + return busy; +} +#endif + +#ifdef CONFIG_PROC_FS +static void +show_client_class(struct seq_file *m, + struct i915_drm_client *client, + unsigned int class) +{ + unsigned int capacity; + u64 total; + + total =3D get_class_active_ns(client, class, &capacity); + if (capacity) seq_printf(m, "drm-engine-%s:\t%llu ns\n", uabi_class_names[class], total); diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/= i915_drm_client.h index 69496af996d9..c8439eaa89be 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.h +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -65,4 +65,6 @@ void i915_drm_client_fdinfo(struct seq_file *m, struct fi= le *f); =20 void i915_drm_clients_fini(struct i915_drm_clients *clients); =20 +u64 i915_drm_cgroup_get_active_time_us(struct drm_file *file); + #endif /* !__I915_DRM_CLIENT_H__ */ --=20 2.37.2 From nobody Wed Feb 11 13:06:11 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BF2EDC6FD1C for ; Tue, 14 Mar 2023 14:21:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229932AbjCNOVH (ORCPT ); Tue, 14 Mar 2023 10:21:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47950 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231470AbjCNOUy (ORCPT ); Tue, 14 Mar 2023 10:20:54 -0400 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCAA59BA71; Tue, 14 Mar 2023 07:20:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1678803618; x=1710339618; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=E6ZuJSeUKadzeCBjA+1GZqfjJV7vLBhQi3Js8kSATYs=; b=N3j/NMjagR6nZTbIr9IdiQl0PVzWfkZRlWNrXufWhZzBYcUH0XmCttz4 tk9Oi6DLaksuxyIzfvFNDDhIinESOeVz8QHg4OpGfh4k0ZAIyStqzO0dT EdhpaBwhcgfq2B/NJSn7b/z2g08Q9GTI8Bx9PIh2UkSdchXxG9hB0rV9C AqkpAYFzWCSxy1yEyGA+fT1Ji+fHZdbkq5R4DDokNNu1c5bvDkjHoxX3R VuNbGujoKr4/FmX598KYD+ulCtA1bhsGjEUvhlhq/uIvctNtVwR0vjR7q XNkfEgFmlqd/Spb4xF6z+WTvzJXa6hAx2ZZpB7SFAT3cs2qMXDuPmqI6T g==; X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="321284971" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="321284971" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:58 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10649"; a="656363309" X-IronPort-AV: E=Sophos;i="5.98,260,1673942400"; d="scan'208";a="656363309" Received: from mjtillin-mobl.ger.corp.intel.com (HELO localhost.localdomain) ([10.213.236.227]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Mar 2023 07:19:54 -0700 From: Tvrtko Ursulin To: Intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Cc: cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Tejun Heo , Johannes Weiner , Zefan Li , Dave Airlie , Daniel Vetter , Rob Clark , =?UTF-8?q?St=C3=A9phane=20Marchesin?= , "T . J . Mercier" , Kenny.Ho@amd.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Brian Welty , Tvrtko Ursulin Subject: [RFC 10/10] drm/i915: Implement cgroup controller over budget throttling Date: Tue, 14 Mar 2023 14:19:04 +0000 Message-Id: <20230314141904.1210824-11-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> References: <20230314141904.1210824-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Tvrtko Ursulin When notified by the drm core we are over our allotted time budget, i915 instance will check if any of the GPU engines it is reponsible for is fully saturated. If it is, and the client in question is using that engine, it will throttle it. For now throttling is done simplistically by lowering the scheduling priority while clients are throttled. Signed-off-by: Tvrtko Ursulin --- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 38 ++++- drivers/gpu/drm/i915/i915_driver.c | 1 + drivers/gpu/drm/i915/i915_drm_client.c | 133 ++++++++++++++++++ drivers/gpu/drm/i915/i915_drm_client.h | 11 ++ 4 files changed, 182 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/d= rm/i915/gem/i915_gem_execbuffer.c index 9dce2957b4e5..25ac3e065d1c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -3065,6 +3065,42 @@ static void retire_requests(struct intel_timeline *t= l, struct i915_request *end) break; } =20 +#ifdef CONFIG_CGROUP_DRM +static unsigned int +__get_class(struct drm_i915_file_private *fpriv, const struct i915_request= *rq) +{ + unsigned int class; + + class =3D rq->context->engine->uabi_class; + + if (WARN_ON_ONCE(class >=3D ARRAY_SIZE(fpriv->client->throttle))) + class =3D 0; + + return class; +} + +static void copy_priority(struct i915_sched_attr *attr, + const struct i915_execbuffer *eb, + const struct i915_request *rq) +{ + struct drm_i915_file_private *file_priv =3D eb->file->driver_priv; + int prio; + + *attr =3D eb->gem_context->sched; + + prio =3D file_priv->client->throttle[__get_class(file_priv, rq)]; + if (prio) + attr->priority =3D prio; +} +#else +static void copy_priority(struct i915_sched_attr *attr, + const struct i915_execbuffer *eb, + const struct i915_request *rq) +{ + *attr =3D eb->gem_context->sched; +} +#endif + static int eb_request_add(struct i915_execbuffer *eb, struct i915_request = *rq, int err, bool last_parallel) { @@ -3081,7 +3117,7 @@ static int eb_request_add(struct i915_execbuffer *eb,= struct i915_request *rq, =20 /* Check that the context wasn't destroyed before submission */ if (likely(!intel_context_is_closed(eb->context))) { - attr =3D eb->gem_context->sched; + copy_priority(&attr, eb, rq); } else { /* Serialise with context_close via the add_to_timeline */ i915_request_set_error_once(rq, -ENOENT); diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915= _driver.c index e956990a9870..ebe1bd45ced1 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -1780,6 +1780,7 @@ static const struct drm_ioctl_desc i915_ioctls[] =3D { #ifdef CONFIG_CGROUP_DRM static const struct drm_cgroup_ops i915_drm_cgroup_ops =3D { .active_time_us =3D i915_drm_cgroup_get_active_time_us, + .signal_budget =3D i915_drm_cgroup_signal_budget, }; #endif =20 diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/= i915_drm_client.c index c9754cb0277f..72d92ee292ae 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.c +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -4,6 +4,7 @@ */ =20 #include +#include #include #include =20 @@ -159,6 +160,138 @@ u64 i915_drm_cgroup_get_active_time_us(struct drm_fil= e *file) =20 return busy; } + +int i915_drm_cgroup_signal_budget(struct drm_file *file, u64 usage, u64 bu= dget) +{ + struct drm_i915_file_private *fpriv =3D file->driver_priv; + u64 class_usage[I915_LAST_UABI_ENGINE_CLASS + 1]; + u64 class_last[I915_LAST_UABI_ENGINE_CLASS + 1]; + struct drm_i915_private *i915 =3D fpriv->dev_priv; + struct i915_drm_client *client =3D fpriv->client; + struct intel_engine_cs *engine; + bool over =3D usage > budget; + struct task_struct *task; + struct pid *pid; + unsigned int i; + ktime_t unused; + int ret =3D 0; + u64 t; + + if (!supports_stats(i915)) + return -EINVAL; + + if (usage =3D=3D 0 && budget =3D=3D 0) + return 0; + + rcu_read_lock(); + pid =3D rcu_dereference(file->pid); + task =3D pid_task(pid, PIDTYPE_TGID); + if (over) { + client->over_budget++; + if (!client->over_budget) + client->over_budget =3D 2; + + drm_dbg(&i915->drm, "%s[%u] over budget (%llu/%llu)\n", + task ? task->comm : "", pid_vnr(pid), + usage, budget); + } else { + client->over_budget =3D 0; + memset(client->class_last, 0, sizeof(client->class_last)); + memset(client->throttle, 0, sizeof(client->throttle)); + + drm_dbg(&i915->drm, "%s[%u] un-throttled; under budget\n", + task ? task->comm : "", pid_vnr(pid)); + + rcu_read_unlock(); + return 0; + } + rcu_read_unlock(); + + memset(class_usage, 0, sizeof(class_usage)); + for_each_uabi_engine(engine, i915) + class_usage[engine->uabi_class] +=3D + ktime_to_ns(intel_engine_get_busy_time(engine, &unused)); + + memcpy(class_last, client->class_last, sizeof(class_last)); + memcpy(client->class_last, class_usage, sizeof(class_last)); + + for (i =3D 0; i < ARRAY_SIZE(uabi_class_names); i++) + class_usage[i] -=3D class_last[i]; + + t =3D client->last; + client->last =3D ktime_get_raw_ns(); + t =3D client->last - t; + + if (client->over_budget =3D=3D 1) + return 0; + + for (i =3D 0; i < ARRAY_SIZE(uabi_class_names); i++) { + u64 client_class_usage[I915_LAST_UABI_ENGINE_CLASS + 1]; + unsigned int capacity, rel_usage; + + if (!i915->engine_uabi_class_count[i]) + continue; + + t =3D DIV_ROUND_UP_ULL(t, 1000); + class_usage[i] =3D DIV_ROUND_CLOSEST_ULL(class_usage[i], 1000); + rel_usage =3D DIV_ROUND_CLOSEST_ULL(class_usage[i] * 100ULL, + t * + i915->engine_uabi_class_count[i]); + if (rel_usage < 95) { + /* Physical class not oversubsribed. */ + if (client->throttle[i]) { + client->throttle[i] =3D 0; + + rcu_read_lock(); + pid =3D rcu_dereference(file->pid); + task =3D pid_task(pid, PIDTYPE_TGID); + drm_dbg(&i915->drm, + "%s[%u] un-throttled; physical class %s utilisation %u%%\n", + task ? task->comm : "", + pid_vnr(pid), + uabi_class_names[i], + rel_usage); + rcu_read_unlock(); + } + continue; + } + + client_class_usage[i] =3D + get_class_active_ns(client, i, &capacity); + if (client_class_usage[i]) { + int permille; + + ret |=3D 1; + + permille =3D DIV_ROUND_CLOSEST_ULL((usage - budget) * + 1000, + budget); + client->throttle[i] =3D + DIV_ROUND_CLOSEST(permille * + I915_CONTEXT_MIN_USER_PRIORITY, + 1000); + if (client->throttle[i] < + I915_CONTEXT_MIN_USER_PRIORITY) + client->throttle[i] =3D + I915_CONTEXT_MIN_USER_PRIORITY; + + rcu_read_lock(); + pid =3D rcu_dereference(file->pid); + task =3D pid_task(pid, PIDTYPE_TGID); + drm_dbg(&i915->drm, + "%s[%u] %d=E2=80=B0 over budget, throttled to priority %d; physical cl= ass %s utilisation %u%%\n", + task ? task->comm : "", + pid_vnr(pid), + permille, + client->throttle[i], + uabi_class_names[i], + rel_usage); + rcu_read_unlock(); + } + } + + return ret; +} #endif =20 #ifdef CONFIG_PROC_FS diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/= i915_drm_client.h index c8439eaa89be..092a7952a67b 100644 --- a/drivers/gpu/drm/i915/i915_drm_client.h +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -15,6 +15,8 @@ =20 #define I915_LAST_UABI_ENGINE_CLASS I915_ENGINE_CLASS_COMPUTE =20 +struct drm_file; + struct drm_i915_private; =20 struct i915_drm_clients { @@ -38,6 +40,13 @@ struct i915_drm_client { * @past_runtime: Accumulation of pphwsp runtimes from closed contexts. */ atomic64_t past_runtime[I915_LAST_UABI_ENGINE_CLASS + 1]; + +#ifdef CONFIG_CGROUP_DRM + int throttle[I915_LAST_UABI_ENGINE_CLASS + 1]; + unsigned int over_budget; + u64 last; + u64 class_last[I915_LAST_UABI_ENGINE_CLASS + 1]; +#endif }; =20 void i915_drm_clients_init(struct i915_drm_clients *clients, @@ -66,5 +75,7 @@ void i915_drm_client_fdinfo(struct seq_file *m, struct fi= le *f); void i915_drm_clients_fini(struct i915_drm_clients *clients); =20 u64 i915_drm_cgroup_get_active_time_us(struct drm_file *file); +int i915_drm_cgroup_signal_budget(struct drm_file *file, + u64 usage, u64 budget); =20 #endif /* !__I915_DRM_CLIENT_H__ */ --=20 2.37.2