All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] parisc: Disable huge pages on Mako machines
@ 2015-12-06 20:43 Helge Deller
  2015-12-06 20:43 ` [PATCH 2/3] parisc: Disable tlb flush optimization with huge pages Helge Deller
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Helge Deller @ 2015-12-06 20:43 UTC (permalink / raw)
  To: linux-parisc; +Cc: James Bottomley, John David Anglin

Mako-based machines (PA8800 and PA8900 CPUs) don't allow aliasing on
non-equaivalent addresses.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 arch/parisc/include/asm/pgtable.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index d8534f9..291cee2 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -372,7 +372,8 @@ static inline pte_t pte_mkspecial(pte_t pte)	{ return pte; }
  */
 #ifdef CONFIG_HUGETLB_PAGE
 #define pte_huge(pte)           (pte_val(pte) & _PAGE_HUGE)
-#define pte_mkhuge(pte)         (__pte(pte_val(pte) | _PAGE_HUGE))
+#define pte_mkhuge(pte)         (__pte(pte_val(pte) | \
+				 (parisc_requires_coherency() ? 0 : _PAGE_HUGE)))
 #else
 #define pte_huge(pte)           (0)
 #define pte_mkhuge(pte)         (pte)
-- 
2.1.0


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

* [PATCH 2/3] parisc: Disable tlb flush optimization with huge pages
  2015-12-06 20:43 [PATCH 1/3] parisc: Disable huge pages on Mako machines Helge Deller
@ 2015-12-06 20:43 ` Helge Deller
  2015-12-06 20:43 ` [PATCH 3/3] parisc: protect huge pte changes with spinlocks Helge Deller
  2015-12-07 15:13 ` [PATCH 1/3] parisc: Disable huge pages on Mako machines John David Anglin
  2 siblings, 0 replies; 6+ messages in thread
From: Helge Deller @ 2015-12-06 20:43 UTC (permalink / raw)
  To: linux-parisc; +Cc: James Bottomley, John David Anglin

It seems calling flush_tlb_all() doesn't reliable flush the tlb on all
CPUs. Disable it when used with huge pages.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 arch/parisc/kernel/cache.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index cda6dbb..aee27e1 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -442,13 +442,15 @@ EXPORT_SYMBOL(copy_user_page);
 int __flush_tlb_range(unsigned long sid, unsigned long start,
 		      unsigned long end)
 {
-	unsigned long flags, size;
+	unsigned long flags;
 
-	size = (end - start);
+#if !defined(CONFIG_HUGETLB_PAGE)
+	unsigned long size = (end - start);
 	if (size >= parisc_tlb_flush_threshold) {
 		flush_tlb_all();
 		return 1;
 	}
+#endif
 
 	/* Purge TLB entries for small ranges using the pdtlb and
 	   pitlb instructions.  These instructions execute locally
-- 
2.1.0


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

* [PATCH 3/3] parisc: protect huge pte changes with spinlocks
  2015-12-06 20:43 [PATCH 1/3] parisc: Disable huge pages on Mako machines Helge Deller
  2015-12-06 20:43 ` [PATCH 2/3] parisc: Disable tlb flush optimization with huge pages Helge Deller
@ 2015-12-06 20:43 ` Helge Deller
  2015-12-07 15:13 ` [PATCH 1/3] parisc: Disable huge pages on Mako machines John David Anglin
  2 siblings, 0 replies; 6+ messages in thread
From: Helge Deller @ 2015-12-06 20:43 UTC (permalink / raw)
  To: linux-parisc; +Cc: James Bottomley, John David Anglin

Protect all changes of huge page pte entries with purge_tlb_start() and
purge_tlb_end() spinlocks.

Signed-off-by: Helge Deller <deller@gmx.de>
---
 arch/parisc/include/asm/hugetlb.h | 20 +++----------
 arch/parisc/mm/hugetlbpage.c      | 60 +++++++++++++++++++++++++++++++--------
 2 files changed, 52 insertions(+), 28 deletions(-)

diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h
index 7d56a9c..a65d888 100644
--- a/arch/parisc/include/asm/hugetlb.h
+++ b/arch/parisc/include/asm/hugetlb.h
@@ -54,24 +54,12 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
 	return pte_wrprotect(pte);
 }
 
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
-					   unsigned long addr, pte_t *ptep)
-{
-	pte_t old_pte = *ptep;
-	set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
-}
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+					   unsigned long addr, pte_t *ptep);
 
-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 					     unsigned long addr, pte_t *ptep,
-					     pte_t pte, int dirty)
-{
-	int changed = !pte_same(*ptep, pte);
-	if (changed) {
-		set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
-		flush_tlb_page(vma, addr);
-	}
-	return changed;
-}
+					     pte_t pte, int dirty);
 
 static inline pte_t huge_ptep_get(pte_t *ptep)
 {
diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c
index f6fdc77..54ba392 100644
--- a/arch/parisc/mm/hugetlbpage.c
+++ b/arch/parisc/mm/hugetlbpage.c
@@ -105,15 +105,13 @@ static inline void purge_tlb_entries_huge(struct mm_struct *mm, unsigned long ad
 	addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT;
 
 	for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) {
-		mtsp(mm->context, 1);
-		pdtlb(addr);
-		if (unlikely(split_tlb))
-			pitlb(addr);
+		purge_tlb_entries(mm, addr);
 		addr += (1UL << REAL_HPAGE_SHIFT);
 	}
 }
 
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+/* __set_huge_pte_at() must be called holding the pa_tlb_lock. */
+static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 		     pte_t *ptep, pte_t entry)
 {
 	unsigned long addr_start;
@@ -123,14 +121,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	addr_start = addr;
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		/* Directly write pte entry.  We could call set_pte_at(mm, addr, ptep, entry)
-		 * instead, but then we get double locking on pa_tlb_lock. */
-		*ptep = entry;
+		set_pte(ptep, entry);
 		ptep++;
 
-		/* Drop the PAGE_SIZE/non-huge tlb entry */
-		purge_tlb_entries(mm, addr);
-
 		addr += PAGE_SIZE;
 		pte_val(entry) += PAGE_SIZE;
 	}
@@ -138,18 +131,61 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 	purge_tlb_entries_huge(mm, addr_start);
 }
 
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t entry)
+{
+	unsigned long flags;
+
+	purge_tlb_start(flags);
+	__set_huge_pte_at(mm, addr, ptep, entry);
+	purge_tlb_end(flags);
+}
+
 
 pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep)
 {
+	unsigned long flags;
 	pte_t entry;
 
+	purge_tlb_start(flags);
 	entry = *ptep;
-	set_huge_pte_at(mm, addr, ptep, __pte(0));
+	__set_huge_pte_at(mm, addr, ptep, __pte(0));
+	purge_tlb_end(flags);
 
 	return entry;
 }
 
+
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+				unsigned long addr, pte_t *ptep)
+{
+	unsigned long flags;
+	pte_t old_pte;
+
+	purge_tlb_start(flags);
+	old_pte = *ptep;
+	__set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+	purge_tlb_end(flags);
+}
+
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+				unsigned long addr, pte_t *ptep,
+				pte_t pte, int dirty)
+{
+	unsigned long flags;
+	int changed;
+
+	purge_tlb_start(flags);
+	changed = !pte_same(*ptep, pte);
+	if (changed) {
+		__set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+	}
+	purge_tlb_end(flags);
+	return changed;
+}
+
+
 int pmd_huge(pmd_t pmd)
 {
 	return 0;
-- 
2.1.0


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

* Re: [PATCH 1/3] parisc: Disable huge pages on Mako machines
  2015-12-06 20:43 [PATCH 1/3] parisc: Disable huge pages on Mako machines Helge Deller
  2015-12-06 20:43 ` [PATCH 2/3] parisc: Disable tlb flush optimization with huge pages Helge Deller
  2015-12-06 20:43 ` [PATCH 3/3] parisc: protect huge pte changes with spinlocks Helge Deller
@ 2015-12-07 15:13 ` John David Anglin
  2015-12-07 21:19   ` Helge Deller
  2 siblings, 1 reply; 6+ messages in thread
From: John David Anglin @ 2015-12-07 15:13 UTC (permalink / raw)
  To: Helge Deller, linux-parisc; +Cc: James Bottomley

On 2015-12-06 3:43 PM, Helge Deller wrote:
> Mako-based machines (PA8800 and PA8900 CPUs) don't allow aliasing on
> non-equaivalent addresses.
Where do the non equivalent addresses come from?  When non equivalent 
mappings are
used in the kernel, we try pretty hard to ensure that the user mappings 
are flushed prior
to using the kernel mapping and then we flush the kernel mapping. 
There's also the
copy_user_page_asm and clear_user_page_asm routines that do copies and 
clear operations
using equivalent addresses.  I have some notes on the flushing needed 
using these routines.

One source of non equivalent addresses is the boundary between text and 
data in user
applications.  At one time, we had data immediately after the text and 
non equivalent
addresses.  Now, the start of data is rounded up so it starts on a 4K 
page boundary.
This may need adjustment for huge pages, but that implies a rebuild of 
user space.

I tend to think flush_tlb_all() doesn't work because the aliasing rules 
are being broken.
Disabling it causes a significant increase in time to flush the tlb.

Dave

-- 
John David Anglin  dave.anglin@bell.net


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

* Re: [PATCH 1/3] parisc: Disable huge pages on Mako machines
  2015-12-07 15:13 ` [PATCH 1/3] parisc: Disable huge pages on Mako machines John David Anglin
@ 2015-12-07 21:19   ` Helge Deller
  2015-12-08  2:03     ` John David Anglin
  0 siblings, 1 reply; 6+ messages in thread
From: Helge Deller @ 2015-12-07 21:19 UTC (permalink / raw)
  To: John David Anglin, linux-parisc; +Cc: James Bottomley

Hi Dave,

On 07.12.2015 16:13, John David Anglin wrote:
> On 2015-12-06 3:43 PM, Helge Deller wrote:
>> Mako-based machines (PA8800 and PA8900 CPUs) don't allow aliasing on
>> non-equaivalent addresses.

> Where do the non equivalent addresses come from?

I think the main problem is the gateway page.
It's mapped at address 0 into userspace, but needs to jump into kernel space too.
This somehow breaks the huge page mapping.

> When non equivalent mappings are
> used in the kernel, we try pretty hard to ensure that the user mappings are flushed prior
> to using the kernel mapping and then we flush the kernel mapping. There's also the
> copy_user_page_asm and clear_user_page_asm routines that do copies and clear operations
> using equivalent addresses.  I have some notes on the flushing needed using these routines.

Yes.

> One source of non equivalent addresses is the boundary between text and data in user
> applications.  At one time, we had data immediately after the text and non equivalent
> addresses.  Now, the start of data is rounded up so it starts on a 4K page boundary.
> This may need adjustment for huge pages, but that implies a rebuild of user space.

No, userspace is not mapped in huge pages (but it could if someone gets libhugetlbfs working).
Right now, only hugepages would only be used for mmap() or shmget() memory if the flags
are given. 

> I tend to think flush_tlb_all() doesn't work because the aliasing rules are being broken.
> Disabling it causes a significant increase in time to flush the tlb.

Yes.
Right now the patches I sent don't seem to work as I expected them to do.
So, it's not what I currently tend to commit. I'm still working on it, but my time
is very limited, so it will need some time.
My current top goal is to push patches for kernel v4.4 which fixes the boot crash on Mako machines.

Helge

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

* Re: [PATCH 1/3] parisc: Disable huge pages on Mako machines
  2015-12-07 21:19   ` Helge Deller
@ 2015-12-08  2:03     ` John David Anglin
  0 siblings, 0 replies; 6+ messages in thread
From: John David Anglin @ 2015-12-08  2:03 UTC (permalink / raw)
  To: Helge Deller; +Cc: linux-parisc, James Bottomley

On 2015-12-07, at 4:19 PM, Helge Deller wrote:

>> Where do the non equivalent addresses come from?
> 
> I think the main problem is the gateway page.
> It's mapped at address 0 into userspace, but needs to jump into kernel space too.
> This somehow breaks the huge page mapping.

With latest debian kernel, I see:

000000004015d000 <linux_gateway_page>:
        ...

000000004015d0b0 <lws_entry>:

Possibly, this needs to be aligned to huge page boundary.

Dave
--
John David Anglin	dave.anglin@bell.net




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

end of thread, other threads:[~2015-12-08  2:03 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-06 20:43 [PATCH 1/3] parisc: Disable huge pages on Mako machines Helge Deller
2015-12-06 20:43 ` [PATCH 2/3] parisc: Disable tlb flush optimization with huge pages Helge Deller
2015-12-06 20:43 ` [PATCH 3/3] parisc: protect huge pte changes with spinlocks Helge Deller
2015-12-07 15:13 ` [PATCH 1/3] parisc: Disable huge pages on Mako machines John David Anglin
2015-12-07 21:19   ` Helge Deller
2015-12-08  2:03     ` John David Anglin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.