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 16/31] vfio/pci: Revoke and re-arm one device-specific region
Date: Fri, 16 Oct 2026 21:48:23 +0530 [thread overview]
Message-ID: <20261016161839.2765592-17-mhonap@nvidia.com> (raw)
In-Reply-To: <20261016161839.2765592-1-mhonap@nvidia.com>
From: Manish Honap <mhonap@nvidia.com>
The BARs of a vfio PCI device follow the memory enable bit: clearing it
zaps their mmaps and revokes their dma-bufs, and setting it re-arms the
dma-bufs. A device-specific region does not have to follow that bit. The
HDM memory region of a CXL Type-2 device follows the committed HDM
decoder, which changes across reset, bus reset and low power, not with
Memory Space Enable. Other device-specific regions, such as nvgrace
coherent memory or the IGD OpRegion, do not depend on it either.
Record the region index of each dma-buf at export. vfio_pci_dma_buf_move()
now moves only the BAR dma-bufs, and vfio_pci_dma_buf_cleanup() still
drains every dma-buf of the device.
Export vfio_pci_core_revoke_region(), which zaps the user mmaps of one
device-specific region and revokes its dma-bufs, and
vfio_pci_core_rearm_region(), which re-arms them. A provider calls them
under memory_lock when the state its region depends on changes. Also
export __vfio_pci_vmf_insert_pfn(), the pfn insert of
vfio_pci_vmf_insert_pfn() without its memory enable and runtime PM
checks, for the fault handler of such a region. Export
vfio_pci_core_clear_memory_enable() for a provider whose failed
operation left Memory Space off in the device: it zaps the BAR mmaps,
revokes the BAR dma-bufs and clears vfio's record of the bit.
Suggested-by: Alex Williamson <alex@shazbot.org>
Assisted-by: LLM
Signed-off-by: Manish Honap <mhonap@nvidia.com>
---
drivers/vfio/pci/vfio_pci_core.c | 109 +++++++++++++++++++++++++++--
drivers/vfio/pci/vfio_pci_dmabuf.c | 98 +++++++++++++++++---------
drivers/vfio/pci/vfio_pci_priv.h | 7 ++
include/linux/vfio_pci_core.h | 8 +++
4 files changed, 180 insertions(+), 42 deletions(-)
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 6676c561465b..9d0c22a4f3c6 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1982,6 +1982,77 @@ static void vfio_pci_zap_bars(struct vfio_pci_core_device *vdev)
unmap_mapping_range(core_vdev->inode->i_mapping, start, len, true);
}
+/**
+ * vfio_pci_core_revoke_region() - take a device-specific region out of use
+ * @vdev: vfio PCI device, with memory_lock held for write
+ * @index: vfio region index of a device-specific region
+ *
+ * Zap the user mmaps of the region and revoke its dma-bufs, for a provider
+ * whose region depends on device state that is about to change. The BARs
+ * follow the memory enable bit instead; a device-specific region may not.
+ * A later fault on the region goes back to the region's own fault handler.
+ */
+void vfio_pci_core_revoke_region(struct vfio_pci_core_device *vdev,
+ unsigned int index)
+{
+ struct vfio_pci_region *region;
+
+ lockdep_assert_held_write(&vdev->memory_lock);
+
+ if (WARN_ON(index < VFIO_PCI_NUM_REGIONS ||
+ index - VFIO_PCI_NUM_REGIONS >= vdev->num_regions))
+ return;
+
+ region = &vdev->region[index - VFIO_PCI_NUM_REGIONS];
+ unmap_mapping_range(vdev->vdev.inode->i_mapping,
+ VFIO_PCI_INDEX_TO_OFFSET(index), region->size, true);
+ vfio_pci_dma_buf_move_region(vdev, index, true);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_revoke_region);
+
+/**
+ * vfio_pci_core_rearm_region() - put a revoked device-specific region back
+ * @vdev: vfio PCI device, with memory_lock held for write
+ * @index: vfio region index passed to vfio_pci_core_revoke_region()
+ */
+void vfio_pci_core_rearm_region(struct vfio_pci_core_device *vdev,
+ unsigned int index)
+{
+ lockdep_assert_held_write(&vdev->memory_lock);
+
+ vfio_pci_dma_buf_move_region(vdev, index, false);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_rearm_region);
+
+/**
+ * vfio_pci_core_clear_memory_enable() - follow a device that lost Memory Space
+ * @vdev: vfio PCI device, with memory_lock held for write
+ *
+ * For a provider whose failed operation left Memory Space disabled in the
+ * device. Zap the BAR mmaps, revoke the BAR dma-bufs and clear vfio's record
+ * of the Memory Space bit, as a user write that clears the bit would. The
+ * user's next Memory Space write enables it again.
+ */
+void vfio_pci_core_clear_memory_enable(struct vfio_pci_core_device *vdev)
+{
+ __le16 *virt_cmd;
+
+ lockdep_assert_held_write(&vdev->memory_lock);
+
+ /* Closed, or not open yet: vfio_config_init() reads the device. */
+ if (!vdev->vconfig)
+ return;
+
+ virt_cmd = (__le16 *)&vdev->vconfig[PCI_COMMAND];
+ if (!(*virt_cmd & cpu_to_le16(PCI_COMMAND_MEMORY)))
+ return;
+
+ vfio_pci_zap_bars(vdev);
+ vfio_pci_dma_buf_move(vdev, true);
+ *virt_cmd &= cpu_to_le16(~PCI_COMMAND_MEMORY);
+}
+EXPORT_SYMBOL_GPL(vfio_pci_core_clear_memory_enable);
+
void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device *vdev)
{
down_write(&vdev->memory_lock);
@@ -2019,16 +2090,26 @@ static unsigned long vma_to_pfn(struct vm_area_struct *vma)
return (pci_resource_start(vdev->pdev, index) >> PAGE_SHIFT) + pgoff;
}
-vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
- struct vm_fault *vmf,
- unsigned long pfn,
- unsigned int order)
+/**
+ * __vfio_pci_vmf_insert_pfn() - insert a pfn without the memory enable and
+ * runtime PM checks
+ * @vdev: vfio PCI device, with memory_lock held for read
+ * @vmf: the fault being served
+ * @pfn: first pfn to insert
+ * @order: page order of the mapping
+ *
+ * For a device-specific region that does not follow the memory enable bit.
+ * The caller checks the state its region depends on under memory_lock, and
+ * revokes the region with vfio_pci_core_revoke_region() when it changes or
+ * before the device leaves D0.
+ */
+vm_fault_t __vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
+ struct vm_fault *vmf,
+ unsigned long pfn,
+ unsigned int order)
{
lockdep_assert_held_read(&vdev->memory_lock);
- if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
- return VM_FAULT_SIGBUS;
-
if (!order)
return vmf_insert_pfn(vmf->vma, vmf->address, pfn);
@@ -2040,6 +2121,20 @@ vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
return VM_FAULT_FALLBACK;
}
+EXPORT_SYMBOL_GPL(__vfio_pci_vmf_insert_pfn);
+
+vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
+ struct vm_fault *vmf,
+ unsigned long pfn,
+ unsigned int order)
+{
+ lockdep_assert_held_read(&vdev->memory_lock);
+
+ if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
+ return VM_FAULT_SIGBUS;
+
+ return __vfio_pci_vmf_insert_pfn(vdev, vmf, pfn, order);
+}
EXPORT_SYMBOL_GPL(vfio_pci_vmf_insert_pfn);
static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c
index 8606c15ab2fe..d0f7ec5487de 100644
--- a/drivers/vfio/pci/vfio_pci_dmabuf.c
+++ b/drivers/vfio/pci/vfio_pci_dmabuf.c
@@ -19,6 +19,7 @@ struct vfio_pci_dma_buf {
u32 nr_ranges;
struct kref kref;
struct completion comp;
+ u32 region_index;
u8 revoked : 1;
};
@@ -288,6 +289,7 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
priv->vdev = vdev;
priv->nr_ranges = get_dma_buf.nr_ranges;
priv->size = length;
+ priv->region_index = get_dma_buf.region_index;
ret = vdev->pci_ops->get_dmabuf_phys(vdev, &priv->provider,
get_dma_buf.region_index,
priv->phys_vec, dma_ranges,
@@ -347,6 +349,49 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
return ret;
}
+static void vfio_pci_dma_buf_move_one(struct vfio_pci_dma_buf *priv,
+ bool revoked)
+{
+ if (!get_file_active(&priv->dmabuf->file))
+ return;
+
+ if (priv->revoked != revoked) {
+ dma_resv_lock(priv->dmabuf->resv, NULL);
+ if (revoked)
+ priv->revoked = true;
+ dma_buf_invalidate_mappings(priv->dmabuf);
+ dma_resv_wait_timeout(priv->dmabuf->resv,
+ DMA_RESV_USAGE_BOOKKEEP, false,
+ MAX_SCHEDULE_TIMEOUT);
+ dma_resv_unlock(priv->dmabuf->resv);
+ if (revoked) {
+ kref_put(&priv->kref, vfio_pci_dma_buf_done);
+ wait_for_completion(&priv->comp);
+ /*
+ * Re-arm the registered kref reference and the
+ * completion so the post-revoke state matches the
+ * post-creation state. An un-revoke followed by a
+ * new mapping needs the kref to be non-zero before
+ * kref_get(), and vfio_pci_dma_buf_cleanup()
+ * delegates its drain back through this revoke
+ * path on a possibly-already-revoked dma-buf.
+ */
+ kref_init(&priv->kref);
+ reinit_completion(&priv->comp);
+ } else {
+ dma_resv_lock(priv->dmabuf->resv, NULL);
+ priv->revoked = false;
+ dma_resv_unlock(priv->dmabuf->resv);
+ }
+ }
+ fput(priv->dmabuf->file);
+}
+
+/*
+ * Revoke or re-arm the dma-bufs of the BARs, which follow the memory enable
+ * bit. A device-specific region is moved by its provider through
+ * vfio_pci_dma_buf_move_region().
+ */
void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
{
struct vfio_pci_dma_buf *priv;
@@ -354,41 +399,23 @@ void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
lockdep_assert_held_write(&vdev->memory_lock);
- list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
- if (!get_file_active(&priv->dmabuf->file))
- continue;
+ list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm)
+ if (priv->region_index < VFIO_PCI_NUM_REGIONS)
+ vfio_pci_dma_buf_move_one(priv, revoked);
+}
- if (priv->revoked != revoked) {
- dma_resv_lock(priv->dmabuf->resv, NULL);
- if (revoked)
- priv->revoked = true;
- dma_buf_invalidate_mappings(priv->dmabuf);
- dma_resv_wait_timeout(priv->dmabuf->resv,
- DMA_RESV_USAGE_BOOKKEEP, false,
- MAX_SCHEDULE_TIMEOUT);
- dma_resv_unlock(priv->dmabuf->resv);
- if (revoked) {
- kref_put(&priv->kref, vfio_pci_dma_buf_done);
- wait_for_completion(&priv->comp);
- /*
- * Re-arm the registered kref reference and the
- * completion so the post-revoke state matches the
- * post-creation state. An un-revoke followed by a
- * new mapping needs the kref to be non-zero before
- * kref_get(), and vfio_pci_dma_buf_cleanup()
- * delegates its drain back through this revoke
- * path on a possibly-already-revoked dma-buf.
- */
- kref_init(&priv->kref);
- reinit_completion(&priv->comp);
- } else {
- dma_resv_lock(priv->dmabuf->resv, NULL);
- priv->revoked = false;
- dma_resv_unlock(priv->dmabuf->resv);
- }
- }
- fput(priv->dmabuf->file);
- }
+/* Revoke or re-arm the dma-bufs exported from one device-specific region. */
+void vfio_pci_dma_buf_move_region(struct vfio_pci_core_device *vdev,
+ unsigned int index, bool revoked)
+{
+ struct vfio_pci_dma_buf *priv;
+ struct vfio_pci_dma_buf *tmp;
+
+ lockdep_assert_held_write(&vdev->memory_lock);
+
+ list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm)
+ if (priv->region_index == index)
+ vfio_pci_dma_buf_move_one(priv, revoked);
}
void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev)
@@ -405,7 +432,8 @@ void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev)
* ready, so cleanup itself does not need to participate in kref
* bookkeeping.
*/
- vfio_pci_dma_buf_move(vdev, true);
+ list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm)
+ vfio_pci_dma_buf_move_one(priv, true);
list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
if (!get_file_active(&priv->dmabuf->file))
diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h
index dbede6e24fa9..23bccfbb7eb7 100644
--- a/drivers/vfio/pci/vfio_pci_priv.h
+++ b/drivers/vfio/pci/vfio_pci_priv.h
@@ -141,6 +141,8 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
size_t argsz);
void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev);
void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked);
+void vfio_pci_dma_buf_move_region(struct vfio_pci_core_device *vdev,
+ unsigned int index, bool revoked);
#else
static inline int
vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags,
@@ -156,6 +158,11 @@ static inline void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev,
bool revoked)
{
}
+static inline void
+vfio_pci_dma_buf_move_region(struct vfio_pci_core_device *vdev,
+ unsigned int index, bool revoked)
+{
+}
#endif
#endif
diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
index cb9ba92b696a..7dd93ef103cb 100644
--- a/include/linux/vfio_pci_core.h
+++ b/include/linux/vfio_pci_core.h
@@ -227,6 +227,11 @@ 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,
size_t size, u32 flags, void *data);
+void vfio_pci_core_revoke_region(struct vfio_pci_core_device *vdev,
+ unsigned int index);
+void vfio_pci_core_rearm_region(struct vfio_pci_core_device *vdev,
+ unsigned int index);
+void vfio_pci_core_clear_memory_enable(struct vfio_pci_core_device *vdev);
void vfio_pci_core_close_device(struct vfio_device *core_vdev);
int vfio_pci_core_init_dev(struct vfio_device *core_vdev);
void vfio_pci_core_release_dev(struct vfio_device *core_vdev);
@@ -250,6 +255,9 @@ ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
size_t count, loff_t *ppos);
ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
size_t count, loff_t *ppos);
+vm_fault_t __vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
+ struct vm_fault *vmf, unsigned long pfn,
+ unsigned int order);
vm_fault_t vfio_pci_vmf_insert_pfn(struct vfio_pci_core_device *vdev,
struct vm_fault *vmf, unsigned long pfn,
unsigned int order);
--
2.53.0
next prev parent reply other threads:[~2026-10-16 16:23 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 ` [PATCH v6 09/31] vfio/pci: Advertise the mmap areas around excluded ranges mhonap
2026-10-16 16:18 ` [PATCH v6 10/31] vfio/pci: Refuse ioeventfds and dma-buf exports over " 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 ` mhonap [this message]
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-17-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