From: <mhonap@nvidia.com>
To: <alex@shazbot.org>, <jgg@ziepe.ca>, <ankita@nvidia.com>,
<jic23@kernel.org>, <dave.jiang@intel.com>,
<alejandro.lucero-palau@amd.com>, <smadhavan@nvidia.com>,
<corbet@lwn.net>, <skhan@linuxfoundation.org>,
<dave@stgolabs.net>, <alison.schofield@intel.com>,
<vishal.l.verma@intel.com>, <iweiny@kernel.org>,
<ming.li@zohomail.com>, <yishaih@nvidia.com>,
<skolothumtho@nvidia.com>, <kevin.tian@intel.com>,
<bhelgaas@google.com>, <dmatlack@google.com>, <kees@kernel.org>,
<gustavoars@kernel.org>
Cc: <cjia@nvidia.com>, <kjaju@nvidia.com>, <vsethi@nvidia.com>,
<zhiw@nvidia.com>, <mhonap@nvidia.com>,
<linux-doc@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<kvm@vger.kernel.org>, <linux-cxl@vger.kernel.org>,
<linux-pci@vger.kernel.org>, <linux-kselftest@vger.kernel.org>,
<linux-hardening@vger.kernel.org>
Subject: [PATCH v6 09/31] vfio/pci: Advertise the mmap areas around excluded ranges
Date: Fri, 16 Oct 2026 21:48:16 +0530 [thread overview]
Message-ID: <20261016161839.2765592-10-mhonap@nvidia.com> (raw)
In-Reply-To: <20261016161839.2765592-1-mhonap@nvidia.com>
From: Manish Honap <mhonap@nvidia.com>
A range excluded from mmap must not be reachable through an mmap of its
BAR. Refuse an mmap that overlaps such a range, and advertise the BAR
with a sparse mmap capability that lists the areas between the excluded
ranges, so a VMM maps those and traps the rest.
mmap is page granular, so each range is rounded out to whole pages, and
ranges that meet after rounding form one hole. The sorted list gives the
areas in two walks: the first counts them and the second fills them.
A BAR without mmap-excluded ranges gets no new capability. The MSI-X
table is excluded from read and write only, so the MSI-X BAR is
unchanged.
Assisted-by: LLM
Signed-off-by: Manish Honap <mhonap@nvidia.com>
---
drivers/vfio/pci/vfio_pci_core.c | 91 ++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index bee3d1b4d8d2..f099a294af34 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1106,6 +1106,88 @@ static void vfio_pci_free_excluded_ranges(struct vfio_pci_core_device *vdev)
}
}
+/* True when [start, start + len) on @bar overlaps a range with any of @flags. */
+static bool vfio_pci_bar_range_excluded(struct vfio_pci_core_device *vdev,
+ int bar, u64 start, u64 len, u32 flags)
+{
+ struct vfio_pci_excluded_range *range;
+
+ /* Only BARs have excluded ranges; a device-specific region has none. */
+ if (bar >= PCI_STD_NUM_BARS)
+ return false;
+
+ list_for_each_entry(range, &vdev->excluded_ranges[bar], entry) {
+ if (range->start >= start + len)
+ break;
+ if ((range->flags & flags) &&
+ start < range->start + range->size)
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Advertise a BAR with mmap-excluded ranges as the mmap-able areas between
+ * them. mmap is page granular, so each range is rounded out to whole pages;
+ * ranges that meet after rounding merge into one hole. The first walk counts
+ * the areas and the second fills them.
+ */
+static int vfio_pci_excluded_sparse_cap(struct vfio_pci_core_device *vdev,
+ int bar, struct vfio_info_cap *caps)
+{
+ struct vfio_region_info_cap_sparse_mmap *sparse __free(kfree) = NULL;
+ u64 bar_len = pci_resource_len(vdev->pdev, bar);
+ struct vfio_pci_excluded_range *range;
+ u32 nr_areas = 0;
+ bool holes = false;
+ u64 pos = 0;
+ u32 i = 0;
+
+ list_for_each_entry(range, &vdev->excluded_ranges[bar], entry) {
+ if (!(range->flags & VFIO_PCI_EXCLUDE_MMAP))
+ continue;
+ holes = true;
+ if (ALIGN_DOWN(range->start, PAGE_SIZE) > pos)
+ nr_areas++;
+ pos = max(pos, ALIGN(range->start + range->size, PAGE_SIZE));
+ }
+ if (!holes)
+ return 0;
+ if (pos < bar_len)
+ nr_areas++;
+
+ sparse = kzalloc_flex(*sparse, areas, nr_areas);
+ if (!sparse)
+ return -ENOMEM;
+
+ sparse->header.id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
+ sparse->header.version = 1;
+ sparse->nr_areas = nr_areas;
+
+ pos = 0;
+ list_for_each_entry(range, &vdev->excluded_ranges[bar], entry) {
+ u64 hole = ALIGN_DOWN(range->start, PAGE_SIZE);
+
+ if (!(range->flags & VFIO_PCI_EXCLUDE_MMAP))
+ continue;
+ if (hole > pos)
+ sparse->areas[i++] = (struct vfio_region_sparse_mmap_area) {
+ .offset = pos,
+ .size = hole - pos,
+ };
+ pos = max(pos, ALIGN(range->start + range->size, PAGE_SIZE));
+ }
+ if (pos < bar_len)
+ sparse->areas[i] = (struct vfio_region_sparse_mmap_area) {
+ .offset = pos,
+ .size = bar_len - pos,
+ };
+
+ return vfio_info_add_capability(caps, &sparse->header,
+ struct_size(sparse, areas, nr_areas));
+}
+
int vfio_pci_core_register_dev_region(struct vfio_pci_core_device *vdev,
unsigned int type, unsigned int subtype,
const struct vfio_pci_regops *ops,
@@ -1254,6 +1336,10 @@ int vfio_pci_ioctl_get_region_info(struct vfio_device *core_vdev,
if (ret)
return ret;
}
+ ret = vfio_pci_excluded_sparse_cap(vdev, info->index,
+ caps);
+ if (ret)
+ return ret;
}
break;
@@ -1947,6 +2033,11 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma
if (req_start + req_len > phys_len)
return -EINVAL;
+ /* An excluded sub-range is reachable only through its trap, not mmap. */
+ if (vfio_pci_bar_range_excluded(vdev, index, req_start, req_len,
+ VFIO_PCI_EXCLUDE_MMAP))
+ return -EINVAL;
+
/*
* Ensure the BAR resource region is reserved for use.
*/
--
2.53.0
next prev parent reply other threads:[~2026-10-16 16:21 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 16:18 [PATCH v6 00/31] vfio/pci: Add CXL Type-2 device passthrough support mhonap
2026-10-16 16:18 ` [PATCH v6 01/31] cxl/regs: Split the BAR block request and ioremap helpers mhonap
2026-10-16 16:18 ` [PATCH v6 02/31] cxl/regs: Let a BAR-owning driver own the component register block mhonap
2026-10-16 16:18 ` [PATCH v6 03/31] cxl: Move component register defines to uapi/cxl/cxl_regs.h mhonap
2026-10-16 16:18 ` [PATCH v6 04/31] PCI/CXL: Let the driver that owns the HDM range run CXL Reset mhonap
2026-10-16 16:18 ` [PATCH v6 05/31] PCI: Refuse bus and slot reset below a CXL port with SBR masked mhonap
2026-10-16 16:18 ` [PATCH v6 06/31] vfio/pci: Add the CXL provider ops registration interface mhonap
2026-10-16 16:18 ` [PATCH v6 07/31] vfio/pci: Detect CXL devices and load the CXL provider on demand mhonap
2026-10-16 16:18 ` [PATCH v6 08/31] vfio/pci: Add a generic excluded-range list mhonap
2026-10-16 16:18 ` mhonap [this message]
2026-10-16 16:18 ` [PATCH v6 10/31] vfio/pci: Refuse ioeventfds and dma-buf exports over excluded ranges mhonap
2026-10-16 16:18 ` [PATCH v6 11/31] vfio/pci: Virtualize the CXL DVSEC in vfio_pci_config.c mhonap
2026-10-16 16:18 ` [PATCH v6 12/31] vfio/pci: Call the CXL open and close hooks around device use mhonap
2026-10-16 16:18 ` [PATCH v6 13/31] vfio/pci: Bracket PCI resets with the CXL reset hooks mhonap
2026-10-16 16:18 ` [PATCH v6 14/31] vfio/pci: Provide an opt-out for the CXL Type-2 extensions mhonap
2026-10-16 16:18 ` [PATCH v6 15/31] vfio/pci: Route every reset point through a try-reset helper mhonap
2026-10-16 16:18 ` [PATCH v6 16/31] vfio/pci: Revoke and re-arm one device-specific region mhonap
2026-10-16 16:18 ` [PATCH v6 17/31] vfio/pci: Call the device provider across low-power transitions mhonap
2026-10-16 16:18 ` [PATCH v6 18/31] vfio/cxl: Add the vfio-cxl provider module skeleton mhonap
2026-10-16 16:18 ` [PATCH v6 19/31] vfio/cxl: Create the CXL memdev and set media ready at bind mhonap
2026-10-16 16:18 ` [PATCH v6 20/31] vfio/cxl: Own the whole component register BAR mhonap
2026-10-16 16:18 ` [PATCH v6 21/31] vfio/cxl: Expose the HDM memory region to the guest mhonap
2026-10-16 16:18 ` [PATCH v6 22/31] vfio/cxl: Allow mmap of the HDM memory region mhonap
2026-10-16 16:18 ` [PATCH v6 23/31] vfio/cxl: Contain HDM memory errors with memory_failure() mhonap
2026-10-16 16:18 ` [PATCH v6 24/31] vfio/cxl: Expose the HDM decoder registers read-only to the guest mhonap
2026-10-16 16:18 ` [PATCH v6 25/31] vfio/cxl: Exclude the HDM decoder registers from direct BAR access mhonap
2026-10-16 16:18 ` [PATCH v6 26/31] vfio/cxl: Restore the HDM decoder after a hot reset mhonap
2026-10-16 16:18 ` [PATCH v6 27/31] vfio/cxl: Describe the CXL device and decoder geometry to userspace mhonap
2026-10-16 16:18 ` [PATCH v6 28/31] vfio/cxl: Export the HDM memory region as a dma-buf mhonap
2026-10-16 16:18 ` [PATCH v6 29/31] vfio/cxl: Run the CXL reset at the vfio reset points mhonap
2026-10-16 16:18 ` [PATCH v6 30/31] Documentation: vfio-pci: Document CXL Type-2 device passthrough mhonap
2026-10-16 16:18 ` [PATCH v6 31/31] selftests/vfio: Add CXL Type-2 passthrough tests mhonap
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261016161839.2765592-10-mhonap@nvidia.com \
--to=mhonap@nvidia.com \
--cc=alejandro.lucero-palau@amd.com \
--cc=alex@shazbot.org \
--cc=alison.schofield@intel.com \
--cc=ankita@nvidia.com \
--cc=bhelgaas@google.com \
--cc=cjia@nvidia.com \
--cc=corbet@lwn.net \
--cc=dave.jiang@intel.com \
--cc=dave@stgolabs.net \
--cc=dmatlack@google.com \
--cc=gustavoars@kernel.org \
--cc=iweiny@kernel.org \
--cc=jgg@ziepe.ca \
--cc=jic23@kernel.org \
--cc=kees@kernel.org \
--cc=kevin.tian@intel.com \
--cc=kjaju@nvidia.com \
--cc=kvm@vger.kernel.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=ming.li@zohomail.com \
--cc=skhan@linuxfoundation.org \
--cc=skolothumtho@nvidia.com \
--cc=smadhavan@nvidia.com \
--cc=vishal.l.verma@intel.com \
--cc=vsethi@nvidia.com \
--cc=yishaih@nvidia.com \
--cc=zhiw@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox