diff mbox series

[RFC,12/13] iommufd, guestmemfs: Ensure persistent file used for persistent DMA

Message ID 20240916113102.710522-13-jgowans@amazon.com (mailing list archive)
State New, archived
Headers show
Series Support iommu(fd) persistence for live update | expand

Commit Message

Gowans, James Sept. 16, 2024, 11:31 a.m. UTC
When IOASes and hardware page tables are made persistent then DMA will
continue accessing memory which is mapped for DMA during and after
kexec. This is only legal if we are sure that the memory being accessed
by that DMA is also persistent. It would not be legal to map normal
buddy-list managed anonymous memory for persistent DMA.

Currently there is one provider of persistent memory: guestmemfs:
https://lore.kernel.org/all/20240805093245.889357-1-jgowans@amazon.com/

This commit ensures that only guestmemfs memory can be mapped into
persistent iommufds. This is almost certainly the wrong way and place to
do it, but something similar to this is needed. Perhaps in page.c?
As more persistent memory providers become available they can be added
to the list to check for.
---
 drivers/iommu/iommufd/ioas.c | 22 ++++++++++++++++++++++
 fs/guestmemfs/file.c         |  5 +++++
 include/linux/guestmemfs.h   |  7 +++++++
 3 files changed, 34 insertions(+)

Comments

Jason Gunthorpe Oct. 3, 2024, 1:36 p.m. UTC | #1
On Mon, Sep 16, 2024 at 01:31:01PM +0200, James Gowans wrote:

> +#ifdef CONFIG_GUESTMEMFS_FS
> +		struct vm_area_struct *vma;
> +		struct mm_struct *mm = current->mm;
> +
> +		mmap_read_lock(mm);
> +		vma = find_vma_intersection(current->mm,
> +				 cmd->user_va, cmd->user_va + cmd->length);
> +		if (!vma || !is_guestmemfs_file(vma->vm_file)) {
> +			mmap_read_unlock(mm);
> +			return -EFAULT;
> +		}
> +		mmap_read_unlock(mm);
> +#else

Any kind of FD interaction needs to go through the new FD path that
Steve is building:

https://lore.kernel.org/linux-iommu/1727190338-385692-1-git-send-email-steven.sistare@oracle.com

I'm expecting multiple kinds of fds to fall into that pattern,
including memfs, guestmemfd, and dmabuf. guestmemfd can just be one
more..

Jason
diff mbox series

Patch

diff --git a/drivers/iommu/iommufd/ioas.c b/drivers/iommu/iommufd/ioas.c
index 742248276548..ce76b41d2d72 100644
--- a/drivers/iommu/iommufd/ioas.c
+++ b/drivers/iommu/iommufd/ioas.c
@@ -2,9 +2,11 @@ 
 /*
  * Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES
  */
+#include <linux/guestmemfs.h>
 #include <linux/interval_tree.h>
 #include <linux/iommufd.h>
 #include <linux/iommu.h>
+#include <linux/mm_types.h>
 #include <uapi/linux/iommufd.h>
 
 #include "io_pagetable.h"
@@ -217,6 +219,26 @@  int iommufd_ioas_map(struct iommufd_ucmd *ucmd)
 	if (IS_ERR(ioas))
 		return PTR_ERR(ioas);
 
+	pr_info("iommufd_ioas_map persistent id %lu\n",
+			ucmd->ictx->persistent_id);
+	if (ucmd->ictx->persistent_id) {
+#ifdef CONFIG_GUESTMEMFS_FS
+		struct vm_area_struct *vma;
+		struct mm_struct *mm = current->mm;
+
+		mmap_read_lock(mm);
+		vma = find_vma_intersection(current->mm,
+				 cmd->user_va, cmd->user_va + cmd->length);
+		if (!vma || !is_guestmemfs_file(vma->vm_file)) {
+			mmap_read_unlock(mm);
+			return -EFAULT;
+		}
+		mmap_read_unlock(mm);
+#else
+		return -EFAULT;
+#endif /* CONFIG_GUESTMEMFS_FS */
+	}
+
 	if (!(cmd->flags & IOMMU_IOAS_MAP_FIXED_IOVA))
 		flags = IOPT_ALLOC_IOVA;
 	rc = iopt_map_user_pages(ucmd->ictx, &ioas->iopt, &iova,
diff --git a/fs/guestmemfs/file.c b/fs/guestmemfs/file.c
index 8707a9d3ad90..ecacaf200a31 100644
--- a/fs/guestmemfs/file.c
+++ b/fs/guestmemfs/file.c
@@ -104,3 +104,8 @@  const struct file_operations guestmemfs_file_fops = {
 	.owner = THIS_MODULE,
 	.mmap = mmap,
 };
+
+bool is_guestmemfs_file(struct file const *file)
+{
+	return file && file->f_op == &guestmemfs_file_fops;
+}
diff --git a/include/linux/guestmemfs.h b/include/linux/guestmemfs.h
index 60e769c8e533..c5cd7b6a5630 100644
--- a/include/linux/guestmemfs.h
+++ b/include/linux/guestmemfs.h
@@ -3,14 +3,21 @@ 
 #ifndef _LINUX_GUESTMEMFS_H
 #define _LINUX_GUESTMEMFS_H
 
+#include <linux/fs.h>
+
 /*
  * Carves out chunks of memory from memblocks for guestmemfs.
  * Must be called in early boot before memblocks are freed.
  */
 # ifdef CONFIG_GUESTMEMFS_FS
 void guestmemfs_reserve_mem(void);
+bool is_guestmemfs_file(struct file const *filp);
 #else
 void guestmemfs_reserve_mem(void) { }
+inline bool is_guestmemfs_file(struct file const *filp)
+{
+	return 0;
+}
 #endif
 
 #endif