ioapic: fix potential resume deadlock
PATCH 1/1 ioapic: fix potential resume deadlock
Fix a potential deadlock when resuming; here the calling function has disabled interrupts, so we cannot sleep.
--- arch/x86/kernel/apic/io_apic.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +2 -2
@@ -621,14 +621,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)struct IO_APIC_route_entry **ioapic_entries; ioapic_entries =kzalloc (sizeof (*ioapic_entries) * nr_ioapics, -GFP_KERNEL ); +GFP_ATOMIC );if (!ioapic_entries)return 0 ;for (apic =0 ; apic < nr_ioapics; apic++) { ioapic_entries[apic] =kzalloc (sizeof (struct IO_APIC_route_entry ) * - nr_ioapic_registers[apic],GFP_KERNEL ); + nr_ioapic_registers[apic],GFP_ATOMIC );if (!ioapic_entries[apic]) goto nomem; }
Signature · 1 line
1.7.4.1
Hi Thomas, Ingo, HPA,
Quoted 23 lines · Daniel J Blueman
Fix a potential deadlock when resuming; here the calling function has disabled interrupts, so we cannot sleep.
Signed-off-by Daniel J Blueman <[email protected]>---
arch/x86/kernel/apic/io_apic.c | 4 ++--1 files changed, 2 insertions(+), 2 deletions(-)arch/x86/kernel/apic/io_apic.c +1
-1@@ -621,14 +621,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void) struct IO_APIC_route_entry **ioapic_entries; ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics, - GFP_KERNEL); + GFP_ATOMIC); if (!ioapic_entries) return 0; for (apic = 0; apic < nr_ioapics; apic++) {
Quoted 7 lines
ioapic_entries[apic] =
kzalloc(sizeof(structIO_APIC_route_entry) *
- nr_ioapic_registers[apic],GFP_KERNEL);
+ nr_ioapic_registers[apic],GFP_ATOMIC); if (!ioapic_entries[apic])
goto nomem;
}
Any feedback on this? I tested it on 2.6.39-rc6 and it does address the potential deadlock warning I receive when resuming from suspend. If positive, it would be good to get into -rc8, as rc7 is released.
Thanks,
Daniel
Signature · 1 line
Daniel J Blueman
Quoted 20 lines · Daniel J Blueman
Fix a potential deadlock when resuming; here the calling function has disabled interrupts, so we cannot sleep.
Signed-off-by Daniel J Blueman <[email protected]>--- arch/x86/kernel/apic/io_apic.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)arch/x86/kernel/apic/io_apic.c +1
-1@@ -621,14 +621,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)struct IO_APIC_route_entry **ioapic_entries; ioapic_entries =kzalloc (sizeof (*ioapic_entries) * nr_ioapics, -GFP_KERNEL ); +GFP_ATOMIC );if (!ioapic_entries)
arch/x86/kernel/apic/io_apic.c struct IO_APIC_route_entry **alloc_ioapic_entries(void) · line 634
Quoted 10 lines
arch/x86/kernel/apic/io_apic.c +1
-1return 0 ;for (apic =0 ; apic < nr_ioapics; apic++) { ioapic_entries[apic] =kzalloc (sizeof (struct IO_APIC_route_entry ) * - nr_ioapic_registers[apic],GFP_KERNEL ); + nr_ioapic_registers[apic],GFP_ATOMIC );if (!ioapic_entries[apic]) goto nomem; }
Hm, there must be some other bug here.
ioapic entries should be allocated on system bootup and should never really be deallocated.
The bug might be in the idea to call to enable_IR_x2apic() on resume - why are ioapic entries reallocated there? That call in default_setup_apic_routing() was introduced some time ago in:
fa47f7e52874: x86, x2apic: Simplify apic init in SMP and UP builds
and that it results in reallocation in the suspend patch is distinctly wrong.
I suspect the reason why this has not triggered for others is the relative rarity of affected systems?
Suresh?
Thanks,
Ingo
Quoted 42 lines · Ingo Molnar
Quoted 23 lines · Daniel J Blueman
Fix a potential deadlock when resuming; here the calling function has disabled interrupts, so we cannot sleep.
Signed-off-by Daniel J Blueman <[email protected]>---
arch/x86/kernel/apic/io_apic.c | 4 ++--1 files changed, 2 insertions(+), 2 deletions(-)arch/x86/kernel/apic/io_apic.c +1
-1@@ -621,14 +621,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void) struct IO_APIC_route_entry **ioapic_entries; ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics, - GFP_KERNEL); + GFP_ATOMIC); if (!ioapic_entries) return 0; for (apic = 0; apic < nr_ioapics; apic++) {Quoted 7 lines
ioapic_entries[apic] =
kzalloc(sizeof(structIO_APIC_route_entry) *
- nr_ioapic_registers[apic],GFP_KERNEL);
+ nr_ioapic_registers[apic],GFP_ATOMIC); if (!ioapic_entries[apic])
goto nomem;
}Hm, there must be some other bug here.
ioapic entries should be allocated on system bootup and should never really be deallocated.
The bug might be in the idea to call to
enable_IR_x2apic()on resume - why are ioapic entries reallocated there? That call indefault_setup_apic_routing()was introduced some time ago in:
Quoted 8 lines
fa47f7e52874: x86, x2apic: Simplify apic init in SMP and UP builds
and that it results in reallocation in the suspend patch is distinctly wrong.
I suspect the reason why this has not triggered for others is the relative rarity of affected systems?
Suresh?
For reference, this is the warning I get on resume with debugging enabled:
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 0, irqs_disabled(): 1, pid: 1842, name: pm-suspend INFO: lockdep is turned off. irq event stamp: 0 hardirqs last enabled at (0): [< (null)>] (null) hardirqs last disabled at (0): [<ffffffff8105eca2>] copy_process+ 0x4e2/0x1040 softirqs last enabled at (0): [<ffffffff8105eca2>] copy_process+0x4e2/0x1040 softirqs last disabled at (0): [< (null)>] (null) Pid: 1842, comm: pm-suspend Tainted: G M 2.6.39-rc6-330cd+ #3 Call Trace: [<ffffffff81098290>] ? print_irqtrace_events+0xd0/0xe0 [<ffffffff8104a11d>] __might_sleep+0xed/0x120 [<ffffffff8112f7c3>] __kmalloc+0xd3/0x140 [<ffffffff81025566>] alloc_ioapic_entries+0x66/0xb0 [<ffffffff81022bc5>] lapic_resume+0x265/0x350 [<ffffffff814059d5>] syscore_resume+0x35/0xd0 [<ffffffff810a8ace>] suspend_enter+0xde/0x120 [<ffffffff810a8b7a>] suspend_devices_and_enter+0x6a/0xb0 [<ffffffff810a8c91>] enter_state+0xd1/0x100 [<ffffffff810a81c6>] state_store+0xc6/0x100 [<ffffffff81329c37>] kobj_attr_store+0x17/0x20 [<ffffffff811a78d1>] sysfs_write_file+0xe1/0x160 [<ffffffff811400c6>] vfs_write+0xc6/0x180 [<ffffffff811403dc>] sys_write+0x4c/0x90 [<ffffffff8170927b>] system_call_fastpath+0x16/0x1b
Signature · 1 line
Daniel J Blueman
Quoted 10 lines · Daniel J Blueman
Quoted 9 lines · Ingo Molnar
Hm, there must be some other bug here.
ioapic entries should be allocated on system bootup and should never really be deallocated.
The bug might be in the idea to call to
enable_IR_x2apic()on resume - why are ioapic entries reallocated there? That call indefault_setup_apic_routing()was introduced some time ago in:
Quoted 8 lines
Quoted 8 lines
fa47f7e52874: x86, x2apic: Simplify apic init in SMP and UP buildsand that it results in reallocation in the suspend patch is distinctly wrong.
I suspect the reason why this has not triggered for others is the relative rarity of affected systems?
Suresh?
This will happen only on interrupt-remapping enabled systems and hence hidden so far.
enable_IR_x2apic() / default_setup_apic_routing() routines don't get called during resume. Problem is with the lapic_resume() path which is trying to re-enable x2apic mode and this requires masking io-apic entries, re-enabling x2apic and interrupt-remapping, restoring io-apic entries etc. ioapic entry allocation that is happening in lapic_resume() is just for storing the original io-apic RTE's during the mask/restore operations that happen around re-enabling x2apic.
Anyways looking at that code, there is some duplicate code between x2apic code and the io-apic suspend/resume sequence. So a better fix will be to remove this duplicate code.
Daniel, I appended a quick patch which should fix the problem you reported. This is not a final patch, as I can do some more cleanup and re-use the io-apic suspend/resume code a bit more.
If this patch works for you, then I can spend some more time to do the complete cleanup patch in a day or two. Thanks.
arch/x86/include/asm/io_apic.h | 1 + arch/x86/kernel/apic/apic.c | 26 ++++---------------------- arch/x86/kernel/apic/io_apic.c | 2 +- 3 files changed, 6 insertions(+), 23 deletions(-)
arch/x86/include/asm/io_apic.h +1 -0
@@ -177,6 +177,7 @@ extern void __init pre_init_apic_IRQ0(void);extern void mp_save_irq (struct mpc_intsrc *m);extern void disable_ioapic_support (void ); +extern struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS ];#else /* !CONFIG_X86_IO_APIC */
arch/x86/kernel/apic/apic.c +4 -22
@@ -2088,28 +2088,14 @@ static void lapic_resume(void) {unsigned int l, h;unsigned long flags; -int maxlvt, ret; -struct IO_APIC_route_entry **ioapic_entries =NULL ; +int maxlvt;if (!apic_pm_state.active)return ;local_irq_save (flags);if (intr_remapping_enabled) { - ioapic_entries =alloc_ioapic_entries (); -if (!ioapic_entries) { -WARN (1 ,"Alloc ioapic_entries in lapic resume failed." ); - goto restore; - } - - ret =save_IO_APIC_setup (ioapic_entries); -if (ret) { -WARN (1 ,"Saving IO-APIC state failed: %d\n" , ret); -free_ioapic_entries (ioapic_entries); - goto restore; - } - -mask_IO_APIC_setup (ioapic_entries); +mask_IO_APIC_setup (ioapic_saved_data); legacy_pic->mask_all (); }
@@ -2152,13 +2138,9 @@ static void lapic_resume(void)apic_write (APIC_ESR ,0 );apic_read (APIC_ESR ); -if (intr_remapping_enabled) { +if (intr_remapping_enabled)reenable_intr_remapping (x2apic_mode); - legacy_pic->restore_mask (); -restore_IO_APIC_setup (ioapic_entries); -free_ioapic_entries (ioapic_entries); - } -restore: +local_irq_restore (flags); }
arch/x86/kernel/apic/io_apic.c +1 -1
@@ -2918,7 +2918,7 @@ static int __init io_apic_bug_finalize(void)late_initcall (io_apic_bug_finalize); -static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS ]; +struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS ];static void suspend_ioapic (int ioapic_id) {
Daniel J Blueman
Tested-byQuoted 35 lines · Suresh Siddha
Quoted 10 lines · Daniel J Blueman
Quoted 9 lines · Ingo Molnar
Hm, there must be some other bug here.
ioapic entries should be allocated on system bootup and should never really be deallocated.
The bug might be in the idea to call to
enable_IR_x2apic()on resume - why are ioapic entries reallocated there? That call indefault_setup_apic_routing()was introduced some time ago in:Quoted 8 lines
Quoted 8 lines
fa47f7e52874: x86, x2apic: Simplify apic init in SMP and UP builds
and that it results in reallocation in the suspend patch is distinctly wrong.
I suspect the reason why this has not triggered for others is the relative rarity of affected systems?
Suresh?
This will happen only on interrupt-remapping enabled systems and hence hidden so far.
enable_IR_x2apic()/default_setup_apic_routing()routines don't get called during resume. Problem is with thelapic_resume()path which is trying to re-enable x2apic mode and this requires masking io-apic entries, re-enabling x2apic and interrupt-remapping, restoring io-apic entries etc. ioapic entry allocation that is happening inlapic_resume()is just for storing the original io-apic RTE's during the mask/restore operations that happen around re-enabling x2apic.Anyways looking at that code, there is some duplicate code between x2apic code and the io-apic suspend/resume sequence. So a better fix will be to remove this duplicate code.
Quoted 6 lines
Daniel, I appended a quick patch which should fix the problem you reported. This is not a final patch, as I can do some more cleanup and re-use the io-apic suspend/resume code a bit more.
If this patch works for you, then I can spend some more time to do the complete cleanup patch in a day or two. Thanks.
[...]
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context at mm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.
Thanks,
Daniel
Signature · 1 line
Daniel J Blueman
Quoted 6 lines · Daniel J Blueman
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context atmm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.Tested-by Daniel J Blueman <[email protected]>
Thanks Daniel for testing my quick patch. I have appended the complete patch which cleans up this code.
Ingo, This patch is relatively big (mostly removes the duplicate code and changes the location where we allocate ioapic_saved_data, so that this can be shared between interrupt-remapping and io-apic suspend/resume flows). May be this can go into 2.6.40-rc1 and probably go to 2.6.39-stable?
Or we can take the Daniel's GFP_ATOMIC patch for 2.6.39 and push this patch for 2.6.40-rc1. I am ok either way.
Thanks.
---
From: Suresh Siddha <[email protected]>
Subject: x86, ioapic: Remove the duplicate code for saving/restoring io-apic RTE's
Daniel reported that x2apic and interrupt-remapping resume code flow is allocating memory with GFP_KERNEL while the interrupts are disabled.
Code flow for enabling interrupt-remapping has its own routines for saving and restoring io-apic RTE's. ioapic suspend/resume code flow also has similar routines. Remove the duplicate code. This will consolidate code aswell as remove the unnecessary allocation/free of the temporary buffers during suspend/resume of interrupt-remapping enabled platforms (and thus avoid the GFP_KERNEL allocation in the interrupts disabled context).
---
arch/x86/include/asm/io_apic.h | 21 ++---- arch/x86/kernel/apic/apic.c | 49 ++++---------- arch/x86/kernel/apic/io_apic.c | 148 +++++++++++----------------------------- 3 files changed, 61 insertions(+), 157 deletions(-)
arch/x86/include/asm/io_apic.h +6 -15
@@ -152,11 +152,9 @@ extern void ioapic_insert_resources(void);int io_apic_setup_irq_pin_once (unsigned int irq,int node,struct io_apic_irq_attr *attr); -extern struct IO_APIC_route_entry **alloc_ioapic_entries (void ); -extern void free_ioapic_entries (struct IO_APIC_route_entry **ioapic_entries); -extern int save_IO_APIC_setup (struct IO_APIC_route_entry **ioapic_entries); -extern void mask_IO_APIC_setup (struct IO_APIC_route_entry **ioapic_entries); -extern int restore_IO_APIC_setup (struct IO_APIC_route_entry **ioapic_entries); +extern int save_ioapic_entries (void ); +extern void mask_ioapic_entries (void ); +extern void restore_ioapic_entries (void );extern int get_nr_irqs_gsi (void );
@@ -192,21 +190,14 @@ struct io_apic_irq_attr;static inline int io_apic_set_pci_routing (struct device *dev,int irq,struct io_apic_irq_attr *irq_attr) {return 0 ; } -static inline struct IO_APIC_route_entry **alloc_ioapic_entries (void ) -{ -return NULL ; -} - -static inline void free_ioapic_entries (struct IO_APIC_route_entry **ent) { } -static inline int save_IO_APIC_setup (struct IO_APIC_route_entry **ent) +static inline int save_ioapic_entries (void ) {return -ENOMEM ; } -static inline void mask_IO_APIC_setup (struct IO_APIC_route_entry **ent) { } -static inline int restore_IO_APIC_setup (struct IO_APIC_route_entry **ent) +static inline void mask_ioapic_entries (void ) { } +static inline void restore_ioapic_entries (void ) { -return -ENOMEM ; }static inline void mp_save_irq (struct mpc_intsrc *m) { };
arch/x86/kernel/apic/apic.c +14 -35
96 lines not on this page · raw message
arch/x86/kernel/apic/io_apic.c +41 -107
246 lines not on this page · raw message
Hi Suresh,
Quoted 11 lines · Suresh Siddha
Quoted 6 lines · Daniel J Blueman
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context atmm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.Tested-by Daniel J Blueman <[email protected]>Thanks Daniel for testing my quick patch. I have appended the complete patch which cleans up this code.
Quoted 8 lines
Ingo, This patch is relatively big (mostly removes the duplicate code and changes the location where we allocate
ioapic_saved_data, so that this can be shared between interrupt-remapping and io-apic suspend/resume flows). May be this can go into 2.6.40-rc1 and probably go to 2.6.39-stable?Or we can take the Daniel's
GFP_ATOMICpatch for 2.6.39 and push this patch for 2.6.40-rc1. I am ok either way.
[]
Testing this, all looks well in that the patch resolves the potentially sleeping allocation, however I do see (on boot) this suspicious message (though suspend and resume does work):
IOAPIC 0: suspend/resume impossible!
I guess it's not expected...
Signature · 1 line
Daniel J Blueman
Quoted 24 lines · Daniel J Blueman
Hi Suresh,
Quoted 11 lines · Suresh Siddha
Quoted 6 lines · Daniel J Blueman
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context atmm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.Tested-by Daniel J Blueman <[email protected]>Thanks Daniel for testing my quick patch. I have appended the complete patch which cleans up this code.
Quoted 8 lines
Ingo, This patch is relatively big (mostly removes the duplicate code and changes the location where we allocate
ioapic_saved_data, so that this can be shared between interrupt-remapping and io-apic suspend/resume flows). May be this can go into 2.6.40-rc1 and probably go to 2.6.39-stable?Or we can take the Daniel's
GFP_ATOMICpatch for 2.6.39 and push this patch for 2.6.40-rc1. I am ok either way.[]
Quoted 7 lines
Testing this, all looks well in that the patch resolves the potentially sleeping allocation, however I do see (on boot) this suspicious message (though suspend and resume does work):
IOAPIC 0: suspend/resume impossible!
I guess it's not expected...
No. Has this been introduced by Suresh's patch?
Thanks,
Ingo
Quoted 26 lines · Ingo Molnar
Quoted 24 lines · Daniel J Blueman
Hi Suresh,
Quoted 11 lines · Suresh Siddha
Quoted 6 lines · Daniel J Blueman
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context atmm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.Tested-by Daniel J Blueman <[email protected]>Thanks Daniel for testing my quick patch. I have appended the complete patch which cleans up this code.
Quoted 8 lines
Ingo, This patch is relatively big (mostly removes the duplicate code and changes the location where we allocate
ioapic_saved_data, so that this can be shared between interrupt-remapping and io-apic suspend/resume flows). May be this can go into 2.6.40-rc1 and probably go to 2.6.39-stable?Or we can take the Daniel's
GFP_ATOMICpatch for 2.6.39 and push this patch for 2.6.40-rc1. I am ok either way.[]
Quoted 7 lines
Quoted 7 lines
Testing this, all looks well in that the patch resolves the potentially sleeping allocation, however I do see (on boot) this suspicious message (though suspend and resume does work):
IOAPIC 0: suspend/resume impossible!
I guess it's not expected...
oops. I had a spurious initialization, from the earlier attempts to fix this that was still left out.
Quoted 1 line
No. Has this been introduced by Suresh's patch?
Ofcourse yes ;(
Will fix this and split the patch into multiple steps.
thanks,
suresh
Quoted 8 lines · Suresh Siddha
Quoted 6 lines · Daniel J Blueman
Superb, this works, tested against 2.6.39-rc7 and addresses the "BUG:
sleeping function called from invalid context atmm/slub.c:824" warning I was previously seeing. It would be good to get this fix into 2.6.39-final if possible.Tested-by Daniel J Blueman <[email protected]>
Quoted 8 lines
Thanks Daniel for testing my quick patch. I have appended the complete patch which cleans up this code.
Ingo, This patch is relatively big (mostly removes the duplicate code and changes the location where we allocate
ioapic_saved_data, so that this can be shared between interrupt-remapping and io-apic suspend/resume flows). May be this can go into 2.6.40-rc1 and probably go to 2.6.39-stable?
Could you please split it up into multiple steps? Commits with such a diffstat:
Quoted 4 lines
arch/x86/include/asm/io_apic.h | 21 ++---- arch/x86/kernel/apic/apic.c | 49 ++++---------- arch/x86/kernel/apic/io_apic.c | 148 +++++++++++----------------------------- 3 files changed, 61 insertions(+), 157 deletions(-)
... rarely come without regressions attached, and it's a whole lot easier to figure out what's wrong with a small patch out of 3-4 than with such a big patch.
I'd suggest to make the end result exactly the same as this one big patch, so that we preserve Daniel's testing results.
Thanks,
Ingo