From patchwork Fri Dec 20 10:04:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Honglei Huang X-Patchwork-Id: 13916451 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2C6EDE77188 for ; Fri, 20 Dec 2024 10:04:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9317510EF5E; Fri, 20 Dec 2024 10:04:36 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=amd.com header.i=@amd.com header.b="1sHCj/ZV"; dkim-atps=neutral Received: from NAM12-MW2-obe.outbound.protection.outlook.com (mail-mw2nam12on2069.outbound.protection.outlook.com [40.107.244.69]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4B6F010EF5E for ; Fri, 20 Dec 2024 10:04:35 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=VDFlqeoVn9as9SICI371ANO7s3H+tiUIfDE/Ggg4JZNAK00/llAYxfiTcQgBZxSHIos7XTM0pwufZuQrLsT+QWpZ8e8Yn3e1bAzMZbS2GVnxxu/Qxd5hEy6zwX4IIQrv5b83/yCZKbNTBV/Ui532JcL7IIj3vDU4o7p2tkGnNRL4TOFs9GvIqBCtIVV6H+Kv/W4SSTbjMAHZNKkL9DAKI8C52CT8Xr7wt/02idSUuWjy+ci8fxH7UME0/537Fs/4qphibvkGmaq2bejOysp0TFtz+PXCvmwl+SzWNBx9Pqb8qNhzCRxPRxoCxdhMDRC+/CNP9wwc0aaEmSaI+HE3Iw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=GBH9Yo9uMkdoYwQaSF1iiAQitS74rwVFqomdfW5w3l0=; b=xBv8dFA0JAmuQeQVNapU08HcMZiXIU7+1LK/Fr/mtVFGxmMqIkVGlOBDaD+I0Wm5RMCk1JxDm8qa3Cx9+xXtqk9kcTr2WVZOLBHkp0tWh6lWyN+EUp3U+Pb6jLvztx0Q5GJ0yFv3mUbB8HfgdTbNgfiyV9Gtj5bXof5ABn+X+m2lUQ/D4cD62v6pNBKVdlEBglcDL80/3uCWTBCsn9NM+nEiFCGTUQIKREBf2Lrv6UQ2Iu0EqnzS7JHUMHrLfHmex+mhCdN7VcWQCbtSX1qBejX9slUw1nT+d6qWFMJ5/KN1XPxKvLexWJMd8fX5wOsrJtZL6pvZdx5vvIAgHKLn7A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.linux-foundation.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=GBH9Yo9uMkdoYwQaSF1iiAQitS74rwVFqomdfW5w3l0=; b=1sHCj/ZVLVavjOk3u8+qGxsX0N2DB0vVZaJnDX6uH+yH4Zw5l9FNR5W4Il70C5KRBpYpKZg40Vr46+WbBv4m/bH+qZtZ3gNuk8ckIvr1ZUZDtCyhLGjy5i25opyQq/aeDObOgK0ONe2DXOBQDj/lFFA0OGGRhRYw+m4vVz4Mawo= Received: from BN0PR04CA0175.namprd04.prod.outlook.com (2603:10b6:408:eb::30) by BY5PR12MB4307.namprd12.prod.outlook.com (2603:10b6:a03:20c::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8272.16; Fri, 20 Dec 2024 10:04:27 +0000 Received: from BL02EPF0001A0F9.namprd03.prod.outlook.com (2603:10b6:408:eb:cafe::51) by BN0PR04CA0175.outlook.office365.com (2603:10b6:408:eb::30) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8272.16 via Frontend Transport; Fri, 20 Dec 2024 10:04:27 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BL02EPF0001A0F9.mail.protection.outlook.com (10.167.242.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8251.15 via Frontend Transport; Fri, 20 Dec 2024 10:04:26 +0000 Received: from jenkins-honglei.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 20 Dec 2024 04:04:22 -0600 From: Honglei Huang To: Huang Rui , , , Dmitry Osipenko , , David Airlie , "Gerd Hoffmann" , Gurchetan Singh , Chia-I Wu , Daniel Vetter , Akihiko Odaki CC: Lingshan Zhu , Demi Marie Obenour , Honglei Huang Subject: [RFC PATCH 1/3] virtio-gpu api: add blob userptr resource Date: Fri, 20 Dec 2024 18:04:07 +0800 Message-ID: <20241220100409.4007346-1-honglei1.huang@amd.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF0001A0F9:EE_|BY5PR12MB4307:EE_ X-MS-Office365-Filtering-Correlation-Id: 1d9f759d-acd5-4652-9bb4-08dd20ddaf9a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|376014|7416014|1800799024|82310400026|36860700013|921020; X-Microsoft-Antispam-Message-Info: hKKsQVnmJdY5dFpHyW2MVgA8rNlHwpgVwnibD/0v50gJoCCT0ATAOi3pvUUwPSmb0CDL82hy6Mwpkt/qsBJuFe2P7lh4VJ6TC5jHQ9DmgDB78YfonQqp0ac0/wzJoHXFzpsrf0mbTBcDpO2CQ3OELsJyDmpA5jStA55iHst3/Oeo2MdD6KOKJSHDyvWhN0FbmSJWU0/GZCVa6JVbd1bqnUKc/j/sa6AFtlrSoTAhSsSQ710VhEJsA98yOgDSYD3xOBEeTo31lKqbK9qdAjzUME+IjpEAUmVDfQnWFMvGvu/yfchb27zmiQRH4jtz2VPoLAhKC1X3oJiRk0zmzT1v+WkrUzHEm3Mx21zNU5C6CIHOh/pgGUKSY68A/vOxCgdT2+Tj62Q0thhDtImz93PUEqVp5W7+ANToesbPwrO5j/UixG+AY2iIolVXzRuvtEnjcPyQKoIBgig+naQHSiK7DiDqEhcBi1juT5k8OVPMyW5M/KE2OEcxGHrkuQPiaFGws6XFQpZnHOUYSttHZMU5r4DkPlHl7qHwb3z6qYclwpC0qBr6DH5NjJlJkC0/fDH5Wmlr6sFQNr/QemRoK7KEqf6SPVgt7DSj815xftjRi/zFhATbK7PPy8LFKIqxCtMxlsCht2HZMJ8lZ2YuvX/ImDK2EaP/LPgtQBB8/5uC/rkQdZ9o4aOkF71gEU/5T13VfWBn7Oxgqt2g2nEv9a+PvIHf8npu0S3SbJRmmxp8WqSO9BxXbWSaVUMIHs9mZTsk7nJTE1ZFkvf2B+nIrZb5YTOQ8OlCzMGv8/bV3M+ddW01rYm1e25Bj7Pt5Se5nDcGTw2VaqHPsXNT2Zka2hN1PF35VG7TYGIryuRg5+WvgWFbN8qKoHIr7sEYaJB9e8zrkTJ1nopNt4P/xeEHmzC1mCwZmB+yGIy+eghhlknKqRaOVzf9Ve7J00zmkgbxB9hdqg4flMVSpaDZOdh8gKI1iAA0U0pJNrY4vDaF/IuUvrQmF+/B3AZd27lITJozKOvEDFPuzGag0tjVxgygQkMLfVbho3WADRzxX8Rh6I8m/lWJ0VIw6cwjUaYY5/QZCsOiICiQ6G4yjb1c7jxN9znyEDw4vM6IgSMFvQnUJYUY9C7o9LUbt+Xj5wCEwI7pafCOWV0SIuaWRP4KVqwRd9AJoxt4kGuSmvp8l5hjUAgKL/QAyDohY8l3X7O+2/trAnTfdMhPRhN+RiCKkzWkbIpvm5TPPnaHch2scnI/obGTKcpOoDf80VDMfqjEWnicXsmp7dsd2Dm+zHH4AacnxS/djWvZ4DhNFTMpDoQgI+qawCfkrlZzg8p5noIEWN9Az9mBywpKOBgqDnugeMALGsVRIYX9AhPiEr5uUOA/tp+0NZshMY8asUwmDQc4oZI48SH1irZxEMwT2sYHv5J2P6ObwmcS8c7dfJEnSgkMYrSthdtGP+KR+X2vkCx3cmiTB1ZM5zCPzByQMfIYJICfWK8YNsERJvmJkoPqYyR5yDUb5oM= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(376014)(7416014)(1800799024)(82310400026)(36860700013)(921020); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2024 10:04:26.1859 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1d9f759d-acd5-4652-9bb4-08dd20ddaf9a X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF0001A0F9.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR12MB4307 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Honglei Huang Add a new resource for blob resource, called userptr, used for let host access guest user space memory, to acquire a simple SVM features in virtio GPU. - The capset VIRTIO_GPU_CAPSET_HSAKMT used for context init, in this series patches only HSAKMT context can use the userptr feature. HSAKMT is a GPU compute library in HSA stack, like the role libdrm in mesa stack. - New flag VIRTIO_GPU_BLOB_FLAG_USE_USERPTR used in blob create to indicate the blob create ioctl is used for create a userptr blob resource. Signed-off-by: Honglei Huang --- include/uapi/linux/virtio_gpu.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h index b9a9783f0b14..0a6b56acbc13 100644 --- a/include/uapi/linux/virtio_gpu.h +++ b/include/uapi/linux/virtio_gpu.h @@ -323,6 +323,7 @@ struct virtio_gpu_cmd_submit { #define VIRTIO_GPU_CAPSET_VIRGL 1 #define VIRTIO_GPU_CAPSET_VIRGL2 2 +#define VIRTIO_GPU_CAPSET_HSAKMT 7 /* VIRTIO_GPU_CMD_GET_CAPSET_INFO */ struct virtio_gpu_get_capset_info { @@ -415,6 +416,7 @@ struct virtio_gpu_resource_create_blob { #define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001 #define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002 #define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004 +#define VIRTIO_GPU_BLOB_FLAG_USE_USERPTR 0x0008 /* zero is invalid blob mem */ __le32 blob_mem; __le32 blob_flags; From patchwork Fri Dec 20 10:04:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Honglei Huang X-Patchwork-Id: 13916452 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 29C82E7718A for ; Fri, 20 Dec 2024 10:04:41 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A249C10E14D; Fri, 20 Dec 2024 10:04:40 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=amd.com header.i=@amd.com header.b="PQILLCcp"; dkim-atps=neutral Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11on2071.outbound.protection.outlook.com [40.107.236.71]) by gabe.freedesktop.org (Postfix) with ESMTPS id 2D52F10EF5E for ; Fri, 20 Dec 2024 10:04:36 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=azS/nsIhSCIjlwlB0jx2R2exb8Sv++etq+hGJzx/gmEjs3gTJTkclP/i9Zw8eT52nkMAtH80QHLn7m/Wtnc5exB6Q9NfS+S07M0hCYnytFRNA+q/hefkCuPR/u8/GfbQ+yf08mP98EhCifAW+jsz1JR6+Kh9sFKfOJQ5VBtW4I0qb7q208Nd/IB6Pd/JSYVpp6g7h1a+EJZIFYu9hRy3+jHMx2Qhax04G1JtEb/e3vyQpSXA3fegn5qF2MsQBkIpx+BfXZHZTQPqel8pF+MHaLRCW9/pwzzYh/6fD01lJObYIg9Tan4W7kHQNdzCvH510p844UioyIOLd7UWH+tSCA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=sz9qHFH07VCF/w1pHtRrlle9YmLvpw6IU0lonHHo7yI=; b=Vj3PDxAX2jZ1hoXwT54tvEjbrzAHIJvjuo9F1AvRSc2UyCnb1qHjPc35uoQd4OBTU916VcuVrr/yXr8VaaWBAMHZ7k8fbOkZIzesrhQaxq6mgMLMOCGq4KlwV7+EHV41r/1wDbYwMnpSWPSnvEuO1E94pnzLCuJ66lEvq+yhsV4Fy+Dne1anT5FMrC68NtoGzlcSNmO2HKUDrcYm3zUwjy6/6zmIZNBGCzCj/PJzK+L1WE+2nYMKkQn2vztTYax8tIOHIvrvCAyrAvWksOmm3DCbTzSPeH/Ep/NzNqiOVd3xQrqtmARmMX2WPtfqx0DIeWX/zysc14pQrjredThxiA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.linux-foundation.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=sz9qHFH07VCF/w1pHtRrlle9YmLvpw6IU0lonHHo7yI=; b=PQILLCcpeD9jr+yMmOeKrFCvjxLZY3D5kKpj2QTs3M6xShmV6yuH6KGz2AY40SfHZOoVHDRumunXWPFEjHENk1oY0kKXMjp25RIhZdF3q23aGVjTqo3VqSCS9URKqYRMXEc+m1ctyK/1U52HivnJBbWy4n7s6rfgVOKQUCruj2c= Received: from BN0PR04CA0174.namprd04.prod.outlook.com (2603:10b6:408:eb::29) by PH8PR12MB7328.namprd12.prod.outlook.com (2603:10b6:510:214::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8272.15; Fri, 20 Dec 2024 10:04:31 +0000 Received: from BL02EPF0001A0F9.namprd03.prod.outlook.com (2603:10b6:408:eb:cafe::73) by BN0PR04CA0174.outlook.office365.com (2603:10b6:408:eb::29) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8272.16 via Frontend Transport; Fri, 20 Dec 2024 10:04:31 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BL02EPF0001A0F9.mail.protection.outlook.com (10.167.242.100) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8251.15 via Frontend Transport; Fri, 20 Dec 2024 10:04:30 +0000 Received: from jenkins-honglei.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 20 Dec 2024 04:04:27 -0600 From: Honglei Huang To: Huang Rui , , , Dmitry Osipenko , , David Airlie , "Gerd Hoffmann" , Gurchetan Singh , Chia-I Wu , Daniel Vetter , Akihiko Odaki CC: Lingshan Zhu , Demi Marie Obenour , Honglei Huang Subject: [RFC PATCH 2/3] drm/virtgpu api: add blob userptr resource Date: Fri, 20 Dec 2024 18:04:08 +0800 Message-ID: <20241220100409.4007346-2-honglei1.huang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241220100409.4007346-1-honglei1.huang@amd.com> References: <20241220100409.4007346-1-honglei1.huang@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF0001A0F9:EE_|PH8PR12MB7328:EE_ X-MS-Office365-Filtering-Correlation-Id: 51c0f6ca-5870-4eed-411d-08dd20ddb268 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|82310400026|7416014|376014|1800799024|36860700013|921020; X-Microsoft-Antispam-Message-Info: W4Rv9YKUXbkjoUEQRu4sg1sWyKcR367srSVXKsK0J8Wit6MY87Sht/lNs2cctGutBz/aaXwik1x6mqhPqYq4V11QMZ0WcJwFXaFQCXsK964ekZ/J8/VF6Ic/DA9Z34h4/UtQZ/udsMXqF5Zk+aexTjFdT6l+BQWEeNfORyrXqMXYNpJJo5YFsdyvzlr4idWMQvx3Xtljxsq1jr5SqFwf4YODkf94lhE4RIahg+stxXsO/C0O6vPciunwVg5dl6XCClDF+pGU8v6Ew5B77SWoePOE21x8tCQaxlFGQUsb3CVh/WIA+PnaggVGQtKfbmbR2wkKeBipdgUTcISxFdcTXzd7xOg+3IWrvEfpTARM0i7Au3ri/DvbL8+bDU9bo94mI7JhzZYb52DmVE7eIujEqHv94rIpM2gZViphaCwBpk850CndHltFXUAX6jyy2GHoK9IhlmJpwqYpPCpg+uHI+vVdXwd++kaSwGymynmo4WzjDcIsgTCY3hchGQxITwsvSUpQC3V3aRqjryVTaGXlm8q3OWf3NgmE5VID4dFqHx9NFB6nO8lu7tkOI8vL7boHjyouZW7BCzwB03WtZ1aKZEhUrZzcN63FSPy5e7ZYuYxV+kJHdOC9y6ayTCos24E7zBUvB5PB7iRgOrMmHNTMdbQc0HSIWr8oLgm7M24S4RRRJALDwNAXNWaCptyv40i2FPoTGA7P7F45w+C6KeZvOMouKoUCsd4jtUBxDg2lCVtTyz3KluqGfNLWyKPOeupxav3pS32xK4qEdODIxCvsLrbrHh2OIlm82dCYTvHRQyk7iuiJrtUF2ZHXnqMJeDp6Nj90OB7d7Rf3uyxk7m7jnhxRAM5F0pUFA+uwkqF7xr9IDs3ucKqthpn0VWgRgyoiVI6Oq5FQ+4nRq3f8rZ371biO3z6mgZio5DWEnURwegB9utlL9kh+NL2C44PKbiaqh8BFPpStByF8O2K8U0hytjRdAMSIbjrNZGNCZCTucLy3wmGNGxJpzbcEBgKuJrmFSE6KXYmpP1+nxQ/cO30v2l9QtmH4KMzAjApIrD9ALN9t+ObghwBU5mUMiKgm1UuX0L8P9WyY0Fittl5HP4b3P+SbHrqnkVTVsjPFowlpQO0TtxEjGq4DLQMhSvQuE0O2AlZzbDB3F3oguKkJ/9HS/pv1v0SoTH71RJUQv7zaIW0mG2/YaYN1CqTBqVzShf1/5G/sWHdZ9HAmbwQAAgKftTHa/FmeBNchzpUT5t1r3PxiQiT/34ig/FRi1DfqfYMLBwNyjwPCEf3RsCkwRwcb4+BQGEigjwvb358SjTFD3cbp3CSve3N9Dop2ixDO2ua7MXxw6obdona3IzLSWdI5uUpnBJYAoLQHBsi7Z04sd/oDn4OBya+GxOCqPox7J58nfm0NcA/geS3f63TTRFAAlT8IeBfbOXmBtOKMxNftFQg2J7M0bSZmtWhwFjjis6vmoD0TDUAFXHdsZcZdUd6mEhObQiTip6l77KtdL384JB+VGB7WZHsTNNcMNJRj3iUx X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(82310400026)(7416014)(376014)(1800799024)(36860700013)(921020); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2024 10:04:30.8891 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 51c0f6ca-5870-4eed-411d-08dd20ddb268 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF0001A0F9.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH8PR12MB7328 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Honglei Huang This makes blob userptr resource available to guest userspace. - Flag VIRTGPU_BLOB_FLAG_USE_USERPTR for guest userspace blob create, enable this flag to indicate blob userptr resource create. - New parameter blob_userptr for bypass userspace memory address to virtio GPU, like other SVM design, virtio GPU needs a userspace memory for device access. - New parameter offset used for the already created blob userptr resource to get the address offset between the create one. The blob userptr resource is used for SVM feature, in compute side, this feature is must needed. like in OpenCL SVM feature also called userptr feature, it is for let device to access userspace memory, a very basic and important feature to prevent large memory copy between UMD and KMD. Signed-off-by: Honglei Huang --- include/uapi/drm/virtgpu_drm.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h index 2bb2d3a0c7bd..19fced75708c 100644 --- a/include/uapi/drm/virtgpu_drm.h +++ b/include/uapi/drm/virtgpu_drm.h @@ -181,6 +181,7 @@ struct drm_virtgpu_resource_create_blob { #define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001 #define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002 #define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004 +#define VIRTGPU_BLOB_FLAG_USE_USERPTR 0x0008 /* zero is invalid blob_mem */ __u32 blob_mem; __u32 blob_flags; @@ -196,6 +197,8 @@ struct drm_virtgpu_resource_create_blob { __u32 cmd_size; __u64 cmd; __u64 blob_id; + __u64 blob_userptr; + __u64 offset; }; #define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001 From patchwork Fri Dec 20 10:04:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Honglei Huang X-Patchwork-Id: 13916453 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 gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 56636E7718A for ; Fri, 20 Dec 2024 10:04:48 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id CDDAF10EF6D; Fri, 20 Dec 2024 10:04:47 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=amd.com header.i=@amd.com header.b="K73C8mso"; dkim-atps=neutral Received: from NAM02-BN1-obe.outbound.protection.outlook.com (mail-bn1nam02on2054.outbound.protection.outlook.com [40.107.212.54]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7764510EF67 for ; Fri, 20 Dec 2024 10:04:45 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=uk+aNiRv94QRcdoBeCxXuMqBxkPw6c/FS0BmyzFhSIaXIRnQPkFcFoV8Wf0NiIbtmT6Lza/EoRtXYD0y2BCxz7WiWlmsVLbCQA3NgaS7+auqG0FGIBV74luT2J2D7rYWfQBpSRNEcbxpUklmJMVJOYfOHh59LIT5DZ9wnDlYTqEAg9+Hb6YCUp2xcxTcWTXrEdV3U6Sk1ZiJB++IB2b3IP8/Hq0nG8riMKt3rhdYlHI6Zc54WUvIZiJKGcOUcoqW2TT+dgtKGMep6Du8aIemSk5AFwBX4NLv1fkFEYuoVducx7GvaNPUDeqqLjme2d3IWIbS6jQvT6+dPYJXhiSW6A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=rk+4JEw1R7LJJDqm1KZild+m02ezA2VWKkeYA3p0Yok=; b=L4CtRvq1jSTLit2OmxDr+eAGW270KktUL8gW9LOmaxE/raY2iwFtH3Qj73y+Ae6XGUrR4ZAyuN1AEy/r73DjnCx5l6jkh5aKRBDoX6DYrEwEikgTN4MhC+UioD77nVzEy4fGZeuQcj3eJPnQ+mfa2+FRLA9+QDgTdqhjNuIfg1mgV+5bOoEhPPdGG8rcVcxNsBArq6rlLMUZPHaZUCW6uZic1/BqDX5KStWdHsfiptg08g51B2tASkXgK8nhkCn1OcmxLR5z3PbhkQc6a6CzeVTXJVc2Mz+FKYpql9OguZFHC4dZtKx4K/K/3e/Tt/5uopQSuJh9yHeb4ONWR4oF5w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=lists.linux-foundation.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=rk+4JEw1R7LJJDqm1KZild+m02ezA2VWKkeYA3p0Yok=; b=K73C8msoNd6R2aSUIJeUGJwEKWysEnBAj3YnIDGsLoJhgv8k2CTOL9KmPTdxvVDKHkn5ohw0DnyplWqBDVpBF1Y9YJR1VqTxW8pvtz4UF6+8jhDpshf2ACjfFx3wjkA+psCAQ6+rscwxJE53tUuBLnJC1p7Dt1ipJ5kkFHfhDL4= Received: from BL1P221CA0007.NAMP221.PROD.OUTLOOK.COM (2603:10b6:208:2c5::33) by SJ0PR12MB6877.namprd12.prod.outlook.com (2603:10b6:a03:47f::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8272.13; Fri, 20 Dec 2024 10:04:39 +0000 Received: from BL02EPF0001A0FD.namprd03.prod.outlook.com (2603:10b6:208:2c5:cafe::9b) by BL1P221CA0007.outlook.office365.com (2603:10b6:208:2c5::33) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8251.23 via Frontend Transport; Fri, 20 Dec 2024 10:04:39 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BL02EPF0001A0FD.mail.protection.outlook.com (10.167.242.104) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8251.15 via Frontend Transport; Fri, 20 Dec 2024 10:04:37 +0000 Received: from jenkins-honglei.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Fri, 20 Dec 2024 04:04:33 -0600 From: Honglei Huang To: Huang Rui , , , Dmitry Osipenko , , David Airlie , "Gerd Hoffmann" , Gurchetan Singh , Chia-I Wu , Daniel Vetter , Akihiko Odaki CC: Lingshan Zhu , Demi Marie Obenour , Honglei Huang Subject: [RFC PATCH 3/3] drm/virtio: implement blob userptr resource object Date: Fri, 20 Dec 2024 18:04:09 +0800 Message-ID: <20241220100409.4007346-3-honglei1.huang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241220100409.4007346-1-honglei1.huang@amd.com> References: <20241220100409.4007346-1-honglei1.huang@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF0001A0FD:EE_|SJ0PR12MB6877:EE_ X-MS-Office365-Filtering-Correlation-Id: cbd3d061-0c46-4867-2580-08dd20ddb6a4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|376014|7416014|1800799024|82310400026|921020; X-Microsoft-Antispam-Message-Info: +oxCD4/00FN1o3xuxIkTA5l9BExejUdhzCkGKzHmsbyXs62rzX1bAPADgfutdFq6Fs+i0/j7UeRZO0v0sXxRJMK/TjOr7bTm/x8u5v+rLabkgih5NI+nSrIGVBAVlwIfRN+Vb5DE+xKnm7pR4i0IK56dfX4jOi2yRCJHCAWzdt77w/0EEBGpbBxBGhMc9ChyXhgKKD8LXWXHqD0Agk8dtt1iZEkWGuKDQsrYXAi4z606I80pCNL7RRQTk2GhJm4Phe4IdzlUjdr8y1CX7wWT0etES/yNbraNYj5bQbOriDnnNHZfwptOoDluccm1+zzcOwWpvG0LDPJuqa4mGdiue50DUithF6qBoDLHl91X8QArqOzj4afJhVDVoJNIm5RM5LyMmnsc+36CBQD7IXw/EI5hn1WrnyvO9UrHvNRSvLfUwlNo1shIEJtGUHEQ/sb1F/9jjSLXBlfTA88/pTDP4xnSbm5I6sQmcqb3dq8uahLUSFcQiZyTuS2O/mLpgQURlQioT66v83eaq8zTuxecC9kC12P6zehJ17ZP72I1EtxjE2LU/l7rMEEE88oIBFgOxDkIj+W5EOd6XQQRNTYZdaroxqW6LYh8U5heziAlLee5E2uVeldfbBhCAuHNpuR/Os0Iu5q1HaDEfPu2VbMuRn2lmIJ64BQr1FG7mq1dGRWKe3CEKnJXvgW8xNj01SlDZn3MGa0fBx9+iuwCxnZvUStLSjQqfPQSOVE5UQq8TW4BS2aFv+FM/n59fdASZfklXnj4WpXjqLR35afdIB0dGPxyt9OF5KcOKDgOH5Z2kTRXiFXrtpzQKMmxl8Fmbx9YjzKQZy9nZPtNkFyiKsJIYRb4RAifE+a9ZlzY9mZdDEbGIz3OqoZKr6wn+WMwZsYoaGr84vV8clPWlS/45/FPQ+RLHhmaazZ+4Z5g/Eohogl1e4ew+mNGfCprjRQNOYwGdrx6DrOeJpTHe6lDcMqDhWBzHZpNN5RbdDGvVFFCv+kJQ8DxKT94N3FQ/HT/Cen/lQQWHJvZ8YuYxpxfTjaF8E4GFO+omwdA/waMxHPZXD4V8oHKsOmI9xinZFONNcVVb99Rq5Z0raGyA8ELF6aWeEzZY/m+t8XRXpj9PGgC3Djf0F0DDAJx5s+dPnWHN+H4rUMzOL8Hxu2YhDSgWzlZN+axgvf88pEDlUvuOXRpci3WNLdXyHz6q6h1BctIDwKeKcJ/JOkgaJLSx4Uc4qwwDGqeKbdAJWSUMZWvtDXxTjAp6gj72fTLHgSxWj907ETJLAfjBMF1gzXUFlSPL+oAbGxym3BEeKEANPZqM9Wo/JvvouwSd8jOgH2l/CETM17GjH93xEtLsztZ+JiAwlHYU1JLNLYuC3izDmGoY6VojrQg4pAgejJ08ILgtzrDxHBdnSkfEU0G/iXkN1uUNojox320hxgYVJ0cRTux+EDXlEcM99jC1cYx3mTRmi7EbtuymiZNBRRN7yZBa2OFx7UEysHs3keRbWn9GsC7Pj1I/3o= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(36860700013)(376014)(7416014)(1800799024)(82310400026)(921020); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2024 10:04:37.9925 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: cbd3d061-0c46-4867-2580-08dd20ddb6a4 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF0001A0FD.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB6877 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Honglei Huang A virtio-gpu userptr is based on HMM notifier. Used for let host access guest userspace memory and notice the change of userspace memory. This series patches are in very beginning state, User space are pinned currently to ensure the host device memory operations are correct. The free and unmap operations for userspace can be handled by MMU notifier this is a simple and basice SVM feature for this series patches. The physical PFNS update operations is splited into two OPs in here. The evicted memories won't be used anymore but remap into host again to achieve same effect with hmm_rang_fault. Signed-off-by: Honglei Huang --- drivers/gpu/drm/virtio/Makefile | 3 +- drivers/gpu/drm/virtio/virtgpu_drv.h | 72 +++ drivers/gpu/drm/virtio/virtgpu_ioctl.c | 25 +- drivers/gpu/drm/virtio/virtgpu_kms.c | 2 + drivers/gpu/drm/virtio/virtgpu_object.c | 5 + drivers/gpu/drm/virtio/virtgpu_userptr.c | 738 +++++++++++++++++++++++ drivers/gpu/drm/virtio/virtgpu_vq.c | 29 + 7 files changed, 871 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/virtio/virtgpu_userptr.c diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile index d2e1788a8227..351c45e1e7d1 100644 --- a/drivers/gpu/drm/virtio/Makefile +++ b/drivers/gpu/drm/virtio/Makefile @@ -2,8 +2,9 @@ # # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. +# virtgpu_userptr.o -virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o \ +virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o virtgpu_vram.o virtgpu_userptr.o \ virtgpu_display.o virtgpu_vq.o \ virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \ virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o virtgpu_submit.o diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index e1ee17466f6b..5d15c018201d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -85,6 +87,7 @@ struct virtio_gpu_object_params { uint32_t blob_mem; uint32_t blob_flags; uint64_t blob_id; + uint64_t blob_userptr; }; struct virtio_gpu_object { @@ -112,12 +115,50 @@ struct virtio_gpu_object_vram { struct drm_mm_node vram_node; }; +enum userptr_work_list_ops { + USERPTR_OP_NULL, + USERPTR_OP_UNMAP, + USERPTR_OP_UPDATE, + USERPTR_OP_EVICT, +}; + +struct virtio_gpu_object_userptr { + struct virtio_gpu_object base; + + struct page **pages; + uint64_t userptr_inital_start; + uint64_t userptr_start; + uint64_t userptr_last; + uint32_t npages; + uint32_t bo_handle; + struct list_head work_list; + struct virtio_gpu_device *vgdev; + struct mmu_interval_notifier notifier; + struct drm_file *file; + + /* for list work */ + struct mm_struct *mm; + enum userptr_work_list_ops op; + uint64_t notifier_start; + uint64_t notifier_last; + + /* userptr interval tree node */ + struct interval_tree_node it_node; + + /* in release list work queue */ + atomic_t in_release; + struct mutex lock; +}; + #define to_virtio_gpu_shmem(virtio_gpu_object) \ container_of((virtio_gpu_object), struct virtio_gpu_object_shmem, base) #define to_virtio_gpu_vram(virtio_gpu_object) \ container_of((virtio_gpu_object), struct virtio_gpu_object_vram, base) +#define to_virtio_gpu_userptr(virtio_gpu_object) \ + container_of((virtio_gpu_object), struct virtio_gpu_object_userptr, base) + struct virtio_gpu_object_array { struct ww_acquire_ctx ticket; struct list_head next; @@ -279,6 +320,16 @@ struct virtio_gpu_fpriv { uint64_t base_fence_ctx; uint64_t ring_idx_mask; struct mutex context_lock; + + /* for userptr mmu notifier invalidate */ + struct work_struct userptr_invalidate_work; + struct list_head userptr_invalidate_list; + spinlock_t userptr_invalidate_list_lock; + + /* userptr interval tree */ + struct rb_root_cached userptrs_tree; + struct mutex userptrs_tree_lock; + char debug_name[DEBUG_NAME_MAX_LEN]; bool explicit_debug_name; bool fence_passing_enabled; @@ -422,6 +473,14 @@ virtio_gpu_cmd_resource_create_blob(struct virtio_gpu_device *vgdev, struct virtio_gpu_object_params *params, struct virtio_gpu_mem_entry *ents, uint32_t nents); + +void +virtio_gpu_cmd_resource_create_userptr(struct virtio_gpu_device *vgdev, + struct virtio_gpu_object *bo, + struct virtio_gpu_object_params *params, + unsigned long *pfns, + uint32_t npfns); + void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, uint32_t scanout_id, @@ -497,4 +556,17 @@ void virtio_gpu_vram_unmap_dma_buf(struct device *dev, int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +/* virtgpu_userptr.c */ +void virtio_gpu_userptr_set_handle(struct virtio_gpu_object *qobj, + uint32_t handle); +uint32_t virtio_gpu_userptr_get_handle(struct virtio_gpu_object *qobj); +void virtio_gpu_userptr_list_work_init(struct virtio_gpu_fpriv *vfpriv); +void virtio_gpu_userptr_interval_tree_init(struct virtio_gpu_fpriv *vfpriv); +uint64_t virtio_gpu_userptr_get_offset(struct virtio_gpu_object *qobj, + uint64_t addr); +bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo); +int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev, + struct drm_file *file, + struct virtio_gpu_object_params *params, + struct virtio_gpu_object **bo_ptr); #endif diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index d40c7402720d..519278443c66 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -36,7 +36,8 @@ #define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \ VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ - VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) + VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE | \ + VIRTGPU_BLOB_FLAG_USE_USERPTR) /* Must be called with &virtio_gpu_fpriv.struct_mutex held. */ static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev, @@ -489,6 +490,7 @@ static int verify_blob(struct virtio_gpu_device *vgdev, params->size = rc_blob->size; params->blob = true; params->blob_flags = rc_blob->blob_flags; + params->blob_userptr = rc_blob->blob_userptr; return 0; } @@ -528,8 +530,20 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, rc_blob->cmd_size, 0); } - if (guest_blob) + if (guest_blob && !params.blob_userptr) ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL); + else if (guest_blob && params.blob_userptr) { + ret = virtio_gpu_userptr_create(vgdev, file, ¶ms, &bo); + if (unlikely(ret < 0)) + return ret; + if (ret > 0) { + /* userptr already exist */ + rc_blob->res_handle = bo->hw_res_handle; + rc_blob->bo_handle = virtio_gpu_userptr_get_handle(bo); + rc_blob->offset = virtio_gpu_userptr_get_offset(bo, rc_blob->blob_userptr); + return ret; + } + } else if (!guest_blob && host3d_blob) ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo); else @@ -560,6 +574,9 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, rc_blob->res_handle = bo->hw_res_handle; rc_blob->bo_handle = handle; + /* for mmu notifier auto release */ + if (guest_blob && params.blob_userptr) + virtio_gpu_userptr_set_handle(bo, handle); /* * The handle owns the reference now. But we must drop our @@ -691,6 +708,10 @@ static int virtio_gpu_context_init_ioctl(struct drm_device *dev, goto out_unlock; } } + if (vfpriv->context_init & VIRTIO_GPU_CAPSET_HSAKMT) { + virtio_gpu_userptr_list_work_init(vfpriv); + virtio_gpu_userptr_interval_tree_init(vfpriv); + } virtio_gpu_create_context_locked(vgdev, vfpriv); virtio_gpu_notify(vgdev); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 9f4617a75edd..3af40ed8936a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -346,6 +346,8 @@ void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file) return; if (vfpriv->context_created) { + if (vfpriv->context_init & VIRTIO_GPU_CAPSET_HSAKMT) + flush_work(&vfpriv->userptr_invalidate_work); virtio_gpu_cmd_context_destroy(vgdev, vfpriv->ctx_id); virtio_gpu_notify(vgdev); } diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index c7e74cf13022..31659b0a028d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -80,6 +80,11 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo) drm_gem_free_mmap_offset(&vram->base.base.base); drm_gem_object_release(&vram->base.base.base); kfree(vram); + } else if (virtio_gpu_is_userptr(bo)) { + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo); + + drm_gem_object_release(&userptr->base.base.base); + kfree(userptr); } } diff --git a/drivers/gpu/drm/virtio/virtgpu_userptr.c b/drivers/gpu/drm/virtio/virtgpu_userptr.c new file mode 100644 index 000000000000..646088f7f72b --- /dev/null +++ b/drivers/gpu/drm/virtio/virtgpu_userptr.c @@ -0,0 +1,738 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +#include "virtgpu_drv.h" + +#include + +#include +#include + +#include "drm/drm_gem.h" + +#include + +#define USERPTR_PFNS_NO_CHANGE 0 +#define USERPTR_PFNS_CHANGED 1 +#define USERPTR_PFNS_NONE 2 + +#define USERPTR_EXISTS 1 + +static bool +virtio_gpu_userptr_invalidate(struct mmu_interval_notifier *mn, + const struct mmu_notifier_range *range, + unsigned long cur_seq); + +static const struct mmu_interval_notifier_ops virtio_gpu_userptr_mn_ops = { + .invalidate = virtio_gpu_userptr_invalidate, +}; + +static void virtio_gpu_userptr_unlink(struct virtio_gpu_fpriv *vfpriv, + struct virtio_gpu_object_userptr *userptr) +{ + if (userptr->it_node.start != 0 && userptr->it_node.last != 0) + interval_tree_remove(&userptr->it_node, &vfpriv->userptrs_tree); +} + +static void virtio_gpu_userptr_free(struct drm_gem_object *obj) +{ + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_device *vgdev = obj->dev->dev_private; + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo); + + if (bo->created) { + unpin_user_pages_dirty_lock(userptr->pages, userptr->npages, + false); + vfree(userptr->pages); + userptr->pages = NULL; + + virtio_gpu_cmd_unref_resource(vgdev, bo); + virtio_gpu_notify(vgdev); + + return; + } +} + +static void virtio_gpu_userptr_object_close(struct drm_gem_object *obj, + struct drm_file *file) +{ + virtio_gpu_gem_object_close(obj, file); +} + +static const struct drm_gem_object_funcs virtio_gpu_userptr_funcs = { + .open = virtio_gpu_gem_object_open, + .close = virtio_gpu_userptr_object_close, + .free = virtio_gpu_userptr_free, +}; + +bool virtio_gpu_is_userptr(struct virtio_gpu_object *bo) +{ + return bo->base.base.funcs == &virtio_gpu_userptr_funcs; +} + +static int +virtio_gpu_userptr_add_notifier(struct virtio_gpu_object_userptr *userptr, + unsigned long start, unsigned long length) +{ + int ret = mmu_interval_notifier_insert_locked( + &userptr->notifier, current->mm, start, length, + &virtio_gpu_userptr_mn_ops); + + if (ret) + pr_err("mmu_interval_notifier_insert_locked failed ret: %d\n", + ret); + return ret; +} + +uint32_t virtio_gpu_userptr_get_handle(struct virtio_gpu_object *qobj) +{ + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(qobj); + + return userptr->bo_handle; +} + +uint64_t virtio_gpu_userptr_get_offset(struct virtio_gpu_object *qobj, + uint64_t addr) +{ + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(qobj); + uint64_t userptr_align_down = ALIGN_DOWN(addr, PAGE_SIZE); + uint64_t offset = userptr_align_down - userptr->userptr_inital_start; + return offset; +} + +void virtio_gpu_userptr_interval_tree_init(struct virtio_gpu_fpriv *vfpriv) +{ + vfpriv->userptrs_tree = RB_ROOT_CACHED; + mutex_init(&vfpriv->userptrs_tree_lock); +} + +static struct virtio_gpu_object_userptr * +virtio_gpu_userptr_from_addr_range(struct virtio_gpu_fpriv *vfpriv, + u_int64_t start, u_int64_t last) +{ + struct interval_tree_node *node; + struct virtio_gpu_object_userptr *userptr = NULL; + struct virtio_gpu_object_userptr *ret = NULL; + uint64_t userptr_size; + + node = interval_tree_iter_first(&vfpriv->userptrs_tree, start, last); + + while (node) { + struct interval_tree_node *next; + + userptr = container_of(node, struct virtio_gpu_object_userptr, + it_node); + + if (start >= userptr->userptr_start && + last <= userptr->userptr_last && + !atomic_read(&userptr->in_release) && !userptr->op) { + ret = userptr; + userptr_size = userptr->userptr_last - + userptr->userptr_start + 1UL; + return ret; + } + + next = interval_tree_iter_next(node, start, last); + node = next; + } + + return ret; +} + +static void +virtio_gpu_userptr_add_interval_tree(struct virtio_gpu_fpriv *vfpriv, + struct virtio_gpu_object_userptr *userptr) +{ + userptr->it_node.start = userptr->userptr_start; + userptr->it_node.last = userptr->userptr_last; + interval_tree_insert(&userptr->it_node, &vfpriv->userptrs_tree); +} + +static void virtio_gpu_userptr_unmap(struct virtio_gpu_object_userptr *userptr) +{ + pr_debug( + "list work remove userptr: [%llx-%llx], resid: %d bo_handle: %d size: %x\n", + userptr->userptr_start, userptr->userptr_last, + userptr->base.hw_res_handle, userptr->bo_handle, + userptr->npages); + + virtio_gpu_userptr_unlink(userptr->file->driver_priv, userptr); + mmu_interval_notifier_remove(&userptr->notifier); + + drm_gem_handle_delete(userptr->file, userptr->bo_handle); +} + +static void virtio_gpu_userptr_update_notifier_and_interval_tree( + struct virtio_gpu_object_userptr *userptr) +{ + unsigned long start = userptr->notifier.interval_tree.start; + unsigned long last = userptr->notifier.interval_tree.last; + + if (userptr->userptr_start == start && userptr->userptr_last == last) + return; + + if (start != 0 && last != 0) { + virtio_gpu_userptr_unlink(userptr->file->driver_priv, userptr); + mmu_interval_notifier_remove(&userptr->notifier); + } + + pr_debug( + "update userptr: [%lx-%lx]-%lx -> [%llx-%llx]-%llx resid: %d\n", + start, last, last - start + 1UL, userptr->userptr_start, + userptr->userptr_last, + userptr->userptr_last - userptr->userptr_start + 1UL, + userptr->base.hw_res_handle); + + virtio_gpu_userptr_add_interval_tree(userptr->file->driver_priv, + userptr); + mmu_interval_notifier_insert_locked( + &userptr->notifier, userptr->mm, userptr->userptr_start, + userptr->userptr_last - userptr->userptr_start + 1UL, + &virtio_gpu_userptr_mn_ops); + + userptr->op = 0; +} + +static int virtio_gpu_userptr_split(struct virtio_gpu_object_userptr *userptr, + unsigned long valid_start, + unsigned long valid_last, + struct virtio_gpu_object_userptr **new) +{ + uint64_t old_start = userptr->userptr_start; + uint64_t old_last = userptr->userptr_last; + + if (old_start != valid_start && old_last != valid_last) + return -EINVAL; + if (valid_start < old_start || valid_last > old_last) + return -EINVAL; + + /* split new userptr is not needed currently, but keep the API parameters here + * for future expansion. + */ + *new = NULL; + + /* update range */ + userptr->userptr_start = valid_start; + userptr->userptr_last = valid_last; + + return 0; +} + +static void +virtio_gpu_userptr_update_split(struct virtio_gpu_object_userptr *userptr, + unsigned long mn_start, unsigned long mn_last) +{ + struct virtio_gpu_object_userptr *head; + struct virtio_gpu_object_userptr *tail; + + if (userptr->op == USERPTR_OP_UNMAP) + return; + + if (mn_start > userptr->userptr_last || + mn_last < userptr->userptr_start) + return; + + head = tail = userptr; + if (mn_start > userptr->userptr_start) + virtio_gpu_userptr_split(userptr, userptr->userptr_start, + mn_start - 1UL, &tail); + else if (mn_last < userptr->userptr_last) + virtio_gpu_userptr_split(userptr, mn_last + 1UL, + userptr->userptr_last, &head); + + /* split tail maybe not needed in virtgpu */ + /* if (mn_last < userptr->userptr_last) */ + /* add child userptr maybe not needed in virtgpu */ +} + +static void +virtio_gpu_userptr_add_list_work(struct virtio_gpu_object_userptr *userptr, + int op) +{ + struct virtio_gpu_fpriv *vfpriv = userptr->file->driver_priv; + + spin_lock(&vfpriv->userptr_invalidate_list_lock); + + if (!list_empty(&userptr->work_list)) { + pr_debug( + "update exist userptr userptr: [%llx-%llx] work op to %d\n", + userptr->userptr_start, userptr->userptr_last, op); + if (op != USERPTR_OP_NULL && userptr->op != USERPTR_OP_UNMAP) + userptr->op = op; + } else { + userptr->op = op; + list_add_tail(&userptr->work_list, + &vfpriv->userptr_invalidate_list); + } + + spin_unlock(&vfpriv->userptr_invalidate_list_lock); +} + +static int +virtio_gpu_userptr_check_pfns(struct virtio_gpu_object_userptr *userptr, + struct vm_area_struct *vma, uint64_t start, + uint64_t end) +{ + uint64_t addr; + int ret; + unsigned long pfn; + spinlock_t *ptl; + pte_t *ptep; + + for (addr = start; addr < end; addr += PAGE_SIZE) { + ret = follow_pte(vma->vm_mm, addr, &ptep, &ptl); + if (ret) { + pr_debug("follow_pfn in userptr failed, addr: %llx\n", + addr); + return USERPTR_PFNS_NONE; + } + pfn = pte_pfn(ptep_get(ptep)); + pte_unmap_unlock(ptep, ptl); + if (page_to_pfn( + userptr->pages[(addr - userptr->userptr_start) >> + PAGE_SHIFT]) != pfn) { + pr_debug("userptr pages not match, addr: %llx\n", addr); + return USERPTR_PFNS_CHANGED; + } + } + + return USERPTR_PFNS_NO_CHANGE; +} + +static int +virtio_gpu_userptr_check_range(struct virtio_gpu_object_userptr *userptr, + uint64_t notifier_start, uint64_t notifier_last) +{ + uint64_t start, end, addr; + int r = 0; + + start = notifier_start; + end = notifier_last + (1UL << PAGE_SHIFT); + + for (addr = start; !r && addr < end;) { + struct vm_area_struct *vma; + uint64_t next = 0; + uint32_t npages; + + vma = vma_lookup(userptr->mm, addr); + + if (vma) { + next = min(vma->vm_end, end); + npages = (next - addr) >> PAGE_SHIFT; + r = virtio_gpu_userptr_check_pfns(userptr, vma, start, + next); + if (r) + break; + } else { + pr_debug("vma not found for addr: %llx\n", addr); + r = -EFAULT; + break; + } + + addr = next; + } + + return r; +} + +static void +virtio_gpu_update_or_remove_userptr(struct virtio_gpu_object_userptr *userptr, + unsigned long start, unsigned long last) +{ + if ((userptr->userptr_start) >= start && + (userptr->userptr_last) <= last) { + if (atomic_xchg(&userptr->in_release, 1) == 0) { + virtio_gpu_userptr_add_list_work(userptr, + USERPTR_OP_UNMAP); + } + } else { + pr_debug( + "mmu notifier: [%lx-%lx]-%lx userptr: [%llx-%llx]-%llx not match need update.\n", + start, last, last - start + 1UL, userptr->userptr_start, + userptr->userptr_last, + userptr->userptr_last - userptr->userptr_start + 1UL); + virtio_gpu_userptr_update_split(userptr, start, last); + virtio_gpu_userptr_add_list_work(userptr, USERPTR_OP_UPDATE); + } +} + +static void virtio_gpu_userptr_evict(struct virtio_gpu_object_userptr *userptr) +{ + if (!userptr->notifier_start || !userptr->notifier_last) { + pr_err("userptr: [%llx-%llx] not have notifier range\n", + userptr->userptr_start, userptr->userptr_last); + return; + } + + if (userptr->notifier_start < userptr->userptr_start || + userptr->notifier_last > userptr->userptr_last) { + pr_err("invalid evict param, userptr: [%llx-%llx] notifier: [%llx-%llx] out of range\n", + userptr->userptr_start, userptr->userptr_last, + userptr->notifier_start, userptr->notifier_last); + return; + } + + if (virtio_gpu_userptr_check_range(userptr, userptr->notifier_start, + userptr->notifier_last)) { + pr_debug("userptr: [%llx-%llx], resid: %d check range failed\n", + userptr->userptr_start, userptr->userptr_last, + userptr->base.hw_res_handle); + /* add to work list or process here directly, add to work list here */ + virtio_gpu_update_or_remove_userptr( + userptr, userptr->notifier_start, + userptr->notifier_last + (1UL << PAGE_SHIFT) - 1UL); + } + + userptr->notifier_start = 0; + userptr->notifier_last = 0; +} + +static void +virtio_gpu_userptr_handle_list_work(struct virtio_gpu_object_userptr *userptr) +{ + switch (userptr->op) { + case USERPTR_OP_NULL: + break; + case USERPTR_OP_UNMAP: + virtio_gpu_userptr_unmap(userptr); + break; + case USERPTR_OP_UPDATE: + virtio_gpu_userptr_update_notifier_and_interval_tree(userptr); + break; + case USERPTR_OP_EVICT: + virtio_gpu_userptr_evict(userptr); + break; + default: + break; + } +} + +static void virtio_gpu_userptr_invalidate_work(struct work_struct *work) +{ + struct virtio_gpu_fpriv *vfpriv; + struct virtio_gpu_object_userptr *userptr; + struct mm_struct *mm; + + vfpriv = container_of(work, struct virtio_gpu_fpriv, + userptr_invalidate_work); + + spin_lock(&vfpriv->userptr_invalidate_list_lock); + while (!list_empty(&vfpriv->userptr_invalidate_list)) { + userptr = list_first_entry(&vfpriv->userptr_invalidate_list, + struct virtio_gpu_object_userptr, + work_list); + spin_unlock(&vfpriv->userptr_invalidate_list_lock); + + mm = userptr->mm; + + mmap_write_lock(mm); + + /* Remove from userptr_invalidate_list_lock must inside mmap write lock, cause: + * after remove from list, the work_item.op may be changed by other thread + * like MMU notifier invalidate callback, and maybe add the userptr to work + * list again. + * What will cause use after free or double free bug. + * So need use mmap_write_lock to prevent the invalidate callback triggering then + * remove the from work list to snsure one work item only be handled once. + */ + spin_lock(&vfpriv->userptr_invalidate_list_lock); + list_del_init(&userptr->work_list); + spin_unlock(&vfpriv->userptr_invalidate_list_lock); + + mutex_lock(&vfpriv->userptrs_tree_lock); + + virtio_gpu_userptr_handle_list_work(userptr); + + mutex_unlock(&vfpriv->userptrs_tree_lock); + mmap_write_unlock(mm); + + spin_lock(&vfpriv->userptr_invalidate_list_lock); + } + spin_unlock(&vfpriv->userptr_invalidate_list_lock); +} + +void virtio_gpu_userptr_list_work_init(struct virtio_gpu_fpriv *vfpriv) +{ + INIT_WORK(&vfpriv->userptr_invalidate_work, + virtio_gpu_userptr_invalidate_work); + INIT_LIST_HEAD(&vfpriv->userptr_invalidate_list); + spin_lock_init(&vfpriv->userptr_invalidate_list_lock); +} + +static void +virtio_gpu_userptr_schedule_list_work(struct virtio_gpu_fpriv *vfpriv) +{ + spin_lock(&vfpriv->userptr_invalidate_list_lock); + if (!list_empty(&vfpriv->userptr_invalidate_list)) + schedule_work(&vfpriv->userptr_invalidate_work); + spin_unlock(&vfpriv->userptr_invalidate_list_lock); +} + +static void virtio_gpu_object_userptr_remove_within_range( + struct virtio_gpu_fpriv *vfpriv, u_int64_t start, u_int64_t last, + bool check_start, const char *from) +{ + struct interval_tree_node *node; + struct virtio_gpu_object_userptr *userptr = NULL; + uint64_t remove_userptr_size = last - start + 1UL; + uint64_t userptr_size; + + mutex_lock(&vfpriv->userptrs_tree_lock); + + node = interval_tree_iter_first(&vfpriv->userptrs_tree, start, last); + + while (node) { + struct interval_tree_node *next; + + userptr = container_of(node, struct virtio_gpu_object_userptr, + it_node); + + userptr_size = + userptr->userptr_last - userptr->userptr_start + 1UL; + if (userptr->userptr_start >= start && + userptr->userptr_last < last) { + if ((!check_start) || + (check_start && userptr->userptr_start == start)) { + if (atomic_xchg(&userptr->in_release, 1) == 0 && + !userptr->op) { + userptr->mm = current->mm; + virtio_gpu_userptr_add_list_work( + userptr, USERPTR_OP_UNMAP); + } + } + } + + next = interval_tree_iter_next(node, start, last); + node = next; + } + mutex_unlock(&vfpriv->userptrs_tree_lock); + + virtio_gpu_userptr_schedule_list_work(userptr->file->driver_priv); +} + +static bool +virtio_gpu_userptr_invalidate(struct mmu_interval_notifier *mn, + const struct mmu_notifier_range *range, + unsigned long cur_seq) +{ + struct virtio_gpu_object_userptr *userptr; + struct virtio_gpu_fpriv *vfpriv; + unsigned long start; + unsigned long last; + + if (range->event == MMU_NOTIFY_RELEASE) + return true; + if (!mmget_not_zero(mn->mm)) + return true; + + start = mn->interval_tree.start; + last = mn->interval_tree.last; + start = (max(start, range->start) >> PAGE_SHIFT) << PAGE_SHIFT; + last = (min(last, range->end - 1UL) >> PAGE_SHIFT) << PAGE_SHIFT; + + userptr = container_of(mn, struct virtio_gpu_object_userptr, notifier); + userptr->mm = mn->mm; + vfpriv = userptr->file->driver_priv; + + mutex_lock(&userptr->lock); + mmu_interval_set_seq(mn, cur_seq); + + pr_debug( + "userptr: [%llx-%llx]-%llx notifier: [%lx-%lx]-%lx check: [%lx-%lx]-%lx resid: %d event: %d\n", + userptr->userptr_start, userptr->userptr_last, + userptr->userptr_last - userptr->userptr_start + 1UL, + range->start, range->end - 1UL, range->end - range->start, + start, last, last - start + (1UL << PAGE_SHIFT), + userptr->base.hw_res_handle, range->event); + + if (userptr->op == USERPTR_OP_UNMAP) { + pr_debug( + "userptr: [%llx-%llx] resid: %d already in unmap op: %d\n", + userptr->userptr_start, userptr->userptr_last, + userptr->base.hw_res_handle, userptr->op); + } else { + switch (range->event) { + case MMU_NOTIFY_UNMAP: + virtio_gpu_update_or_remove_userptr( + userptr, start, + last + (1UL << PAGE_SHIFT) - 1UL); + break; + default: + userptr->notifier_start = start; + userptr->notifier_last = last; + virtio_gpu_userptr_add_list_work(userptr, + USERPTR_OP_EVICT); + break; + } + } + + virtio_gpu_userptr_schedule_list_work(userptr->file->driver_priv); + + mutex_unlock(&userptr->lock); + mmput(mn->mm); + return true; +} + +static void +virtio_gpu_userptr_lock_and_flush_work(struct virtio_gpu_fpriv *vfpriv, + struct mm_struct *mm) +{ +retry_flush_work: + flush_work(&vfpriv->userptr_invalidate_work); + + if (list_empty(&vfpriv->userptr_invalidate_list)) + return; + + goto retry_flush_work; +} + +void virtio_gpu_userptr_set_handle(struct virtio_gpu_object *qobj, + uint32_t handle) +{ + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(qobj); + + userptr->bo_handle = handle; + virtio_gpu_object_userptr_remove_within_range( + userptr->file->driver_priv, userptr->userptr_start, + userptr->userptr_last, false, __func__); + virtio_gpu_userptr_add_notifier(userptr, userptr->userptr_start, + userptr->npages << PAGE_SHIFT); +} + +static int virtio_gpu_userptr_init(struct drm_device *dev, + struct drm_file *file, + struct drm_gem_object *obj, + struct virtio_gpu_object_params *params, + unsigned long **p_pfns, uint32_t *p_npfns) +{ + struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); + struct virtio_gpu_object_userptr *userptr = to_virtio_gpu_userptr(bo); + unsigned long page_offset; + unsigned long aligned_size; + struct page **pages; + unsigned int pinned = 0; + uint64_t aligned_addr; + int ret; + + page_offset = (uint64_t)params->blob_userptr & (PAGE_SIZE - 1UL); + aligned_addr = params->blob_userptr - page_offset; + aligned_size = roundup(page_offset + params->size, PAGE_SIZE); + + pr_debug( + "create userptr addr: %llx size: %lx, aligned: [%llx-%llx]-%lx\n", + params->blob_userptr, params->size, aligned_addr, + aligned_addr + aligned_size - 1UL, aligned_size); + + params->size = aligned_size; + + drm_gem_private_object_init(dev, obj, aligned_size); + + *p_npfns = aligned_size / PAGE_SIZE; + *p_pfns = vmalloc(*p_npfns * sizeof(unsigned long)); + if (!(*p_pfns)) { + pr_err("failed to allocate userptr pfns\n"); + return -ENOMEM; + } + + pages = vmalloc(*p_npfns * sizeof(struct page *)); + if (!pages) + return -ENOMEM; + + userptr->userptr_inital_start = aligned_addr; + userptr->userptr_start = aligned_addr; + userptr->userptr_last = userptr->userptr_start + aligned_size - 1UL; + + do { + unsigned int num_pages = *p_npfns - pinned; + uint64_t ptr = userptr->userptr_start + pinned * PAGE_SIZE; + struct page **pinned_pages = pages + pinned; + + ret = pin_user_pages_fast( + ptr, num_pages, FOLL_WRITE | FOLL_FORCE, pinned_pages); + + if (ret < 0) { + pr_err("pin memory failed, addr: 0x%llx\n", + userptr->userptr_start); + if (pinned && pages) + unpin_user_pages(pages, pinned); + userptr->userptr_start = 0; + vfree(pages); + vfree(*p_pfns); + return -ENOMEM; + } + + pinned += ret; + + } while (pinned < *p_npfns); + + userptr->pages = pages; + userptr->npages = *p_npfns; + bo->base.base.size = aligned_size; + + for (int i = 0; i < (*p_npfns); i++) + (*p_pfns)[i] = page_to_pfn(pages[i]); + + atomic_set(&userptr->in_release, 0); + INIT_LIST_HEAD(&userptr->work_list); + mutex_init(&userptr->lock); + userptr->vgdev = dev->dev_private; + userptr->file = file; + + return 0; +} + +int virtio_gpu_userptr_create(struct virtio_gpu_device *vgdev, + struct drm_file *file, + struct virtio_gpu_object_params *params, + struct virtio_gpu_object **bo_ptr) +{ + struct mm_struct *mm = current->mm; + struct virtio_gpu_fpriv *vfpriv = file->driver_priv; + struct drm_gem_object *obj; + struct virtio_gpu_object_userptr *userptr; + int ret; + unsigned long *pfns; + uint32_t npfns; + + virtio_gpu_userptr_lock_and_flush_work(vfpriv, mm); + + mutex_lock(&vfpriv->userptrs_tree_lock); + userptr = virtio_gpu_userptr_from_addr_range( + vfpriv, params->blob_userptr, + params->blob_userptr + params->size - 1UL); + if (userptr) { + *bo_ptr = &userptr->base; + mutex_unlock(&vfpriv->userptrs_tree_lock); + return USERPTR_EXISTS; + } + + userptr = kzalloc(sizeof(*userptr), GFP_KERNEL); + if (!userptr) + return -ENOMEM; + + obj = &userptr->base.base.base; + obj->funcs = &virtio_gpu_userptr_funcs; + + ret = virtio_gpu_userptr_init(vgdev->ddev, file, obj, params, &pfns, + &npfns); + if (ret) + goto failed_free; + + ret = virtio_gpu_resource_id_get(vgdev, &userptr->base.hw_res_handle); + if (ret) + goto failed_free; + + virtio_gpu_userptr_add_interval_tree(vfpriv, userptr); + /* virtio_gpu_userptr_dump(vfpriv); */ + + mutex_unlock(&vfpriv->userptrs_tree_lock); + + virtio_gpu_cmd_resource_create_userptr(vgdev, &userptr->base, params, + pfns, npfns); + + *bo_ptr = &userptr->base; + return 0; + +failed_free: + mutex_unlock(&vfpriv->userptrs_tree_lock); + kfree(userptr); + return ret; +} diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 29d462b69bad..2699b85829f4 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -1270,6 +1270,35 @@ virtio_gpu_cmd_resource_create_blob(struct virtio_gpu_device *vgdev, bo->created = true; } +void +virtio_gpu_cmd_resource_create_userptr(struct virtio_gpu_device *vgdev, + struct virtio_gpu_object *bo, + struct virtio_gpu_object_params *params, + unsigned long *pfns, + uint32_t npfns) +{ + struct virtio_gpu_resource_create_blob *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + + cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p)); + memset(cmd_p, 0, sizeof(*cmd_p)); + + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB); + cmd_p->hdr.ctx_id = cpu_to_le32(params->ctx_id); + cmd_p->resource_id = cpu_to_le32(bo->hw_res_handle); + cmd_p->blob_mem = cpu_to_le32(params->blob_mem); + cmd_p->blob_flags = cpu_to_le32(params->blob_flags); + cmd_p->blob_id = cpu_to_le64(params->blob_id); + cmd_p->size = cpu_to_le64(params->size); + cmd_p->nr_entries = cpu_to_le32(npfns); + + vbuf->data_buf = pfns; + vbuf->data_size = sizeof(*pfns) * npfns; + + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + bo->created = true; +} + void virtio_gpu_cmd_set_scanout_blob(struct virtio_gpu_device *vgdev, uint32_t scanout_id, struct virtio_gpu_object *bo,