linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] x86/mm/cpa: Unbreak populate_pgd(): stop trying to deallocate failed PUDs
@ 2016-07-23  4:58 Andy Lutomirski
  2016-07-23  7:46 ` [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop " tip-bot for Andy Lutomirski
  2016-07-23 19:15 ` tip-bot for Andy Lutomirski
  0 siblings, 2 replies; 6+ messages in thread
From: Andy Lutomirski @ 2016-07-23  4:58 UTC (permalink / raw)
  To: x86
  Cc: Borislav Petkov, linux-kernel, Brian Gerst, Andy Lutomirski,
	Mike Krinkin

This mostly reverts commit 360cb4d15567a7eca07a5f3ade6de308bbfb4e70.

I broke the case where a PUD table got allocated -- populate_pud()
would wander off a pgd_none entry and get lost.  I'm not sure how
this survived my testing.

Fixing this directly is difficult or impossible because of the awful
state of Linux's page table accessors.

Instead, fix the original issue in a much simpler way.  The problem
was that, if we allocated a PUD table, failed to populate it, and
freed it, another CPU could potentially keep using the PGD entry we
installed (either by copying it via vmalloc_fault or by speculatively
caching it).  There's a straightforward fix: simply leave the
top-level entry in place if this happens.  This can't waste any
significant amount of memory -- there are at most 256 entries like
this systemwide and, as a practical matter, if we hit this failure
path repeatedly, we're likely to reuse the same page anyway.

For context, this is a reversion with this hunk added in:

	if (ret < 0) {
+		/*
+		 * Leave the PUD page in place in case some other CPU or thread
+		 * already found it, but remove any useless entries we just
+		 * added to it.
+		 */
-		unmap_pgd_range(cpa->pgd, addr,
+		unmap_pud_range(pgd_entry, addr,
			        addr + (cpa->numpages << PAGE_SHIFT));
		return ret;
	}

This effectively open-codes what the now-deleted unmap_pgd_range()
function used to do except that unmap_pgd_range() used to try to
free the page as well.

Cc: Mike Krinkin <krinkin.m.u@gmail.com>
Reported-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 arch/x86/mm/pageattr.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 26c93c6e04a0..2bc6ea153f76 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1082,6 +1082,8 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 		pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
 		if (!pud)
 			return -1;
+
+		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
 	}
 
 	pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
@@ -1089,16 +1091,11 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 
 	ret = populate_pud(cpa, addr, pgd_entry, pgprot);
 	if (ret < 0) {
-		if (pud)
-			free_page((unsigned long)pud);
 		unmap_pud_range(pgd_entry, addr,
 				addr + (cpa->numpages << PAGE_SHIFT));
 		return ret;
 	}
 
-	if (pud)
-		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
-
 	cpa->numpages = ret;
 	return 0;
 }
-- 
2.7.4

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

* [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs
  2016-07-23  4:58 [PATCH] x86/mm/cpa: Unbreak populate_pgd(): stop trying to deallocate failed PUDs Andy Lutomirski
@ 2016-07-23  7:46 ` tip-bot for Andy Lutomirski
  2016-07-23  8:32   ` Linus Torvalds
  2016-07-23 19:15 ` tip-bot for Andy Lutomirski
  1 sibling, 1 reply; 6+ messages in thread
From: tip-bot for Andy Lutomirski @ 2016-07-23  7:46 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, peterz, torvalds, dvlasenk, bp, toshi.kani,
	jpoimboe, akpm, brgerst, mcgrof, krinkin.m.u, hpa, luto, mingo,
	tglx, Valdis.Kletnieks

Commit-ID:  e959c4cb39feebe85e2b1191f5f666c79807631a
Gitweb:     http://git.kernel.org/tip/e959c4cb39feebe85e2b1191f5f666c79807631a
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Fri, 22 Jul 2016 21:58:08 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 23 Jul 2016 09:43:42 +0200

x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs

Valdis Kletnieks bisected a boot failure back to this recent commit:

  360cb4d15567 ("x86/mm/cpa: In populate_pgd(), don't set the PGD entry until it's populated")

I broke the case where a PUD table got allocated -- populate_pud()
would wander off a pgd_none entry and get lost.  I'm not sure how
this survived my testing.

Fixing this directly is difficult or impossible because of the awful
state of Linux's page table accessors.

Instead, fix the original issue in a much simpler way.  The problem
was that, if we allocated a PUD table, failed to populate it, and
freed it, another CPU could potentially keep using the PGD entry we
installed (either by copying it via vmalloc_fault or by speculatively
caching it).  There's a straightforward fix: simply leave the
top-level entry in place if this happens.  This can't waste any
significant amount of memory -- there are at most 256 entries like
this systemwide and, as a practical matter, if we hit this failure
path repeatedly, we're likely to reuse the same page anyway.

For context, this is a reversion with this hunk added in:

	if (ret < 0) {
+		/*
+		 * Leave the PUD page in place in case some other CPU or thread
+		 * already found it, but remove any useless entries we just
+		 * added to it.
+		 */
-		unmap_pgd_range(cpa->pgd, addr,
+		unmap_pud_range(pgd_entry, addr,
			        addr + (cpa->numpages << PAGE_SHIFT));
		return ret;
	}

This effectively open-codes what the now-deleted unmap_pgd_range()
function used to do except that unmap_pgd_range() used to try to
free the page as well.

Reported-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Mike Krinkin <krinkin.m.u@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Toshi Kani <toshi.kani@hp.com>
Link: http://lkml.kernel.org/r/21cbc2822aa18aa812c0215f4231dbf5f65afa7f.1469249789.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/pageattr.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 26c93c6..2bc6ea1 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1082,6 +1082,8 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 		pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
 		if (!pud)
 			return -1;
+
+		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
 	}
 
 	pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
@@ -1089,16 +1091,11 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 
 	ret = populate_pud(cpa, addr, pgd_entry, pgprot);
 	if (ret < 0) {
-		if (pud)
-			free_page((unsigned long)pud);
 		unmap_pud_range(pgd_entry, addr,
 				addr + (cpa->numpages << PAGE_SHIFT));
 		return ret;
 	}
 
-	if (pud)
-		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
-
 	cpa->numpages = ret;
 	return 0;
 }

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

* Re: [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs
  2016-07-23  7:46 ` [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop " tip-bot for Andy Lutomirski
@ 2016-07-23  8:32   ` Linus Torvalds
  2016-07-23 19:14     ` Ingo Molnar
  0 siblings, 1 reply; 6+ messages in thread
From: Linus Torvalds @ 2016-07-23  8:32 UTC (permalink / raw)
  To: Peter Zijlstra, Linux Kernel Mailing List, Denys Vlasenko,
	Linus Torvalds, Borislav Petkov, Toshi Kani, Josh Poimboeuf,
	Andrew Morton, Brian Gerst, Luis R. Rodriguez, krinkin.m.u,
	Peter Anvin, Thomas Gleixner, Ingo Molnar, Andrew Lutomirski,
	Valdis Kletnieks
  Cc: linux-tip-commits@vger.kernel.org

On Sat, Jul 23, 2016 at 4:46 PM, tip-bot for Andy Lutomirski
<tipbot@zytor.com> wrote:
>
> Fixing this directly is difficult or impossible because of the awful
> state of Linux's page table accessors.

Quite frankly, this part of the message is misleading and wrong.

The "awful state" is purely "Andy didn't understand the folding".
There is nothing awful about it, quite the reverse. It is what allows
the generic code to mostly not have to care whether a particular level
actually exists or not, or is just folded into the next-higher level.
No, we don't alway have

I do agree that our *naming* is not great, and that when we get
five-level page tables we should strive to start having numbers
instead of the magic letters. The magic letters made sense with three
levels that had fairly well-known names (pgd/pmd/pte is not a Linux
invention), but with four levels it's already fairly questionable.

But the fact that a pud may not even exist, and in fact is just
another nested version of the pgd, is definitely *not* awful. And Andy
not understanding it and getting it wrong *still* doesn't make it
awful.

Yes, a folded level can be subtle. The level above the folded level
has no actual storage of its own, it just contains the folded level
directly. We've had confusion about it, and the naming really doesn't
help. But looking through include/asm-generic/pgtable-nopmd.h can
actually be instructive.

Calling something "awful" just because it's clever and you didn't
understand it is not right.

It would be *truly* awful if we forced everybody to actually have all
the levels, and then had to follow idiotic single-entry pointers at
the upper end that doesn't actually exist in reality, and we'd just
have these silly "software-only" levels to make everything be four
levels even if the hardware only does two.

That would be awful, because it would be *stupid*.

             Linus

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

* Re: [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs
  2016-07-23  8:32   ` Linus Torvalds
@ 2016-07-23 19:14     ` Ingo Molnar
  0 siblings, 0 replies; 6+ messages in thread
From: Ingo Molnar @ 2016-07-23 19:14 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Peter Zijlstra, Linux Kernel Mailing List, Denys Vlasenko,
	Borislav Petkov, Toshi Kani, Josh Poimboeuf, Andrew Morton,
	Brian Gerst, Luis R. Rodriguez, krinkin.m.u, Peter Anvin,
	Thomas Gleixner, Andrew Lutomirski, Valdis Kletnieks,
	linux-tip-commits@vger.kernel.org


* Linus Torvalds <torvalds@linux-foundation.org> wrote:

> On Sat, Jul 23, 2016 at 4:46 PM, tip-bot for Andy Lutomirski
> <tipbot@zytor.com> wrote:
> >
> > Fixing this directly is difficult or impossible because of the awful
> > state of Linux's page table accessors.
> 
> Quite frankly, this part of the message is misleading and wrong.

Fair enough - I amended the commit and pushed out the new version.

Thanks,

	Ingo

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

* [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs
  2016-07-23  4:58 [PATCH] x86/mm/cpa: Unbreak populate_pgd(): stop trying to deallocate failed PUDs Andy Lutomirski
  2016-07-23  7:46 ` [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop " tip-bot for Andy Lutomirski
@ 2016-07-23 19:15 ` tip-bot for Andy Lutomirski
  2016-07-23 20:42   ` Nicolai Stange
  1 sibling, 1 reply; 6+ messages in thread
From: tip-bot for Andy Lutomirski @ 2016-07-23 19:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, bp, akpm, linux-kernel, Valdis.Kletnieks, brgerst, jpoimboe,
	mcgrof, torvalds, hpa, luto, mingo, toshi.kani, krinkin.m.u,
	dvlasenk, peterz

Commit-ID:  530dd8d4b9daf77e3e5d145a26210d91ced954c7
Gitweb:     http://git.kernel.org/tip/530dd8d4b9daf77e3e5d145a26210d91ced954c7
Author:     Andy Lutomirski <luto@kernel.org>
AuthorDate: Fri, 22 Jul 2016 21:58:08 -0700
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 23 Jul 2016 21:13:25 +0200

x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs

Valdis Kletnieks bisected a boot failure back to this recent commit:

  360cb4d15567 ("x86/mm/cpa: In populate_pgd(), don't set the PGD entry until it's populated")

I broke the case where a PUD table got allocated -- populate_pud()
would wander off a pgd_none entry and get lost.  I'm not sure how
this survived my testing.

Fix the original issue in a much simpler way.  The problem
was that, if we allocated a PUD table, failed to populate it, and
freed it, another CPU could potentially keep using the PGD entry we
installed (either by copying it via vmalloc_fault or by speculatively
caching it).  There's a straightforward fix: simply leave the
top-level entry in place if this happens.  This can't waste any
significant amount of memory -- there are at most 256 entries like
this systemwide and, as a practical matter, if we hit this failure
path repeatedly, we're likely to reuse the same page anyway.

For context, this is a reversion with this hunk added in:

	if (ret < 0) {
+		/*
+		 * Leave the PUD page in place in case some other CPU or thread
+		 * already found it, but remove any useless entries we just
+		 * added to it.
+		 */
-		unmap_pgd_range(cpa->pgd, addr,
+		unmap_pud_range(pgd_entry, addr,
			        addr + (cpa->numpages << PAGE_SHIFT));
		return ret;
	}

This effectively open-codes what the now-deleted unmap_pgd_range()
function used to do except that unmap_pgd_range() used to try to
free the page as well.

Reported-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Luis R. Rodriguez <mcgrof@suse.com>
Cc: Mike Krinkin <krinkin.m.u@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Toshi Kani <toshi.kani@hp.com>
Link: http://lkml.kernel.org/r/21cbc2822aa18aa812c0215f4231dbf5f65afa7f.1469249789.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/pageattr.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 26c93c6..2bc6ea1 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -1082,6 +1082,8 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 		pud = (pud_t *)get_zeroed_page(GFP_KERNEL | __GFP_NOTRACK);
 		if (!pud)
 			return -1;
+
+		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
 	}
 
 	pgprot_val(pgprot) &= ~pgprot_val(cpa->mask_clr);
@@ -1089,16 +1091,11 @@ static int populate_pgd(struct cpa_data *cpa, unsigned long addr)
 
 	ret = populate_pud(cpa, addr, pgd_entry, pgprot);
 	if (ret < 0) {
-		if (pud)
-			free_page((unsigned long)pud);
 		unmap_pud_range(pgd_entry, addr,
 				addr + (cpa->numpages << PAGE_SHIFT));
 		return ret;
 	}
 
-	if (pud)
-		set_pgd(pgd_entry, __pgd(__pa(pud) | _KERNPG_TABLE));
-
 	cpa->numpages = ret;
 	return 0;
 }

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

* Re: [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop trying to deallocate failed PUDs
  2016-07-23 19:15 ` tip-bot for Andy Lutomirski
@ 2016-07-23 20:42   ` Nicolai Stange
  0 siblings, 0 replies; 6+ messages in thread
From: Nicolai Stange @ 2016-07-23 20:42 UTC (permalink / raw)
  To: tip-bot for Andy Lutomirski
  Cc: linux-tip-commits, mingo, peterz, dvlasenk, krinkin.m.u,
	toshi.kani, mcgrof, jpoimboe, linux-kernel, Valdis.Kletnieks,
	brgerst, tglx, akpm, bp, luto, hpa, torvalds

tip-bot for Andy Lutomirski <tipbot@zytor.com> writes:

> Valdis Kletnieks bisected a boot failure back to this recent commit:
>
>   360cb4d15567 ("x86/mm/cpa: In populate_pgd(), don't set the PGD entry until it's populated")
>

FYI, I faced the same issue and this patch, applied directly on top of
the faulty 360cb4d15567, fixes it for me.

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

end of thread, other threads:[~2016-07-23 20:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-23  4:58 [PATCH] x86/mm/cpa: Unbreak populate_pgd(): stop trying to deallocate failed PUDs Andy Lutomirski
2016-07-23  7:46 ` [tip:x86/mm] x86/mm/cpa: Fix populate_pgd(): Stop " tip-bot for Andy Lutomirski
2016-07-23  8:32   ` Linus Torvalds
2016-07-23 19:14     ` Ingo Molnar
2016-07-23 19:15 ` tip-bot for Andy Lutomirski
2016-07-23 20:42   ` Nicolai Stange

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).