LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/2] kvm: Use huge pages for DAX-backed files
@ 2018-11-09 20:39 Barret Rhoden
  2018-11-09 20:39 ` [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
                   ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-09 20:39 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

This patch series depends on dax pages not being PageReserved.  Once
that is in place, these changes will let KVM use huge pages with
dax-backed files.  Without the PageReserved change, KVM and DAX still
work with these patches, simply without huge pages - which is the
current situation.

RFC/discussion thread:
https://lore.kernel.org/lkml/20181029210716.212159-1-brho@google.com/

Barret Rhoden (2):
  mm: make dev_pagemap_mapping_shift() externally visible
  kvm: Use huge pages for DAX-backed files

 arch/x86/kvm/mmu.c  | 34 ++++++++++++++++++++++++++++++++--
 include/linux/mm.h  |  3 +++
 mm/memory-failure.c | 38 +++-----------------------------------
 mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 37 deletions(-)

-- 
2.19.1.930.g4563a0d9d0-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible
  2018-11-09 20:39 [PATCH 0/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
@ 2018-11-09 20:39 ` Barret Rhoden
  2018-11-13  9:28   ` David Hildenbrand
  2018-11-09 20:39 ` [PATCH 2/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
  2 siblings, 1 reply; 23+ messages in thread
From: Barret Rhoden @ 2018-11-09 20:39 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Naoya Horiguchi
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang, linux-mm

KVM has a use case for determining the size of a dax mapping.  The KVM
code has easy access to the address and the mm; hence the change in
parameters.

Signed-off-by: Barret Rhoden <brho@google.com>
---
 include/linux/mm.h  |  3 +++
 mm/memory-failure.c | 38 +++-----------------------------------
 mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5411de93a363..51215d695753 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -935,6 +935,9 @@ static inline bool is_pci_p2pdma_page(const struct page *page)
 }
 #endif /* CONFIG_DEV_PAGEMAP_OPS */
 
+unsigned long dev_pagemap_mapping_shift(unsigned long address,
+					struct mm_struct *mm);
+
 static inline void get_page(struct page *page)
 {
 	page = compound_head(page);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 0cd3de3550f0..c3f2c6a8607e 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -265,40 +265,6 @@ void shake_page(struct page *p, int access)
 }
 EXPORT_SYMBOL_GPL(shake_page);
 
-static unsigned long dev_pagemap_mapping_shift(struct page *page,
-		struct vm_area_struct *vma)
-{
-	unsigned long address = vma_address(page, vma);
-	pgd_t *pgd;
-	p4d_t *p4d;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-
-	pgd = pgd_offset(vma->vm_mm, address);
-	if (!pgd_present(*pgd))
-		return 0;
-	p4d = p4d_offset(pgd, address);
-	if (!p4d_present(*p4d))
-		return 0;
-	pud = pud_offset(p4d, address);
-	if (!pud_present(*pud))
-		return 0;
-	if (pud_devmap(*pud))
-		return PUD_SHIFT;
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
-		return 0;
-	if (pmd_devmap(*pmd))
-		return PMD_SHIFT;
-	pte = pte_offset_map(pmd, address);
-	if (!pte_present(*pte))
-		return 0;
-	if (pte_devmap(*pte))
-		return PAGE_SHIFT;
-	return 0;
-}
-
 /*
  * Failure handling: if we can't find or can't kill a process there's
  * not much we can do.	We just print a message and ignore otherwise.
@@ -329,7 +295,9 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
 	tk->addr = page_address_in_vma(p, vma);
 	tk->addr_valid = 1;
 	if (is_zone_device_page(p))
-		tk->size_shift = dev_pagemap_mapping_shift(p, vma);
+		tk->size_shift =
+			dev_pagemap_mapping_shift(vma_address(page, vma),
+						  vma->vm_mm);
 	else
 		tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT;
 
diff --git a/mm/util.c b/mm/util.c
index 8bf08b5b5760..61bc9bab931d 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -780,3 +780,37 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
 out:
 	return res;
 }
+
+unsigned long dev_pagemap_mapping_shift(unsigned long address,
+					struct mm_struct *mm)
+{
+	pgd_t *pgd;
+	p4d_t *p4d;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = pgd_offset(mm, address);
+	if (!pgd_present(*pgd))
+		return 0;
+	p4d = p4d_offset(pgd, address);
+	if (!p4d_present(*p4d))
+		return 0;
+	pud = pud_offset(p4d, address);
+	if (!pud_present(*pud))
+		return 0;
+	if (pud_devmap(*pud))
+		return PUD_SHIFT;
+	pmd = pmd_offset(pud, address);
+	if (!pmd_present(*pmd))
+		return 0;
+	if (pmd_devmap(*pmd))
+		return PMD_SHIFT;
+	pte = pte_offset_map(pmd, address);
+	if (!pte_present(*pte))
+		return 0;
+	if (pte_devmap(*pte))
+		return PAGE_SHIFT;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pagemap_mapping_shift);
-- 
2.19.1.930.g4563a0d9d0-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-09 20:39 [PATCH 0/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
  2018-11-09 20:39 ` [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
@ 2018-11-09 20:39 ` Barret Rhoden
  2018-11-12 19:31   ` Paolo Bonzini
  2018-11-13  9:36   ` David Hildenbrand
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
  2 siblings, 2 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-09 20:39 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

This change allows KVM to map DAX-backed files made of huge pages with
huge mappings in the EPT/TDP.

DAX pages are not PageTransCompound.  The existing check is trying to
determine if the mapping for the pfn is a huge mapping or not.  For
non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
For DAX, we can check the page table itself.

Note that KVM already faulted in the page (or huge page) in the host's
page table, and we hold the KVM mmu spinlock (grabbed before checking
the mmu seq).

Signed-off-by: Barret Rhoden <brho@google.com>
---
 arch/x86/kvm/mmu.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index cf5f572f2305..2df8c459dc6a 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3152,6 +3152,36 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
 	return -EFAULT;
 }
 
+static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
+{
+	struct page *page = pfn_to_page(pfn);
+	unsigned long hva, map_shift;
+
+	if (!is_zone_device_page(page))
+		return PageTransCompoundMap(page);
+
+	/*
+	 * DAX pages do not use compound pages.  The page should have already
+	 * been mapped into the host-side page table during try_async_pf(), so
+	 * we can check the page tables directly.
+	 */
+	hva = gfn_to_hva(kvm, gfn);
+	if (kvm_is_error_hva(hva))
+		return false;
+
+	/*
+	 * Our caller grabbed the KVM mmu_lock with a successful
+	 * mmu_notifier_retry, so we're safe to walk the page table.
+	 */
+	map_shift = dev_pagemap_mapping_shift(hva, current->mm);
+	switch (map_shift) {
+	case PMD_SHIFT:
+	case PUD_SIZE:
+		return true;
+	}
+	return false;
+}
+
 static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 					gfn_t *gfnp, kvm_pfn_t *pfnp,
 					int *levelp)
@@ -3168,7 +3198,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 	 */
 	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
 	    level == PT_PAGE_TABLE_LEVEL &&
-	    PageTransCompoundMap(pfn_to_page(pfn)) &&
+	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
 	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
 		unsigned long mask;
 		/*
@@ -5678,7 +5708,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
 		 */
 		if (sp->role.direct &&
 			!kvm_is_reserved_pfn(pfn) &&
-			PageTransCompoundMap(pfn_to_page(pfn))) {
+			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
 			pte_list_remove(rmap_head, sptep);
 			need_tlb_flush = 1;
 			goto restart;
-- 
2.19.1.930.g4563a0d9d0-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-09 20:39 ` [PATCH 2/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
@ 2018-11-12 19:31   ` Paolo Bonzini
  2018-11-13 16:21     ` Barret Rhoden
  2018-11-13  9:36   ` David Hildenbrand
  1 sibling, 1 reply; 23+ messages in thread
From: Paolo Bonzini @ 2018-11-12 19:31 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams, Dave Jiang, Ross Zwisler,
	Vishal Verma, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

On 09/11/2018 21:39, Barret Rhoden wrote:
> This change allows KVM to map DAX-backed files made of huge pages with
> huge mappings in the EPT/TDP.
> 
> DAX pages are not PageTransCompound.  The existing check is trying to
> determine if the mapping for the pfn is a huge mapping or not.  For
> non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
> For DAX, we can check the page table itself.
> 
> Note that KVM already faulted in the page (or huge page) in the host's
> page table, and we hold the KVM mmu spinlock (grabbed before checking
> the mmu seq).
> 
> Signed-off-by: Barret Rhoden <brho@google.com>
> ---
>  arch/x86/kvm/mmu.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)

Looks good.  What's the plan for removing PageReserved from DAX pages?

Thanks,

Paolo

> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index cf5f572f2305..2df8c459dc6a 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -3152,6 +3152,36 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
>  	return -EFAULT;
>  }
>  
> +static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
> +{
> +	struct page *page = pfn_to_page(pfn);
> +	unsigned long hva, map_shift;
> +
> +	if (!is_zone_device_page(page))
> +		return PageTransCompoundMap(page);
> +
> +	/*
> +	 * DAX pages do not use compound pages.  The page should have already
> +	 * been mapped into the host-side page table during try_async_pf(), so
> +	 * we can check the page tables directly.
> +	 */
> +	hva = gfn_to_hva(kvm, gfn);
> +	if (kvm_is_error_hva(hva))
> +		return false;
> +
> +	/*
> +	 * Our caller grabbed the KVM mmu_lock with a successful
> +	 * mmu_notifier_retry, so we're safe to walk the page table.
> +	 */
> +	map_shift = dev_pagemap_mapping_shift(hva, current->mm);
> +	switch (map_shift) {
> +	case PMD_SHIFT:
> +	case PUD_SIZE:
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>  					gfn_t *gfnp, kvm_pfn_t *pfnp,
>  					int *levelp)
> @@ -3168,7 +3198,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>  	 */
>  	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
>  	    level == PT_PAGE_TABLE_LEVEL &&
> -	    PageTransCompoundMap(pfn_to_page(pfn)) &&
> +	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
>  	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
>  		unsigned long mask;
>  		/*
> @@ -5678,7 +5708,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
>  		 */
>  		if (sp->role.direct &&
>  			!kvm_is_reserved_pfn(pfn) &&
> -			PageTransCompoundMap(pfn_to_page(pfn))) {
> +			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
>  			pte_list_remove(rmap_head, sptep);
>  			need_tlb_flush = 1;
>  			goto restart;
> 


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible
  2018-11-09 20:39 ` [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
@ 2018-11-13  9:28   ` David Hildenbrand
  0 siblings, 0 replies; 23+ messages in thread
From: David Hildenbrand @ 2018-11-13  9:28 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Naoya Horiguchi
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang, linux-mm

On 09.11.18 21:39, Barret Rhoden wrote:
> KVM has a use case for determining the size of a dax mapping.  The KVM
> code has easy access to the address and the mm; hence the change in
> parameters.
> 
> Signed-off-by: Barret Rhoden <brho@google.com>
> ---
>  include/linux/mm.h  |  3 +++
>  mm/memory-failure.c | 38 +++-----------------------------------
>  mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+), 35 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 5411de93a363..51215d695753 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -935,6 +935,9 @@ static inline bool is_pci_p2pdma_page(const struct page *page)
>  }
>  #endif /* CONFIG_DEV_PAGEMAP_OPS */
>  
> +unsigned long dev_pagemap_mapping_shift(unsigned long address,
> +					struct mm_struct *mm);
> +
>  static inline void get_page(struct page *page)
>  {
>  	page = compound_head(page);
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 0cd3de3550f0..c3f2c6a8607e 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -265,40 +265,6 @@ void shake_page(struct page *p, int access)
>  }
>  EXPORT_SYMBOL_GPL(shake_page);
>  
> -static unsigned long dev_pagemap_mapping_shift(struct page *page,
> -		struct vm_area_struct *vma)
> -{
> -	unsigned long address = vma_address(page, vma);
> -	pgd_t *pgd;
> -	p4d_t *p4d;
> -	pud_t *pud;
> -	pmd_t *pmd;
> -	pte_t *pte;
> -
> -	pgd = pgd_offset(vma->vm_mm, address);
> -	if (!pgd_present(*pgd))
> -		return 0;
> -	p4d = p4d_offset(pgd, address);
> -	if (!p4d_present(*p4d))
> -		return 0;
> -	pud = pud_offset(p4d, address);
> -	if (!pud_present(*pud))
> -		return 0;
> -	if (pud_devmap(*pud))
> -		return PUD_SHIFT;
> -	pmd = pmd_offset(pud, address);
> -	if (!pmd_present(*pmd))
> -		return 0;
> -	if (pmd_devmap(*pmd))
> -		return PMD_SHIFT;
> -	pte = pte_offset_map(pmd, address);
> -	if (!pte_present(*pte))
> -		return 0;
> -	if (pte_devmap(*pte))
> -		return PAGE_SHIFT;
> -	return 0;
> -}
> -
>  /*
>   * Failure handling: if we can't find or can't kill a process there's
>   * not much we can do.	We just print a message and ignore otherwise.
> @@ -329,7 +295,9 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
>  	tk->addr = page_address_in_vma(p, vma);
>  	tk->addr_valid = 1;
>  	if (is_zone_device_page(p))
> -		tk->size_shift = dev_pagemap_mapping_shift(p, vma);
> +		tk->size_shift =
> +			dev_pagemap_mapping_shift(vma_address(page, vma),
> +						  vma->vm_mm);
>  	else
>  		tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT;
>  
> diff --git a/mm/util.c b/mm/util.c
> index 8bf08b5b5760..61bc9bab931d 100644
> --- a/mm/util.c
> +++ b/mm/util.c
> @@ -780,3 +780,37 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
>  out:
>  	return res;
>  }
> +
> +unsigned long dev_pagemap_mapping_shift(unsigned long address,
> +					struct mm_struct *mm)
> +{
> +	pgd_t *pgd;
> +	p4d_t *p4d;
> +	pud_t *pud;
> +	pmd_t *pmd;
> +	pte_t *pte;
> +
> +	pgd = pgd_offset(mm, address);
> +	if (!pgd_present(*pgd))
> +		return 0;
> +	p4d = p4d_offset(pgd, address);
> +	if (!p4d_present(*p4d))
> +		return 0;
> +	pud = pud_offset(p4d, address);
> +	if (!pud_present(*pud))
> +		return 0;
> +	if (pud_devmap(*pud))
> +		return PUD_SHIFT;
> +	pmd = pmd_offset(pud, address);
> +	if (!pmd_present(*pmd))
> +		return 0;
> +	if (pmd_devmap(*pmd))
> +		return PMD_SHIFT;
> +	pte = pte_offset_map(pmd, address);
> +	if (!pte_present(*pte))
> +		return 0;
> +	if (pte_devmap(*pte))
> +		return PAGE_SHIFT;
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(dev_pagemap_mapping_shift);
> 

Looks good to me

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-09 20:39 ` [PATCH 2/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
  2018-11-12 19:31   ` Paolo Bonzini
@ 2018-11-13  9:36   ` David Hildenbrand
  2018-11-13 10:02     ` Pankaj Gupta
  2018-11-13 15:50     ` Barret Rhoden
  1 sibling, 2 replies; 23+ messages in thread
From: David Hildenbrand @ 2018-11-13  9:36 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

On 09.11.18 21:39, Barret Rhoden wrote:
> This change allows KVM to map DAX-backed files made of huge pages with
> huge mappings in the EPT/TDP.
> 
> DAX pages are not PageTransCompound.  The existing check is trying to
> determine if the mapping for the pfn is a huge mapping or not.  For
> non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
> For DAX, we can check the page table itself.
> 
> Note that KVM already faulted in the page (or huge page) in the host's
> page table, and we hold the KVM mmu spinlock (grabbed before checking
> the mmu seq).

I wonder if the KVM mmu spinlock is enough for walking (not KVM
exclusive) host page tables. Can you elaborate?

> 
> Signed-off-by: Barret Rhoden <brho@google.com>
> ---
>  arch/x86/kvm/mmu.c | 34 ++++++++++++++++++++++++++++++++--
>  1 file changed, 32 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> index cf5f572f2305..2df8c459dc6a 100644
> --- a/arch/x86/kvm/mmu.c
> +++ b/arch/x86/kvm/mmu.c
> @@ -3152,6 +3152,36 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
>  	return -EFAULT;
>  }
>  
> +static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
> +{
> +	struct page *page = pfn_to_page(pfn);
> +	unsigned long hva, map_shift;
> +
> +	if (!is_zone_device_page(page))
> +		return PageTransCompoundMap(page);
> +
> +	/*
> +	 * DAX pages do not use compound pages.  The page should have already
> +	 * been mapped into the host-side page table during try_async_pf(), so
> +	 * we can check the page tables directly.
> +	 */
> +	hva = gfn_to_hva(kvm, gfn);
> +	if (kvm_is_error_hva(hva))
> +		return false;
> +
> +	/*
> +	 * Our caller grabbed the KVM mmu_lock with a successful
> +	 * mmu_notifier_retry, so we're safe to walk the page table.
> +	 */
> +	map_shift = dev_pagemap_mapping_shift(hva, current->mm);

You could get rid of that local variable map_shift.

> +	switch (map_shift) {
> +	case PMD_SHIFT:
> +	case PUD_SIZE:
> +		return true;
> +	}
> +	return false;
> +}
> +
>  static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>  					gfn_t *gfnp, kvm_pfn_t *pfnp,
>  					int *levelp)
> @@ -3168,7 +3198,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>  	 */
>  	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
>  	    level == PT_PAGE_TABLE_LEVEL &&
> -	    PageTransCompoundMap(pfn_to_page(pfn)) &&
> +	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
>  	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
>  		unsigned long mask;
>  		/*
> @@ -5678,7 +5708,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
>  		 */
>  		if (sp->role.direct &&
>  			!kvm_is_reserved_pfn(pfn) &&
> -			PageTransCompoundMap(pfn_to_page(pfn))) {
> +			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
>  			pte_list_remove(rmap_head, sptep);
>  			need_tlb_flush = 1;
>  			goto restart;
> 

This looks surprisingly simple to me :)

-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13  9:36   ` David Hildenbrand
@ 2018-11-13 10:02     ` Pankaj Gupta
  2018-11-13 12:41       ` Paolo Bonzini
  2018-11-13 15:56       ` Barret Rhoden
  2018-11-13 15:50     ` Barret Rhoden
  1 sibling, 2 replies; 23+ messages in thread
From: Pankaj Gupta @ 2018-11-13 10:02 UTC (permalink / raw)
  To: Barret Rhoden
  Cc: Dan Williams, David Hildenbrand, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu c zhang, yi z zhang


> 
> On 09.11.18 21:39, Barret Rhoden wrote:
> > This change allows KVM to map DAX-backed files made of huge pages with
> > huge mappings in the EPT/TDP.
> > 
> > DAX pages are not PageTransCompound.  The existing check is trying to
> > determine if the mapping for the pfn is a huge mapping or not.  For
> > non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
> > For DAX, we can check the page table itself.
> > 
> > Note that KVM already faulted in the page (or huge page) in the host's
> > page table, and we hold the KVM mmu spinlock (grabbed before checking
> > the mmu seq).
> 
> I wonder if the KVM mmu spinlock is enough for walking (not KVM
> exclusive) host page tables. Can you elaborate?

As this patch is dependent on PageReserved patch(which is in progress), just 
wondering if we are able to test the code path for hugepage with DAX.

Thanks,
Pankaj 
 
> 
> > 
> > Signed-off-by: Barret Rhoden <brho@google.com>
> > ---
> >  arch/x86/kvm/mmu.c | 34 ++++++++++++++++++++++++++++++++--
> >  1 file changed, 32 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
> > index cf5f572f2305..2df8c459dc6a 100644
> > --- a/arch/x86/kvm/mmu.c
> > +++ b/arch/x86/kvm/mmu.c
> > @@ -3152,6 +3152,36 @@ static int kvm_handle_bad_page(struct kvm_vcpu
> > *vcpu, gfn_t gfn, kvm_pfn_t pfn)
> >  	return -EFAULT;
> >  }
> >  
> > +static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
> > +{
> > +	struct page *page = pfn_to_page(pfn);
> > +	unsigned long hva, map_shift;
> > +
> > +	if (!is_zone_device_page(page))
> > +		return PageTransCompoundMap(page);
> > +
> > +	/*
> > +	 * DAX pages do not use compound pages.  The page should have already
> > +	 * been mapped into the host-side page table during try_async_pf(), so
> > +	 * we can check the page tables directly.
> > +	 */
> > +	hva = gfn_to_hva(kvm, gfn);
> > +	if (kvm_is_error_hva(hva))
> > +		return false;
> > +
> > +	/*
> > +	 * Our caller grabbed the KVM mmu_lock with a successful
> > +	 * mmu_notifier_retry, so we're safe to walk the page table.
> > +	 */
> > +	map_shift = dev_pagemap_mapping_shift(hva, current->mm);
> 
> You could get rid of that local variable map_shift.
> 
> > +	switch (map_shift) {
> > +	case PMD_SHIFT:
> > +	case PUD_SIZE:
> > +		return true;
> > +	}
> > +	return false;
> > +}
> > +
> >  static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
> >  					gfn_t *gfnp, kvm_pfn_t *pfnp,
> >  					int *levelp)
> > @@ -3168,7 +3198,7 @@ static void transparent_hugepage_adjust(struct
> > kvm_vcpu *vcpu,
> >  	 */
> >  	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
> >  	    level == PT_PAGE_TABLE_LEVEL &&
> > -	    PageTransCompoundMap(pfn_to_page(pfn)) &&
> > +	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
> >  	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
> >  		unsigned long mask;
> >  		/*
> > @@ -5678,7 +5708,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm
> > *kvm,
> >  		 */
> >  		if (sp->role.direct &&
> >  			!kvm_is_reserved_pfn(pfn) &&
> > -			PageTransCompoundMap(pfn_to_page(pfn))) {
> > +			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
> >  			pte_list_remove(rmap_head, sptep);
> >  			need_tlb_flush = 1;
> >  			goto restart;
> > 
> 
> This looks surprisingly simple to me :)
> 
> --
> 
> Thanks,
> 
> David / dhildenb
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13 10:02     ` Pankaj Gupta
@ 2018-11-13 12:41       ` Paolo Bonzini
  2018-11-13 15:56       ` Barret Rhoden
  1 sibling, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2018-11-13 12:41 UTC (permalink / raw)
  To: Pankaj Gupta, Barret Rhoden
  Cc: Dan Williams, David Hildenbrand, Dave Jiang, Ross Zwisler,
	Vishal Verma, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu c zhang, yi z zhang

On 13/11/2018 11:02, Pankaj Gupta wrote:
> 
>>
>> On 09.11.18 21:39, Barret Rhoden wrote:
>>> This change allows KVM to map DAX-backed files made of huge pages with
>>> huge mappings in the EPT/TDP.
>>>
>>> DAX pages are not PageTransCompound.  The existing check is trying to
>>> determine if the mapping for the pfn is a huge mapping or not.  For
>>> non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
>>> For DAX, we can check the page table itself.
>>>
>>> Note that KVM already faulted in the page (or huge page) in the host's
>>> page table, and we hold the KVM mmu spinlock (grabbed before checking
>>> the mmu seq).
>>
>> I wonder if the KVM mmu spinlock is enough for walking (not KVM
>> exclusive) host page tables. Can you elaborate?
> 
> As this patch is dependent on PageReserved patch(which is in progress), just 
> wondering if we are able to test the code path for hugepage with DAX.

The MMU spinlock is taken in kvm_mmu_notifier_invalidate_range_end, so
it should be enough.

Paolo

> 
> Thanks,
> Pankaj 
>  
>>
>>>
>>> Signed-off-by: Barret Rhoden <brho@google.com>
>>> ---
>>>  arch/x86/kvm/mmu.c | 34 ++++++++++++++++++++++++++++++++--
>>>  1 file changed, 32 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>>> index cf5f572f2305..2df8c459dc6a 100644
>>> --- a/arch/x86/kvm/mmu.c
>>> +++ b/arch/x86/kvm/mmu.c
>>> @@ -3152,6 +3152,36 @@ static int kvm_handle_bad_page(struct kvm_vcpu
>>> *vcpu, gfn_t gfn, kvm_pfn_t pfn)
>>>  	return -EFAULT;
>>>  }
>>>  
>>> +static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
>>> +{
>>> +	struct page *page = pfn_to_page(pfn);
>>> +	unsigned long hva, map_shift;
>>> +
>>> +	if (!is_zone_device_page(page))
>>> +		return PageTransCompoundMap(page);
>>> +
>>> +	/*
>>> +	 * DAX pages do not use compound pages.  The page should have already
>>> +	 * been mapped into the host-side page table during try_async_pf(), so
>>> +	 * we can check the page tables directly.
>>> +	 */
>>> +	hva = gfn_to_hva(kvm, gfn);
>>> +	if (kvm_is_error_hva(hva))
>>> +		return false;
>>> +
>>> +	/*
>>> +	 * Our caller grabbed the KVM mmu_lock with a successful
>>> +	 * mmu_notifier_retry, so we're safe to walk the page table.
>>> +	 */
>>> +	map_shift = dev_pagemap_mapping_shift(hva, current->mm);
>>
>> You could get rid of that local variable map_shift.
>>
>>> +	switch (map_shift) {
>>> +	case PMD_SHIFT:
>>> +	case PUD_SIZE:
>>> +		return true;
>>> +	}
>>> +	return false;
>>> +}
>>> +
>>>  static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
>>>  					gfn_t *gfnp, kvm_pfn_t *pfnp,
>>>  					int *levelp)
>>> @@ -3168,7 +3198,7 @@ static void transparent_hugepage_adjust(struct
>>> kvm_vcpu *vcpu,
>>>  	 */
>>>  	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
>>>  	    level == PT_PAGE_TABLE_LEVEL &&
>>> -	    PageTransCompoundMap(pfn_to_page(pfn)) &&
>>> +	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
>>>  	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
>>>  		unsigned long mask;
>>>  		/*
>>> @@ -5678,7 +5708,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm
>>> *kvm,
>>>  		 */
>>>  		if (sp->role.direct &&
>>>  			!kvm_is_reserved_pfn(pfn) &&
>>> -			PageTransCompoundMap(pfn_to_page(pfn))) {
>>> +			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
>>>  			pte_list_remove(rmap_head, sptep);
>>>  			need_tlb_flush = 1;
>>>  			goto restart;
>>>
>>
>> This looks surprisingly simple to me :)
>>
>> --
>>
>> Thanks,
>>
>> David / dhildenb
>>


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13  9:36   ` David Hildenbrand
  2018-11-13 10:02     ` Pankaj Gupta
@ 2018-11-13 15:50     ` Barret Rhoden
  1 sibling, 0 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-13 15:50 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang, yi.z.zhang

On 2018-11-13 at 10:36 David Hildenbrand <david@redhat.com> wrote:
> > Note that KVM already faulted in the page (or huge page) in the host's
> > page table, and we hold the KVM mmu spinlock (grabbed before checking
> > the mmu seq).  
> 
> I wonder if the KVM mmu spinlock is enough for walking (not KVM
> exclusive) host page tables. Can you elaborate?

I'll update the commit message with the info from Paolo's email (about
kvm_mmu_notifier_invalidate_range_end()).

Thanks,

Barret

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13 10:02     ` Pankaj Gupta
  2018-11-13 12:41       ` Paolo Bonzini
@ 2018-11-13 15:56       ` Barret Rhoden
  2018-11-14  9:09         ` Pankaj Gupta
  1 sibling, 1 reply; 23+ messages in thread
From: Barret Rhoden @ 2018-11-13 15:56 UTC (permalink / raw)
  To: Pankaj Gupta
  Cc: Dan Williams, David Hildenbrand, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu c zhang, yi z zhang

On 2018-11-13 at 05:02 Pankaj Gupta <pagupta@redhat.com> wrote:
> As this patch is dependent on PageReserved patch(which is in progress), just 
> wondering if we are able to test the code path for hugepage with DAX.

For testing, I used the following patch.  It's not 100%, since it
intercepts at kvm_is_reserved_pfn(), and not PageReserved() directly.
The only difference is with kvm_set_pfn_dirty() I think.

I also have a nasty module that would dump the EPT's and the host page
table's mappings so I could confirm that the huge pages are being mapped
correctly.

-----------------------
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2679e476b6c3..1b394a0752a0 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -148,6 +148,10 @@ __weak int kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
 
 bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
 {
+	// XXX hack
+	if (is_zone_device_page(pfn_to_page(pfn)))
+		return false;
+
 	if (pfn_valid(pfn))
 		return PageReserved(pfn_to_page(pfn));
 
-----------------------

Thanks,

Barret


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-12 19:31   ` Paolo Bonzini
@ 2018-11-13 16:21     ` Barret Rhoden
  2018-11-13 18:22       ` Paolo Bonzini
  0 siblings, 1 reply; 23+ messages in thread
From: Barret Rhoden @ 2018-11-13 16:21 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang, yi.z.zhang

On 2018-11-12 at 20:31 Paolo Bonzini <pbonzini@redhat.com> wrote:
> Looks good.  What's the plan for removing PageReserved from DAX pages?

I hear that's going on in this thread:

https://lore.kernel.org/lkml/154145268025.30046.11742652345962594283.stgit@ahduyck-desk1.jf.intel.com/

Though it looks like it's speeding up page initialization, and not
explicitly making the PageReserved change, yet.

Alternatively, I could change kvm_is_reserved_pfn() to single out
zone_device pages if we don't want to wait or if there is a concern
that it won't happen.

On a related note, there are two places in KVM where we check
PageReserved outside of kvm_is_reserved_pfn().

For reference:

bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
{
        if (pfn_valid(pfn))
                return PageReserved(pfn_to_page(pfn));

        return true;
}

One caller of PageReserved():

void kvm_set_pfn_dirty(kvm_pfn_t pfn)
{
        if (!kvm_is_reserved_pfn(pfn)) {
                struct page *page = pfn_to_page(pfn);

                if (!PageReserved(page))
                        SetPageDirty(page);
        }
}

In that one, the PageReserved() check looks redundant, since if the
page was PageReserved, then it would have been kvm_is_reserved.

The other is:

static bool kvm_is_mmio_pfn(kvm_pfn_t pfn)
{
        if (pfn_valid(pfn))
                return !is_zero_pfn(pfn) && PageReserved(pfn_to_page(pfn)) &&
                        /*
                         * Some reserved pages, such as those from NVDIMM
                         * DAX devices, are not for MMIO, and can be mapped
                         * with cached memory type for better performance.
                         * However, the above check misconceives those pages
                         * as MMIO, and results in KVM mapping them with UC
                         * memory type, which would hurt the performance.
                         * Therefore, we check the host memory type in addition
                         * and only treat UC/UC-/WC pages as MMIO.
                         */
                        (!pat_enabled() || pat_pfn_immune_to_uc_mtrr(pfn));

        return true;
}

Where the PAT stuff was motivated by DAX.  The PageReserved check here
looks like a broken-out version of kvm_is_reserved_pfn(), so that we can
make some extra checks around it.

Anyway, I can get rid of those two PageReserved checks and/or have
kvm_is_reserved_pfn() just check DAX pages, if everyone is OK with that.

Thanks,

Barret


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13 16:21     ` Barret Rhoden
@ 2018-11-13 18:22       ` Paolo Bonzini
  0 siblings, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2018-11-13 18:22 UTC (permalink / raw)
  To: Barret Rhoden
  Cc: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang, yi.z.zhang

On 13/11/2018 17:21, Barret Rhoden wrote:
> On 2018-11-12 at 20:31 Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Looks good.  What's the plan for removing PageReserved from DAX pages?
> 
> I hear that's going on in this thread:
> 
> https://lore.kernel.org/lkml/154145268025.30046.11742652345962594283.stgit@ahduyck-desk1.jf.intel.com/
> 
> Though it looks like it's speeding up page initialization, and not
> explicitly making the PageReserved change, yet.
> 
> Alternatively, I could change kvm_is_reserved_pfn() to single out
> zone_device pages if we don't want to wait or if there is a concern
> that it won't happen.
> 
> On a related note, there are two places in KVM where we check
> PageReserved outside of kvm_is_reserved_pfn().
> 
> For reference:
> 
> bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
> {
>         if (pfn_valid(pfn))
>                 return PageReserved(pfn_to_page(pfn));
> 
>         return true;
> }
> 
> One caller of PageReserved():
> 
> void kvm_set_pfn_dirty(kvm_pfn_t pfn)
> {
>         if (!kvm_is_reserved_pfn(pfn)) {
>                 struct page *page = pfn_to_page(pfn);
> 
>                 if (!PageReserved(page))
>                         SetPageDirty(page);
>         }
> }
> 
> In that one, the PageReserved() check looks redundant, since if the
> page was PageReserved, then it would have been kvm_is_reserved.

Make sense, and a patch to fix this is welcome.

> 
> The other is:
> 
> static bool kvm_is_mmio_pfn(kvm_pfn_t pfn)
> {
>         if (pfn_valid(pfn))
>                 return !is_zero_pfn(pfn) && PageReserved(pfn_to_page(pfn)) &&
>                         /*
>                          * Some reserved pages, such as those from NVDIMM
>                          * DAX devices, are not for MMIO, and can be mapped
>                          * with cached memory type for better performance.
>                          * However, the above check misconceives those pages
>                          * as MMIO, and results in KVM mapping them with UC
>                          * memory type, which would hurt the performance.
>                          * Therefore, we check the host memory type in addition
>                          * and only treat UC/UC-/WC pages as MMIO.
>                          */
>                         (!pat_enabled() || pat_pfn_immune_to_uc_mtrr(pfn));
> 
>         return true;
> }
> 
> Where the PAT stuff was motivated by DAX.  The PageReserved check here
> looks like a broken-out version of kvm_is_reserved_pfn(), so that we can
> make some extra checks around it.

Since this one is indeed motivated by DAX, it can be left in for now and
it will DTRT.  But when DAX is not PageReserved anymore, then this
second part of the condition can be reverted.

Paolo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 2/2] kvm: Use huge pages for DAX-backed files
  2018-11-13 15:56       ` Barret Rhoden
@ 2018-11-14  9:09         ` Pankaj Gupta
  0 siblings, 0 replies; 23+ messages in thread
From: Pankaj Gupta @ 2018-11-14  9:09 UTC (permalink / raw)
  To: Barret Rhoden
  Cc: Dan Williams, David Hildenbrand, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	linux-kernel, H. Peter Anvin, x86, kvm, yu c zhang, yi z zhang


> > As this patch is dependent on PageReserved patch(which is in progress),
> > just
> > wondering if we are able to test the code path for hugepage with DAX.
> 
> For testing, I used the following patch.  It's not 100%, since it
> intercepts at kvm_is_reserved_pfn(), and not PageReserved() directly.
> The only difference is with kvm_set_pfn_dirty() I think.
> 

Yes, this should be ok.

Thanks,
Pankaj 

> I also have a nasty module that would dump the EPT's and the host page
> table's mappings so I could confirm that the huge pages are being mapped
> correctly.
> 
> -----------------------
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 2679e476b6c3..1b394a0752a0 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -148,6 +148,10 @@ __weak int kvm_arch_mmu_notifier_invalidate_range(struct
> kvm *kvm,
>  
>  bool kvm_is_reserved_pfn(kvm_pfn_t pfn)
>  {
> +	// XXX hack
> +	if (is_zone_device_page(pfn_to_page(pfn)))
> +		return false;
> +
>  	if (pfn_valid(pfn))
>  		return PageReserved(pfn_to_page(pfn));
>  
> -----------------------
> 
> Thanks,
> 
> Barret
> 
> 

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files
  2018-11-09 20:39 [PATCH 0/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
  2018-11-09 20:39 ` [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
  2018-11-09 20:39 ` [PATCH 2/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
@ 2018-11-14 21:51 ` Barret Rhoden
  2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
                     ` (3 more replies)
  2 siblings, 4 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-14 21:51 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

This patch series depends on dax pages not being PageReserved.  Once
that is in place, these changes will let KVM use huge pages with
dax-backed files.  Without the PageReserved change, KVM and DAX still
work with these patches, simply without huge pages - which is the
current situation.

RFC/discussion thread:
https://lore.kernel.org/lkml/20181029210716.212159-1-brho@google.com/

v1 -> v2:
https://lore.kernel.org/lkml/20181109203921.178363-1-brho@google.com/

- Updated Acks/Reviewed-by
- Minor touchups
- Added patch to remove redundant PageReserved() check
- Rebased onto linux-next


Barret Rhoden (3):
  mm: make dev_pagemap_mapping_shift() externally visible
  kvm: Use huge pages for DAX-backed files
  kvm: remove redundant PageReserved() check

 arch/x86/kvm/mmu.c  | 33 +++++++++++++++++++++++++++++++--
 include/linux/mm.h  |  3 +++
 mm/memory-failure.c | 38 +++-----------------------------------
 mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
 virt/kvm/kvm_main.c |  8 ++------
 5 files changed, 73 insertions(+), 43 deletions(-)

-- 
2.19.1.1215.g8438c0b245-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
@ 2018-11-14 21:51   ` Barret Rhoden
  2018-11-26 16:50     ` Paolo Bonzini
  2018-11-26 18:32     ` Dan Williams
  2018-11-14 21:51   ` [PATCH v2 2/3] kvm: Use huge pages for DAX-backed files Barret Rhoden
                     ` (2 subsequent siblings)
  3 siblings, 2 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-14 21:51 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Naoya Horiguchi
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang, linux-mm, David Hildenbrand

KVM has a use case for determining the size of a dax mapping.  The KVM
code has easy access to the address and the mm; hence the change in
parameters.

Signed-off-by: Barret Rhoden <brho@google.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
---
 include/linux/mm.h  |  3 +++
 mm/memory-failure.c | 38 +++-----------------------------------
 mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5411de93a363..51215d695753 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -935,6 +935,9 @@ static inline bool is_pci_p2pdma_page(const struct page *page)
 }
 #endif /* CONFIG_DEV_PAGEMAP_OPS */
 
+unsigned long dev_pagemap_mapping_shift(unsigned long address,
+					struct mm_struct *mm);
+
 static inline void get_page(struct page *page)
 {
 	page = compound_head(page);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 0cd3de3550f0..c3f2c6a8607e 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -265,40 +265,6 @@ void shake_page(struct page *p, int access)
 }
 EXPORT_SYMBOL_GPL(shake_page);
 
-static unsigned long dev_pagemap_mapping_shift(struct page *page,
-		struct vm_area_struct *vma)
-{
-	unsigned long address = vma_address(page, vma);
-	pgd_t *pgd;
-	p4d_t *p4d;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-
-	pgd = pgd_offset(vma->vm_mm, address);
-	if (!pgd_present(*pgd))
-		return 0;
-	p4d = p4d_offset(pgd, address);
-	if (!p4d_present(*p4d))
-		return 0;
-	pud = pud_offset(p4d, address);
-	if (!pud_present(*pud))
-		return 0;
-	if (pud_devmap(*pud))
-		return PUD_SHIFT;
-	pmd = pmd_offset(pud, address);
-	if (!pmd_present(*pmd))
-		return 0;
-	if (pmd_devmap(*pmd))
-		return PMD_SHIFT;
-	pte = pte_offset_map(pmd, address);
-	if (!pte_present(*pte))
-		return 0;
-	if (pte_devmap(*pte))
-		return PAGE_SHIFT;
-	return 0;
-}
-
 /*
  * Failure handling: if we can't find or can't kill a process there's
  * not much we can do.	We just print a message and ignore otherwise.
@@ -329,7 +295,9 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
 	tk->addr = page_address_in_vma(p, vma);
 	tk->addr_valid = 1;
 	if (is_zone_device_page(p))
-		tk->size_shift = dev_pagemap_mapping_shift(p, vma);
+		tk->size_shift =
+			dev_pagemap_mapping_shift(vma_address(page, vma),
+						  vma->vm_mm);
 	else
 		tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT;
 
diff --git a/mm/util.c b/mm/util.c
index 8bf08b5b5760..61bc9bab931d 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -780,3 +780,37 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
 out:
 	return res;
 }
+
+unsigned long dev_pagemap_mapping_shift(unsigned long address,
+					struct mm_struct *mm)
+{
+	pgd_t *pgd;
+	p4d_t *p4d;
+	pud_t *pud;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pgd = pgd_offset(mm, address);
+	if (!pgd_present(*pgd))
+		return 0;
+	p4d = p4d_offset(pgd, address);
+	if (!p4d_present(*p4d))
+		return 0;
+	pud = pud_offset(p4d, address);
+	if (!pud_present(*pud))
+		return 0;
+	if (pud_devmap(*pud))
+		return PUD_SHIFT;
+	pmd = pmd_offset(pud, address);
+	if (!pmd_present(*pmd))
+		return 0;
+	if (pmd_devmap(*pmd))
+		return PMD_SHIFT;
+	pte = pte_offset_map(pmd, address);
+	if (!pte_present(*pte))
+		return 0;
+	if (pte_devmap(*pte))
+		return PAGE_SHIFT;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dev_pagemap_mapping_shift);
-- 
2.19.1.1215.g8438c0b245-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 2/3] kvm: Use huge pages for DAX-backed files
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
  2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
@ 2018-11-14 21:51   ` Barret Rhoden
  2018-11-14 21:51   ` [PATCH v2 3/3] kvm: remove redundant PageReserved() check Barret Rhoden
  2018-11-15  0:55   ` [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files Dan Williams
  3 siblings, 0 replies; 23+ messages in thread
From: Barret Rhoden @ 2018-11-14 21:51 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

This change allows KVM to map DAX-backed files made of huge pages with
huge mappings in the EPT/TDP.

DAX pages are not PageTransCompound.  The existing check is trying to
determine if the mapping for the pfn is a huge mapping or not.  For
non-DAX maps, e.g. hugetlbfs, that means checking PageTransCompound.
For DAX, we can check the page table itself.

Note that KVM already faulted in the page (or huge page) in the host's
page table, and we hold the KVM mmu spinlock.  We grabbed that lock in
kvm_mmu_notifier_invalidate_range_end, before checking the mmu seq.

Signed-off-by: Barret Rhoden <brho@google.com>
---
- removed map_shift local variable

 arch/x86/kvm/mmu.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index cf5f572f2305..6914989d1e3d 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3152,6 +3152,35 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, gfn_t gfn, kvm_pfn_t pfn)
 	return -EFAULT;
 }
 
+static bool pfn_is_huge_mapped(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn)
+{
+	struct page *page = pfn_to_page(pfn);
+	unsigned long hva;
+
+	if (!is_zone_device_page(page))
+		return PageTransCompoundMap(page);
+
+	/*
+	 * DAX pages do not use compound pages.  The page should have already
+	 * been mapped into the host-side page table during try_async_pf(), so
+	 * we can check the page tables directly.
+	 */
+	hva = gfn_to_hva(kvm, gfn);
+	if (kvm_is_error_hva(hva))
+		return false;
+
+	/*
+	 * Our caller grabbed the KVM mmu_lock with a successful
+	 * mmu_notifier_retry, so we're safe to walk the page table.
+	 */
+	switch (dev_pagemap_mapping_shift(hva, current->mm)) {
+	case PMD_SHIFT:
+	case PUD_SIZE:
+		return true;
+	}
+	return false;
+}
+
 static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 					gfn_t *gfnp, kvm_pfn_t *pfnp,
 					int *levelp)
@@ -3168,7 +3197,7 @@ static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
 	 */
 	if (!is_error_noslot_pfn(pfn) && !kvm_is_reserved_pfn(pfn) &&
 	    level == PT_PAGE_TABLE_LEVEL &&
-	    PageTransCompoundMap(pfn_to_page(pfn)) &&
+	    pfn_is_huge_mapped(vcpu->kvm, gfn, pfn) &&
 	    !mmu_gfn_lpage_is_disallowed(vcpu, gfn, PT_DIRECTORY_LEVEL)) {
 		unsigned long mask;
 		/*
@@ -5678,7 +5707,7 @@ static bool kvm_mmu_zap_collapsible_spte(struct kvm *kvm,
 		 */
 		if (sp->role.direct &&
 			!kvm_is_reserved_pfn(pfn) &&
-			PageTransCompoundMap(pfn_to_page(pfn))) {
+			pfn_is_huge_mapped(kvm, sp->gfn, pfn)) {
 			pte_list_remove(rmap_head, sptep);
 			need_tlb_flush = 1;
 			goto restart;
-- 
2.19.1.1215.g8438c0b245-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v2 3/3] kvm: remove redundant PageReserved() check
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
  2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
  2018-11-14 21:51   ` [PATCH v2 2/3] kvm: Use huge pages for DAX-backed files Barret Rhoden
@ 2018-11-14 21:51   ` Barret Rhoden
  2018-11-27 13:31     ` David Hildenbrand
  2018-11-15  0:55   ` [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files Dan Williams
  3 siblings, 1 reply; 23+ messages in thread
From: Barret Rhoden @ 2018-11-14 21:51 UTC (permalink / raw)
  To: Dan Williams, Dave Jiang, Ross Zwisler, Vishal Verma,
	Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

kvm_is_reserved_pfn() already checks PageReserved().

Signed-off-by: Barret Rhoden <brho@google.com>
---
 virt/kvm/kvm_main.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2679e476b6c3..e0ea6d7dac14 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1700,12 +1700,8 @@ EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty);
 
 void kvm_set_pfn_dirty(kvm_pfn_t pfn)
 {
-	if (!kvm_is_reserved_pfn(pfn)) {
-		struct page *page = pfn_to_page(pfn);
-
-		if (!PageReserved(page))
-			SetPageDirty(page);
-	}
+	if (!kvm_is_reserved_pfn(pfn))
+		SetPageDirty(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
 
-- 
2.19.1.1215.g8438c0b245-goog


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files
  2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
                     ` (2 preceding siblings ...)
  2018-11-14 21:51   ` [PATCH v2 3/3] kvm: remove redundant PageReserved() check Barret Rhoden
@ 2018-11-15  0:55   ` Dan Williams
  2018-12-03 17:40     ` Barret Rhoden
  3 siblings, 1 reply; 23+ messages in thread
From: Dan Williams @ 2018-11-15  0:55 UTC (permalink / raw)
  To: Barret Rhoden
  Cc: Dave Jiang, zwisler, Vishal L Verma, Paolo Bonzini, rkrcmar,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	Linux Kernel Mailing List, H. Peter Anvin, X86 ML, KVM list,
	Zhang, Yu C, Zhang, Yi Z, alexander.h.duyck

[ add Alex who is looking into removing PageReserved for DAX pages. ]
On Wed, Nov 14, 2018 at 1:53 PM Barret Rhoden <brho@google.com> wrote:
>
> This patch series depends on dax pages not being PageReserved.  Once
> that is in place, these changes will let KVM use huge pages with
> dax-backed files.  Without the PageReserved change, KVM and DAX still
> work with these patches, simply without huge pages - which is the
> current situation.
>
> RFC/discussion thread:
> https://lore.kernel.org/lkml/20181029210716.212159-1-brho@google.com/
>
> v1 -> v2:
> https://lore.kernel.org/lkml/20181109203921.178363-1-brho@google.com/
>
> - Updated Acks/Reviewed-by
> - Minor touchups
> - Added patch to remove redundant PageReserved() check
> - Rebased onto linux-next
>
>
> Barret Rhoden (3):
>   mm: make dev_pagemap_mapping_shift() externally visible
>   kvm: Use huge pages for DAX-backed files
>   kvm: remove redundant PageReserved() check
>
>  arch/x86/kvm/mmu.c  | 33 +++++++++++++++++++++++++++++++--
>  include/linux/mm.h  |  3 +++
>  mm/memory-failure.c | 38 +++-----------------------------------
>  mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
>  virt/kvm/kvm_main.c |  8 ++------
>  5 files changed, 73 insertions(+), 43 deletions(-)
>
> --
> 2.19.1.1215.g8438c0b245-goog
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible
  2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
@ 2018-11-26 16:50     ` Paolo Bonzini
  2018-11-26 18:32     ` Dan Williams
  1 sibling, 0 replies; 23+ messages in thread
From: Paolo Bonzini @ 2018-11-26 16:50 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams, Dave Jiang, Ross Zwisler,
	Vishal Verma, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Naoya Horiguchi
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang, linux-mm, David Hildenbrand, Andrew Morton

On 14/11/18 22:51, Barret Rhoden wrote:
> KVM has a use case for determining the size of a dax mapping.  The KVM
> code has easy access to the address and the mm; hence the change in
> parameters.
> 
> Signed-off-by: Barret Rhoden <brho@google.com>
> Reviewed-by: David Hildenbrand <david@redhat.com>
> ---
>  include/linux/mm.h  |  3 +++
>  mm/memory-failure.c | 38 +++-----------------------------------
>  mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
>  3 files changed, 40 insertions(+), 35 deletions(-)
> 
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 5411de93a363..51215d695753 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -935,6 +935,9 @@ static inline bool is_pci_p2pdma_page(const struct page *page)
>  }
>  #endif /* CONFIG_DEV_PAGEMAP_OPS */
>  
> +unsigned long dev_pagemap_mapping_shift(unsigned long address,
> +					struct mm_struct *mm);
> +
>  static inline void get_page(struct page *page)
>  {
>  	page = compound_head(page);
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 0cd3de3550f0..c3f2c6a8607e 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -265,40 +265,6 @@ void shake_page(struct page *p, int access)
>  }
>  EXPORT_SYMBOL_GPL(shake_page);
>  
> -static unsigned long dev_pagemap_mapping_shift(struct page *page,
> -		struct vm_area_struct *vma)
> -{
> -	unsigned long address = vma_address(page, vma);
> -	pgd_t *pgd;
> -	p4d_t *p4d;
> -	pud_t *pud;
> -	pmd_t *pmd;
> -	pte_t *pte;
> -
> -	pgd = pgd_offset(vma->vm_mm, address);
> -	if (!pgd_present(*pgd))
> -		return 0;
> -	p4d = p4d_offset(pgd, address);
> -	if (!p4d_present(*p4d))
> -		return 0;
> -	pud = pud_offset(p4d, address);
> -	if (!pud_present(*pud))
> -		return 0;
> -	if (pud_devmap(*pud))
> -		return PUD_SHIFT;
> -	pmd = pmd_offset(pud, address);
> -	if (!pmd_present(*pmd))
> -		return 0;
> -	if (pmd_devmap(*pmd))
> -		return PMD_SHIFT;
> -	pte = pte_offset_map(pmd, address);
> -	if (!pte_present(*pte))
> -		return 0;
> -	if (pte_devmap(*pte))
> -		return PAGE_SHIFT;
> -	return 0;
> -}
> -
>  /*
>   * Failure handling: if we can't find or can't kill a process there's
>   * not much we can do.	We just print a message and ignore otherwise.
> @@ -329,7 +295,9 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
>  	tk->addr = page_address_in_vma(p, vma);
>  	tk->addr_valid = 1;
>  	if (is_zone_device_page(p))
> -		tk->size_shift = dev_pagemap_mapping_shift(p, vma);
> +		tk->size_shift =
> +			dev_pagemap_mapping_shift(vma_address(page, vma),
> +						  vma->vm_mm);
>  	else
>  		tk->size_shift = compound_order(compound_head(p)) + PAGE_SHIFT;
>  
> diff --git a/mm/util.c b/mm/util.c
> index 8bf08b5b5760..61bc9bab931d 100644
> --- a/mm/util.c
> +++ b/mm/util.c
> @@ -780,3 +780,37 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen)
>  out:
>  	return res;
>  }
> +
> +unsigned long dev_pagemap_mapping_shift(unsigned long address,
> +					struct mm_struct *mm)
> +{
> +	pgd_t *pgd;
> +	p4d_t *p4d;
> +	pud_t *pud;
> +	pmd_t *pmd;
> +	pte_t *pte;
> +
> +	pgd = pgd_offset(mm, address);
> +	if (!pgd_present(*pgd))
> +		return 0;
> +	p4d = p4d_offset(pgd, address);
> +	if (!p4d_present(*p4d))
> +		return 0;
> +	pud = pud_offset(p4d, address);
> +	if (!pud_present(*pud))
> +		return 0;
> +	if (pud_devmap(*pud))
> +		return PUD_SHIFT;
> +	pmd = pmd_offset(pud, address);
> +	if (!pmd_present(*pmd))
> +		return 0;
> +	if (pmd_devmap(*pmd))
> +		return PMD_SHIFT;
> +	pte = pte_offset_map(pmd, address);
> +	if (!pte_present(*pte))
> +		return 0;
> +	if (pte_devmap(*pte))
> +		return PAGE_SHIFT;
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(dev_pagemap_mapping_shift);
> 

Andrew,

can you ack this patch?

Thanks,

Paolo

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible
  2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
  2018-11-26 16:50     ` Paolo Bonzini
@ 2018-11-26 18:32     ` Dan Williams
  1 sibling, 0 replies; 23+ messages in thread
From: Dan Williams @ 2018-11-26 18:32 UTC (permalink / raw)
  To: Barret Rhoden
  Cc: Dave Jiang, zwisler, Vishal L Verma, Paolo Bonzini, rkrcmar,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Naoya Horiguchi,
	linux-nvdimm, Linux Kernel Mailing List, H. Peter Anvin, X86 ML,
	KVM list, Zhang, Yu C, Zhang, Yi Z, Linux MM, David Hildenbrand

On Wed, Nov 14, 2018 at 1:53 PM Barret Rhoden <brho@google.com> wrote:
>
> KVM has a use case for determining the size of a dax mapping.  The KVM
> code has easy access to the address and the mm; hence the change in
> parameters.
>
> Signed-off-by: Barret Rhoden <brho@google.com>
> Reviewed-by: David Hildenbrand <david@redhat.com>

Acked-by: Dan Williams <dan.j.williams@intel.com>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 3/3] kvm: remove redundant PageReserved() check
  2018-11-14 21:51   ` [PATCH v2 3/3] kvm: remove redundant PageReserved() check Barret Rhoden
@ 2018-11-27 13:31     ` David Hildenbrand
  0 siblings, 0 replies; 23+ messages in thread
From: David Hildenbrand @ 2018-11-27 13:31 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams, Dave Jiang, Ross Zwisler,
	Vishal Verma, Paolo Bonzini, Radim Krčmář,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov
  Cc: linux-nvdimm, linux-kernel, H. Peter Anvin, x86, kvm, yu.c.zhang,
	yi.z.zhang

On 14.11.18 22:51, Barret Rhoden wrote:
> kvm_is_reserved_pfn() already checks PageReserved().
> 
> Signed-off-by: Barret Rhoden <brho@google.com>
> ---
>  virt/kvm/kvm_main.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 2679e476b6c3..e0ea6d7dac14 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -1700,12 +1700,8 @@ EXPORT_SYMBOL_GPL(kvm_release_pfn_dirty);
>  
>  void kvm_set_pfn_dirty(kvm_pfn_t pfn)
>  {
> -	if (!kvm_is_reserved_pfn(pfn)) {
> -		struct page *page = pfn_to_page(pfn);
> -
> -		if (!PageReserved(page))
> -			SetPageDirty(page);
> -	}
> +	if (!kvm_is_reserved_pfn(pfn))
> +		SetPageDirty(pfn_to_page(pfn));
>  }
>  EXPORT_SYMBOL_GPL(kvm_set_pfn_dirty);
>  
> 

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files
  2018-11-15  0:55   ` [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files Dan Williams
@ 2018-12-03 17:40     ` Barret Rhoden
  2018-12-03 18:32       ` Alexander Duyck
  0 siblings, 1 reply; 23+ messages in thread
From: Barret Rhoden @ 2018-12-03 17:40 UTC (permalink / raw)
  To: Dan Williams
  Cc: Dave Jiang, zwisler, Vishal L Verma, Paolo Bonzini, rkrcmar,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	Linux Kernel Mailing List, H. Peter Anvin, X86 ML, KVM list,
	Zhang, Yu C, Zhang, Yi Z, alexander.h.duyck

On 2018-11-14 at 16:55 Dan Williams <dan.j.williams@intel.com> wrote:
> [ add Alex who is looking into removing PageReserved for DAX pages. ]

Thanks.  I can keep my eye out for his patches and repost once that's
done.  

Alternatively, if you all want to merge this before the PageReserved /
DAX changes, then I can repost - just Ack/Review tags.  It's harmless
with the existing PageReserved behavior.

Thanks,

Barret


> On Wed, Nov 14, 2018 at 1:53 PM Barret Rhoden <brho@google.com> wrote:
> >
> > This patch series depends on dax pages not being PageReserved.  Once
> > that is in place, these changes will let KVM use huge pages with
> > dax-backed files.  Without the PageReserved change, KVM and DAX still
> > work with these patches, simply without huge pages - which is the
> > current situation.
> >
> > RFC/discussion thread:
> > https://lore.kernel.org/lkml/20181029210716.212159-1-brho@google.com/
> >
> > v1 -> v2:
> > https://lore.kernel.org/lkml/20181109203921.178363-1-brho@google.com/
> >
> > - Updated Acks/Reviewed-by
> > - Minor touchups
> > - Added patch to remove redundant PageReserved() check
> > - Rebased onto linux-next
> >
> >
> > Barret Rhoden (3):
> >   mm: make dev_pagemap_mapping_shift() externally visible
> >   kvm: Use huge pages for DAX-backed files
> >   kvm: remove redundant PageReserved() check
> >
> >  arch/x86/kvm/mmu.c  | 33 +++++++++++++++++++++++++++++++--
> >  include/linux/mm.h  |  3 +++
> >  mm/memory-failure.c | 38 +++-----------------------------------
> >  mm/util.c           | 34 ++++++++++++++++++++++++++++++++++
> >  virt/kvm/kvm_main.c |  8 ++------
> >  5 files changed, 73 insertions(+), 43 deletions(-)
> >
> > --
> > 2.19.1.1215.g8438c0b245-goog
> >  


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files
  2018-12-03 17:40     ` Barret Rhoden
@ 2018-12-03 18:32       ` Alexander Duyck
  0 siblings, 0 replies; 23+ messages in thread
From: Alexander Duyck @ 2018-12-03 18:32 UTC (permalink / raw)
  To: Barret Rhoden, Dan Williams
  Cc: Dave Jiang, zwisler, Vishal L Verma, Paolo Bonzini, rkrcmar,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-nvdimm,
	Linux Kernel Mailing List, H. Peter Anvin, X86 ML, KVM list,
	Zhang, Yu C, Zhang, Yi Z

On Mon, 2018-12-03 at 12:40 -0500, Barret Rhoden wrote:
> On 2018-11-14 at 16:55 Dan Williams <dan.j.williams@intel.com> wrote:
> > [ add Alex who is looking into removing PageReserved for DAX pages. ]
> 
> Thanks.  I can keep my eye out for his patches and repost once that's
> done.  
> 
> Alternatively, if you all want to merge this before the PageReserved /
> DAX changes, then I can repost - just Ack/Review tags.  It's harmless
> with the existing PageReserved behavior.
> 
> Thanks,
> 
> Barret

So the latest version of my generic memory init patches are up at:

https://lore.kernel.org/lkml/154361452447.7497.1348692079883153517.stgit@ahduyck-desk1.amr.corp.intel.com/

To be honest I am not entirely convinced that dropping PageReserved is
the right thing to do for DAX pages. I've been trying to work out a few
different issues but not having much luck. It seems like the main issue
is that the PageReserved bit is being used to indicate 2 different
things in a few spots throughout the kernel.

The definition of the PG_reserved flag reads like it should apply to
DAX pages:
  PG_reserved is set for special pages, which can never be swapped out.
  Some of them might not even exist...

PageReserved essentially means you aren't supposed to be migrating or
swapping the page. The problem here is that I believe this logic should
apply to DAX pages and so in many cases it makes sense to leave the
flag set for DAX pages. Otherwise you have to go through and start
special casing all the spots where normal memory falls through and add
a check to see if we have a DAX page.

The second use for the PG_reserved flag is to test for if you can pin
the page or not. This I think is the reason why many are just assuming
PageReserved == MMIO like KVM does. However this is a bad assumption to
be making since the introduction of DAX, HMM, and P2PDMA allows MMIO
memory to start doing different things like supporting pinning. I also
believe it would be a bad reason to clear the flag for DAX pages.

Thanks.

- Alex


^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, back to index

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-09 20:39 [PATCH 0/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
2018-11-09 20:39 ` [PATCH 1/2] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
2018-11-13  9:28   ` David Hildenbrand
2018-11-09 20:39 ` [PATCH 2/2] kvm: Use huge pages for DAX-backed files Barret Rhoden
2018-11-12 19:31   ` Paolo Bonzini
2018-11-13 16:21     ` Barret Rhoden
2018-11-13 18:22       ` Paolo Bonzini
2018-11-13  9:36   ` David Hildenbrand
2018-11-13 10:02     ` Pankaj Gupta
2018-11-13 12:41       ` Paolo Bonzini
2018-11-13 15:56       ` Barret Rhoden
2018-11-14  9:09         ` Pankaj Gupta
2018-11-13 15:50     ` Barret Rhoden
2018-11-14 21:51 ` [PATCH v2 0/3] " Barret Rhoden
2018-11-14 21:51   ` [PATCH v2 1/3] mm: make dev_pagemap_mapping_shift() externally visible Barret Rhoden
2018-11-26 16:50     ` Paolo Bonzini
2018-11-26 18:32     ` Dan Williams
2018-11-14 21:51   ` [PATCH v2 2/3] kvm: Use huge pages for DAX-backed files Barret Rhoden
2018-11-14 21:51   ` [PATCH v2 3/3] kvm: remove redundant PageReserved() check Barret Rhoden
2018-11-27 13:31     ` David Hildenbrand
2018-11-15  0:55   ` [PATCH v2 0/3] kvm: Use huge pages for DAX-backed files Dan Williams
2018-12-03 17:40     ` Barret Rhoden
2018-12-03 18:32       ` Alexander Duyck

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git
	git clone --mirror https://lore.kernel.org/lkml/8 lkml/git/8.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git