linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] sparc64 mm: Fix more TSB sizing issues
@ 2016-08-30 21:28 Mike Kravetz
  2016-08-30 22:51 ` kbuild test robot
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Kravetz @ 2016-08-30 21:28 UTC (permalink / raw)
  To: linux-kernel, sparclinux
  Cc: David S. Miller, Andrew Morton, Kirill A. Shutemov, Nitin Gupta,
	Mike Kravetz

Commit af1b1a9b36b8 ("sparc64 mm: Fix base TSB sizing when hugetlb
pages are used") addressed the difference between hugetlb and THP
pages when computing TSB sizes.  The following additional issues
were also discovered while working with the code.

In order to save memory, THP makes use of a huge zero page.  This huge
zero page does not count against a task's RSS, but it does consume TSB
entries.  This is similar to hugetlb pages.  Therefore, count huge
zero page entries in hugetlb_pte_count.

Accounting of THP pages is done in the routine set_pmd_at().
Unfortunately, this does not catch the case where a THP page is split.
To handle this case, decrement the count in pmdp_invalidate().
pmdp_invalidate is only called when splitting a THP.  However, 'sanity
checks' are added in case it is ever called for other purposes.

A more general issue exists with HPAGE_SIZE accounting.
hugetlb_pte_count tracks the number of HPAGE_SIZE (8M) pages.  This
value is used to size the TSB for HPAGE_SIZE pages.  However,
each HPAGE_SIZE page consists of two REAL_HPAGE_SIZE (4M) pages.
The TSB contains an entry for each REAL_HPAGE_SIZE page.  Therefore,
the number of REAL_HPAGE_SIZE pages should be used to size the huge
page TSB.  A new compile time constant REAL_HPAGE_PER_HPAGE is used
to multiply hugetlb_pte_count before sizing the TSB.

Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
---
 arch/sparc/include/asm/page_64.h |  1 +
 arch/sparc/mm/fault_64.c         |  1 +
 arch/sparc/mm/tlb.c              | 35 +++++++++++++++++++++++++++++++----
 arch/sparc/mm/tsb.c              | 16 ++++++++++------
 4 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h
index 8c2a8c9..c1263fc 100644
--- a/arch/sparc/include/asm/page_64.h
+++ b/arch/sparc/include/asm/page_64.h
@@ -25,6 +25,7 @@
 #define HPAGE_MASK		(~(HPAGE_SIZE - 1UL))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#define REAL_HPAGE_PER_HPAGE	(_AC(1,UL) << (HPAGE_SHIFT - REAL_HPAGE_SHIFT))
 #endif
 
 #ifndef __ASSEMBLY__
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index e16fdd2..3f291d8 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -484,6 +484,7 @@ good_area:
 		tsb_grow(mm, MM_TSB_BASE, mm_rss);
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
 	mm_rss = mm->context.hugetlb_pte_count + mm->context.thp_pte_count;
+	mm_rss *= REAL_HPAGE_PER_HPAGE;
 	if (unlikely(mm_rss >
 		     mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) {
 		if (mm->context.tsb_block[MM_TSB_HUGE].tsb)
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index 3659d37..c56a195 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -174,10 +174,25 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 		return;
 
 	if ((pmd_val(pmd) ^ pmd_val(orig)) & _PAGE_PMD_HUGE) {
-		if (pmd_val(pmd) & _PAGE_PMD_HUGE)
-			mm->context.thp_pte_count++;
-		else
-			mm->context.thp_pte_count--;
+		/*
+		 * Note that this routine only sets pmds for THP pages.
+		 * Hugetlb pages are handled elsewhere.  We need to check
+		 * for huge zero page.  Huge zero pages are like hugetlb
+		 * pages in that there is no RSS, but there is the need
+		 * for TSB entries.  So, huge zero page counts go into
+		 * hugetlb_pte_count.
+		 */
+		if (pmd_val(pmd) & _PAGE_PMD_HUGE) {
+			if (is_huge_zero_page(pmd_page(pmd)))
+				mm->context.hugetlb_pte_count++;
+			else
+				mm->context.thp_pte_count++;
+		} else {
+			if (is_huge_zero_page(pmd_page(orig)))
+				mm->context.hugetlb_pte_count--;
+			else
+				mm->context.thp_pte_count--;
+		}
 
 		/* Do not try to allocate the TSB hash table if we
 		 * don't have one already.  We have various locks held
@@ -204,6 +219,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 	}
 }
 
+/*
+ * This routine is only called when splitting a THP
+ */
 void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 		     pmd_t *pmdp)
 {
@@ -213,6 +231,15 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 
 	set_pmd_at(vma->vm_mm, address, pmdp, entry);
 	flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+
+	/*
+	 * set_pmd_at() will not be called in a way to decrement
+	 * thp_pte_count when splitting a THP, so do it now.
+	 * Sanity check pmd before doing the actual decrement.
+	 */
+	if ((pmd_val(entry) & _PAGE_PMD_HUGE) &&
+	    !is_huge_zero_page(pmd_page(entry)))
+		(vma->vm_mm)->context.thp_pte_count--;
 }
 
 void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index 6725ed4..bf68969 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -470,7 +470,8 @@ retry_tsb_alloc:
 int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	unsigned long total_huge_pte_count;
+	unsigned long saved_hugetlb_pte_count;
+	unsigned long saved_thp_pte_count;
 #endif
 	unsigned int i;
 
@@ -483,8 +484,8 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 	 * will re-increment the counters as the parent PTEs are
 	 * copied into the child address space.
 	 */
-	total_huge_pte_count = mm->context.hugetlb_pte_count +
-			 mm->context.thp_pte_count;
+	saved_hugetlb_pte_count = mm->context.hugetlb_pte_count;
+	saved_thp_pte_count = mm->context.thp_pte_count;
 	mm->context.hugetlb_pte_count = 0;
 	mm->context.thp_pte_count = 0;
 #endif
@@ -499,11 +500,14 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 	/* If this is fork, inherit the parent's TSB size.  We would
 	 * grow it to that size on the first page fault anyways.
 	 */
-	tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm));
+	tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm) -
+		 saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
 
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-	if (unlikely(total_huge_pte_count))
-		tsb_grow(mm, MM_TSB_HUGE, total_huge_pte_count);
+	if (unlikely(saved_hugetlb_pte_count + saved_thp_pte_count))
+		tsb_grow(mm, MM_TSB_HUGE,
+			 (saved_hugetlb_pte_count + saved_thp_pte_count) *
+			 REAL_HPAGE_PER_HPAGE);
 #endif
 
 	if (unlikely(!mm->context.tsb_block[MM_TSB_BASE].tsb))
-- 
2.4.11

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

* Re: [PATCH] sparc64 mm: Fix more TSB sizing issues
  2016-08-30 21:28 [PATCH] sparc64 mm: Fix more TSB sizing issues Mike Kravetz
@ 2016-08-30 22:51 ` kbuild test robot
  2016-08-31  3:27   ` Mike Kravetz
  0 siblings, 1 reply; 3+ messages in thread
From: kbuild test robot @ 2016-08-30 22:51 UTC (permalink / raw)
  To: Mike Kravetz
  Cc: kbuild-all, linux-kernel, sparclinux, David S. Miller,
	Andrew Morton, Kirill A. Shutemov, Nitin Gupta, Mike Kravetz

[-- Attachment #1: Type: text/plain, Size: 2271 bytes --]

Hi Mike,

[auto build test ERROR on sparc/master]
[also build test ERROR on v4.8-rc4 next-20160825]
[cannot apply to sparc-next/master]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Mike-Kravetz/sparc64-mm-Fix-more-TSB-sizing-issues/20160831-054025
base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git master
config: sparc64-allnoconfig (attached as .config)
compiler: sparc64-linux-gnu-gcc (Debian 5.4.0-6) 5.4.0 20160609
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=sparc64 

All errors (new ones prefixed by >>):

   arch/sparc/mm/tsb.c: In function 'init_new_context':
>> arch/sparc/mm/tsb.c:504:4: error: 'saved_thp_pte_count' undeclared (first use in this function)
       saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
       ^
   arch/sparc/mm/tsb.c:504:4: note: each undeclared identifier is reported only once for each function it appears in
>> arch/sparc/mm/tsb.c:504:27: error: 'HPAGE_SIZE' undeclared (first use in this function)
       saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
                              ^

vim +/saved_thp_pte_count +504 arch/sparc/mm/tsb.c

   498			mm->context.tsb_block[i].tsb = NULL;
   499	
   500		/* If this is fork, inherit the parent's TSB size.  We would
   501		 * grow it to that size on the first page fault anyways.
   502		 */
   503		tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm) -
 > 504			 saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
   505	
   506	#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
   507		if (unlikely(saved_hugetlb_pte_count + saved_thp_pte_count))

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 4948 bytes --]

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

* Re: [PATCH] sparc64 mm: Fix more TSB sizing issues
  2016-08-30 22:51 ` kbuild test robot
@ 2016-08-31  3:27   ` Mike Kravetz
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Kravetz @ 2016-08-31  3:27 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kbuild-all, linux-kernel, sparclinux, David S. Miller,
	Andrew Morton, Kirill A. Shutemov, Nitin Gupta

On 08/30/2016 03:51 PM, kbuild test robot wrote:
> Hi Mike,
> 
> [auto build test ERROR on sparc/master]
> [also build test ERROR on v4.8-rc4 next-20160825]
> [cannot apply to sparc-next/master]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> [Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
> [Check https://git-scm.com/docs/git-format-patch for more information]

Ugh!  I'll send a V2 patch with the non-hugepage/non-thp build error fixed.
I'd really like to fix this without adding another #ifdef to the routine.

-- 
Mike Kravetz

> 
> url:    https://github.com/0day-ci/linux/commits/Mike-Kravetz/sparc64-mm-Fix-more-TSB-sizing-issues/20160831-054025
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc.git master
> config: sparc64-allnoconfig (attached as .config)
> compiler: sparc64-linux-gnu-gcc (Debian 5.4.0-6) 5.4.0 20160609
> reproduce:
>         wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=sparc64 
> 
> All errors (new ones prefixed by >>):
> 
>    arch/sparc/mm/tsb.c: In function 'init_new_context':
>>> arch/sparc/mm/tsb.c:504:4: error: 'saved_thp_pte_count' undeclared (first use in this function)
>        saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
>        ^
>    arch/sparc/mm/tsb.c:504:4: note: each undeclared identifier is reported only once for each function it appears in
>>> arch/sparc/mm/tsb.c:504:27: error: 'HPAGE_SIZE' undeclared (first use in this function)
>        saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
>                               ^
> 
> vim +/saved_thp_pte_count +504 arch/sparc/mm/tsb.c
> 
>    498			mm->context.tsb_block[i].tsb = NULL;
>    499	
>    500		/* If this is fork, inherit the parent's TSB size.  We would
>    501		 * grow it to that size on the first page fault anyways.
>    502		 */
>    503		tsb_grow(mm, MM_TSB_BASE, get_mm_rss(mm) -
>  > 504			 saved_thp_pte_count * (HPAGE_SIZE / PAGE_SIZE));
>    505	
>    506	#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
>    507		if (unlikely(saved_hugetlb_pte_count + saved_thp_pte_count))
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> 

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

end of thread, other threads:[~2016-08-31  3:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-30 21:28 [PATCH] sparc64 mm: Fix more TSB sizing issues Mike Kravetz
2016-08-30 22:51 ` kbuild test robot
2016-08-31  3:27   ` Mike Kravetz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).