diff options
author | Andrea Arcangeli <aarcange@redhat.com> | 2011-02-16 18:45:22 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-03-10 03:41:57 -0500 |
commit | a79e53d85683c6dd9f99c90511028adc2043031f (patch) | |
tree | 191f423331b608a5f7f134f484ce62a9ee7fb4a6 /arch/x86/xen/mmu.c | |
parent | f86268549f424f83b9eb0963989270e14fbfc3de (diff) |
x86/mm: Fix pgd_lock deadlock
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@redhat.com>
Acked-by: Rik van Riel <riel@redhat.com>
Tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: <stable@kernel.org>
LKML-Reference: <201102162345.p1GNjMjm021738@imap1.linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r-- | arch/x86/xen/mmu.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5e92b61ad574..f6089421147a 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -986,10 +986,9 @@ static void xen_pgd_pin(struct mm_struct *mm) | |||
986 | */ | 986 | */ |
987 | void xen_mm_pin_all(void) | 987 | void xen_mm_pin_all(void) |
988 | { | 988 | { |
989 | unsigned long flags; | ||
990 | struct page *page; | 989 | struct page *page; |
991 | 990 | ||
992 | spin_lock_irqsave(&pgd_lock, flags); | 991 | spin_lock(&pgd_lock); |
993 | 992 | ||
994 | list_for_each_entry(page, &pgd_list, lru) { | 993 | list_for_each_entry(page, &pgd_list, lru) { |
995 | if (!PagePinned(page)) { | 994 | if (!PagePinned(page)) { |
@@ -998,7 +997,7 @@ void xen_mm_pin_all(void) | |||
998 | } | 997 | } |
999 | } | 998 | } |
1000 | 999 | ||
1001 | spin_unlock_irqrestore(&pgd_lock, flags); | 1000 | spin_unlock(&pgd_lock); |
1002 | } | 1001 | } |
1003 | 1002 | ||
1004 | /* | 1003 | /* |
@@ -1099,10 +1098,9 @@ static void xen_pgd_unpin(struct mm_struct *mm) | |||
1099 | */ | 1098 | */ |
1100 | void xen_mm_unpin_all(void) | 1099 | void xen_mm_unpin_all(void) |
1101 | { | 1100 | { |
1102 | unsigned long flags; | ||
1103 | struct page *page; | 1101 | struct page *page; |
1104 | 1102 | ||
1105 | spin_lock_irqsave(&pgd_lock, flags); | 1103 | spin_lock(&pgd_lock); |
1106 | 1104 | ||
1107 | list_for_each_entry(page, &pgd_list, lru) { | 1105 | list_for_each_entry(page, &pgd_list, lru) { |
1108 | if (PageSavePinned(page)) { | 1106 | if (PageSavePinned(page)) { |
@@ -1112,7 +1110,7 @@ void xen_mm_unpin_all(void) | |||
1112 | } | 1110 | } |
1113 | } | 1111 | } |
1114 | 1112 | ||
1115 | spin_unlock_irqrestore(&pgd_lock, flags); | 1113 | spin_unlock(&pgd_lock); |
1116 | } | 1114 | } |
1117 | 1115 | ||
1118 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) | 1116 | void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next) |