From nobody Thu Oct 22 19:25:18 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792012269; cv=none; d=zohomail.com; s=zohoarc; b=EVwdtGvTFS7SoPgYrSx5Zm1Dyg1nC1lMET0PQQEg+GHa83D75JPnbXMoe3I1syZNzcaJTbxzVdU2iGDHycwqSGkTNNgfhsmvg8eIvZmEEKuabl5bPej+A+bnGoBva72+BcZMtajvNsuv1iAQ3oDi/yhVR8ZMxpxW5hdEhHY4InE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792012269; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=TKIaFE/kHJ3Rfgy+FVKwCxJYILk57aCM7aP6Pl5rp20=; b=Nv/kjO+mAoRdIrFW7UELuLn9t6YQXbMHRL/ozYSe1Dc/2GklCtHWqOb6ohw4Af/yIGt+mf4mBIavwRqc7O4cPEe76uTgO9MZCSb4kDXqOsMRm7YJu+B4HKRRor6mFX5uS6LgRIDuKgEUuDghuSMMCwwqihUQiqb+7b0bSE5qNoU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792012269094871.6782015733571; Wed, 14 Oct 2026 14:11:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xH6FV-0007Ld-Fn; Wed, 14 Oct 2026 17:10:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <31O_PagsKClE6t5t6zD4tC1z77z4x.v759x5D-wxEx4676z6D.7Az@flex--namangulati.bounces.google.com>) id 1xH6FR-00077Y-4u for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:53 -0400 Received: from mail-qv1-xf45.google.com ([2607:f8b0:4864:20::f45]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <31O_PagsKClE6t5t6zD4tC1z77z4x.v759x5D-wxEx4676z6D.7Az@flex--namangulati.bounces.google.com>) id 1xH6FP-0001De-4i for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:52 -0400 Received: by mail-qv1-xf45.google.com with SMTP id 6a1803df08f44-917a7c17166so87851016d6.1 for ; Wed, 14 Oct 2026 14:10:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792012245; x=1792617045; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=TKIaFE/kHJ3Rfgy+FVKwCxJYILk57aCM7aP6Pl5rp20=; b=el0eNVAjzQDXcQM2mLwDTYdmCZZvAinWiCMnMJ6B3Riv93VOa9pfsETwtpoA/Z/BT1 8d3oMFYtbuzlgHrQahZu0IKde7xc+yumKjv3RWHhZs1OgFuJCiKIsfffIJ7Lu1s2OS81 Ah5NIHhx9ys1hQXWm9FLNk7NREJJugseEA1pOfXx+YPy5F5RIqcK14ki5aOdfFE+YjvB by9styQrNSFRA+7luXh+La6BcBvdnTR5xQOR/HT6EWbHJXpRre1JkhSZkY1ufS+ooBJk 7wPBHnVjsBwB5drEoa0nYReLLENZZUhvyGz9irqwSlpwt+nwT65rN4yR9itCUx+vMN9T ssuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792012245; x=1792617045; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=TKIaFE/kHJ3Rfgy+FVKwCxJYILk57aCM7aP6Pl5rp20=; b=C9/qBfAHn3HoFkWPvoh0ga2Ll6hNbEew6H22EFf1MIYHQznn1C+7RBqI8vmSkfKk2i 9+BaahnFWaP2vyfJ6JsBW1bbHxld7PFcOo5azj0CuvYOuMLw2HaCg0XkBP/XCOUIhlkS AryaTjCUOQMaIqWVJge8wu1tR1ET96bly2PEaOwpTewDyi7V7z1aihlkMLjKTZcmRiGp LheDLQMSNdNyaQcNWIN2MZxZ1ZhgOqc9Y6m7yvWwix2d4wYyyhz6OgMQBen48EWX9Ljk 3nG576hzSaljJA8of38kfjvJpXBpZn3Uhypg86VTMMDAqo76DyMBTehoWemEqzOT0rha +pwQ== X-Gm-Message-State: AFq9FYKsDrCnwzWuKC62e1E4bwgTUnoF3F6hwLZv8DsJqlxkKhgiV4DB AxfS5WJW1IImpvxXhQf1WtBupew3kzl0cAv0Qe1vcSgsAKUXQ0KgFibcLAP0YJOAI2pg7YLJmXz yCNegFDMmrUmP8FDVVFAl7xgLj4RdRlkijvx++tUKT/vImSXDtGsXNFARFKZy4YS3s7oQ5h8NRk 7wbNvmIT5DQLfRTfaB7kFsgbOTFWHO0CL0GdxFD7O/nJqPJiNHrz9ZWg7UBaIwfA== X-Received: from qvbiv8.prod.google.com ([2002:ad4:5ce8:0:b0:91b:98e3:fb03]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:620a:6f05:b0:93e:5fff:db02 with SMTP id af79cd13be357-93ebd1dc7camr2778079285a.28.1792012244738; Wed, 14 Oct 2026 14:10:44 -0700 (PDT) Date: Wed, 14 Oct 2026 21:10:38 +0000 In-Reply-To: <20261014211041.1087331-1-namangulati@google.com> Mime-Version: 1.0 References: <20261014211041.1087331-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.176.g3575e65682-goog Message-ID: <20261014211041.1087331-2-namangulati@google.com> Subject: [PATCH v5 1/4] vfio-user: add multi-fd region mmap capability From: Naman Gulati To: qemu-devel@nongnu.org Cc: John Levon , Thanos Makatos , "=?UTF-8?q?C=C3=A9dric=20Le=20Goater?=" , Alex Williamson , Pierrick Bouvier , Matt Evans , Naman Gulati Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::f45; envelope-from=31O_PagsKClE6t5t6zD4tC1z77z4x.v759x5D-wxEx4676z6D.7Az@flex--namangulati.bounces.google.com; helo=mail-qv1-xf45.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5, WEIRD_QUOTING=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792012270711158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the vfio-user protocol specification to allow servers to pass multiple file descriptors for different sparse memory areas within a single device region with capability VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS (0x8001), negotiated via the "sparse_mmap_fds" capability in VFIO_USER_VERSION. VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS defines an array of sparse mmap areas where each area contains: - offset: Start of the area within the device region (BAR). - fd_offset: Start of the mapping within the backing file descriptor. - size: Size of the mappable area. - fd_index: Zero-based index into the array of file descriptors received in the SCM_RIGHTS ancillary data of the VFIO_USER_DEVICE_GET_REGION_INFO reply message. Reviewed-by: Thanos Makatos Signed-off-by: Naman Gulati Reviewed-by: John Levon --- docs/interop/vfio-user.rst | 86 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/docs/interop/vfio-user.rst b/docs/interop/vfio-user.rst index 1c92f442d2..b49781a755 100644 --- a/docs/interop/vfio-user.rst +++ b/docs/interop/vfio-user.rst @@ -125,7 +125,13 @@ Sparse Regions A region can be memory-mappable in whole or in part. When only a subset of= a region can be mapped by the client, a ``VFIO_REGION_INFO_CAP_SPARSE_MMAP`` capability is included in the region info reply. This capability describes -which portions can be mapped by the client. +which portions can be mapped by the client. When sparse mmap areas are bac= ked +by multiple distinct file descriptors, a +``VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS`` capability is included in the reg= ion +info reply instead. ``VFIO_REGION_INFO_CAP_SPARSE_MMAP`` and +``VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS`` cannot both be specified for the = same +region; however, different regions of a device may independently use either +capability. =20 .. Note:: For example, in a virtual NVMe controller, sparse regions can be used so @@ -536,6 +542,10 @@ Capabilities: | write_multiple | boolean | ``VFIO_USER_REGION_WRITE_MULTI`` messages= | | | | are supported if the value is ``true``. = | +--------------------+---------+------------------------------------------= -----+ +| sparse_mmap_fds | boolean | ``VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS`` = | +| | | capability is supported if the value is = | +| | | ``true``. = | ++--------------------+---------+------------------------------------------= -----+ =20 The ``twin_socket`` capability object holds these name/value pairs: =20 @@ -859,9 +869,11 @@ Reply * ``VFIO_REGION_INFO_FLAG_READ`` allows client read access to the region. * ``VFIO_REGION_INFO_FLAG_WRITE`` allows client write access to the regi= on. * ``VFIO_REGION_INFO_FLAG_MMAP`` specifies the client can mmap() the reg= ion. - When this flag is set, the reply will include a file descriptor in its - meta-data. On ``AF_UNIX`` sockets, the file descriptors will be passed= as - ``SCM_RIGHTS`` type ancillary data. + When this flag is set, the reply will include one or more file descrip= tors + in its meta-data (up to the number of sparse mmap areas when + ``VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS`` is present, or a single file + descriptor otherwise). On ``AF_UNIX`` sockets, the file descriptors wi= ll be + passed as ``SCM_RIGHTS`` type ancillary data. * ``VFIO_REGION_INFO_FLAG_CAPS`` indicates additional capabilities found= in the reply. =20 @@ -950,6 +962,72 @@ The VFIO sparse mmap area is defined in ```` (``struct vfio_region_info_cap_sparse_mmap``). =20 =20 +VFIO sparse mmap fds cap header +""""""""""""""""""""""""""""""" + ++----------------------+--------------------------------------+ +| Name | Value | ++=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=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+ +| id | VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS | ++----------------------+--------------------------------------+ +| version | 0x1 | ++----------------------+--------------------------------------+ +| next | | ++----------------------+--------------------------------------+ +| sparse mmap fds info | VFIO region info sparse mmap fds | ++----------------------+--------------------------------------+ + +This capability is defined when a region supports direct access by the cli= ent +via mmap() where different sparse mmap areas are backed by distinct file +descriptors in the ``SCM_RIGHTS`` ancillary data array. The server may only +include this capability if the client advertised ``sparse_mmap_fds`` as +``true`` in ``VFIO_USER_VERSION``. Capability ID +``VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS`` is defined as ``0x8001`` to avoid +clashing with kernel VFIO capabilities. + +VFIO region info cap sparse mmap fds +"""""""""""""""""""""""""""""""""""" + ++-----------+--------+------+ +| Name | Offset | Size | ++=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+ +| nr_areas | 0 | 4 | ++-----------+--------+------+ +| reserved | 4 | 4 | ++-----------+--------+------+ +| offset | 8 | 8 | ++-----------+--------+------+ +| fd_offset | 16 | 8 | ++-----------+--------+------+ +| size | 24 | 8 | ++-----------+--------+------+ +| fd_index | 32 | 4 | ++-----------+--------+------+ +| pad | 36 | 4 | ++-----------+--------+------+ +| ... | | | ++-----------+--------+------+ + +* *nr_areas* is the number of sparse mmap areas in the region. +* *offset*, *fd_offset*, *size*, and *fd_index* describe a single area tha= t can be + mapped by the client. There will be *nr_areas* tuples of offset, fd_offs= et, size, + fd_index, and pad. Sparse mmap areas must not overlap. +* *offset* specifies the start of the area within the device region (BAR). +* *fd_offset* specifies the start of the mapping within the backing file d= escriptor + referenced by *fd_index*. +* *size* specifies the size of the area. Zero-sized areas (*size* equal to= 0) + are not permitted, and *offset* + *size* must not exceed the region *siz= e*. +* *fd_index* is the zero-based index into the array of file descriptors + received in the ``SCM_RIGHTS`` ancillary data of the + ``VFIO_USER_DEVICE_GET_REGION_INFO`` reply message. The number of file + descriptors sent in ``SCM_RIGHTS`` must be at least 1 and must not exceed + *nr_areas*. + +If all sparse mmap areas are backed by a single file descriptor, the server +may instead send ``VFIO_REGION_INFO_CAP_SPARSE_MMAP`` and exactly one file +descriptor in ``SCM_RIGHTS`` for compatibility with older clients. + + ``VFIO_USER_DEVICE_GET_REGION_IO_FDS`` -------------------------------------- =20 --=20 2.56.0.385.gd3acb90ef8-goog From nobody Thu Oct 22 19:25:18 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792012275; cv=none; d=zohomail.com; s=zohoarc; b=MEMxp7ABDD1BySYgjkkqR7eiQSGAFibq/tIwC7zyw54SbBcA+c5S2Kh5hhqBtXgWp8tm6hf5H9sURGgPvQyYXh+c4F/LnNrjFu7CcGPVaxkXrBNiAj0SNRe2NVnlCsOuiixrkgvVgsXHtVa/4L9vUh8jbbW01bQ05y/rsoX0dqA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792012275; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=FppzXirk5nbi9kcMOQQwDE1EGZz6Q2GpCC2ECGaKeOQ=; b=npLpURCsHy0BuLfeevR5TXoE1+yy3kO03fud5SKevgAqHUBsnzzYbSSDIdU5xGybpJydKnRQN8Rr7LhuXjc1M+ogoqJ8G2cIGl6gCEcEioM5vTB4HFMWBxyoCioGXwplACn7tF3EAhlJ0Gbvh2Rs86zFkN5KDnZpcEn97XSxxeo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792012275826371.46007649751255; Wed, 14 Oct 2026 14:11:15 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xH6FV-0007M9-Ux; Wed, 14 Oct 2026 17:10:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <31e_PagsKClI7u6u70E5uD208805y.w86Ay6E-xyFy578707E.8B0@flex--namangulati.bounces.google.com>) id 1xH6FS-0007Cn-Os for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:54 -0400 Received: from mail-qv1-xf45.google.com ([2607:f8b0:4864:20::f45]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <31e_PagsKClI7u6u70E5uD208805y.w86Ay6E-xyFy578707E.8B0@flex--namangulati.bounces.google.com>) id 1xH6FQ-0001Di-5S for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:54 -0400 Received: by mail-qv1-xf45.google.com with SMTP id 6a1803df08f44-91b8c60c550so81487026d6.0 for ; Wed, 14 Oct 2026 14:10:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792012246; x=1792617046; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=FppzXirk5nbi9kcMOQQwDE1EGZz6Q2GpCC2ECGaKeOQ=; b=u/9ecppcNrMnAxU62XTywYU5QRMIYbBJ3BPtqfIDfnYnNm1gappG302AOsQB6W3g06 9AAnWwduPJUxw7R+atjNH/vkIMoncHmeUpnqV5tj1Apyz6jIR/i/djSMAJI0Ih4efIie Cd8w2fxxGFYbKDjYxXN1Yp1tcw574bgw6KuHbzkT+8x7URD4NJ1DJGnzXk5J7htL73rt egXoCafM25i6VtCwueSAeaHOmrMMunS6YUQMtGu2sWBjDkuTctchm5UF3OdUtFoEiNqD kIWb8hsen5j7cymZSMPNDycHkiqqSATmaO/IKtTCywFJUitj+cUKLpa1uNFGl8HwZfbL b0dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792012246; x=1792617046; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=FppzXirk5nbi9kcMOQQwDE1EGZz6Q2GpCC2ECGaKeOQ=; b=Nhw/ae7J6BeIDGS1u6giDUF0mQF3NA1X6lA1YhL9IzkYoaXRUFTr1MBF0io2k43tiv 31DkCk7LvbDvM+uzltJAPWlxHYydUvKDH3eEVYgZaOnbga90sMQO87UQr1n4aX7Dbs0q aUx4VuObkrwzauKOdfSZnaLVcaKD8nG07+qKEGfZZEN8J4jDJb+wSH5hCnrqLIWDhxLH 2J7f7kb+3jmHIDQ5VPeXlEAPAh0JEQkM0cau4/lU1tG/uK7zGSykIvAWKcPH7DIjd7bz Dw6kmBJNqax/MffMeUCoJ8E7BZEkAunftJdNS9tIuBk7xWl3IBCMyuRhVf+CEy4fx3Y3 FKUw== X-Gm-Message-State: AFq9FYLGpBSufOl1KW+72TGRjcdo8SxqEOiZKfCo7AX2Jt3qFbsP4TLV PJ/4h1yOvltIHO0dKQc5p6dir2BdnaoxpUVuVwY+XaywmefqVmHT3+1htwHGMCtJiY0L5uZh2q9 olDP0qyKIYss1wSW+L2tNsGvWcf7IB9eUfhiXwToyFREY8H4tKuE7eT2OO5vRGxSgDFP5Gq2Eus kXe2ZWQNZwRfZExojWi7H1eZ/9prtTxksgEl/PjpDhKu316hX0pt21HRvFV/cWuA== X-Received: from qvuc11.prod.google.com ([2002:a05:6214:1eb:b0:919:85db:35a7]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6214:5085:b0:917:8d3f:29da with SMTP id 6a1803df08f44-91b557cbea3mr298663626d6.27.1792012245728; Wed, 14 Oct 2026 14:10:45 -0700 (PDT) Date: Wed, 14 Oct 2026 21:10:39 +0000 In-Reply-To: <20261014211041.1087331-1-namangulati@google.com> Mime-Version: 1.0 References: <20261014211041.1087331-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.176.g3575e65682-goog Message-ID: <20261014211041.1087331-3-namangulati@google.com> Subject: [PATCH v5 2/4] vfio: add 'fd' and 'fd_offset' to VFIOMmap From: Naman Gulati To: qemu-devel@nongnu.org Cc: John Levon , Thanos Makatos , "=?UTF-8?q?C=C3=A9dric=20Le=20Goater?=" , Alex Williamson , Pierrick Bouvier , Matt Evans , Naman Gulati Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::f45; envelope-from=31e_PagsKClI7u6u70E5uD208805y.w86Ay6E-xyFy578707E.8B0@flex--namangulati.bounces.google.com; helo=mail-qv1-xf45.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792012277055158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow each sparse mmap subregion to specify its own file descriptor and file offset for the mmap call. Add 'fd' (set to -1 when the region fd should be used) and 'fd_offset' to VFIOMmap, and update vfio_region_mmap() to use them. Reviewed-by: Thanos Makatos Signed-off-by: Naman Gulati Reviewed-by: C=C3=A9dric Le Goater Reviewed-by: John Levon --- hw/vfio/vfio-region.h | 4 +++- hw/vfio/pci.c | 2 ++ hw/vfio/region.c | 26 +++++++++++++++++++------- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/hw/vfio/vfio-region.h b/hw/vfio/vfio-region.h index 58b236f113..9f6a5cf7d5 100644 --- a/hw/vfio/vfio-region.h +++ b/hw/vfio/vfio-region.h @@ -14,8 +14,10 @@ typedef struct VFIOMmap { MemoryRegion mem; void *mmap; - off_t offset; + off_t offset; /* offset within the region */ size_t size; + int fd; /* per-mmap fd, or -1 to use the region fd */ + uint64_t fd_offset; /* offset within fd for the mmap call */ } VFIOMmap; =20 typedef struct VFIODevice VFIODevice; diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index 428ab2f069..f851082114 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -1623,6 +1623,7 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice = *vdev) vdev->msix->table_bar, 0, 0); } else { region->mmaps[0].offset =3D end; + region->mmaps[0].fd_offset +=3D end; region->mmaps[0].size =3D region->size - end; trace_vfio_msix_fixup(vdev->vbasedev.name, vdev->msix->table_bar, region->mmaps[0].offs= et, @@ -1649,6 +1650,7 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice = *vdev) region->mmaps[0].offset + region->mmaps[0].s= ize); =20 region->mmaps[1].offset =3D end; + region->mmaps[1].fd_offset +=3D end; region->mmaps[1].size =3D region->size - end; trace_vfio_msix_fixup(vdev->vbasedev.name, vdev->msix->table_bar, region->mmaps[1].offs= et, diff --git a/hw/vfio/region.c b/hw/vfio/region.c index 54ad11a6c8..16efed2fce 100644 --- a/hw/vfio/region.c +++ b/hw/vfio/region.c @@ -189,6 +189,9 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *r= egion, sparse->areas[i].size - 1); region->mmaps[j].offset =3D sparse->areas[i].offset; region->mmaps[j].size =3D sparse->areas[i].size; + region->mmaps[j].fd =3D -1; + region->mmaps[j].fd_offset =3D region->fd_offset + + sparse->areas[i].offset; j++; } } @@ -262,6 +265,8 @@ int vfio_region_setup(Object *obj, VFIODevice *vbasedev= , VFIORegion *region, region->mmaps =3D g_new0(VFIOMmap, region->nr_mmaps); region->mmaps[0].offset =3D 0; region->mmaps[0].size =3D region->size; + region->mmaps[0].fd =3D -1; + region->mmaps[0].fd_offset =3D region->fd_offset; } else if (ret) { return ret; } @@ -354,7 +359,6 @@ int vfio_region_mmap(VFIORegion *region) off_t map_offset =3D 0; size_t align; char *name; - int fd; =20 if (!region->mem || !region->nr_mmaps) { return 0; @@ -391,8 +395,6 @@ int vfio_region_mmap(VFIORegion *region) return ret; } =20 - fd =3D vfio_device_get_region_fd(region->vbasedev, region->nr); - map_align =3D (void *)ROUND_UP((uintptr_t)map_base, (uintptr_t)align); munmap(map_base, map_align - map_base); munmap(map_align + region->size, @@ -404,12 +406,22 @@ int vfio_region_mmap(VFIORegion *region) * offsets being in ascending order. */ for (i =3D 0; i < region->nr_mmaps; i++) { + int fd =3D region->mmaps[i].fd; + + if (fd < 0) { + fd =3D vfio_device_get_region_fd(region->vbasedev, region->nr); + } + if (fd < 0) { + ret =3D -EINVAL; + munmap(map_align + map_offset, region->size - map_offset); + goto no_mmap; + } + munmap(map_align + map_offset, region->mmaps[i].offset - map_offse= t); region->mmaps[i].mmap =3D mmap(map_align + region->mmaps[i].offset, region->mmaps[i].size, prot, MAP_SHARED | MAP_FIXED, fd, - region->fd_offset + - region->mmaps[i].offset); + region->mmaps[i].fd_offset); if (region->mmaps[i].mmap =3D=3D MAP_FAILED) { ret =3D -errno; /* @@ -454,8 +466,8 @@ int vfio_region_mmap(VFIORegion *region) =20 no_mmap: trace_vfio_region_mmap_fault(memory_region_name(region->mem), i, - region->fd_offset + region->mmaps[i].offs= et, - region->fd_offset + region->mmaps[i].offs= et + + region->mmaps[i].fd_offset, + region->mmaps[i].fd_offset + region->mmaps[i].size - 1, ret); =20 region->mmaps[i].mmap =3D NULL; --=20 2.56.0.385.gd3acb90ef8-goog From nobody Thu Oct 22 19:25:18 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792012289; cv=none; d=zohomail.com; s=zohoarc; b=m9VQfd/yWdYVPUBhHTkKED4eIKWxnfeqdxQRICgDNyQHwkbUjEpHQQJFE0R1h2H2puQqkJye3S6zKB6TqWuFnBg6+GUaRCbsDsdWEuYXOnkhty8hxoSs+RDeUrYuE+5siNwkNSiHJxOLvvjPT7C2S/rtHudjSSM2C3rf2e/Y4+w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792012289; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BHAaWWEJMCHHxNcrFC5T+b9snoojTnLGaAfiiw4oB8c=; b=EktAMEcKFmu+wRaP+YkWxxVtX4MetHYo2xOAiulDzoKVJMJxVy6tpZBSWTz37jesvU5RLYY7C3zT1U8RvBBEGxbpdA3jOul1sFs5Myp4JrByH09N5ZeSdj0vlNb6h/brMT28WVALJwrTjENh3omgYQMgLRspirpRfrCtR+2vI/Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792012289370184.85547319511056; Wed, 14 Oct 2026 14:11:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xH6FT-0007Ga-Vk; Wed, 14 Oct 2026 17:10:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <31u_PagsKClM8v7v81F6vE319916z.x97Bz7F-yzGz689818F.9C1@flex--namangulati.bounces.google.com>) id 1xH6FS-0007CU-HE for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:54 -0400 Received: from mail-yw1-x1146.google.com ([2607:f8b0:4864:20::1146]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <31u_PagsKClM8v7v81F6vE319916z.x97Bz7F-yzGz689818F.9C1@flex--namangulati.bounces.google.com>) id 1xH6FP-0001Dm-P5 for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:54 -0400 Received: by mail-yw1-x1146.google.com with SMTP id 00721157ae682-88322409239so52774117b3.1 for ; Wed, 14 Oct 2026 14:10:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792012247; x=1792617047; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=BHAaWWEJMCHHxNcrFC5T+b9snoojTnLGaAfiiw4oB8c=; b=AhKq1em9azmIrc41DYw/mBp3H54wGBXvnHTR0yRWSnCMfetR7KUGgEjWPprGjUXEbC bN47xLvCVXmAsqWiuo0VZbhoj62tI40fuiR44ZHEKD94kNSP72YYUbi4EvqCl8ENqZBV 0af/b0/2wk/QCM35aEiEG5kKmCyRaRUU7T5DN/wgmd+jgUIeZJ48scWmJDpqzqCBPC3G 8JnvkqF+HBgMiJIihvleL0p2S+g71yCtDCyrD2SU1LjO2OYLRmHsYE433o+g6VCuuDWD fkRvm7rxPdEgEsPEEOYqZkmG/T76QuebpWan/lshbqqqXYZjXK6AoWY93NQG3YpLSWzM +NQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792012247; x=1792617047; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BHAaWWEJMCHHxNcrFC5T+b9snoojTnLGaAfiiw4oB8c=; b=Q62WrxxaWcIegQNfBQlfPNEtowzmbNRv2TVZ38g1PSnTBxde5FtV7bB0TrEYOVN4LR cMnEgrLIHgThrVc2n1qp0j4N7eL1dQUHnDjA0GX2V8P1VStCcj3CRUByrjFoTQaTEUj2 wn+eC021k0ttNf51t4QDsNemsEmPQoJvQzttCsI/maNNOxeT7+a6tFSlPC7ZoxK5cyP0 Pt6jqcTsFZOZiEdZmXORUIBXpFs3lKQ33v3+dXHLmnOa4GOrvytD3nkS/3tetUvkZ7v8 ZeIC3K7Uryy4ot7iEDzlcpne9uBcCTXkK97g81A1W+5WAIzleKPyDLT7rgsgUcspiZVb xeww== X-Gm-Message-State: AFq9FYLmbJJGA3v3NjiIoUxROvkCPe4GWAlPNqmuiePuNP8GVH8TJlne eMCSycHeWo/TFulcFO3Xf2B1zVerJYqQrRMdB2EaMSrWh/4lKKT+2YFWif8JMsg0n5B7feX9BaQ C5hMdLwM0AC/WDu8VkTWQURBFl2rkCv41t0U9q3xE7ATTsRd9l3Blo0vLpPnnEYL0T+8b6g5Tu6 r8tsDROkyYqUobXmpOqFm33KN2si/1UN5K1UUIoZwMKFI6oyCCJ9FnhfWC3rvIKA== X-Received: from ywb9.prod.google.com ([2002:a05:690c:9509:b0:8ac:6bf3:16a6]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:690c:10d:b0:8b0:88b7:cfe3 with SMTP id 00721157ae682-8b088b7d19bmr60655457b3.40.1792012246749; Wed, 14 Oct 2026 14:10:46 -0700 (PDT) Date: Wed, 14 Oct 2026 21:10:40 +0000 In-Reply-To: <20261014211041.1087331-1-namangulati@google.com> Mime-Version: 1.0 References: <20261014211041.1087331-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.176.g3575e65682-goog Message-ID: <20261014211041.1087331-4-namangulati@google.com> Subject: [PATCH v5 3/4] vfio: add setup_sparse_mmaps hook to VFIODeviceIOOps From: Naman Gulati To: qemu-devel@nongnu.org Cc: John Levon , Thanos Makatos , "=?UTF-8?q?C=C3=A9dric=20Le=20Goater?=" , Alex Williamson , Pierrick Bouvier , Matt Evans , Naman Gulati Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::1146; envelope-from=31u_PagsKClM8v7v81F6vE319916z.x97Bz7F-yzGz689818F.9C1@flex--namangulati.bounces.google.com; helo=mail-yw1-x1146.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792012290997158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a setup_sparse_mmaps callback to VFIODeviceIOOps so transport backends (such as vfio-user) can parse custom sparse mmap capabilities, falling back to vfio_default_setup_sparse_mmaps() to process shared VFIO mmap capabilities. Reviewed-by: Thanos Makatos Signed-off-by: Naman Gulati Reviewed-by: C=C3=A9dric Le Goater Reviewed-by: John Levon --- hw/vfio/vfio-region.h | 5 +++++ include/hw/vfio/vfio-device.h | 16 ++++++++++++++++ hw/vfio/device.c | 1 + hw/vfio/region.c | 19 ++++++++++++++++--- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hw/vfio/vfio-region.h b/hw/vfio/vfio-region.h index 9f6a5cf7d5..a0c9533f9f 100644 --- a/hw/vfio/vfio-region.h +++ b/hw/vfio/vfio-region.h @@ -46,4 +46,9 @@ void vfio_region_mmaps_set_enabled(VFIORegion *region, bo= ol enabled); void vfio_region_exit(VFIORegion *region); void vfio_region_finalize(VFIORegion *region); =20 +struct vfio_region_info; +int vfio_default_setup_sparse_mmaps(VFIORegion *region, + struct vfio_region_info *info, + Error **errp); + #endif /* HW_VFIO_REGION_H */ diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h index 8472420d3f..3136e152f2 100644 --- a/include/hw/vfio/vfio-device.h +++ b/include/hw/vfio/vfio-device.h @@ -43,6 +43,7 @@ enum { =20 typedef struct VFIODeviceOps VFIODeviceOps; typedef struct VFIODeviceIOOps VFIODeviceIOOps; +typedef struct VFIORegion VFIORegion; typedef struct VFIOMigration VFIOMigration; =20 typedef struct IOMMUFDBackend IOMMUFDBackend; @@ -218,6 +219,21 @@ struct VFIODeviceIOOps { int (*get_region_info)(VFIODevice *vdev, struct vfio_region_info *info, int *fd); =20 + /** + * @setup_sparse_mmaps + * + * Parse sparse mmap capabilities for a region and initialize region->= mmaps. + * + * @region: #VFIORegion to set up + * @info: region info struct containing capabilities + * @errp: pointer to Error*, to store an error if it happens + * + * Returns 0 on success, -ENODEV if not sparse, or negative error code. + */ + int (*setup_sparse_mmaps)(VFIORegion *region, + struct vfio_region_info *info, + Error **errp); + /** * @get_irq_info * diff --git a/hw/vfio/device.c b/hw/vfio/device.c index 4f11959633..94d6e7ce09 100644 --- a/hw/vfio/device.c +++ b/hw/vfio/device.c @@ -662,6 +662,7 @@ static VFIODeviceIOOps vfio_device_io_ops_ioctl =3D { =20 .device_feature =3D vfio_device_io_device_feature, .get_region_info =3D vfio_device_io_get_region_info, + .setup_sparse_mmaps =3D vfio_default_setup_sparse_mmaps, .get_irq_info =3D vfio_device_io_get_irq_info, .set_irqs =3D vfio_device_io_set_irqs, .region_read =3D vfio_device_io_region_read, diff --git a/hw/vfio/region.c b/hw/vfio/region.c index 16efed2fce..94cfb708bf 100644 --- a/hw/vfio/region.c +++ b/hw/vfio/region.c @@ -162,9 +162,9 @@ static int vfio_mmap_compare_offset(const void *a, cons= t void *b) return 0; } =20 -static int vfio_setup_region_sparse_mmaps(VFIORegion *region, - struct vfio_region_info *info, - Error **errp) +int vfio_default_setup_sparse_mmaps(VFIORegion *region, + struct vfio_region_info *info, + Error **errp) { struct vfio_info_cap_header *hdr; struct vfio_region_info_cap_sparse_mmap *sparse; @@ -198,6 +198,19 @@ static int vfio_setup_region_sparse_mmaps(VFIORegion *= region, =20 region->nr_mmaps =3D j; region->mmaps =3D g_realloc(region->mmaps, j * sizeof(VFIOMmap)); + return 0; +} + +static int vfio_setup_region_sparse_mmaps(VFIORegion *region, + struct vfio_region_info *info, + Error **errp) +{ + int ret, i; + + ret =3D region->vbasedev->io_ops->setup_sparse_mmaps(region, info, err= p); + if (ret) { + return ret; + } =20 /* * Sort sparse mmaps by offset to ensure proper handling of gaps --=20 2.56.0.385.gd3acb90ef8-goog From nobody Thu Oct 22 19:25:18 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=google.com ARC-Seal: i=1; a=rsa-sha256; t=1792012304; cv=none; d=zohomail.com; s=zohoarc; b=iMBuPzX9ioj8lyEbQPGoGrqQejsSXcJ/f8I3UssKJNyi6cbPX69mMD5finBxPx0keY9IkAaOhCdtUiaP8yVNcLyLI+94QpiEAQKZql22Xjgvp+P7fm2aeevrom58AAs+hg/DEU4/1OjPI1T67UyJ5wEkjig33/QYfH7pfO7j4cM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792012304; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=He/Kolb9n738un8N+H51VZf/wJDaOi503JnwQBDbw0k=; b=SRHfMaKi3W0ORg4OpORrzIO83pXfnbeSKpdb9s1JXCcz4GlMzeEDfdUVTjXFBV98q7CdxlQxhTSqNaSRhq48oAj30CTrUJHfzwcmCSiXrjT1Gs/MgMQ9Z3Um+Ik7a/XFCrmuiWK/0X0z4c+Wy8ApgMmugbP//c1ixn8jQfNWeFU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1792012304455657.8788432180731; Wed, 14 Oct 2026 14:11:44 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xH6FU-0007J0-KV; Wed, 14 Oct 2026 17:10:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from <31-_PagsKClQ9w8w92G7wF42AA270.yA8C08G-z0H079A929G.AD2@flex--namangulati.bounces.google.com>) id 1xH6FT-0007E3-BD for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:55 -0400 Received: from mail-qv1-xf45.google.com ([2607:f8b0:4864:20::f45]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <31-_PagsKClQ9w8w92G7wF42AA270.yA8C08G-z0H079A929G.AD2@flex--namangulati.bounces.google.com>) id 1xH6FQ-0001Dq-3x for qemu-devel@nongnu.org; Wed, 14 Oct 2026 17:10:54 -0400 Received: by mail-qv1-xf45.google.com with SMTP id 6a1803df08f44-9179a556c43so95521826d6.3 for ; Wed, 14 Oct 2026 14:10:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792012248; x=1792617048; darn=nongnu.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=He/Kolb9n738un8N+H51VZf/wJDaOi503JnwQBDbw0k=; b=O+wrx4eqyxOc/yVDE97TvqgfHt0ocW6QWgVIfl8FMLZe08JNGmbyS5QJIgTTxXKg05 Aoa9wEI7N7iiVpAU7O1v7sm14qVODnlf7gLwXyeVvfK/JICvY2k/p6rwG14aFcY2ozcf 2T3Kgtl+yuqro+6E2nASNGlr1KAFnvp8jzwuUdXDypBj0bWGhe35ImueYLeIknEwKs+g ZvdPBnH1TfX0XCFhdvs9kxelLgrcLb2MCzC8fMCVU38MrpQpt8lyFYOsk+paQ7sLZIka XZ3dvtDqwb+qvRW1j29XBYVNseYiDosDta4cU12T+1EmnV3AtTxLYM9UjSTOKPlBYkf+ S7eA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792012248; x=1792617048; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=He/Kolb9n738un8N+H51VZf/wJDaOi503JnwQBDbw0k=; b=jhkcAT0QKtxhuOqE6gQFc52Hkk+MvMg6OOO9zRpX2KO/SAoxkvNsp+v1Vbg9oaCaTf N+dFq9wr34ezbn7DAVw70Nx+1KUBBgS8kP0L25nu6htRzgYkOahZTC/Z5OImWMtuOyx6 86FI46p2FOETML6j6vlBnPybdGI5352uBKfOY8hBdSQL3OGNKdCW3oRUDS3Ynz/l16Kl SlRRPgzzlbuh2FNUEZUC8+neMiKHPryWzLQJBU4ch1LVsKg6/RgVVf57XyWtsuDE/zdi hUXmWnQFkkKDurYwwQrHcTPFUY+SirPJKj3lbEtbzucUP5k2Y9czmRXv+kvgidquYe/Z bn1w== X-Gm-Message-State: AFq9FYIF9JEe5Ot1emOYxYoRQShEICSISLzN+bRwm6MfMeUaUMB0U42z 1psGGU7D7cZ2Gn3aJqxRIpKrll2W1EyWjGh/Mr2Iamb7qIr8jo2po3UuFxEzKX9cEAWVlFeSVbw iiDgdI19xrBxymsodz7TVDEtF7JwKaPm/wkjoT70BrEBX4FY0s2Sr0NMo/k3Klw/WTekg8EC6c9 K70elSZeEgaCSuuhkJQ3i2qlbhw/qbjjC5J1dA8AkzJTmtT9vBgQxgRRh0ismOOw== X-Received: from qkcbr5-n2.prod.google.com ([2002:a05:620a:90c5:20b0:93f:a6c:3612]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:620a:17ac:b0:93e:5cf8:e5a4 with SMTP id af79cd13be357-93ebd27554amr2640283085a.58.1792012247868; Wed, 14 Oct 2026 14:10:47 -0700 (PDT) Date: Wed, 14 Oct 2026 21:10:41 +0000 In-Reply-To: <20261014211041.1087331-1-namangulati@google.com> Mime-Version: 1.0 References: <20261014211041.1087331-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.176.g3575e65682-goog Message-ID: <20261014211041.1087331-5-namangulati@google.com> Subject: [PATCH v5 4/4] vfio-user: support multiple FDs for sparse mmap regions From: Naman Gulati To: qemu-devel@nongnu.org Cc: John Levon , Thanos Makatos , "=?UTF-8?q?C=C3=A9dric=20Le=20Goater?=" , Alex Williamson , Pierrick Bouvier , Matt Evans , Naman Gulati Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::f45; envelope-from=31-_PagsKClQ9w8w92G7wF42AA270.yA8C08G-z0H079A929G.AD2@flex--namangulati.bounces.google.com; helo=mail-qv1-xf45.google.com X-Spam_score_int: -95 X-Spam_score: -9.6 X-Spam_bar: --------- X-Spam_report: (-9.6 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_MED=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, USER_IN_DEF_DKIM_WL=-7.5 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @google.com) X-ZM-MESSAGEID: 1792012305394158500 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add client support for capability VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS (capability ID 0x8001) in vfio-user, and advertise support via the "sparse_mmap_fds" capability in VFIO_USER_VERSION. Update vfio_user_device_io_get_region_info() to receive multiple file descriptors passed in SCM_RIGHTS ancillary data for a region, store them in VFIOUserProxy, and implement setup_sparse_mmaps in vfio_user_device_io_ops_sock to validate and populate per-area file descriptors and fd_offset values. Signed-off-by: Naman Gulati --- hw/vfio-user/protocol.h | 35 ++++++++++-- hw/vfio-user/proxy.h | 2 + hw/vfio-user/device.c | 121 +++++++++++++++++++++++++++++++++++++--- hw/vfio-user/proxy.c | 52 +++++++++++++++-- 4 files changed, 193 insertions(+), 17 deletions(-) diff --git a/hw/vfio-user/protocol.h b/hw/vfio-user/protocol.h index c478d1353f..b823689254 100644 --- a/hw/vfio-user/protocol.h +++ b/hw/vfio-user/protocol.h @@ -15,6 +15,8 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ =20 +#define VFIO_USER_MAX_REGIONS 100 + typedef struct { uint16_t id; uint16_t command; @@ -69,12 +71,13 @@ typedef struct { #define VFIO_USER_CAP "capabilities" =20 /* "capabilities" members */ -#define VFIO_USER_CAP_MAX_FDS "max_msg_fds" -#define VFIO_USER_CAP_MAX_XFER "max_data_xfer_size" -#define VFIO_USER_CAP_PGSIZES "pgsizes" -#define VFIO_USER_CAP_MAP_MAX "max_dma_maps" -#define VFIO_USER_CAP_MIGR "migration" -#define VFIO_USER_CAP_MULTI "write_multiple" +#define VFIO_USER_CAP_MAX_FDS "max_msg_fds" +#define VFIO_USER_CAP_MAX_XFER "max_data_xfer_size" +#define VFIO_USER_CAP_PGSIZES "pgsizes" +#define VFIO_USER_CAP_MAP_MAX "max_dma_maps" +#define VFIO_USER_CAP_MIGR "migration" +#define VFIO_USER_CAP_MULTI "write_multiple" +#define VFIO_USER_CAP_SPARSE_MMAP_FDS "sparse_mmap_fds" =20 /* "migration" members */ #define VFIO_USER_CAP_PGSIZE "pgsize" @@ -166,6 +169,26 @@ typedef struct { uint64_t offset; } VFIOUserRegionInfo; =20 +/* + * VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS + */ +#define VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS 0x8001 + +struct vfio_region_sparse_mmap_fd_area { + uint64_t offset; + uint64_t fd_offset; + uint64_t size; + uint32_t fd_index; + uint32_t pad; +}; + +struct vfio_region_info_cap_sparse_mmap_fds { + struct vfio_info_cap_header header; + uint32_t nr_areas; + uint32_t reserved; + struct vfio_region_sparse_mmap_fd_area areas[]; +}; + /* * VFIO_USER_DEVICE_GET_IRQ_INFO * imported from struct vfio_irq_info diff --git a/hw/vfio-user/proxy.h b/hw/vfio-user/proxy.h index 7b97460cc5..4b9834a436 100644 --- a/hw/vfio-user/proxy.h +++ b/hw/vfio-user/proxy.h @@ -72,6 +72,7 @@ typedef struct VFIOUserProxy { AioContext *ctx; QEMUBH *req_bh; bool async_ops; + VFIOUserFDs *region_fds[VFIO_USER_MAX_REGIONS]; =20 /* * above only changed when BQL is held @@ -111,6 +112,7 @@ bool vfio_user_validate_version(VFIOUserProxy *proxy, E= rror **errp); =20 VFIOUserFDs *vfio_user_getfds(int numfds); void vfio_user_putfds(VFIOUserMsg *msg); +void vfio_user_free_fds(VFIOUserFDs *fds); =20 void vfio_user_disable_posted_writes(VFIOUserProxy *proxy); =20 diff --git a/hw/vfio-user/device.c b/hw/vfio-user/device.c index 1a01e748cd..4fbf536a04 100644 --- a/hw/vfio-user/device.c +++ b/hw/vfio-user/device.c @@ -14,12 +14,14 @@ =20 #include "hw/vfio-user/device.h" #include "hw/vfio-user/trace.h" +#include "hw/vfio/vfio-region.h" +#include "hw/vfio/vfio-helpers.h" +#include "hw/vfio/trace.h" =20 /* * These are to defend against a malign server trying * to force us to run out of memory. */ -#define VFIO_USER_MAX_REGIONS 100 #define VFIO_USER_MAX_IRQS 50 =20 bool vfio_user_get_device_info(VFIOUserProxy *proxy, @@ -209,14 +211,17 @@ static int vfio_user_device_io_get_region_info(VFIODe= vice *vbasedev, struct vfio_region_info *in= fo, int *fd) { - VFIOUserFDs fds =3D { 0, 1, fd}; - int ret; + int fds[VFIO_USER_MAX_MAX_FDS]; + VFIOUserFDs user_fds =3D { 0, VFIO_USER_MAX_MAX_FDS, fds }; + int i, ret; + + *fd =3D -1; =20 if (info->index > vbasedev->num_initial_regions) { return -EINVAL; } =20 - ret =3D vfio_user_get_region_info(vbasedev->proxy, info, &fds); + ret =3D vfio_user_get_region_info(vbasedev->proxy, info, &user_fds); if (ret) { return ret; } @@ -225,10 +230,30 @@ static int vfio_user_device_io_get_region_info(VFIODe= vice *vbasedev, if ((info->flags & VFIO_REGION_INFO_FLAG_CAPS) && (info->cap_offset < sizeof(*info) || info->cap_offset + sizeof(struct vfio_info_cap_header) > info-= >argsz)) { - return -EINVAL; + ret =3D -EINVAL; + } else if (vfio_get_region_info_cap(info, + VFIO_REGION_INFO_CAP_SPARSE_MMAP_F= DS)) { + if (user_fds.recv_fds > 0) { + VFIOUserFDs *saved =3D vfio_user_getfds(user_fds.recv_fds); + + saved->recv_fds =3D user_fds.recv_fds; + memcpy(saved->fds, fds, user_fds.recv_fds * sizeof(int)); + vfio_user_free_fds(vbasedev->proxy->region_fds[info->index]); + vbasedev->proxy->region_fds[info->index] =3D saved; + return 0; + } + ret =3D -EINVAL; + } else if (user_fds.recv_fds > 0) { + *fd =3D fds[0]; + fds[0] =3D -1; } =20 - return 0; + for (i =3D 0; i < user_fds.recv_fds; i++) { + if (fds[i] >=3D 0) { + close(fds[i]); + } + } + return ret; } =20 static int vfio_user_device_io_get_irq_info(VFIODevice *vbasedev, @@ -518,12 +543,94 @@ static int vfio_user_device_io_region_write(VFIODevic= e *vbasedev, uint8_t index, /* * Socket-based io_ops */ +static int vfio_user_device_io_setup_sparse_mmaps(VFIORegion *region, + struct vfio_region_info = *info, + Error **errp) +{ + struct vfio_info_cap_header *hdr; + struct vfio_region_info_cap_sparse_mmap_fds *sparse_fds; + VFIOUserFDs *user_fds; + size_t cap_offset; + int i; + + hdr =3D vfio_get_region_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMA= P_FDS); + if (!hdr) { + return vfio_default_setup_sparse_mmaps(region, info, errp); + } + + if (vfio_get_region_info_cap(info, VFIO_REGION_INFO_CAP_SPARSE_MMAP)) { + error_setg(errp, "%s: region %d cannot specify both " + "SPARSE_MMAP and SPARSE_MMAP_FDS", __func__, region->nr= ); + return -EINVAL; + } + + sparse_fds =3D container_of(hdr, struct vfio_region_info_cap_sparse_mm= ap_fds, + header); + + cap_offset =3D (uintptr_t)hdr - (uintptr_t)info; + if (cap_offset > info->argsz || + info->argsz - cap_offset < sizeof(*sparse_fds) || + sparse_fds->nr_areas > + (info->argsz - cap_offset - sizeof(*sparse_fds)) / + sizeof(sparse_fds->areas[0])) { + error_setg(errp, "%s: invalid nr_areas %u in region %d", + __func__, sparse_fds->nr_areas, region->nr); + return -EINVAL; + } + + trace_vfio_region_sparse_mmap_header(region->vbasedev->name, + region->nr, sparse_fds->nr_areas); + + user_fds =3D region->vbasedev->proxy->region_fds[region->nr]; + if (!user_fds || user_fds->recv_fds > sparse_fds->nr_areas) { + error_setg(errp, "%s: invalid fd count %d for %u sparse mmap areas= " + "in region %d", __func__, + user_fds ? user_fds->recv_fds : 0, + sparse_fds->nr_areas, region->nr); + return -EINVAL; + } + + region->mmaps =3D g_try_new0(VFIOMmap, sparse_fds->nr_areas); + if (!region->mmaps) { + error_setg(errp, "%s: failed to allocate %u mmaps for region %d", + __func__, sparse_fds->nr_areas, region->nr); + return -ENOMEM; + } + + for (i =3D 0; i < sparse_fds->nr_areas; i++) { + struct vfio_region_sparse_mmap_fd_area *area =3D &sparse_fds->area= s[i]; + + if (area->size =3D=3D 0 || area->offset > region->size || + area->size > region->size - area->offset || + area->fd_index >=3D user_fds->recv_fds) { + error_setg(errp, "%s: invalid sparse mmap area %d in region %d= " + "(offset=3D0x%"PRIx64" size=3D0x%"PRIx64 + " fd_offset=3D0x%"PRIx64" fd_index=3D%u)", + __func__, i, region->nr, area->offset, area->size, + area->fd_offset, area->fd_index); + g_free(region->mmaps); + region->mmaps =3D NULL; + return -EINVAL; + } + + trace_vfio_region_sparse_mmap_entry(i, area->offset, + area->offset + area->size - 1); + region->mmaps[i].offset =3D area->offset; + region->mmaps[i].fd_offset =3D area->fd_offset; + region->mmaps[i].size =3D area->size; + region->mmaps[i].fd =3D user_fds->fds[area->fd_index]; + } + + region->nr_mmaps =3D sparse_fds->nr_areas; + return 0; +} + VFIODeviceIOOps vfio_user_device_io_ops_sock =3D { .device_feature =3D vfio_user_device_io_device_feature, .get_region_info =3D vfio_user_device_io_get_region_info, + .setup_sparse_mmaps =3D vfio_user_device_io_setup_sparse_mmaps, .get_irq_info =3D vfio_user_device_io_get_irq_info, .set_irqs =3D vfio_user_device_io_set_irqs, .region_read =3D vfio_user_device_io_region_read, .region_write =3D vfio_user_device_io_region_write, - }; diff --git a/hw/vfio-user/proxy.c b/hw/vfio-user/proxy.c index 197aee07bf..ba29085321 100644 --- a/hw/vfio-user/proxy.c +++ b/hw/vfio-user/proxy.c @@ -363,6 +363,13 @@ static int vfio_user_recv_one(VFIOUserProxy *proxy, Er= ror **errp) } =20 memcpy(msg->fds->fds, fdp, numfds * sizeof(int)); + } else if (msg->fds !=3D NULL) { + /* + * recv_fds holds the capacity of msg->fds->fds on entry; reset it + * to 0 when the reply carries no FDs so the caller knows none were + * received. + */ + msg->fds->recv_fds =3D 0; } =20 /* @@ -740,6 +747,11 @@ bool vfio_user_send_wait(VFIOUserProxy *proxy, VFIOUse= rHdr *hdr, =20 qemu_mutex_unlock(&proxy->lock); =20 + if (!ok && fds !=3D NULL) { + /* No reply was received; report 0 received FDs to the caller. */ + fds->recv_fds =3D 0; + } + return ok; } =20 @@ -867,17 +879,30 @@ void vfio_user_send_error(VFIOUserProxy *proxy, VFIOU= serHdr *hdr, int error) } =20 /* - * Close FDs erroneously received in an incoming request. + * Close and free received FDs. */ -void vfio_user_putfds(VFIOUserMsg *msg) +void vfio_user_free_fds(VFIOUserFDs *fds) { - VFIOUserFDs *fds =3D msg->fds; int i; =20 + if (!fds) { + return; + } + for (i =3D 0; i < fds->recv_fds; i++) { - close(fds->fds[i]); + if (fds->fds[i] >=3D 0) { + close(fds->fds[i]); + } } g_free(fds); +} + +/* + * Close FDs erroneously received in an incoming request. + */ +void vfio_user_putfds(VFIOUserMsg *msg) +{ + vfio_user_free_fds(msg->fds); msg->fds =3D NULL; } =20 @@ -967,6 +992,7 @@ void vfio_user_set_handler(VFIODevice *vbasedev, void vfio_user_disconnect(VFIOUserProxy *proxy) { VFIOUserMsg *r1, *r2; + int i; =20 qemu_mutex_lock(&proxy->lock); =20 @@ -1027,6 +1053,10 @@ void vfio_user_disconnect(VFIOUserProxy *proxy) vfio_user_iothread =3D NULL; } =20 + for (i =3D 0; i < VFIO_USER_MAX_REGIONS; i++) { + vfio_user_free_fds(proxy->region_fds[i]); + } + g_free(proxy->sockname); g_free(proxy); } @@ -1214,6 +1244,18 @@ static bool check_multi(VFIOUserProxy *proxy, QObjec= t *qobj, Error **errp) return true; } =20 +static bool check_sparse_mmap_fds(VFIOUserProxy *proxy, QObject *qobj, + Error **errp) +{ + QBool *qb =3D qobject_to(QBool, qobj); + + if (qb =3D=3D NULL) { + error_setg(errp, "malformed %s", VFIO_USER_CAP_SPARSE_MMAP_FDS); + return false; + } + return true; +} + static struct cap_entry caps_cap[] =3D { { VFIO_USER_CAP_MAX_FDS, check_max_fds }, { VFIO_USER_CAP_MAX_XFER, check_max_xfer }, @@ -1221,6 +1263,7 @@ static struct cap_entry caps_cap[] =3D { { VFIO_USER_CAP_MAP_MAX, check_max_dma }, { VFIO_USER_CAP_MIGR, check_migr }, { VFIO_USER_CAP_MULTI, check_multi }, + { VFIO_USER_CAP_SPARSE_MMAP_FDS, check_sparse_mmap_fds }, { NULL } }; =20 @@ -1280,6 +1323,7 @@ static GString *caps_json(void) qdict_put_int(capdict, VFIO_USER_CAP_PGSIZES, VFIO_USER_DEF_PGSIZE); qdict_put_int(capdict, VFIO_USER_CAP_MAP_MAX, VFIO_USER_DEF_MAP_MAX); qdict_put_bool(capdict, VFIO_USER_CAP_MULTI, true); + qdict_put_bool(capdict, VFIO_USER_CAP_SPARSE_MMAP_FDS, true); =20 qdict_put_obj(dict, VFIO_USER_CAP, QOBJECT(capdict)); =20 --=20 2.56.0.385.gd3acb90ef8-goog