From nobody Sun Oct 25 10:08:00 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=1792795181; cv=none; d=zohomail.com; s=zohoarc; b=L9kyyEqMTQWCsEBnwV2KVSPi7hmm2knZh4cXkA2TuDaiC6eyCsi79ZUdVGT/a2yJ/QY5bhZ4Gq0fk3yKxw4A5JR/jtC+yJBV0lyX1kCt1JT036O1FQjojhhd005RI+mZaBoR5QA2HXEliletxJUBIIqMQaBROSK+HfoecAaA4xc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792795181; 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=Bj9I7NS/Mbo1XKKLr845QtWiXSncejy2rSX4zZ1ZuzE=; b=TUWEy2dvQUymsD7iCL30g2gAOMGkRKcN648z61NnBBsKwwaTFtDt8rcS6SYw48vSjVAQ49BTiTMQaKK0GDTP/JFyHahGmNxStuXTUFJEAczp7D6OVTDGKh6anryChrfsyOBRObSWyWbkXQeBc3q+VjQGPdoBbeDKZUn+ckBJMYY= 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 1792795181501623.694676528345; Fri, 23 Oct 2026 15:39:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xKNuq-0006eG-Ro; Fri, 23 Oct 2026 18:39:13 -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 <3C-LbagsKCpwJ6I6JCQH6PECKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@flex--namangulati.bounces.google.com>) id 1xKNup-0006e1-Sq for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:11 -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 <3C-LbagsKCpwJ6I6JCQH6PECKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@flex--namangulati.bounces.google.com>) id 1xKNun-0002le-V2 for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:11 -0400 Received: by mail-qv1-xf45.google.com with SMTP id 6a1803df08f44-917a7fffbe0so30112966d6.1 for ; Fri, 23 Oct 2026 15:39:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792795148; x=1793399948; 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=Bj9I7NS/Mbo1XKKLr845QtWiXSncejy2rSX4zZ1ZuzE=; b=SVko7xWvpeYVJvZrzcDK278dvHIfrtq7jpl3sw9nSkIdO4HU0rcSOj/WB+qvAnmdgt acPjRR+/sV6CqQ2F60yRV4sMQkgKn6j+kS+UaPVmdIeb+s++KZGdTvvOymToG6/KQwUm xAZ+WPb54C/LwJE0Fy2hxQl+LBKzsArw7z7rkyzqBDKt+23cIb2DrtG/5eBwCbL8rcgV XAOFOpU+j3AYlVnS7QpRifVI38hUJltthHMQLpGjk87TD0m2KM54h2wPYXnkhYRc2I3P b9ij6eU3qPauYAtx+4ujlnNNPdL8bhd/CzlvL83W1ZFgKyAPm0u/7CMG2LAkBUWpQtfO EsKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792795148; x=1793399948; 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=Bj9I7NS/Mbo1XKKLr845QtWiXSncejy2rSX4zZ1ZuzE=; b=BWffjgclpOf0AnRNtThPMgP5yClDnqeNjvAXJ8GuvArKKv4pXI/BVB8eN43pc3WlsG V3o4kNztMKm/3SvdgOZ1IIC8u+IomuFK/aFKZqpb+CQUqlc3pZHB/1AHDSOVkiqwMOcF 1blBMhtKT0VmBnPaOBkUDxSEuwkDgl4Dh1POpzvR8bWoaFvIBBljNUcUHaiCbzKDzyJ+ X+DaQrFEXrmvHVmOdb/yl6AJIxOZK9Yozmswi4unpuqci3vrZDdEYPDfZ8nEJGDHNAKA UxSw+sKyjRbSDjvA7G1W+xZZbZPDsS6bZGVkBfC48oNflEcuJYVz8KGGoEYhXloDiPuS GcxQ== X-Gm-Message-State: AFq9FYIcxzdZyhwASLn9BuVydhNo+jeait1cCRvY7MucpIUlfR+uw/w+ bhT3VyGIH7G1pmk4EVETiJynaZL3NVGcvSYRM4tAFdEgvaoASEW7YZvCpIFN0Pp9Nhae3/MGPMe e0GRujpOhIM7iaiRxR1BASKfj5wwUn2aNT7YUnhMJimkwX9FeCTIUvjMfHsYVP5ob1ilDwFSjAv 0WcZTajNXT5gPFKAwLdvXvNX7kDkJxRQnQNTDHshm7sXfeY857TpfX7t4yiW1H3Q== X-Received: from qvho9.prod.google.com ([2002:ad4:5c89:0:b0:91b:bbc2:a88b]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6214:2b83:b0:91b:d5d7:8c90 with SMTP id 6a1803df08f44-91c48cdbfd0mr7424726d6.5.1792795147611; Fri, 23 Oct 2026 15:39:07 -0700 (PDT) Date: Fri, 23 Oct 2026 22:38:59 +0000 In-Reply-To: <20261023223902.1275539-1-namangulati@google.com> Mime-Version: 1.0 References: <20261023223902.1275539-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.307.g5fe7bd680c-goog Message-ID: <20261023223902.1275539-2-namangulati@google.com> Subject: [PATCH v6 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=3C-LbagsKCpwJ6I6JCQH6PECKKCHA.8KIMAIQ-9ARAHJKJCJQ.KNC@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: 1792795183558158500 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 Reviewed-by: John Levon Signed-off-by: Naman Gulati --- 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.307.g5fe7bd680c-goog From nobody Sun Oct 25 10:08:00 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=1792795194; cv=none; d=zohomail.com; s=zohoarc; b=LdHgRwX9f24VUROpwa+XP2aqFes/e4k/0kKJnnoH3T4nIdHm9rnJ8awNRiPQxlXw7dvewkz6xkbpV28h3KYcauGcMCdIuP7CdxEHXV1qurUxfHyz/xxhsItubpPBndqu6KzIDuDTvCwzZ2htWqupxalFEugnjhkJA2aUeW2HcdU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792795194; h=Content-Type:Content-Transfer-Encoding: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=i3s6G9UXyyWKN96oYix/BdTbsZN/E2nnhD3cWxRyhVQ=; b=ZQU/5TZDH//zYjExtrO0JrI0/GMzfC+2VUVHjaMFqs32+A8aMcFd7eZMufEYr+henxKg2IEYWthDEE/CFYBS4QU7JYLm1Wbt6SGYT6l/4GPyuTkh6GkVUi4f8Q8Z8aAAgmUEcsWInT9PtZPPKZpntEp8A8Wj+TA2yStMHwUNxT8= 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 1792795194891934.5338587848448; Fri, 23 Oct 2026 15:39:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xKNus-0006fA-M6; Fri, 23 Oct 2026 18:39:14 -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 <3DOLbagsKCp0K7J7KDRI7QFDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--namangulati.bounces.google.com>) id 1xKNur-0006eK-1q for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:13 -0400 Received: from mail-qk1-x748.google.com ([2607:f8b0:4864:20::748]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3DOLbagsKCp0K7J7KDRI7QFDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--namangulati.bounces.google.com>) id 1xKNuo-0002li-WD for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:12 -0400 Received: by mail-qk1-x748.google.com with SMTP id af79cd13be357-936aa34873bso265597285a.3 for ; Fri, 23 Oct 2026 15:39:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792795149; x=1793399949; darn=nongnu.org; h=content-transfer-encoding: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=i3s6G9UXyyWKN96oYix/BdTbsZN/E2nnhD3cWxRyhVQ=; b=RyH4CiYYG8K23FaHPWfouNbiNKhMTY5M0kmKOCfA3QDHtjDjsiravinhXQlOhs/J5o +QWhfkJFr1i/hggpueEhVE/oP3uI7MSBLIBQ8AvGYuanA55v+FG7/6AZDTv4lROS5aoi EAKjVxez8mE/xukS6dhTMp4j9x7JSlllZJhPFQuT4b+CR1mdqQG4021sQgDWWAxqZp8B fjDbRBEalljWU4HPQQAf7rTso7rEOAWmptfYzetBc9fw0g/9loAsmBl5KkcVDFaG43R6 xc1UioPHgEpXOYMyv09f8F1RkR48MqV9DfFW/yFEHCF1y3mLZn9aVZBmV6WhZHmIzSnP 6rTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792795149; x=1793399949; h=content-transfer-encoding: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=i3s6G9UXyyWKN96oYix/BdTbsZN/E2nnhD3cWxRyhVQ=; b=0USFPZA7aO9plsEfd9Am39tPZ5bSmjJ0g4yIAue3QuXrI9BBi4PML9WpqTwv6MR4CJ VIOs+m7H8RiZDYZziDCJPplCwo2J/F6Kbwn4eGkHJ2mRYm+XcanByt6XlPGcJQm+OBtP 4dQT0ujclBNXdQOL2h0jZp0EwCfwfomDXEFh7YBqffH9fUohnaW4LPwnOcV9wEGgEaCc BZRmB/Vr3G7jIpc3jYEdDQq+CS1rcpQQMUnzf9Xxm67WIuALASVk0dlabWyooyL18v4e LzkDfLZeIWku0SMtUlSon43D9ESW0ceMtoAoANA/FS27MlVGiq588BZ8zG2pRnn0IPN5 Pg7w== X-Gm-Message-State: AFq9FYLtPjrnuGkmBARXs06te0cBPjXt0ivHPzMmvQl0MQfTB1+FhXjq 06gG0W3EKU4uYtjhfPa+dJHH+fVFmNRj4AfFT42mBJyUpLE8fboPOla5wBvFGeTOxpLgiGKIyRB TtAwfp7E8gYp/g+LA/ChK0UYmllqR6KPqKpvcnLgf7ydHdcCybagPaSQCjSiphT6AhDIQnSQ0ZL tqaEPob0H4pNUUtpi6qo382nvZU2ZU29g2E9shdviAFVYWQN18OZA9GYn2vJrdZA== X-Received: from qkla13.prod.google.com ([2002:a05:620a:124d:b0:93f:a6c:3612]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:620a:6887:b0:93f:567b:6157 with SMTP id af79cd13be357-940ef964f93mr73649685a.46.1792795148719; Fri, 23 Oct 2026 15:39:08 -0700 (PDT) Date: Fri, 23 Oct 2026 22:39:00 +0000 In-Reply-To: <20261023223902.1275539-1-namangulati@google.com> Mime-Version: 1.0 References: <20261023223902.1275539-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.307.g5fe7bd680c-goog Message-ID: <20261023223902.1275539-3-namangulati@google.com> Subject: [PATCH v6 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 Content-Transfer-Encoding: quoted-printable 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::748; envelope-from=3DOLbagsKCp0K7J7KDRI7QFDLLDIB.9LJNBJR-ABSBIKLKDKR.LOD@flex--namangulati.bounces.google.com; helo=mail-qk1-x748.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: 1792795196332158500 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 Reviewed-by: C=C3=A9dric Le Goater Reviewed-by: John Levon Signed-off-by: Naman Gulati --- 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.307.g5fe7bd680c-goog From nobody Sun Oct 25 10:08:00 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=1792795207; cv=none; d=zohomail.com; s=zohoarc; b=H6gkQl2SycUeXxy8WHCGRVPMJKgfk3zaE613H6XCYhUF2GORfC1j1Y10NGH4TV4pSzZZGXNtKF7lOveCBm7QgI7o+sKekmL8VURLxBjMuxykyjRhQv0mnMR2/pp3HmMBUsXSeEFZfk6U6u2UdRwetXNrB8Q2QJikMRBPNe6Fsu8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792795207; h=Content-Type:Content-Transfer-Encoding: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=TG/3qCag+2MZxljLg2V3FvMRPJf+QVtBuFAEftc9fWc=; b=KGMuaS9cUD+d3fkY5I5N6QripLP7WuOc1PakucHbijP0pkTcrTRnByqXnQJPP/0VNbBmZE4upm8qPVcX+zeR7nYlcb8yn4u1Ck64Ou/5ZnV4y2cW9nopTJiK0JZC1b9qy0lQCcbLOGLS0S3LoUHtOoNe9rXho88W4/YbCytEdY4= 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 1792795207207560.0769571421108; Fri, 23 Oct 2026 15:40:07 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xKNut-0006fQ-88; Fri, 23 Oct 2026 18:39:15 -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 <3DeLbagsKCp4L8K8LESJ8RGEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--namangulati.bounces.google.com>) id 1xKNur-0006ec-Kp for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:13 -0400 Received: from mail-qk1-x745.google.com ([2607:f8b0:4864:20::745]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3DeLbagsKCp4L8K8LESJ8RGEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--namangulati.bounces.google.com>) id 1xKNup-0002lq-MC for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:13 -0400 Received: by mail-qk1-x745.google.com with SMTP id af79cd13be357-93f1e62510cso348880485a.1 for ; Fri, 23 Oct 2026 15:39:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792795150; x=1793399950; darn=nongnu.org; h=content-transfer-encoding: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=TG/3qCag+2MZxljLg2V3FvMRPJf+QVtBuFAEftc9fWc=; b=c30ETfrvjVwVpuQqeMhW7rwuZfNfn9SQqPhPF+bldIKlKHwiz7Lnn+ndPDhzeaEzKV uk+8bpyaz6P4cd5aQV87ju6fHlh9Mq7LtRY4YKnsrPZfyAS9SZeGYrLJgiqDu6qnc17L SWRW+52Od75WjEqKNXheDyj+qfI/ZtL7kqaVnn6vyQxpf9lb1UYcYfJdm0A7ZTO8gG0f j+mhhTkszEBZZ1ACwMw19gfigJfZtU8bRZwbvr2ykhnye7Qi9+dbow8jrO5PvZ+C3H8C 6Nm2J8qTdfDmssRDLxkELiWug6/YujdZcxtjedWGzTaf2x7maptlrh9Z/R8Tdx1bINxU kJwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792795150; x=1793399950; h=content-transfer-encoding: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=TG/3qCag+2MZxljLg2V3FvMRPJf+QVtBuFAEftc9fWc=; b=20J0DXAzFsnPynPDPxdaz6ZjQ3ew4xDUQrD9zO4cu48vM7C6JFG2fRqlkvto/o5dHu U2fRQHiVij/iq4e/5m+w5xzCTUcZ9IJh235sDEkd46AG7GjvM4y6fEkmE6JS5Mm5BtVB Y361POqKdmlf9XXV9xbVA+nkbYoe81zcH60JPPzPvsJS3TwVL/ro5qsLff8UVeRDqp8n LmKPBjZ1NQA+VnciSmIFzEXGWG+IvhsDcpoo4Um8ZKPzwE7MtkjzDpddBYNyi5vZwPqJ eru/X7EFK/f0LFvzD8mjVJcfI209neHcu6aZgT4r2wTxi18V323uJIXf0Q/nRbdNTyQ3 NtBA== X-Gm-Message-State: AFq9FYI5qXguxNzdIJPYBhvzrPP7k7ZABx0YNerFVzPStMH+OJv7+m+P wfNOiP/H5X6j7nMZ0eUGxArAWfCnIENQfmlxgcVM+PQlp2UM5OBFQvwFTpZIyqOrE7wo1XDJPFh ahMSGuqeN7LRbOUHj/WvjdSXZSPVjowjB/TCldOZFgqKgPthTXGPzfg/SiFAJKLO+yOK9YRa/8W /NNnwLEMJ9qRihUwWVYnevXLNXgChHtyLyBLQirJX3j7IzMollK7MROnMmV97glg== X-Received: from qvnv9.prod.google.com ([2002:a0c:f909:0:b0:919:91a7:dc5c]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:a05:620a:458e:b0:93a:83d:1d0e with SMTP id af79cd13be357-940ef9526a1mr76758885a.38.1792795149604; Fri, 23 Oct 2026 15:39:09 -0700 (PDT) Date: Fri, 23 Oct 2026 22:39:01 +0000 In-Reply-To: <20261023223902.1275539-1-namangulati@google.com> Mime-Version: 1.0 References: <20261023223902.1275539-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.307.g5fe7bd680c-goog Message-ID: <20261023223902.1275539-4-namangulati@google.com> Subject: [PATCH v6 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 Content-Transfer-Encoding: quoted-printable 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::745; envelope-from=3DeLbagsKCp4L8K8LESJ8RGEMMEJC.AMKOCKS-BCTCJLMLELS.MPE@flex--namangulati.bounces.google.com; helo=mail-qk1-x745.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: 1792795208036158500 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_region_setup_sparse_mmaps() to process shared VFIO mmap capabilities. Reviewed-by: Thanos Makatos Reviewed-by: C=C3=A9dric Le Goater Reviewed-by: John Levon Signed-off-by: Naman Gulati --- 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..abcfbacfff 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_region_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..339c7242ed 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_region_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..8de26f3d9b 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_region_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.307.g5fe7bd680c-goog From nobody Sun Oct 25 10:08:00 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=1792795181; cv=none; d=zohomail.com; s=zohoarc; b=OE8LL5NvgxSg/7J2ku8UApsLbWzpYBQ4TsgcXrRRKj8Y1QhdlNuN+hh37rXEJw5P6W2wkeBbQWex5GgQ0XVuAaY5MAFcFBsbUMgx+HCwn22s19fqz/QCTp1N6sU9AgrP4CNpeARTnG9zlH3hrn2htjtIEkYi3WIrwOPEcYy6OgY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1792795181; 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=Zh4si5+ahjoaX2a6AmK362oqYngcMSaNcjH/8nZt+IU=; b=CQl8Fwxp1Un5CN3UKFGNlZGj/k4cC/l2zeLFWaBup4E3naVpYTOxdal+wOkAnGOrP5wfasl8ClarImMvkx7tXpBwVykZvszGKbHVU4HSvj8Aft73DfHsPTkf57TiLkyk1EA7uxiWcoSF0Ab+SWKLAaMGy4z6x+hu6p2pljaZBjs= 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 1792795181445166.0928032304165; Fri, 23 Oct 2026 15:39:41 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1xKNuu-0006fv-Jy; Fri, 23 Oct 2026 18:39:16 -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 <3DuLbagsKCp8M9L9MFTK9SHFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--namangulati.bounces.google.com>) id 1xKNut-0006fd-7Z for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:15 -0400 Received: from mail-qt1-x846.google.com ([2607:f8b0:4864:20::846]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from <3DuLbagsKCp8M9L9MFTK9SHFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--namangulati.bounces.google.com>) id 1xKNuq-0002lz-My for qemu-devel@nongnu.org; Fri, 23 Oct 2026 18:39:14 -0400 Received: by mail-qt1-x846.google.com with SMTP id d75a77b69052e-5337f26ee19so39679741cf.2 for ; Fri, 23 Oct 2026 15:39:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1792795151; x=1793399951; 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=Zh4si5+ahjoaX2a6AmK362oqYngcMSaNcjH/8nZt+IU=; b=N7QV2dKcDD8Ak8kcPoDOsuPjpPY1jfzrEbBZf1xEe+Ca3uCm5xrtp6gwqax3psnsv7 RcFQZyk/DhmZjHroDBxtO18kaM1Cg3PLIV3ufiq28W02xQyGtXTTnDFa5xg7aEQZTFbs BmUYc5oRY9Zqf92yNJrAIYvdxcZt0MrelfU6pArT/j7JDb0Mj//pekrwALTfsE6Oxwia 2VYve/OAmHHI3sy67Ou5o97leSUxaZWoAD21ZuH9HkFmK5tuTXAxjDKERGjqMnYXsCop +HFEPC72SOqJCCpnDKNcQGnOEJpPHXDdRf7c/a6+I0IzMQiJnZsxwTi0XxsWNV07cn+/ EJ5Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792795151; x=1793399951; 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=Zh4si5+ahjoaX2a6AmK362oqYngcMSaNcjH/8nZt+IU=; b=n6uD4LL5A3S1h99WedGXewNvMZuMuGB0CneAoQhIwQwK0Fc0ELwfR4mR5ROYLLvxgM G7XSXsG/0NJd3NwCgp0WcmeRxvDnlBBdNDimz6L5/LZg/earpHrZlEZQiyJsLqxOvFIa /1lNGAuJPLNvVJillvg/PQuDIIUQSDs7JIzfNR9E98R1OTPEp/4vyaxwPxlwDtI9sG9z lT2HMfAf72wZJq6OBGZVd2j62T7y8FHH1Vu4DlmJXjOWnJqPsfG5s9MbFPZGEdsB0yn3 xHQBk1cb3mfpcoN5QQXwdqx0IpfppwbqgI4JhL7jshJg4myFfhppn18/r9dOg97o3ZQq Ty1g== X-Gm-Message-State: AFq9FYI0T4fABdDqcuBaIxKefe22db3OmgjDKmCCTqCJpqAbnkGP2J4t 0VdRoiJqdbq9NWeRZ0Bjk5Gjkjo34rxxIvHIID5G+JoEKrlipz67jMkdkkDPFoaicaaFKSEJPRb Qj6BUckqZNvd22NIqbL5BJP0SdVrtxpEJAWStRS9kAdd6icHbmSJWC9BywqKmxnrI6EZuVL+UVa 6DWo/mc6TsTId1WINe0YujupUeIiHUSJw2frjQqjWaky80nfGnh9891ZNJqkV4Vw== X-Received: from qtbr5-n2.prod.google.com ([2002:a05:622a:e445:20b0:536:841d:8e1e]) (user=namangulati job=prod-delivery.src-stubby-dispatcher) by 2002:ac8:5d4e:0:b0:536:6378:c7ff with SMTP id d75a77b69052e-5383b66b188mr4632411cf.34.1792795150579; Fri, 23 Oct 2026 15:39:10 -0700 (PDT) Date: Fri, 23 Oct 2026 22:39:02 +0000 In-Reply-To: <20261023223902.1275539-1-namangulati@google.com> Mime-Version: 1.0 References: <20261023223902.1275539-1-namangulati@google.com> X-Mailer: git-send-email 2.56.0.307.g5fe7bd680c-goog Message-ID: <20261023223902.1275539-5-namangulati@google.com> Subject: [PATCH v6 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::846; envelope-from=3DuLbagsKCp8M9L9MFTK9SHFNNFKD.BNLPDLT-CDUDKMNMFMT.NQF@flex--namangulati.bounces.google.com; helo=mail-qt1-x846.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: 1792795183667158500 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. Reviewed-by: Thanos Makatos Signed-off-by: Naman Gulati --- hw/vfio-user/protocol.h | 39 +++++++++++-- hw/vfio-user/proxy.h | 2 + hw/vfio-user/device.c | 126 +++++++++++++++++++++++++++++++++++++--- hw/vfio-user/proxy.c | 52 +++++++++++++++-- 4 files changed, 202 insertions(+), 17 deletions(-) diff --git a/hw/vfio-user/protocol.h b/hw/vfio-user/protocol.h index c478d1353f..b5d258c92b 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,30 @@ typedef struct { uint64_t offset; } VFIOUserRegionInfo; =20 +/* + * VFIO_REGION_INFO_CAP_SPARSE_MMAP_FDS + * + * Capability IDs with the most significant bit set (id >=3D 0x8000) are + * reserved for userspace VFIO extensions (such as vfio-user) to avoid + * colliding with kernel VFIO capabilities. + */ +#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..237e33b57b 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, @@ -179,6 +181,11 @@ static int vfio_user_get_region_info(VFIOUserProxy *pr= oxy, return -EINVAL; } =20 + if (msgp->index !=3D info->index) { + error_printf("vfio_user_get_region_info reply index mismatch\n"); + return -EINVAL; + } + /* * The server can respond with a larger argsz in the reply to request a * larger buffer on the next iteration via vfio_device_get_region_info= (). @@ -209,14 +216,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 +235,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 +548,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_region_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.307.g5fe7bd680c-goog