[kernel] r18948 - in dists/squeeze/linux-2.6/debian: . patches/bugfix/x86 patches/features/all/xen patches/series
Ben Hutchings
benh at alioth.debian.org
Tue Apr 24 03:37:14 UTC 2012
Author: benh
Date: Tue Apr 24 03:37:12 2012
New Revision: 18948
Log:
[x86] mm: Fix pgd_lock deadlock (Closes: #669335)
This fix was already in the xen featureset had this but not in the
standard patch set. Fix up the xen patch series accordingly.
Added:
dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch
dists/squeeze/linux-2.6/debian/patches/series/44
dists/squeeze/linux-2.6/debian/patches/series/44-extra
- copied, changed from r18947, dists/squeeze/linux-2.6/debian/patches/series/42-extra
Deleted:
dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Fix-pgd_lock-deadlock.patch
dists/squeeze/linux-2.6/debian/patches/series/42-extra
Modified:
dists/squeeze/linux-2.6/debian/changelog
dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch
Modified: dists/squeeze/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze/linux-2.6/debian/changelog Mon Apr 23 05:33:50 2012 (r18947)
+++ dists/squeeze/linux-2.6/debian/changelog Tue Apr 24 03:37:12 2012 (r18948)
@@ -1,3 +1,10 @@
+linux-2.6 (2.6.32-44) UNRELEASED; urgency=low
+
+ [ Ben Hutchings ]
+ * [x86] mm: Fix pgd_lock deadlock (Closes: #669335)
+
+ -- Ben Hutchings <ben at decadent.org.uk> Tue, 24 Apr 2012 04:24:55 +0100
+
linux-2.6 (2.6.32-43) stable; urgency=high
* Ignore arch_pick_mmap_layout ABI change on s390
Added: dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch Tue Apr 24 03:37:12 2012 (r18948)
@@ -0,0 +1,224 @@
+From: Andrea Arcangeli <aarcange at redhat.com>
+Date: Wed, 16 Feb 2011 15:45:22 -0800
+Subject: [PATCH] x86/mm: Fix pgd_lock deadlock
+
+commit a79e53d85683c6dd9f99c90511028adc2043031f upstream.
+
+It's forbidden to take the page_table_lock with the irq disabled
+or if there's contention the IPIs (for tlb flushes) sent with
+the page_table_lock held will never run leading to a deadlock.
+
+Nobody takes the pgd_lock from irq context so the _irqsave can be
+removed.
+
+Signed-off-by: Andrea Arcangeli <aarcange at redhat.com>
+Acked-by: Rik van Riel <riel at redhat.com>
+Tested-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
+Cc: Peter Zijlstra <peterz at infradead.org>
+Cc: Linus Torvalds <torvalds at linux-foundation.org>
+Cc: <stable at kernel.org>
+LKML-Reference: <201102162345.p1GNjMjm021738 at imap1.linux-foundation.org>
+Signed-off-by: Ingo Molnar <mingo at elte.hu>
+[Backported to 2.6.32 by various people, adjusting context]
+---
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -223,15 +223,14 @@ void vmalloc_sync_all(void)
+ address >= TASK_SIZE && address < FIXADDR_TOP;
+ address += PMD_SIZE) {
+
+- unsigned long flags;
+ struct page *page;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ list_for_each_entry(page, &pgd_list, lru) {
+ if (!vmalloc_sync_one(page_address(page), address))
+ break;
+ }
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+ }
+
+@@ -331,13 +330,12 @@ void vmalloc_sync_all(void)
+ address += PGDIR_SIZE) {
+
+ const pgd_t *pgd_ref = pgd_offset_k(address);
+- unsigned long flags;
+ struct page *page;
+
+ if (pgd_none(*pgd_ref))
+ continue;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ list_for_each_entry(page, &pgd_list, lru) {
+ pgd_t *pgd;
+ pgd = (pgd_t *)page_address(page) + pgd_index(address);
+@@ -346,7 +344,7 @@ void vmalloc_sync_all(void)
+ else
+ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ }
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+ }
+
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -56,12 +56,10 @@ static unsigned long direct_pages_count[
+
+ void update_page_count(int level, unsigned long pages)
+ {
+- unsigned long flags;
+-
+ /* Protect against CPA */
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ direct_pages_count[level] += pages;
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+
+ static void split_page_count(int level)
+@@ -354,7 +352,7 @@ static int
+ try_preserve_large_page(pte_t *kpte, unsigned long address,
+ struct cpa_data *cpa)
+ {
+- unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
++ unsigned long nextpage_addr, numpages, pmask, psize, addr, pfn;
+ pte_t new_pte, old_pte, *tmp;
+ pgprot_t old_prot, new_prot;
+ int i, do_split = 1;
+@@ -363,7 +361,7 @@ try_preserve_large_page(pte_t *kpte, uns
+ if (cpa->force_split)
+ return 1;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ /*
+ * Check for races, another CPU might have split this page
+ * up already:
+@@ -458,14 +456,14 @@ try_preserve_large_page(pte_t *kpte, uns
+ }
+
+ out_unlock:
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+
+ return do_split;
+ }
+
+ static int split_large_page(pte_t *kpte, unsigned long address)
+ {
+- unsigned long flags, pfn, pfninc = 1;
++ unsigned long pfn, pfninc = 1;
+ unsigned int i, level;
+ pte_t *pbase, *tmp;
+ pgprot_t ref_prot;
+@@ -479,7 +477,7 @@ static int split_large_page(pte_t *kpte,
+ if (!base)
+ return -ENOMEM;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ /*
+ * Check for races, another CPU might have split this page
+ * up for us already:
+@@ -551,7 +549,7 @@ out_unlock:
+ */
+ if (base)
+ __free_page(base);
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+
+ return 0;
+ }
+--- a/arch/x86/mm/pgtable.c
++++ b/arch/x86/mm/pgtable.c
+@@ -110,14 +110,12 @@ static void pgd_ctor(pgd_t *pgd)
+
+ static void pgd_dtor(pgd_t *pgd)
+ {
+- unsigned long flags; /* can be called from interrupt context */
+-
+ if (SHARED_KERNEL_PMD)
+ return;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+ pgd_list_del(pgd);
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+
+ /*
+@@ -248,7 +246,6 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+ pgd_t *pgd;
+ pmd_t *pmds[PREALLOCATED_PMDS];
+- unsigned long flags;
+
+ pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);
+
+@@ -268,12 +265,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ * respect to anything walking the pgd_list, so that they
+ * never see a partially populated pgd.
+ */
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+
+ pgd_ctor(pgd);
+ pgd_prepopulate_pmd(mm, pgd, pmds);
+
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+
+ return pgd;
+
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -988,10 +988,9 @@ static void xen_pgd_pin(struct mm_struct
+ */
+ void xen_mm_pin_all(void)
+ {
+- unsigned long flags;
+ struct page *page;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+
+ list_for_each_entry(page, &pgd_list, lru) {
+ if (!PagePinned(page)) {
+@@ -1000,7 +999,7 @@ void xen_mm_pin_all(void)
+ }
+ }
+
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+
+ /*
+@@ -1101,10 +1100,9 @@ static void xen_pgd_unpin(struct mm_stru
+ */
+ void xen_mm_unpin_all(void)
+ {
+- unsigned long flags;
+ struct page *page;
+
+- spin_lock_irqsave(&pgd_lock, flags);
++ spin_lock(&pgd_lock);
+
+ list_for_each_entry(page, &pgd_list, lru) {
+ if (PageSavePinned(page)) {
+@@ -1114,7 +1112,7 @@ void xen_mm_unpin_all(void)
+ }
+ }
+
+- spin_unlock_irqrestore(&pgd_lock, flags);
++ spin_unlock(&pgd_lock);
+ }
+
+ void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
Modified: dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch Mon Apr 23 05:33:50 2012 (r18947)
+++ dists/squeeze/linux-2.6/debian/patches/features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch Tue Apr 24 03:37:12 2012 (r18948)
@@ -21,6 +21,8 @@
LKML-Reference: <4CB88A4C.1080305 at goop.org>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge at citrix.com>
Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>
+[bwh: Adjust context to apply after backported commit
+ a79e53d85683c6dd9f99c90511028adc2043031f 'x86/mm: Fix pgd_lock deadlock']
---
arch/x86/include/asm/pgtable.h | 2 ++
arch/x86/mm/fault.c | 11 ++++++++++-
@@ -28,8 +30,6 @@
arch/x86/mm/pgtable.c | 20 +++++++++++++++++---
4 files changed, 36 insertions(+), 4 deletions(-)
-diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
-index 2d0a33b..ada823a 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -28,6 +28,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
@@ -41,13 +41,11 @@
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else /* !CONFIG_PARAVIRT */
-diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
-index caec229..6c27c39 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -229,7 +229,16 @@ void vmalloc_sync_all(void)
- spin_lock_irqsave(&pgd_lock, flags);
+ spin_lock(&pgd_lock);
list_for_each_entry(page, &pgd_list, lru) {
- if (!vmalloc_sync_one(page_address(page), address))
+ spinlock_t *pgt_lock;
@@ -62,9 +60,9 @@
+ if (!ret)
break;
}
- spin_unlock_irqrestore(&pgd_lock, flags);
+ spin_unlock(&pgd_lock);
@@ -349,11 +349,19 @@
- spin_lock_irqsave(&pgd_lock, flags);
+ spin_lock(&pgd_lock);
list_for_each_entry(page, &pgd_list, lru) {
pgd_t *pgd;
+ spinlock_t *pgt_lock;
@@ -81,10 +79,8 @@
+
+ spin_unlock(pgt_lock);
}
- spin_unlock_irqrestore(&pgd_lock, flags);
+ spin_unlock(&pgd_lock);
}
-diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
-index 5c4ee42..c70e57d 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -87,7 +87,19 @@ static inline void pgd_list_del(pgd_t *pgd)
@@ -122,13 +118,10 @@
static void pgd_dtor(pgd_t *pgd)
@@ -272,7 +286,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
*/
- spin_lock_irqsave(&pgd_lock, flags);
+ spin_lock(&pgd_lock);
- pgd_ctor(pgd);
+ pgd_ctor(mm, pgd);
pgd_prepopulate_pmd(mm, pgd, pmds);
- spin_unlock_irqrestore(&pgd_lock, flags);
---
-1.7.4.1
-
+ spin_unlock(&pgd_lock);
Added: dists/squeeze/linux-2.6/debian/patches/series/44
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dists/squeeze/linux-2.6/debian/patches/series/44 Tue Apr 24 03:37:12 2012 (r18948)
@@ -0,0 +1 @@
++ bugfix/x86/x86-mm-Fix-pgd_lock-deadlock.patch
Copied and modified: dists/squeeze/linux-2.6/debian/patches/series/44-extra (from r18947, dists/squeeze/linux-2.6/debian/patches/series/42-extra)
==============================================================================
--- dists/squeeze/linux-2.6/debian/patches/series/42-extra Mon Apr 23 05:33:50 2012 (r18947, copy source)
+++ dists/squeeze/linux-2.6/debian/patches/series/44-extra Tue Apr 24 03:37:12 2012 (r18948)
@@ -40,7 +40,6 @@
+ features/all/xen/x86-mm-Hold-mm-page_table_lock-while-doing-vmalloc_s.patch featureset=xen
+ features/all/xen/x86-mm-Fix-incorrect-data-type-in-vmalloc_sync_all.patch featureset=xen
+ features/all/xen/vmalloc-eagerly-clear-ptes-on-vunmap.patch featureset=xen
-+ features/all/xen/x86-mm-Fix-pgd_lock-deadlock.patch featureset=xen
+ features/all/xen/xen-apic-use-handle_edge_irq-for-pirq-events.patch featureset=xen
+ features/all/xen/xen-pirq-do-EOI-properly-for-pirq-events.patch featureset=xen
More information about the Kernel-svn-changes
mailing list