sleeping while atomic warning while modprobing oprofile.
I just saw this when after I did a 'modprobe oprofile' on my amd64 box.
Dave
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
Quoted 1 line · Dave Jones
I just saw this when after I did a 'modprobe oprofile' on my amd64 box.
Thanks for reporting this. This happens in init_ibs(). We are actually too strict here with disabling preemption, though we still need it. Will change that code.
-Robert
Quoted 24 lines
Dave
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
Signature · 2 lines
Advanced Micro Devices, Inc. Operating System Research Center
Quoted 31 lines · Robert Richter
Quoted 1 line · Dave Jones
I just saw this when after I did a 'modprobe oprofile' on my amd64 box.
Thanks for reporting this. This happens in
init_ibs(). We are actually too strict here with disabling preemption, though we still need it. Will change that code.-Robert
Quoted 22 lines
Dave
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
Dave,
the patch below should fix this.
-Robert
Quoted 1 line
From
3d2606f42984613d324ad3047cf503bcddc3880aMon Sep 17 00:00:00 2001
From: Robert Richter <[email protected]>
Date: Fri, 20 May 2011 09:46:54 +0200
Subject: [PATCH] oprofile, x86: Enable preemption during pci device setup in
IBS init
IBS initialization is a mix of per-core register access and per-node pci device setup. Register access should be pinned to the cpu, but pci setup must run with preemption enabled.
This patch better separates the code into non-/preemptible sections and fixes sleeping with preemption disabled. See bug message below.
Fixes also freeing the eilvt entry by introducing put_eilvt().
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
--- arch/x86/oprofile/op_model_amd.c | 95 +++++++++++++++++++++---------------- 1 files changed, 54 insertions(+), 41 deletions(-)
arch/x86/oprofile/op_model_amd.c +54 -41
@@ -316,16 +316,23 @@ static void op_amd_stop_ibs(void)wrmsrl (MSR_AMD64_IBSOPCTL ,0 ); } -static inline int eilvt_is_available (int offset) +static inline int get_eilvt (int offset) { -/* check if we may assign a vector */ return !setup_APIC_eilvt (offset,0 ,APIC_EILVT_MSG_NMI ,1 ); } +static inline int put_eilvt (int offset) +{ +return !setup_APIC_eilvt (offset,0 ,0 ,1 ); +} +static inline int ibs_eilvt_valid (void ) {int offset;u64 val; +int valid =0 ; + +preempt_disable ();rdmsrl (MSR_AMD64_IBSCTL , val); offset = val &IBSCTL_LVT_OFFSET_MASK ;
@@ -333,16 +340,20 @@ static inline int ibs_eilvt_valid(void)if (!(val &IBSCTL_LVT_OFFSET_VALID )) {pr_err (FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n" ,smp_processor_id (), offset,MSR_AMD64_IBSCTL , val); -return 0 ; + goto out; } -if (!eilvt_is_available (offset)) { +if (!get_eilvt (offset)) {pr_err (FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n" ,smp_processor_id (), offset,MSR_AMD64_IBSCTL , val); -return 0 ; + goto out; } -return 1 ; + valid =1 ; +out: +preempt_enable (); + +return valid; }static inline int get_ibs_offset (void )
@@ -600,67 +611,69 @@ static int setup_ibs_ctl(int ibs_eilvt_off)static int force_ibs_eilvt_setup (void ) { -int i; +int offset;int ret; -/* find the next free available EILVT entry */ -for (i =1 ; i <4 ; i++) { -if (!eilvt_is_available (i)) -continue ; - ret =setup_ibs_ctl (i); -if (ret) -return ret; -pr_err (FW_BUG "using offset %d for IBS interrupts\n" , i); -return 0 ; +/* +* find the next free available EILVT entry, skip offset 0, +* pin search to this cpu +*/ +preempt_disable (); +for (offset =1 ; offset <APIC_EILVT_NR_MAX ; offset++) { +if (get_eilvt (offset)) +break ; } +preempt_enable (); -printk (KERN_DEBUG "No EILVT entry available\n" ); - -return -EBUSY ; -} - -static int __init_ibs_nmi (void ) -{ -int ret; - -if (ibs_eilvt_valid ()) -return 0 ; +if (offset ==APIC_EILVT_NR_MAX ) { +printk (KERN_DEBUG "No EILVT entry available\n" ); +return -EBUSY ; + } - ret =force_ibs_eilvt_setup (); + ret =setup_ibs_ctl (offset);if (ret) -return ret; + goto out; -if (!ibs_eilvt_valid ()) -return -EFAULT ; +if (!ibs_eilvt_valid ()) { + ret = -EFAULT ; + goto out; + } +pr_err (FW_BUG "using offset %d for IBS interrupts\n" , offset);pr_err (FW_BUG "workaround enabled for IBS LVT offset\n" );return 0 ; +out: +preempt_disable (); +put_eilvt (offset); +preempt_enable (); +return ret; }/* * check and reserve APIC extended interrupt LVT offset for IBS if * available -* -* init_ibs() preforms implicitly cpu-local operations, so pin this -* thread to its current CPU */ static void init_ibs (void ) { -preempt_disable (); - ibs_caps =get_ibs_caps (); +if (!ibs_caps) +return ; + +if (ibs_eilvt_valid ()) goto out; -if (__init_ibs_nmi () <0 ) - ibs_caps =0 ; -else -printk (KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n" , ibs_caps); +if (!force_ibs_eilvt_setup ()) + goto out; + +/* Failed to setup ibs */ + ibs_caps =0 ; +return ; out: -preempt_enable (); +printk (KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n" , ibs_caps); }static int (*create_arch_files)(struct super_block *sb,struct dentry *root);
Signature · 7 lines
1.7.5.rc3 -- Advanced Micro Devices, Inc. Operating System Research Center
PATCH 1/1 oprofile, x86: Enable preemption during pci device setup in IBS init
In reply to Robert Richter(modified subject)
Quoted 31 lines · Robert Richter
Quoted 1 line · Dave Jones
I just saw this when after I did a 'modprobe oprofile' on my amd64 box.
Thanks for reporting this. This happens in
init_ibs(). We are actually too strict here with disabling preemption, though we still need it. Will change that code.-Robert
Quoted 22 lines
Dave
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
Dave,
the patch below should fix this.
-Robert
Quoted 1 line
From
3d2606f42984613d324ad3047cf503bcddc3880aMon Sep 17 00:00:00 2001
From: Robert Richter <[email protected]>
Date: Fri, 20 May 2011 09:46:54 +0200
Subject: [PATCH] oprofile, x86: Enable preemption during pci device setup in
IBS init
IBS initialization is a mix of per-core register access and per-node pci device setup. Register access should be pinned to the cpu, but pci setup must run with preemption enabled.
This patch better separates the code into non-/preemptible sections and fixes sleeping with preemption disabled. See bug message below.
Fixes also freeing the eilvt entry by introducing put_eilvt().
BUG: sleeping function called from invalid context at mm/slub.c:824 in_atomic(): 1, irqs_disabled(): 0, pid: 32357, name: modprobe INFO: lockdep is turned off. Pid: 32357, comm: modprobe Not tainted 2.6.39-rc7+ #14 Call Trace: [<ffffffff8104bdc8>] __might_sleep+0x112/0x117 [<ffffffff81129693>] kmem_cache_alloc_trace+0x4b/0xe7 [<ffffffff81278f14>] kzalloc.constprop.0+0x29/0x2b [<ffffffff81278f4c>] pci_get_subsys+0x36/0x78 [<ffffffff81022689>] ? setup_APIC_eilvt+0xfb/0x139 [<ffffffff81278fa4>] pci_get_device+0x16/0x18 [<ffffffffa06c8b5d>] op_amd_init+0xd3/0x211 [oprofile] [<ffffffffa064d000>] ? 0xffffffffa064cfff [<ffffffffa064d298>] op_nmi_init+0x21e/0x26a [oprofile] [<ffffffffa064d062>] oprofile_arch_init+0xe/0x26 [oprofile] [<ffffffffa064d010>] oprofile_init+0x10/0x42 [oprofile] [<ffffffff81002099>] do_one_initcall+0x7f/0x13a [<ffffffff81096524>] sys_init_module+0x132/0x281 [<ffffffff814cc682>] system_call_fastpath+0x16/0x1b
--- arch/x86/oprofile/op_model_amd.c | 95 +++++++++++++++++++++---------------- 1 files changed, 54 insertions(+), 41 deletions(-)
arch/x86/oprofile/op_model_amd.c +54 -41
@@ -316,16 +316,23 @@ static void op_amd_stop_ibs(void)wrmsrl (MSR_AMD64_IBSOPCTL ,0 ); } -static inline int eilvt_is_available (int offset) +static inline int get_eilvt (int offset) { -/* check if we may assign a vector */ return !setup_APIC_eilvt (offset,0 ,APIC_EILVT_MSG_NMI ,1 ); } +static inline int put_eilvt (int offset) +{ +return !setup_APIC_eilvt (offset,0 ,0 ,1 ); +} +static inline int ibs_eilvt_valid (void ) {int offset;u64 val; +int valid =0 ; + +preempt_disable ();rdmsrl (MSR_AMD64_IBSCTL , val); offset = val &IBSCTL_LVT_OFFSET_MASK ;
@@ -333,16 +340,20 @@ static inline int ibs_eilvt_valid(void)if (!(val &IBSCTL_LVT_OFFSET_VALID )) {pr_err (FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n" ,smp_processor_id (), offset,MSR_AMD64_IBSCTL , val); -return 0 ; + goto out; } -if (!eilvt_is_available (offset)) { +if (!get_eilvt (offset)) {pr_err (FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n" ,smp_processor_id (), offset,MSR_AMD64_IBSCTL , val); -return 0 ; + goto out; } -return 1 ; + valid =1 ; +out: +preempt_enable (); + +return valid; }static inline int get_ibs_offset (void )
@@ -600,67 +611,69 @@ static int setup_ibs_ctl(int ibs_eilvt_off)static int force_ibs_eilvt_setup (void ) { -int i; +int offset;int ret; -/* find the next free available EILVT entry */ -for (i =1 ; i <4 ; i++) { -if (!eilvt_is_available (i)) -continue ; - ret =setup_ibs_ctl (i); -if (ret) -return ret; -pr_err (FW_BUG "using offset %d for IBS interrupts\n" , i); -return 0 ; +/* +* find the next free available EILVT entry, skip offset 0, +* pin search to this cpu +*/ +preempt_disable (); +for (offset =1 ; offset <APIC_EILVT_NR_MAX ; offset++) { +if (get_eilvt (offset)) +break ; } +preempt_enable (); -printk (KERN_DEBUG "No EILVT entry available\n" ); - -return -EBUSY ; -} - -static int __init_ibs_nmi (void ) -{ -int ret; - -if (ibs_eilvt_valid ()) -return 0 ; +if (offset ==APIC_EILVT_NR_MAX ) { +printk (KERN_DEBUG "No EILVT entry available\n" ); +return -EBUSY ; + } - ret =force_ibs_eilvt_setup (); + ret =setup_ibs_ctl (offset);if (ret) -return ret; + goto out; -if (!ibs_eilvt_valid ()) -return -EFAULT ; +if (!ibs_eilvt_valid ()) { + ret = -EFAULT ; + goto out; + } +pr_err (FW_BUG "using offset %d for IBS interrupts\n" , offset);pr_err (FW_BUG "workaround enabled for IBS LVT offset\n" );return 0 ; +out: +preempt_disable (); +put_eilvt (offset); +preempt_enable (); +return ret; }/* * check and reserve APIC extended interrupt LVT offset for IBS if * available -* -* init_ibs() preforms implicitly cpu-local operations, so pin this -* thread to its current CPU */ static void init_ibs (void ) { -preempt_disable (); - ibs_caps =get_ibs_caps (); +if (!ibs_caps) +return ; + +if (ibs_eilvt_valid ()) goto out; -if (__init_ibs_nmi () <0 ) - ibs_caps =0 ; -else -printk (KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n" , ibs_caps); +if (!force_ibs_eilvt_setup ()) + goto out; + +/* Failed to setup ibs */ + ibs_caps =0 ; +return ; out: -preempt_enable (); +printk (KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n" , ibs_caps); }static int (*create_arch_files)(struct super_block *sb,struct dentry *root);
Signature · 7 lines
1.7.5.rc3 -- Advanced Micro Devices, Inc. Operating System Research Center