From nobody Sun Jun 28 05:33:38 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 D92B8C433FE for ; Fri, 11 Feb 2022 16:18:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351272AbiBKQSw (ORCPT ); Fri, 11 Feb 2022 11:18:52 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:46648 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351206AbiBKQSu (ORCPT ); Fri, 11 Feb 2022 11:18:50 -0500 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F5292E6 for ; Fri, 11 Feb 2022 08:18:48 -0800 (PST) Received: by mail-yb1-xb4a.google.com with SMTP id f32-20020a25b0a0000000b0061dad37dcd6so19577819ybj.16 for ; Fri, 11 Feb 2022 08:18:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=kKcjEXjOeEH0mGAkUcoWrOf4L77tAlhRMN7oO+B50iM=; b=T9LUWLemzPZzWYno8+slJF7qkK9H6xZtLOTMdahBN5x+c0VFhJMUx8wFWEMkCbnPAF c49tzOGzV24vKh6ZcteeJfm3K/h9dxxJPqP4MdiFOtfB6ha8vES8N3btoQrzDj99NC6N NThuVzfB1W1O0Kh++ZNdvtrId5jUcr1F28amVcqkRC74pjDyEHpBeQS8e/cQfBjFt7hj X67UvBvdRjeJR8maJKVWPqHkmcP8r4DnFCaYNX+KPCQut2f8zjoSvF0Y11POa8xywdg4 pNi7vTlLa3ElD0YVicbwppcwiTNNz6d3MAEHWfh4tsR1cEwGnXSja5hctDRznDh1fBfM Jfvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=kKcjEXjOeEH0mGAkUcoWrOf4L77tAlhRMN7oO+B50iM=; b=YATva+dFzLWBBvYgggU0evdSCzXHZ/BNLIXF/py4yqRvt3hfR7qnsMRXEAGf/ppZ5u j+s5nRw4vVaHVJ73gZg59CskpHDFzvdtyKsWTXX7D0u2sOE6PUhvyPSXBMcAcmZBJ8sV FhtACTDVPpu6Wa+YmD1VkaxMltZfmwKmW2MeAWzb27OgKU+Dwvzl8lXnMMmKZDWV7DlA AhC1k59IuoU366PHdR3qsDl27lkoSHBTIavfJ3GX9SSq4jj3CHk7doK1zBzYRYTaOJXK C9Is39VuTJ+DT38a9eeJZ5YjXafiRx7cWgGIiQ14uvDYxHDHyIcm7Bu7YlZ59U3NSMC9 1/mA== X-Gm-Message-State: AOAM533gKULoeUjA80L0nRS+Zram7juZ9zMyvIrI8RTs8sptAsFkvkQD JP99mXmkY8xR6NRg0/ZWu1sPkNtOgbMziqA= X-Google-Smtp-Source: ABdhPJycT0YOG160oFos0c32qQdd1BG3KkZireh624cMDeZCi951f8jFV6xjhpQwy90JhdPUdi2Jed9M+wpOVmI= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:a25:8a8a:: with SMTP id h10mr1988762ybl.49.1644596327676; Fri, 11 Feb 2022 08:18:47 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:24 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-2-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 1/6] gpu: rfc: Proposal for a GPU cgroup controller From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This patch adds a proposal for a new GPU cgroup controller for accounting/limiting GPU and GPU-related memory allocations. The proposed controller is based on the DRM cgroup controller[1] and follows the design of the RDMA cgroup controller. The new cgroup controller would: * Allow setting per-cgroup limits on the total size of buffers charged to it. * Allow setting per-device limits on the total size of buffers allocated by device within a cgroup. * Expose a per-device/allocator breakdown of the buffers charged to a cgroup. The prototype in the following patches is only for memory accounting using the GPU cgroup controller and does not implement limit setting. [1]: https://lore.kernel.org/amd-gfx/20210126214626.16260-1-brian.welty@int= el.com/ From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- Documentation/gpu/rfc/gpu-cgroup.rst | 195 +++++++++++++++++++++++++++ Documentation/gpu/rfc/index.rst | 4 + 2 files changed, 199 insertions(+) create mode 100644 Documentation/gpu/rfc/gpu-cgroup.rst diff --git a/Documentation/gpu/rfc/gpu-cgroup.rst b/Documentation/gpu/rfc/g= pu-cgroup.rst new file mode 100644 index 000000000000..0bb761223b97 --- /dev/null +++ b/Documentation/gpu/rfc/gpu-cgroup.rst @@ -0,0 +1,195 @@ +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +GPU cgroup controller +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +Goals +=3D=3D=3D=3D=3D +This document intends to outline a plan to create a cgroup v2 controller s= ubsystem +for the per-cgroup accounting of device and system memory allocated by the= GPU +and related subsystems. + +The new cgroup controller would: + +* Allow setting per-cgroup limits on the total size of buffers charged to = it. + +* Allow setting per-device limits on the total size of buffers allocated b= y a + device/allocator within a cgroup. + +* Expose a per-device/allocator breakdown of the buffers charged to a cgro= up. + +Alternatives Considered +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The following alternatives were considered: + +The memory cgroup controller +____________________________ + +1. As was noted in [1], memory accounting provided by the GPU cgroup +controller is not a good fit for integration into memcg due to the +differences in how accounting is performed. It implements a mechanism +for the allocator attribution of GPU and GPU-related memory by +charging each buffer to the cgroup of the process on behalf of which +the memory was allocated. The buffer stays charged to the cgroup until +it is freed regardless of whether the process retains any references +to it. On the other hand, the memory cgroup controller offers a more +fine-grained charging and uncharging behavior depending on the kind of +page being accounted. + +2. Memcg performs accounting in units of pages. In the DMA-BUF buffer shar= ing model, +a process takes a reference to the entire buffer(hence keeping it alive) e= ven if +it is only accessing parts of it. Therefore, per-page memory tracking for = DMA-BUF +memory accounting would only introduce additional overhead without any ben= efits. + +[1]: https://patchwork.kernel.org/project/dri-devel/cover/20190501140438.9= 506-1-brian.welty@intel.com/#22624705 + +Userspace service to keep track of buffer allocations and releases +__________________________________________________________________ + +1. There is no way for a userspace service to intercept all allocations an= d releases. +2. In case the process gets killed or restarted, we lose all accounting so= far. + +UAPI +=3D=3D=3D=3D +When enabled, the new cgroup controller would create the following files i= n every cgroup. + +:: + + gpu.memory.current (R) + gpu.memory.max (R/W) + +gpu.memory.current is a read-only file and would contain per-device memory= allocations +in a key-value format where key is a string representing the device name +and the value is the size of memory charged to the device in the cgroup in= bytes. + +For example: + +:: + + cat /sys/kernel/fs/cgroup1/gpu.memory.current + dev1 4194304 + dev2 4194304 + +The string key for each device is set by the device driver when the device= registers +with the GPU cgroup controller to participate in resource accounting(see s= ection +'Design and Implementation' for more details). + +gpu.memory.max is a read/write file. It would show the current total +size limits on memory usage for the cgroup and the limits on total memory = usage +for each allocator/device. + +Setting a total limit for a cgroup can be done as follows: + +:: + + echo =E2=80=9Ctotal 41943040=E2=80=9D > /sys/kernel/fs/cgroup1/gpu= .memory.max + +Setting a total limit for a particular device/allocator can be done as fol= lows: + +:: + + echo =E2=80=9Cdev1 4194304=E2=80=9D > /sys/kernel/fs/cgroup1/gpu.= memory.max + +In this example, 'dev1' is the string key set by the device driver during +registration. + +Design and Implementation +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D + +The cgroup controller would closely follow the design of the RDMA cgroup c= ontroller +subsystem where each cgroup maintains a list of resource pools. +Each resource pool contains a struct device and the counter to track curre= nt total, +and the maximum limit set for the device. + +The below code block is a preliminary estimation on how the core kernel da= ta structures +and APIs would look like. + +.. code-block:: c + + /** + * The GPU cgroup controller data structure. + */ + struct gpucg { + struct cgroup_subsys_state css; + + /* list of all resource pools that belong to this cgroup */ + struct list_head rpools; + }; + + struct gpucg_device { + /* + * list of various resource pools in various cgroups that= the device is + * part of. + */ + struct list_head rpools; + + /* list of all devices registered for GPU cgroup accountin= g */ + struct list_head dev_node; + + /* name to be used as identifier for accounting and limit = setting */ + const char *name; + }; + + struct gpucg_resource_pool { + /* The device whose resource usage is tracked by this reso= urce pool */ + struct gpucg_device *device; + + /* list of all resource pools for the cgroup */ + struct list_head cg_node; + + /* + * list maintained by the gpucg_device to keep track of its + * resource pools + */ + struct list_head dev_node; + + /* tracks memory usage of the resource pool */ + struct page_counter total; + }; + + /** + * gpucg_register_device - Registers a device for memory accountin= g using the + * GPU cgroup controller. + * + * @device: The device to register for memory accounting. Must rem= ain valid + * after registration. + * @name: Pointer to a string literal to denote the name of the de= vice. + */ + void gpucg_register_device(struct gpucg_device *gpucg_dev, const c= har *name); + + /** + * gpucg_try_charge - charge memory to the specified gpucg and gpu= cg_device. + * + * @gpucg: The gpu cgroup to charge the memory to. + * @device: The device to charge the memory to. + * @usage: size of memory to charge in bytes. + * + * Return: returns 0 if the charging is successful and otherwise r= eturns an + * error code. + */ + int gpucg_try_charge(struct gpucg *gpucg, struct gpucg_device *dev= ice, u64 usage); + + /** + * gpucg_uncharge - uncharge memory from the specified gpucg and g= pucg_device. + * + * @gpucg: The gpu cgroup to uncharge the memory from. + * @device: The device to charge the memory from. + * @usage: size of memory to uncharge in bytes. + */ + void gpucg_uncharge(struct gpucg *gpucg, struct gpucg_device *devi= ce, u64 usage); + +Future Work +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +Additional GPU resources can be supported by adding new controller files. + +Upstreaming Plan +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +* Decide on a UAPI that accommodates all use-cases for the upstream GPU ec= osystem + as well as for Android. + +* Prototype the GPU cgroup controller and integrate its usage into the DMA= -BUF + system heap. + +* Demonstrate its usage from userspace in the Android Open Space Project. + +* Send out RFCs to LKML for the GPU cgroup controller and iterate. diff --git a/Documentation/gpu/rfc/index.rst b/Documentation/gpu/rfc/index.= rst index 91e93a705230..0a9bcd94e95d 100644 --- a/Documentation/gpu/rfc/index.rst +++ b/Documentation/gpu/rfc/index.rst @@ -23,3 +23,7 @@ host such documentation: .. toctree:: =20 i915_scheduler.rst + +.. toctree:: + + gpu-cgroup.rst --=20 2.35.1.265.g69c8d7142f-goog From nobody Sun Jun 28 05:33:38 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 EC3FEC433EF for ; Fri, 11 Feb 2022 16:18:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243230AbiBKQS7 (ORCPT ); Fri, 11 Feb 2022 11:18:59 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:46832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351377AbiBKQS6 (ORCPT ); Fri, 11 Feb 2022 11:18:58 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EB44C2F3 for ; Fri, 11 Feb 2022 08:18:54 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id a12-20020a056902056c00b0061dc0f2a94aso19722802ybt.6 for ; Fri, 11 Feb 2022 08:18:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Bc1BT8FVz1a5rx9060s9LPPape8rDeYKznWc0mQdTXk=; b=H8A0zu+FuKCo6H4HI7eac6LOZXdEM2EFBzjk/aN6ovipOGCEqFD851Qopn66zFcu9J 8cYm9+vvAfuvZPEztbDMdMrzA6tYRvP6k6HOL3PqTuFaGKOvl81kjDZvVxH/xRYvA9IM n5uRZA4n8QkC9ulGCv2zTSoTuo+dSOj96sJrIANOQFvGaK/A9j7i0N5VKOG9HiMJ9y27 367tMe4FRXDxffQtlVzUCsKW28mb0nn40ye0cAHegwhyzDyyS9N4p1Yn48vKvriERKKC SJGLny8KfhQTI+ebJ46M65eeDIuCLXAqz+JMikwq7dZiENFSbp8GTpvv1silt91IC16T Hz7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Bc1BT8FVz1a5rx9060s9LPPape8rDeYKznWc0mQdTXk=; b=rRywJEuiwq2YLYwc/otV5X9Vn6JAqHFToVBSlYO0o1yaZ1qS/tYvKoADch5titphws kUdPfTOgf5zFn5KRHXtU2jk7AgJzsZFPG8ktqoc+RS02jFw0cNxRIGP9hnw8V8yabfQY vVvft4tamAQIYzrS+qn5FdCzUtK4ANSdMezWwEbYrOEtBFtyv5i/nIMmwsBISizYEXAQ 0Nv5plQts9EskMIq16DfNIqnba8O5woYyCmsmX1HnjbPNEdnUXC/EKKjlQkhQJANtxPd Pd1pcRFE4nOIJoX03eS0WL/aKM5UAZ64Mgq/2t/3Rc/vKQJLktYtYF7tB2RFYkvbMNdD /OfA== X-Gm-Message-State: AOAM532puCX+rhLp5zoz22GetN+CaK+NqhJIuldBYTn5K/Q5MTeWTtoU 5B3NJVJ8B/V+pq+XAlrxDSk7y2cJHHbcLxQ= X-Google-Smtp-Source: ABdhPJz8FVOrKOqKlsZ8ZK1aeLaet/rzq36w6hlMxoTN9ZtZ5W4OHsMR855nOGYigUpqCN7vkYc6o9TtTcKm5nU= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:a81:7e43:: with SMTP id p3mr2491823ywn.135.1644596334140; Fri, 11 Feb 2022 08:18:54 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:25 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-3-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 2/6] cgroup: gpu: Add a cgroup controller for allocator attribution of GPU memory From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The cgroup controller provides accounting for GPU and GPU-related memory allocations. The memory being accounted can be device memory or memory allocated from pools dedicated to serve GPU-related tasks. This patch adds APIs to: -allow a device to register for memory accounting using the GPU cgroup controller. -charge and uncharge allocated memory to a cgroup. When the cgroup controller is enabled, it would expose information about the memory allocated by each device(registered for GPU cgroup memory accounting) for each cgroup. The API/UAPI can be extended to set per-device/total allocation limits in the future. The cgroup controller has been named following the discussion in [1]. [1]: https://lore.kernel.org/amd-gfx/YCJp%2F%2FkMC7YjVMXv@phenom.ffwll.loca= l/ From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- changes in v2 - Fix incorrect Kconfig help section indentation per Randy Dunlap. include/linux/cgroup_gpu.h | 127 ++++++++++++++ include/linux/cgroup_subsys.h | 4 + init/Kconfig | 7 + kernel/cgroup/Makefile | 1 + kernel/cgroup/gpu.c | 304 ++++++++++++++++++++++++++++++++++ 5 files changed, 443 insertions(+) create mode 100644 include/linux/cgroup_gpu.h create mode 100644 kernel/cgroup/gpu.c diff --git a/include/linux/cgroup_gpu.h b/include/linux/cgroup_gpu.h new file mode 100644 index 000000000000..c5bc2b882783 --- /dev/null +++ b/include/linux/cgroup_gpu.h @@ -0,0 +1,127 @@ +/* SPDX-License-Identifier: MIT + * Copyright 2019 Advanced Micro Devices, Inc. + * Copyright (C) 2022 Google LLC. + */ +#ifndef _CGROUP_GPU_H +#define _CGROUP_GPU_H + +#include +#include + +#ifdef CONFIG_CGROUP_GPU + /* The GPU cgroup controller data structure */ +struct gpucg { + struct cgroup_subsys_state css; + + /* list of all resource pools that belong to this cgroup */ + struct list_head rpools; +}; + +struct gpucg_device { + /* + * list of various resource pools in various cgroups that the device is + * part of. + */ + struct list_head rpools; + + /* list of all devices registered for GPU cgroup accounting */ + struct list_head dev_node; + + /* + * pointer to string literal to be used as identifier for accounting and + * limit setting + */ + const char *name; +}; + +/** + * css_to_gpucg - get the corresponding gpucg ref from a cgroup_subsys_sta= te + * @css: the target cgroup_subsys_state + * + * Returns: gpu cgroup that contains the @css + */ +static inline struct gpucg *css_to_gpucg(struct cgroup_subsys_state *css) +{ + return css ? container_of(css, struct gpucg, css) : NULL; +} + +/** + * gpucg_get - get the gpucg reference that a task belongs to + * @task: the target task + * + * This increases the reference count of the css that the @task belongs to. + * + * Returns: reference to the gpu cgroup the task belongs to. + */ +static inline struct gpucg *gpucg_get(struct task_struct *task) +{ + if (!cgroup_subsys_enabled(gpu_cgrp_subsys)) + return NULL; + return css_to_gpucg(task_get_css(task, gpu_cgrp_id)); +} + +/** + * gpucg_put - put a gpucg reference + * @gpucg: the target gpucg + * + * Put a reference obtained via gpucg_get + */ +static inline void gpucg_put(struct gpucg *gpucg) +{ + if (gpucg) + css_put(&gpucg->css); +} + +/** + * gpucg_parent - find the parent of a gpu cgroup + * @cg: the target gpucg + * + * This does not increase the reference count of the parent cgroup + * + * Returns: parent gpu cgroup of @cg + */ +static inline struct gpucg *gpucg_parent(struct gpucg *cg) +{ + return css_to_gpucg(cg->css.parent); +} + +int gpucg_try_charge(struct gpucg *gpucg, struct gpucg_device *device, u64= usage); +void gpucg_uncharge(struct gpucg *gpucg, struct gpucg_device *device, u64 = usage); +void gpucg_register_device(struct gpucg_device *gpucg_dev, const char *nam= e); +#else /* CONFIG_CGROUP_GPU */ + +struct gpucg; +struct gpucg_device; + +static inline struct gpucg *css_to_gpucg(struct cgroup_subsys_state *css) +{ + return NULL; +} + +static inline struct gpucg *gpucg_get(struct task_struct *task) +{ + return NULL; +} + +static inline void gpucg_put(struct gpucg *gpucg) {} + +static inline struct gpucg *gpucg_parent(struct gpucg *cg) +{ + return NULL; +} + +static inline int gpucg_try_charge(struct gpucg *gpucg, + struct gpucg_device *device, + u64 usage) +{ + return 0; +} + +static inline void gpucg_uncharge(struct gpucg *gpucg, + struct gpucg_device *device, + u64 usage) {} + +static inline void gpucg_register_device(struct gpucg_device *gpucg_dev, + const char *name) {} +#endif /* CONFIG_CGROUP_GPU */ +#endif /* _CGROUP_GPU_H */ diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 445235487230..46a2a7b93c41 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_GPU) +SUBSYS(gpu) +#endif + /* * The following subsystems are not supported on the default hierarchy. */ diff --git a/init/Kconfig b/init/Kconfig index e9119bf54b1f..43568472930a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -980,6 +980,13 @@ config BLK_CGROUP =20 See Documentation/admin-guide/cgroup-v1/blkio-controller.rst for more inf= ormation. =20 +config CGROUP_GPU + bool "gpu cgroup controller (EXPERIMENTAL)" + select PAGE_COUNTER + help + Provides accounting and limit setting for memory allocations by the GPU= and + GPU-related subsystems. + config CGROUP_WRITEBACK bool depends on MEMCG && BLK_CGROUP diff --git a/kernel/cgroup/Makefile b/kernel/cgroup/Makefile index 12f8457ad1f9..be95a5a532fc 100644 --- a/kernel/cgroup/Makefile +++ b/kernel/cgroup/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_CGROUP_RDMA) +=3D rdma.o obj-$(CONFIG_CPUSETS) +=3D cpuset.o obj-$(CONFIG_CGROUP_MISC) +=3D misc.o obj-$(CONFIG_CGROUP_DEBUG) +=3D debug.o +obj-$(CONFIG_CGROUP_GPU) +=3D gpu.o diff --git a/kernel/cgroup/gpu.c b/kernel/cgroup/gpu.c new file mode 100644 index 000000000000..3e9bfb45c6af --- /dev/null +++ b/kernel/cgroup/gpu.c @@ -0,0 +1,304 @@ +// SPDX-License-Identifier: MIT +// Copyright 2019 Advanced Micro Devices, Inc. +// Copyright (C) 2022 Google LLC. + +#include +#include +#include +#include +#include +#include + +static struct gpucg *root_gpucg __read_mostly; + +/* + * Protects list of resource pools maintained on per cgroup basis + * and list of devices registered for memory accounting using the GPU cgro= up + * controller. + */ +static DEFINE_MUTEX(gpucg_mutex); +static LIST_HEAD(gpucg_devices); + +struct gpucg_resource_pool { + /* The device whose resource usage is tracked by this resource pool */ + struct gpucg_device *device; + + /* list of all resource pools for the cgroup */ + struct list_head cg_node; + + /* + * list maintained by the gpucg_device to keep track of its + * resource pools + */ + struct list_head dev_node; + + /* tracks memory usage of the resource pool */ + struct page_counter total; +}; + +static void free_cg_rpool_locked(struct gpucg_resource_pool *rpool) +{ + lockdep_assert_held(&gpucg_mutex); + + list_del(&rpool->cg_node); + list_del(&rpool->dev_node); + kfree(rpool); +} + +static void gpucg_css_free(struct cgroup_subsys_state *css) +{ + struct gpucg_resource_pool *rpool, *tmp; + struct gpucg *gpucg =3D css_to_gpucg(css); + + // delete all resource pools + mutex_lock(&gpucg_mutex); + list_for_each_entry_safe(rpool, tmp, &gpucg->rpools, cg_node) + free_cg_rpool_locked(rpool); + mutex_unlock(&gpucg_mutex); + + kfree(gpucg); +} + +static struct cgroup_subsys_state * +gpucg_css_alloc(struct cgroup_subsys_state *parent_css) +{ + struct gpucg *gpucg, *parent; + + gpucg =3D kzalloc(sizeof(struct gpucg), GFP_KERNEL); + if (!gpucg) + return ERR_PTR(-ENOMEM); + + parent =3D css_to_gpucg(parent_css); + if (!parent) + root_gpucg =3D gpucg; + + INIT_LIST_HEAD(&gpucg->rpools); + + return &gpucg->css; +} + +static struct gpucg_resource_pool *find_cg_rpool_locked( + struct gpucg *cg, + struct gpucg_device *device) +{ + struct gpucg_resource_pool *pool; + + lockdep_assert_held(&gpucg_mutex); + + list_for_each_entry(pool, &cg->rpools, cg_node) + if (pool->device =3D=3D device) + return pool; + + return NULL; +} + +static struct gpucg_resource_pool *init_cg_rpool(struct gpucg *cg, + struct gpucg_device *device) +{ + struct gpucg_resource_pool *rpool =3D kzalloc(sizeof(*rpool), + GFP_KERNEL); + if (!rpool) + return ERR_PTR(-ENOMEM); + + rpool->device =3D device; + + page_counter_init(&rpool->total, NULL); + INIT_LIST_HEAD(&rpool->cg_node); + INIT_LIST_HEAD(&rpool->dev_node); + list_add_tail(&rpool->cg_node, &cg->rpools); + list_add_tail(&rpool->dev_node, &device->rpools); + + return rpool; +} + +/** + * get_cg_rpool_locked - find the resource pool for the specified device a= nd + * specified cgroup. If the resource pool does not exist for the cg, it is + * created in a hierarchical manner in the cgroup and its ancestor cgroups= who + * do not already have a resource pool entry for the device. + * + * @cg: The cgroup to find the resource pool for. + * @device: The device associated with the returned resource pool. + * + * Return: return resource pool entry corresponding to the specified devic= e in + * the specified cgroup (hierarchically creating them if not existing alre= ady). + * + */ +static struct gpucg_resource_pool * +get_cg_rpool_locked(struct gpucg *cg, struct gpucg_device *device) +{ + struct gpucg *parent_cg, *p, *stop_cg; + struct gpucg_resource_pool *rpool, *tmp_rpool; + struct gpucg_resource_pool *parent_rpool =3D NULL, *leaf_rpool =3D NULL; + + rpool =3D find_cg_rpool_locked(cg, device); + if (rpool) + return rpool; + + stop_cg =3D cg; + do { + rpool =3D init_cg_rpool(stop_cg, device); + if (IS_ERR(rpool)) + goto err; + + if (!leaf_rpool) + leaf_rpool =3D rpool; + + stop_cg =3D gpucg_parent(stop_cg); + if (!stop_cg) + break; + + rpool =3D find_cg_rpool_locked(stop_cg, device); + } while (!rpool); + + /* + * Re-initialize page counters of all rpools created in this invocation + * to enable hierarchical charging. + * stop_cg is the first ancestor cg who already had a resource pool for + * the device. It can also be NULL if no ancestors had a pre-existing + * resource pool for the device before this invocation. + */ + rpool =3D leaf_rpool; + for (p =3D cg; p !=3D stop_cg; p =3D parent_cg) { + parent_cg =3D gpucg_parent(p); + if (!parent_cg) + break; + parent_rpool =3D find_cg_rpool_locked(parent_cg, device); + page_counter_init(&rpool->total, &parent_rpool->total); + + rpool =3D parent_rpool; + } + + return leaf_rpool; +err: + for (p =3D cg; p !=3D stop_cg; p =3D gpucg_parent(p)) { + tmp_rpool =3D find_cg_rpool_locked(p, device); + free_cg_rpool_locked(tmp_rpool); + } + return rpool; +} + +/** + * gpucg_try_charge - charge memory to the specified gpucg and gpucg_devic= e. + * Caller must hold a reference to @gpucg obtained through gpucg_get(). Th= e size + * of the memory is rounded up to be a multiple of the page size. + * + * @gpucg: The gpu cgroup to charge the memory to. + * @device: The device to charge the memory to. + * @usage: size of memory to charge in bytes. + * + * Return: returns 0 if the charging is successful and otherwise returns an + * error code. + */ +int gpucg_try_charge(struct gpucg *gpucg, struct gpucg_device *device, u64= usage) +{ + struct page_counter *counter; + u64 nr_pages; + struct gpucg_resource_pool *rp; + int ret =3D 0; + + mutex_lock(&gpucg_mutex); + rp =3D get_cg_rpool_locked(gpucg, device); + /* + * gpucg_mutex can be unlocked here, rp will stay valid until gpucg is + * freed and the caller is holding a reference to the gpucg. + */ + mutex_unlock(&gpucg_mutex); + + if (IS_ERR(rp)) + return PTR_ERR(rp); + + nr_pages =3D PAGE_ALIGN(usage) >> PAGE_SHIFT; + if (page_counter_try_charge(&rp->total, nr_pages, &counter)) + css_get_many(&gpucg->css, nr_pages); + else + ret =3D -ENOMEM; + + return ret; +} + +/** + * gpucg_uncharge - uncharge memory from the specified gpucg and gpucg_dev= ice. + * The caller must hold a reference to @gpucg obtained through gpucg_get(). + * + * @gpucg: The gpu cgroup to uncharge the memory from. + * @device: The device to uncharge the memory from. + * @usage: size of memory to uncharge in bytes. + */ +void gpucg_uncharge(struct gpucg *gpucg, struct gpucg_device *device, u64 = usage) +{ + u64 nr_pages; + struct gpucg_resource_pool *rp; + + mutex_lock(&gpucg_mutex); + rp =3D find_cg_rpool_locked(gpucg, device); + /* + * gpucg_mutex can be unlocked here, rp will stay valid until gpucg is + * freed and there are active refs on gpucg. + */ + mutex_unlock(&gpucg_mutex); + + if (unlikely(!rp)) { + pr_err("Resource pool not found, incorrect charge/uncharge ordering?\n"); + return; + } + + nr_pages =3D PAGE_ALIGN(usage) >> PAGE_SHIFT; + page_counter_uncharge(&rp->total, nr_pages); + css_put_many(&gpucg->css, nr_pages); +} + +/** + * gpucg_register_device - Registers a device for memory accounting using = the + * GPU cgroup controller. + * + * @device: The device to register for memory accounting. + * @name: Pointer to a string literal to denote the name of the device. + * + * Both @device andd @name must remain valid. + */ +void gpucg_register_device(struct gpucg_device *device, const char *name) +{ + if (!device) + return; + + INIT_LIST_HEAD(&device->dev_node); + INIT_LIST_HEAD(&device->rpools); + + mutex_lock(&gpucg_mutex); + list_add_tail(&device->dev_node, &gpucg_devices); + mutex_unlock(&gpucg_mutex); + + device->name =3D name; +} + +static int gpucg_resource_show(struct seq_file *sf, void *v) +{ + struct gpucg_resource_pool *rpool; + struct gpucg *cg =3D css_to_gpucg(seq_css(sf)); + + mutex_lock(&gpucg_mutex); + list_for_each_entry(rpool, &cg->rpools, cg_node) { + seq_printf(sf, "%s %lu\n", rpool->device->name, + page_counter_read(&rpool->total) * PAGE_SIZE); + } + mutex_unlock(&gpucg_mutex); + + return 0; +} + +struct cftype files[] =3D { + { + .name =3D "memory.current", + .seq_show =3D gpucg_resource_show, + }, + { } /* terminate */ +}; + +struct cgroup_subsys gpu_cgrp_subsys =3D { + .css_alloc =3D gpucg_css_alloc, + .css_free =3D gpucg_css_free, + .early_init =3D false, + .legacy_cftypes =3D files, + .dfl_cftypes =3D files, +}; --=20 2.35.1.265.g69c8d7142f-goog From nobody Sun Jun 28 05:33:38 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 B5703C433FE for ; Fri, 11 Feb 2022 16:19:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351414AbiBKQTG (ORCPT ); Fri, 11 Feb 2022 11:19:06 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:46996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351411AbiBKQTE (ORCPT ); Fri, 11 Feb 2022 11:19:04 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3F9D72EE for ; Fri, 11 Feb 2022 08:18:59 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id v134-20020a25618c000000b00620dc86b9d6so12359552ybb.0 for ; Fri, 11 Feb 2022 08:18:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=sjycs3J1raw78h/CcVrcAvxXNJMm38YGwWJkg+hcSJk=; b=HCicQU9wOvrep9Zko1Sp6f1kcNJH7vA3zXU3TjVhgtj7ecoJwQbiD5zNwlfXKnd3Uk fKTPKQahF2g4Y6Yl7OC7kdWe7Xj8Eip01fQ6bgZwKtUVfM3OdrQeD+P6IfjP4J6lHMxA 3Wd8KCv9vSHVzLrGft5zgckgtzVcnmXlHGqDJHcNNED707tgW9lJ0MnWqLKY0kp2dvQ/ UUurtSGmuV/6T387NDPTkYw+EQTiIjeuuZAohK9DBXj7o64/5JeY3gPt76JuMQ8y3+Fu NHs0H9pPGSnyHfRViau6furuWINKT4TIcOBlhZR4UuboJcrJaNNaihVZN+Vu6nhzK9qs mgTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=sjycs3J1raw78h/CcVrcAvxXNJMm38YGwWJkg+hcSJk=; b=pG+fCi3SFvX/SA8DWh3fxALnu2wTEHfYOXS43FQKKLhegwCFbg8YORXc6g19QOPk46 0LaVKTnSmTv6SzM1gxzudjqc7tdWPqv0FEK/yM3PPtLOmeXQ1t4ssPD0oP9uP0St9M80 S6JIL/UCxwqV5frzxT7UVjvVe72LE+/LcqY09C7VtbNuJ2hW/9CGqQ4ATKb4e+CQ87my Cwxl8xpu/bERV+e9PsvnkreLDy3UAJ0hmLxGHLDUc40H0wg6aE+0cZukpJvnO9UV/O3p iRZ+0OvJNBsnVSH55Qmk0YdBxMiES6W9WZ2E2gWl7sBuXVSHhTmWI2ohvg+Gbnvc2tPu VqQA== X-Gm-Message-State: AOAM533Nnx1wdPurmqmPXqU5b/hIfugaLKMLYAK6BMxxqQDDV+Hg191H D0ZYUmdiDXmD/db2NZ2elWSTJmNCAYM48M0= X-Google-Smtp-Source: ABdhPJyO8mB9+1hjpEI4c2iys3oGoAzHpKFN+ZZyeFAfnRemdzA9D7jOCwPVue2W9QmLyraSfSF4AB2bqc0vndI= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:a81:ae0c:: with SMTP id m12mr2454548ywh.19.1644596338464; Fri, 11 Feb 2022 08:18:58 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:26 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-4-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 3/6] dmabuf: Use the GPU cgroup charge/uncharge APIs From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This patch uses the GPU cgroup charge/uncharge APIs to charge buffers allocated by any DMA-BUF exporter that exports a buffer with a GPU cgroup device association. By doing so, it becomes possible to track who allocated/exported a DMA-BUF even after the allocating process drops all references to a buffer. From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- changes in v2 - Move dma-buf cgroup charging/uncharging from a dma_buf_op defined by every heap to a single dma-buf function for all heaps per Daniel Vetter and Christian K=C3=B6nig. drivers/dma-buf/dma-buf.c | 52 +++++++++++++++++++++++++++++++++++++++ include/linux/dma-buf.h | 20 +++++++++++++-- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 602b12d7470d..83d0d1b91547 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -56,6 +56,50 @@ static char *dmabuffs_dname(struct dentry *dentry, char = *buffer, int buflen) dentry->d_name.name, ret > 0 ? name : ""); } =20 +#ifdef CONFIG_CGROUP_GPU +static inline struct gpucg_device * +exp_info_gpucg_dev(const struct dma_buf_export_info *exp_info) +{ + return exp_info->gpucg_dev; +} + +static bool dmabuf_try_charge(struct dma_buf *dmabuf, + struct gpucg_device *gpucg_dev) +{ + dmabuf->gpucg =3D gpucg_get(current); + dmabuf->gpucg_dev =3D gpucg_dev; + if (gpucg_try_charge(dmabuf->gpucg, dmabuf->gpucg_dev, dmabuf->size)) { + gpucg_put(dmabuf->gpucg); + dmabuf->gpucg =3D NULL; + dmabuf->gpucg_dev =3D NULL; + return false; + } + return true; +} + +static void dmabuf_uncharge(struct dma_buf *dmabuf) +{ + if (dmabuf->gpucg && dmabuf->gpucg_dev) { + gpucg_uncharge(dmabuf->gpucg, dmabuf->gpucg_dev, dmabuf->size); + gpucg_put(dmabuf->gpucg); + } +} +#else /* CONFIG_CGROUP_GPU */ +static inline struct gpucg_device *exp_info_gpucg_dev( +const struct dma_buf_export_info *exp_info) +{ + return NULL; +} + +static inline bool dmabuf_try_charge(struct dma_buf *dmabuf, + struct gpucg_device *gpucg_dev)) +{ + return false; +} + +static inline void dmabuf_uncharge(struct dma_buf *dmabuf) {} +#endif /* CONFIG_CGROUP_GPU */ + static void dma_buf_release(struct dentry *dentry) { struct dma_buf *dmabuf; @@ -79,6 +123,8 @@ static void dma_buf_release(struct dentry *dentry) if (dmabuf->resv =3D=3D (struct dma_resv *)&dmabuf[1]) dma_resv_fini(dmabuf->resv); =20 + dmabuf_uncharge(dmabuf); + WARN_ON(!list_empty(&dmabuf->attachments)); module_put(dmabuf->owner); kfree(dmabuf->name); @@ -484,6 +530,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_exp= ort_info *exp_info) { struct dma_buf *dmabuf; struct dma_resv *resv =3D exp_info->resv; + struct gpucg_device *gpucg_dev =3D exp_info_gpucg_dev(exp_info); struct file *file; size_t alloc_size =3D sizeof(struct dma_buf); int ret; @@ -534,6 +581,9 @@ struct dma_buf *dma_buf_export(const struct dma_buf_exp= ort_info *exp_info) } dmabuf->resv =3D resv; =20 + if (gpucg_dev && !dmabuf_try_charge(dmabuf, gpucg_dev)) + goto err_charge; + file =3D dma_buf_getfile(dmabuf, exp_info->flags); if (IS_ERR(file)) { ret =3D PTR_ERR(file); @@ -565,6 +615,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_exp= ort_info *exp_info) file->f_path.dentry->d_fsdata =3D NULL; fput(file); err_dmabuf: + dmabuf_uncharge(dmabuf); +err_charge: kfree(dmabuf); err_module: module_put(exp_info->owner); diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 7ab50076e7a6..742f29c3daaf 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -13,6 +13,7 @@ #ifndef __DMA_BUF_H__ #define __DMA_BUF_H__ =20 +#include #include #include #include @@ -303,7 +304,7 @@ struct dma_buf { /** * @size: * - * Size of the buffer; invariant over the lifetime of the buffer. + * Size of the buffer in bytes; invariant over the lifetime of the buffer. */ size_t size; =20 @@ -453,6 +454,17 @@ struct dma_buf { struct dma_buf *dmabuf; } *sysfs_entry; #endif + +#ifdef CONFIG_CGROUP_GPU + /** @gpucg: Pointer to the cgroup this buffer currently belongs to. */ + struct gpucg *gpucg; + + /** @gpucg_dev: + * + * Pointer to the cgroup GPU device whence this buffer originates. + */ + struct gpucg_device *gpucg_dev; +#endif }; =20 /** @@ -529,9 +541,10 @@ struct dma_buf_attachment { * @exp_name: name of the exporter - useful for debugging. * @owner: pointer to exporter module - used for refcounting kernel module * @ops: Attach allocator-defined dma buf ops to the new buffer - * @size: Size of the buffer - invariant over the lifetime of the buffer + * @size: Size of the buffer in bytes - invariant over the lifetime of the= buffer * @flags: mode flags for the file * @resv: reservation-object, NULL to allocate default one + * @gpucg_dev: pointer to the gpu cgroup device this buffer belongs to * @priv: Attach private data of allocator to this buffer * * This structure holds the information required to export the buffer. Used @@ -544,6 +557,9 @@ struct dma_buf_export_info { size_t size; int flags; struct dma_resv *resv; +#ifdef CONFIG_CGROUP_GPU + struct gpucg_device *gpucg_dev; +#endif void *priv; }; =20 --=20 2.35.1.265.g69c8d7142f-goog From nobody Sun Jun 28 05:33:38 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 8F3E6C433F5 for ; Fri, 11 Feb 2022 16:19:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351422AbiBKQTI (ORCPT ); Fri, 11 Feb 2022 11:19:08 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:47002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351366AbiBKQTE (ORCPT ); Fri, 11 Feb 2022 11:19:04 -0500 Received: from mail-pj1-x1049.google.com (mail-pj1-x1049.google.com [IPv6:2607:f8b0:4864:20::1049]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4AB70301 for ; Fri, 11 Feb 2022 08:19:03 -0800 (PST) Received: by mail-pj1-x1049.google.com with SMTP id 62-20020a17090a09c400b001b80b0742b0so5966290pjo.8 for ; Fri, 11 Feb 2022 08:19:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=H9ElGyQs3gn6zkZHkaswT2uUcjDtIMKU0yBKyPd+zRw=; b=pqlxHsof189xym//3NOb/X4sUEqabODThOYWzG6aE6YJ7NVdPjULt2IJ1cr9fGd286 TqN8Vwy43pbjAeV0VM9D9lBgLG4vSp0hd5VeYAKLDd4c+fBW8AVWzET7AUF9gs3d9DnW gj6vH7NfEcDQIT5DTgijFUOnIfHCxeO7XgA/CHN9DVWmhsFC84dmykrVDNiTyVAb0Uga lAiN/rH84g/hNRQgrPyaLunHyngW5zJcDyWr3zfhJNVeBxDY4SR5wMNbeFGNJd7Ub9kP G4ZlAh2HeMqycTHUESlobX2v63RZoLJURMn7i3CeIYfJRL5Jz9s0DxOG0Oh6xijpBQgi i4IQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=H9ElGyQs3gn6zkZHkaswT2uUcjDtIMKU0yBKyPd+zRw=; b=smIwest3iXzLRoSPy9XEzjDxbSrBkOqi52T3L0L17Wgqkj2ZBo61kqD+xb2Zidwc02 Gzs29BrNibWkznIhRuMHwlD6rzETLSi0A46TFVo+V9rrX1pcx+552/rcATSVm9MGGQ30 YbB5liLxO4Q2f+2/CQaXKHvv+EhouLzBJME2W2LKbOvb1DsBS73sCQr9YriCJsDddSYy yJxwp3ihmGvvFfYxxbVNqdR5miC/TfM1EGRO0sVWO3u8Kx44BmxpBR/7gMe7be91rfnW pOOK1f8w0R99+ZykTv9ua5K9TuIxgTNLCP+ijPwTLNKQzL6AwrrdVGAfTryRZxEVKm9Z RcnQ== X-Gm-Message-State: AOAM533FbMMi3qcqIRW05e09DrlrTex2NADJpy/8eCmVuCc+GDGTDLnK OLz9Xo2RLBaHBfPjad93/Beyxm/bEf1or4I= X-Google-Smtp-Source: ABdhPJw+X052tlo7rO4R6ZJggau2VhHkvqL4TWCXAHP2/z0pcE7Hcx1yJPi6R86BW0yLQibs4VQNry7tP5PL4gI= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:aa7:8883:: with SMTP id z3mr2365344pfe.65.1644596342665; Fri, 11 Feb 2022 08:19:02 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:27 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-5-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 4/6] dmabuf: heaps: export system_heap buffers with GPU cgroup charging From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" All DMA heaps now register a new GPU cgroup device upon creation, and the system_heap now exports buffers associated with its GPU cgroup device for tracking purposes. From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- changes in v2 - Move dma-buf cgroup charge transfer from a dma_buf_op defined by every heap to a single dma-buf function for all heaps per Daniel Vetter and Christian K=C3=B6nig. drivers/dma-buf/dma-heap.c | 27 +++++++++++++++++++++++++++ drivers/dma-buf/heaps/system_heap.c | 3 +++ include/linux/dma-heap.h | 11 +++++++++++ 3 files changed, 41 insertions(+) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 8f5848aa144f..885072427775 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -7,6 +7,7 @@ */ =20 #include +#include #include #include #include @@ -31,6 +32,7 @@ * @heap_devt heap device node * @list list head connecting to list of heaps * @heap_cdev heap char device + * @gpucg_dev gpu cgroup device for memory accounting * * Represents a heap of memory from which buffers can be made. */ @@ -41,6 +43,9 @@ struct dma_heap { dev_t heap_devt; struct list_head list; struct cdev heap_cdev; +#ifdef CONFIG_CGROUP_GPU + struct gpucg_device gpucg_dev; +#endif }; =20 static LIST_HEAD(heap_list); @@ -216,6 +221,26 @@ const char *dma_heap_get_name(struct dma_heap *heap) return heap->name; } =20 +#ifdef CONFIG_CGROUP_GPU +/** + * dma_heap_get_gpucg_dev() - get struct gpucg_device for the heap. + * @heap: DMA-Heap to get the gpucg_device struct for. + * + * Returns: + * The gpucg_device struct for the heap. NULL if the GPU cgroup controller= is + * not enabled. + */ +struct gpucg_device *dma_heap_get_gpucg_dev(struct dma_heap *heap) +{ + return &heap->gpucg_dev; +} +#else /* CONFIG_CGROUP_GPU */ +struct gpucg_device *dma_heap_get_gpucg_dev(struct dma_heap *heap) +{ + return NULL; +} +#endif /* CONFIG_CGROUP_GPU */ + struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) { struct dma_heap *heap, *h, *err_ret; @@ -288,6 +313,8 @@ struct dma_heap *dma_heap_add(const struct dma_heap_exp= ort_info *exp_info) list_add(&heap->list, &heap_list); mutex_unlock(&heap_list_lock); =20 + gpucg_register_device(dma_heap_get_gpucg_dev(heap), exp_info->name); + return heap; =20 err2: diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/sy= stem_heap.c index ab7fd896d2c4..752a05c3cfe2 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -395,6 +395,9 @@ static struct dma_buf *system_heap_allocate(struct dma_= heap *heap, exp_info.ops =3D &system_heap_buf_ops; exp_info.size =3D buffer->len; exp_info.flags =3D fd_flags; +#ifdef CONFIG_CGROUP_GPU + exp_info.gpucg_dev =3D dma_heap_get_gpucg_dev(heap); +#endif exp_info.priv =3D buffer; dmabuf =3D dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) { diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index 0c05561cad6e..e447a61d054e 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -10,6 +10,7 @@ #define _DMA_HEAPS_H =20 #include +#include #include =20 struct dma_heap; @@ -59,6 +60,16 @@ void *dma_heap_get_drvdata(struct dma_heap *heap); */ const char *dma_heap_get_name(struct dma_heap *heap); =20 +/** + * dma_heap_get_gpucg_dev() - get a pointer to the struct gpucg_device for= the + * heap. + * @heap: DMA-Heap to retrieve gpucg_device for. + * + * Returns: + * The gpucg_device struct for the heap. + */ +struct gpucg_device *dma_heap_get_gpucg_dev(struct dma_heap *heap); + /** * dma_heap_add - adds a heap to dmabuf heaps * @exp_info: information needed to register this heap --=20 2.35.1.265.g69c8d7142f-goog From nobody Sun Jun 28 05:33:38 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 54741C433FE for ; Fri, 11 Feb 2022 16:19:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351464AbiBKQTU (ORCPT ); Fri, 11 Feb 2022 11:19:20 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:47370 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351428AbiBKQTO (ORCPT ); Fri, 11 Feb 2022 11:19:14 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D7E612F6 for ; Fri, 11 Feb 2022 08:19:07 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id v10-20020a05690204ca00b0061dd584eb83so19540761ybs.21 for ; Fri, 11 Feb 2022 08:19:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=yvZODKlks7uSqzZPx/QuM2FpvgBeZ2Sk/1s0RF7z1Xc=; b=ec1Yy1HYUYsk8sjBv+NO8SvcoXRcbLd5uiv9OPxDsNNur23ie7DmHnG9pRO3ilNRJc 1WvllX32ogWUY0ES0dpiEE0PkkZAqEtGHDkIOKsW2C7o8MPYg3yfWoNyM+WdEiwbD35T Wm/nnsqgsS4c257blD2h2q3WLvab8g25Dj83ORJVcsTjGYJyVICqcM/zkGknDnaHwtni S4ZDOVi8GlgnNuE1vqJ9LyP4yV9NB3a+ujEPEu7FgVA5ADIEY9Yho6UbQZlXhZiHM4fN WFpGmfjmGs9WnZVI4xN8jGbbfCl8+QIJaWkRzPaFr5hx6+gvkC/2/iIAsFPFyG5TXVMH vNVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=yvZODKlks7uSqzZPx/QuM2FpvgBeZ2Sk/1s0RF7z1Xc=; b=CB/AsVJsTn3nZCqMITVTgsAQjcGXmbV0NVwH5PAc2q0f12hoDNS7QNcmVSjGkKuRT/ rHwHEvgD8teQ5ohfKzQ5fKV4GMcCtdZRPxwczMPTctJx9EZ5lX4au2urIl/soVKsaoIw EediudJ4Q+atcx/L/8yZ2EqjwXNIwOw/pZ0stCa+b9nTxkUuqLnoQ7cNNlh1DjiuLozt Hvxw3U8EmCU2SXdjFfXglv3jl39TQJW8JvGh6vLAED11VNvtVSJ6Oc1MuiLDQt4Z2P+4 L4lAwdmoBB+0gYeMJsZN7MQDnuzS7FcNFcXY2LJPXjqxUviFwPwvLCXPyiM/PkFL0iBR gD5g== X-Gm-Message-State: AOAM533R8Wf0gTFNZj6v5bnMhNmhMnnFO5niupF/RAQbbpQZPA5haImT VjXi9wtFIi7zCNgqXK57Swf8RXnM2hYeprM= X-Google-Smtp-Source: ABdhPJyzRZpguSr08v/JtkpnGzL6Z+Soi+F7TZB5Jn0SLwqv4tx2BBp/V2mC7+AUgYjetHM8LbPfONmE/Uc6VpY= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:a81:2d03:: with SMTP id t3mr2496118ywt.215.1644596347024; Fri, 11 Feb 2022 08:19:07 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:28 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-6-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 5/6] dmabuf: Add gpu cgroup charge transfer function From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The dma_buf_charge_transfer function provides a way for processes to transfer charge of a buffer to a different process. This is essential for the cases where a central allocator process does allocations for various subsystems, hands over the fd to the client who requested the memory and drops all references to the allocated memory. From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- changes in v2 - Move dma-buf cgroup charge transfer from a dma_buf_op defined by every heap to a single dma-buf function for all heaps per Daniel Vetter and Christian K=C3=B6nig. drivers/dma-buf/dma-buf.c | 48 +++++++++++++++++++++++++++++++++++++++ include/linux/dma-buf.h | 2 ++ 2 files changed, 50 insertions(+) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 83d0d1b91547..55e1b982f840 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -1374,6 +1374,54 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct d= ma_buf_map *map) } EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF); =20 +/** + * dma_buf_charge_transfer - Change the GPU cgroup to which the provided d= ma_buf + * is charged. + * @dmabuf: [in] buffer whose charge will be migrated to a different GPU + * cgroup + * @gpucg: [in] the destination GPU cgroup for dmabuf's charge + * + * Only tasks that belong to the same cgroup the buffer is currently charg= ed to + * may call this function, otherwise it will return -EPERM. + * + * Returns 0 on success, or a negative errno code otherwise. + */ +int dma_buf_charge_transfer(struct dma_buf *dmabuf, struct gpucg *gpucg) +{ +#ifdef CONFIG_CGROUP_GPU + struct gpucg *current_gpucg; + int ret =3D 0; + + /* + * Verify that the cgroup of the process requesting the transfer is the + * same as the one the buffer is currently charged to. + */ + current_gpucg =3D gpucg_get(current); + mutex_lock(&dmabuf->lock); + if (current_gpucg !=3D dmabuf->gpucg) { + ret =3D -EPERM; + goto err; + } + + ret =3D gpucg_try_charge(gpucg, dmabuf->gpucg_dev, dmabuf->size); + if (ret) + goto err; + + dmabuf->gpucg =3D gpucg; + + /* uncharge the buffer from the cgroup it's currently charged to. */ + gpucg_uncharge(current_gpucg, dmabuf->gpucg_dev, dmabuf->size); + +err: + mutex_unlock(&dmabuf->lock); + gpucg_put(current_gpucg); + return ret; +#else + return 0; +#endif /* CONFIG_CGROUP_GPU */ +} +EXPORT_SYMBOL_NS_GPL(dma_buf_charge_transfer, DMA_BUF); + #ifdef CONFIG_DEBUG_FS static int dma_buf_debug_show(struct seq_file *s, void *unused) { diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 742f29c3daaf..85c940c08867 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -646,4 +646,6 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struc= t *, unsigned long); int dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map); void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map); + +int dma_buf_charge_transfer(struct dma_buf *dmabuf, struct gpucg *gpucg); #endif /* __DMA_BUF_H__ */ --=20 2.35.1.265.g69c8d7142f-goog From nobody Sun Jun 28 05:33:38 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 4526AC433F5 for ; Fri, 11 Feb 2022 16:19:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231518AbiBKQTa (ORCPT ); Fri, 11 Feb 2022 11:19:30 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:47410 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351460AbiBKQTP (ORCPT ); Fri, 11 Feb 2022 11:19:15 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFA8ED8D for ; Fri, 11 Feb 2022 08:19:12 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id s73-20020a25aa4f000000b0061d764d3c13so19896525ybi.1 for ; Fri, 11 Feb 2022 08:19:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=09UL10d0I9UYF+bVDoR9sZ50jMDUcLUx49HZh4jVL78=; b=JE1EYWsWmJMVKKKziQTWEWuNUsyaPxqCZ/opyUrIE1QJ2zMzT8OF9HdxhY+GhtuCaK HyDDiusYJME2veTyqvuwR1555jPMqz95nnShokOB0VNQWEe93IdgXongToVPd90O3dAV IimzoYc1rIm15su0G+eGvhoRyruDLS+nZbjAQSDDWgXzx6DUp60nKevkdTlnOcGS/yxC 7VDKvQJbgIkNVOdKUHyv+vhK1BCP41v5/xbIT27E+bix812dIwb5ma26aGylR3U5/hbr /YZu4e+ldXsQQ0aLJTqhpqIkZ/qs9fg8ieI0b6EipnVFoSEM/clguN4lkL+c5q3or2+f JMAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=09UL10d0I9UYF+bVDoR9sZ50jMDUcLUx49HZh4jVL78=; b=uEmsucrzVGgMjaFB0Lal+Xg9wzT+IcUjGzVC3jqYodzE4cMDe8pWrvBk6HPivV+5lL mj4+C7qXFksFFbEQoQQJDZ0185q44489b+3X0KF5vMEFmk37JNbkRlbTEYR3a27jYcpl hLnZfFSVNa12zIX0VbaMo0e0W30iyxlhfZwYHJKz68rks8vqrOsQRmIbSVPeAphEjI7x qcNuStKttbRJZLgTOGYmXvxfLx7o7wQpyT33/cxKJGFp9IvYJdX5MW/VwV+rJoNYLaUZ JsW/kBT5cqaOaPvgWGf+C8vnhCiuR91SnAwGR9rBK5JQ0Xugrco4N/vhL3Fm6gML2Fu+ lpnw== X-Gm-Message-State: AOAM532aNrsuPNEap7JzR7Ho3LtwT/gmhzAGUwtK8+Ju6AKwdT4M4ZXp NVE0Wj+fIFcZDbdaiizNZQehCbJKgxeEDfg= X-Google-Smtp-Source: ABdhPJyt28xsiqi+oRkwIgJ74WzjQyOoBVx2xkYnBQvOje0p3ZB58ZSdJeKE27JlSq7ErJdcjRoIy8BigQrNax8= X-Received: from tj2.c.googlers.com ([fda3:e722:ac3:cc00:20:ed76:c0a8:187]) (user=tjmercier job=sendgmr) by 2002:a81:d007:: with SMTP id v7mr2415829ywi.88.1644596352146; Fri, 11 Feb 2022 08:19:12 -0800 (PST) Date: Fri, 11 Feb 2022 16:18:29 +0000 In-Reply-To: <20220211161831.3493782-1-tjmercier@google.com> Message-Id: <20220211161831.3493782-7-tjmercier@google.com> Mime-Version: 1.0 References: <20220211161831.3493782-1-tjmercier@google.com> X-Mailer: git-send-email 2.35.1.265.g69c8d7142f-goog Subject: [RFC v2 6/6] android: binder: Add a buffer flag to relinquish ownership of fds From: "T.J. Mercier" To: Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Daniel Vetter , Jonathan Corbet , Greg Kroah-Hartman , "=?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=" , Todd Kjos , Martijn Coenen , Joel Fernandes , Christian Brauner , Hridya Valsaraju , Suren Baghdasaryan , Sumit Semwal , "=?UTF-8?q?Christian=20K=C3=B6nig?=" , Benjamin Gaignard , Liam Mark , Laura Abbott , Brian Starkey , John Stultz , Tejun Heo , Zefan Li , Johannes Weiner Cc: kaleshsingh@google.com, Kenny.Ho@amd.com, "T.J. Mercier" , dri-devel@lists.freedesktop.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, cgroups@vger.kernel.org Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" This patch introduces a buffer flag BINDER_BUFFER_FLAG_SENDER_NO_NEED that a process sending an fd array to another process over binder IPC can set to relinquish ownership of the fds being sent for memory accounting purposes. If the flag is found to be set during the fd array translation and the fd is for a DMA-BUF, the buffer is uncharged from the sender's cgroup and charged to the receiving process's cgroup instead. It is up to the sending process to ensure that it closes the fds regardless of whether the transfer failed or succeeded. Most graphics shared memory allocations in Android are done by the graphics allocator HAL process. On requests from clients, the HAL process allocates memory and sends the fds to the clients over binder IPC. The graphics allocator HAL will not retain any references to the buffers. When the HAL sets the BINDER_BUFFER_FLAG_SENDER_NO_NEED for fd arrays holding DMA-BUF fds, the gpu cgroup controller will be able to correctly charge the buffers to the client processes instead of the graphics allocator HAL. From: Hridya Valsaraju Signed-off-by: Hridya Valsaraju Co-developed-by: T.J. Mercier Signed-off-by: T.J. Mercier --- changes in v2 - Move dma-buf cgroup charge transfer from a dma_buf_op defined by every heap to a single dma-buf function for all heaps per Daniel Vetter and Christian K=C3=B6nig. drivers/android/binder.c | 26 ++++++++++++++++++++++++++ include/uapi/linux/android/binder.h | 1 + 2 files changed, 27 insertions(+) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 8351c5638880..f50d88ded188 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -42,6 +42,7 @@ =20 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 +#include #include #include #include @@ -2482,8 +2483,10 @@ static int binder_translate_fd_array(struct list_hea= d *pf_head, { binder_size_t fdi, fd_buf_size; binder_size_t fda_offset; + bool transfer_gpu_charge =3D false; const void __user *sender_ufda_base; struct binder_proc *proc =3D thread->proc; + struct binder_proc *target_proc =3D t->to_proc; int ret; =20 fd_buf_size =3D sizeof(u32) * fda->num_fds; @@ -2521,8 +2524,15 @@ static int binder_translate_fd_array(struct list_hea= d *pf_head, if (ret) return ret; =20 + if (IS_ENABLED(CONFIG_CGROUP_GPU) && + parent->flags & BINDER_BUFFER_FLAG_SENDER_NO_NEED) + transfer_gpu_charge =3D true; + for (fdi =3D 0; fdi < fda->num_fds; fdi++) { u32 fd; + struct dma_buf *dmabuf; + struct gpucg *gpucg; + binder_size_t offset =3D fda_offset + fdi * sizeof(fd); binder_size_t sender_uoffset =3D fdi * sizeof(fd); =20 @@ -2532,6 +2542,22 @@ static int binder_translate_fd_array(struct list_hea= d *pf_head, in_reply_to); if (ret) return ret > 0 ? -EINVAL : ret; + + if (!transfer_gpu_charge) + continue; + + dmabuf =3D dma_buf_get(fd); + if (IS_ERR(dmabuf)) + continue; + + gpucg =3D gpucg_get(target_proc->tsk); + ret =3D dma_buf_charge_transfer(dmabuf, gpucg); + if (ret) { + pr_warn("%d:%d Unable to transfer DMA-BUF fd charge to %d", + proc->pid, thread->pid, target_proc->pid); + gpucg_put(gpucg); + } + dma_buf_put(dmabuf); } return 0; } diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/andro= id/binder.h index 3246f2c74696..169fd5069a1a 100644 --- a/include/uapi/linux/android/binder.h +++ b/include/uapi/linux/android/binder.h @@ -137,6 +137,7 @@ struct binder_buffer_object { =20 enum { BINDER_BUFFER_FLAG_HAS_PARENT =3D 0x01, + BINDER_BUFFER_FLAG_SENDER_NO_NEED =3D 0x02, }; =20 /* struct binder_fd_array_object - object describing an array of fds in a = buffer --=20 2.35.1.265.g69c8d7142f-goog