diff mbox series

[v3,2/3] mm/hmm: allow snapshot of the special zero page

Message ID 20191023195515.13168-3-rcampbell@nvidia.com (mailing list archive)
State Superseded
Delegated to: Jason Gunthorpe
Headers show
Series HMM tests and minor fixes | expand

Commit Message

Ralph Campbell Oct. 23, 2019, 7:55 p.m. UTC
If a device driver like nouveau tries to use hmm_range_fault() to access
the special shared zero page in system memory, hmm_range_fault() will
return -EFAULT and kill the process.
Allow hmm_range_fault() to return success (0) when the CPU pagetable
entry points to the special shared zero page.
page_to_pfn() and pfn_to_page() are defined on the zero page so just
handle it like any other page.

Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Jason Gunthorpe <jgg@mellanox.com>
---
 mm/hmm.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Jerome Glisse Oct. 23, 2019, 8:27 p.m. UTC | #1
On Wed, Oct 23, 2019 at 12:55:14PM -0700, Ralph Campbell wrote:
> If a device driver like nouveau tries to use hmm_range_fault() to access
> the special shared zero page in system memory, hmm_range_fault() will
> return -EFAULT and kill the process.
> Allow hmm_range_fault() to return success (0) when the CPU pagetable
> entry points to the special shared zero page.
> page_to_pfn() and pfn_to_page() are defined on the zero page so just
> handle it like any other page.
> 
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> Cc: Christoph Hellwig <hch@lst.de>

Reviewed-by: "Jérôme Glisse" <jglisse@redhat.com>

> Cc: Jason Gunthorpe <jgg@mellanox.com>
> ---
>  mm/hmm.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/hmm.c b/mm/hmm.c
> index acf7a664b38c..8c96c9ddcae5 100644
> --- a/mm/hmm.c
> +++ b/mm/hmm.c
> @@ -529,8 +529,14 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
>  		if (unlikely(!hmm_vma_walk->pgmap))
>  			return -EBUSY;
>  	} else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
> -		*pfn = range->values[HMM_PFN_SPECIAL];
> -		return -EFAULT;
> +		if (!is_zero_pfn(pte_pfn(pte))) {
> +			*pfn = range->values[HMM_PFN_SPECIAL];
> +			return -EFAULT;
> +		}
> +		/*
> +		 * Since each architecture defines a struct page for the zero
> +		 * page, just fall through and treat it like a normal page.
> +		 */
>  	}
>  
>  	*pfn = hmm_device_entry_from_pfn(range, pte_pfn(pte)) | cpu_flags;
> -- 
> 2.20.1
>
David Hildenbrand Oct. 24, 2019, 9:27 a.m. UTC | #2
On 23.10.19 21:55, Ralph Campbell wrote:
> If a device driver like nouveau tries to use hmm_range_fault() to access
> the special shared zero page in system memory, hmm_range_fault() will
> return -EFAULT and kill the process.
> Allow hmm_range_fault() to return success (0) when the CPU pagetable
> entry points to the special shared zero page.
> page_to_pfn() and pfn_to_page() are defined on the zero page so just
> handle it like any other page.
> 
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: "Jérôme Glisse" <jglisse@redhat.com>
> Cc: Jason Gunthorpe <jgg@mellanox.com>
> ---
>   mm/hmm.c | 10 ++++++++--
>   1 file changed, 8 insertions(+), 2 deletions(-)
> 
> diff --git a/mm/hmm.c b/mm/hmm.c
> index acf7a664b38c..8c96c9ddcae5 100644
> --- a/mm/hmm.c
> +++ b/mm/hmm.c
> @@ -529,8 +529,14 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
>   		if (unlikely(!hmm_vma_walk->pgmap))
>   			return -EBUSY;
>   	} else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
> -		*pfn = range->values[HMM_PFN_SPECIAL];
> -		return -EFAULT;
> +		if (!is_zero_pfn(pte_pfn(pte))) {
> +			*pfn = range->values[HMM_PFN_SPECIAL];
> +			return -EFAULT;
> +		}
> +		/*
> +		 * Since each architecture defines a struct page for the zero
> +		 * page, just fall through and treat it like a normal page.
> +		 */
>   	}
>   
>   	*pfn = hmm_device_entry_from_pfn(range, pte_pfn(pte)) | cpu_flags;
> 

Acked-by: David Hildenbrand <david@redhat.com>
Jason Gunthorpe Oct. 29, 2019, 5:27 p.m. UTC | #3
On Wed, Oct 23, 2019 at 12:55:14PM -0700, Ralph Campbell wrote:
> If a device driver like nouveau tries to use hmm_range_fault() to access
> the special shared zero page in system memory, hmm_range_fault() will
> return -EFAULT and kill the process.
> Allow hmm_range_fault() to return success (0) when the CPU pagetable
> entry points to the special shared zero page.
> page_to_pfn() and pfn_to_page() are defined on the zero page so just
> handle it like any other page.
> 
> Signed-off-by: Ralph Campbell <rcampbell@nvidia.com>
> Cc: Christoph Hellwig <hch@lst.de>
> Cc: "Jérôme Glisse" <jglisse@redhat.com>
> Cc: Jason Gunthorpe <jgg@mellanox.com>
> ---
>  mm/hmm.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)

Applied to hmm.git

Thanks,
Jason
diff mbox series

Patch

diff --git a/mm/hmm.c b/mm/hmm.c
index acf7a664b38c..8c96c9ddcae5 100644
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -529,8 +529,14 @@  static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
 		if (unlikely(!hmm_vma_walk->pgmap))
 			return -EBUSY;
 	} else if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL) && pte_special(pte)) {
-		*pfn = range->values[HMM_PFN_SPECIAL];
-		return -EFAULT;
+		if (!is_zero_pfn(pte_pfn(pte))) {
+			*pfn = range->values[HMM_PFN_SPECIAL];
+			return -EFAULT;
+		}
+		/*
+		 * Since each architecture defines a struct page for the zero
+		 * page, just fall through and treat it like a normal page.
+		 */
 	}
 
 	*pfn = hmm_device_entry_from_pfn(range, pte_pfn(pte)) | cpu_flags;