aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-02-06 16:39:45 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-06 16:39:45 -0500
commit58d5d0d8dd52cbca988af24b5692a20b00285543 (patch)
tree285539cf1ad60d9ebcda310b97f818c17ef634c8 /arch/x86/mm
parenta09771bef9a375091f8ae706d992e20970e5d1e7 (diff)
x86: fix deadlock, make pgd_lock irq-safe
lockdep just caught this one: ================================= [ INFO: inconsistent lock state ] 2.6.24 #38 --------------------------------- inconsistent {in-softirq-W} -> {softirq-on-W} usage. swapper/1 [HC0[0]:SC0[0]:HE1:SE1] takes: (pgd_lock){-+..}, at: [<ffffffff8022a9ea>] mm_init+0x1da/0x250 {in-softirq-W} state was registered at: [<ffffffffffffffff>] 0xffffffffffffffff irq event stamp: 394559 hardirqs last enabled at (394559): [<ffffffff80267f0a>] get_page_from_freelist+0x30a/0x4c0 hardirqs last disabled at (394558): [<ffffffff80267d25>] get_page_from_freelist+0x125/0x4c0 softirqs last enabled at (393952): [<ffffffff80232f8e>] __do_softirq+0xce/0xe0 softirqs last disabled at (393945): [<ffffffff8020c57c>] call_softirq+0x1c/0x30 other info that might help us debug this: no locks held by swapper/1. stack backtrace: Pid: 1, comm: swapper Not tainted 2.6.24 #38 Call Trace: [<ffffffff8024e1fb>] print_usage_bug+0x18b/0x190 [<ffffffff8024f55d>] mark_lock+0x53d/0x560 [<ffffffff8024fffa>] __lock_acquire+0x3ca/0xed0 [<ffffffff80250ba8>] lock_acquire+0xa8/0xe0 [<ffffffff8022a9ea>] ? mm_init+0x1da/0x250 [<ffffffff809bcd10>] _spin_lock+0x30/0x70 [<ffffffff8022a9ea>] mm_init+0x1da/0x250 [<ffffffff8022aa99>] mm_alloc+0x39/0x50 [<ffffffff8028b95a>] bprm_mm_init+0x2a/0x1a0 [<ffffffff8028d12b>] do_execve+0x7b/0x220 [<ffffffff80209776>] sys_execve+0x46/0x70 [<ffffffff8020c214>] kernel_execve+0x64/0xd0 [<ffffffff8020901e>] ? _stext+0x1e/0x20 [<ffffffff802090ba>] init_post+0x9a/0xf0 [<ffffffff809bc5f6>] ? trace_hardirqs_on_thunk+0x35/0x3a [<ffffffff8024f75a>] ? trace_hardirqs_on+0xba/0xd0 [<ffffffff8020c1a8>] ? child_rip+0xa/0x12 [<ffffffff8020bcbc>] ? restore_args+0x0/0x44 [<ffffffff8020c19e>] ? child_rip+0x0/0x12 turns out that pgd_lock has been used on 64-bit x86 in an irq-unsafe way for almost two years, since commit 8c914cb704a11460e. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/fault.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index d8ed4006b3d2..621afb6343dc 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -958,11 +958,12 @@ void vmalloc_sync_all(void)
958 for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) { 958 for (address = start; address <= VMALLOC_END; address += PGDIR_SIZE) {
959 if (!test_bit(pgd_index(address), insync)) { 959 if (!test_bit(pgd_index(address), insync)) {
960 const pgd_t *pgd_ref = pgd_offset_k(address); 960 const pgd_t *pgd_ref = pgd_offset_k(address);
961 unsigned long flags;
961 struct page *page; 962 struct page *page;
962 963
963 if (pgd_none(*pgd_ref)) 964 if (pgd_none(*pgd_ref))
964 continue; 965 continue;
965 spin_lock(&pgd_lock); 966 spin_lock_irqsave(&pgd_lock, flags);
966 list_for_each_entry(page, &pgd_list, lru) { 967 list_for_each_entry(page, &pgd_list, lru) {
967 pgd_t *pgd; 968 pgd_t *pgd;
968 pgd = (pgd_t *)page_address(page) + pgd_index(address); 969 pgd = (pgd_t *)page_address(page) + pgd_index(address);
@@ -971,7 +972,7 @@ void vmalloc_sync_all(void)
971 else 972 else
972 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); 973 BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
973 } 974 }
974 spin_unlock(&pgd_lock); 975 spin_unlock_irqrestore(&pgd_lock, flags);
975 set_bit(pgd_index(address), insync); 976 set_bit(pgd_index(address), insync);
976 } 977 }
977 if (address == start) 978 if (address == start)