From 5a4ccaf37ffece09ef33f1cfec67efa8ee56f967 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 6 Jan 2009 21:15:32 +0100 Subject: kprobes: check CONFIG_FREEZER instead of CONFIG_PM Check CONFIG_FREEZER instead of CONFIG_PM because kprobe booster depends on freeze_processes() and thaw_processes() when CONFIG_PREEMPT=y. This fixes a linkage error which occurs when CONFIG_PREEMPT=y, CONFIG_PM=y and CONFIG_FREEZER=n. Reported-by: Cheng Renquan Signed-off-by: Masami Hiramatsu Signed-off-by: Rafael J. Wysocki Acked-by: Ingo Molnar Signed-off-by: Len Brown --- arch/ia64/kernel/kprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/ia64/kernel') diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index f90be51b112..9adac441ac9 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -870,7 +870,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) return 1; ss_probe: -#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PM) +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER) if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) { /* Boost up -- we can execute copied instructions directly */ ia64_psr(regs)->ri = p->ainsn.slot; -- cgit v1.2.3 From 66db2e6331612bbec193a358885854330596a92a Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 9 Feb 2009 11:16:16 -0700 Subject: [IA64] Revert "prevent ia64 from invoking irq handlers on offline CPUs" This reverts commit e7b140365b86aaf94374214c6f4e6decbee2eb0a. Commit e7b14036 removes the targetted disabled CPU from the cpu_online_map after calls to migrate_platform_irqs and fixup_irqs. Paul McKenney states that the reasoning behind the patch was to prevent irq handlers from running on CPUs marked offline because: RCU happily ignores CPUs that don't have their bits set in cpu_online_map, so if there are RCU read-side critical sections in the irq handlers being run, RCU will ignore them. If the other CPUs were running, they might sequence through the RCU state machine, which could result in data structures being yanked out from under those irq handlers, which in turn could result in oopses or worse. Unfortunately, both ia64 functions above look at cpu_online_map to find a new CPU to migrate interrupts onto. This means we can potentially migrate an interrupt off ourself back to... ourself. Uh oh. This causes an oops when we finally try to process pending interrupts on the CPU we want to disable. The oops results from calling __do_IRQ with a NULL pt_regs: Unable to handle kernel NULL pointer dereference (address 0000000000000040) Call Trace: [] show_stack+0x50/0xa0 sp=e0000009c922fa00 bsp=e0000009c92214d0 [] show_regs+0x820/0x860 sp=e0000009c922fbd0 bsp=e0000009c9221478 [] die+0x1a0/0x2e0 sp=e0000009c922fbd0 bsp=e0000009c9221438 [] ia64_do_page_fault+0x950/0xa80 sp=e0000009c922fbd0 bsp=e0000009c92213d8 [] ia64_native_leave_kernel+0x0/0x270 sp=e0000009c922fc60 bsp=e0000009c92213d8 [] profile_tick+0xd0/0x1c0 sp=e0000009c922fe30 bsp=e0000009c9221398 [] timer_interrupt+0x170/0x3e0 sp=e0000009c922fe30 bsp=e0000009c9221330 [] handle_IRQ_event+0x80/0x120 sp=e0000009c922fe30 bsp=e0000009c92212f8 [] __do_IRQ+0x160/0x4a0 sp=e0000009c922fe30 bsp=e0000009c9221290 [] ia64_process_pending_intr+0x2b0/0x360 sp=e0000009c922fe30 bsp=e0000009c9221208 [] fixup_irqs+0xf0/0x2a0 sp=e0000009c922fe30 bsp=e0000009c92211a8 [] __cpu_disable+0x140/0x240 sp=e0000009c922fe30 bsp=e0000009c9221168 [] take_cpu_down+0x50/0xa0 sp=e0000009c922fe30 bsp=e0000009c9221148 [] stop_cpu+0xd0/0x200 sp=e0000009c922fe30 bsp=e0000009c92210f0 [] kthread+0xc0/0x140 sp=e0000009c922fe30 bsp=e0000009c92210c8 [] kernel_thread_helper+0xd0/0x100 sp=e0000009c922fe30 bsp=e0000009c92210a0 [] start_kernel_thread+0x20/0x40 sp=e0000009c922fe30 bsp=e0000009c92210a0 I don't like this revert because it is fragile. ia64 is getting lucky because we seem to only ever process timer interrupts in this path, but if we ever race with an IPI here, we definitely use RCU and have the potential of hitting an oops that Paul describes above. Patching ia64's timer_interrupt() to check for NULL pt_regs is insufficient though, as we still hit the above oops. As a short term solution, I do think that this revert is the right answer. The revert hold up under repeated testing (24+ hour test runs) with this setup: - 8-way rx6600 - randomly toggling CPU online/offline state every 2 seconds - running CPU exercisers, memory hog, disk exercisers, and network stressors - average system load around ~160 In the long term, we really need to figure out why we set pt_regs = NULL in ia64_process_pending_intr(). If it turns out that it is unnecessary to do so, then we could safely re-introduce e7b14036 (along with some other logic to be smarter about migrating interrupts). One final note: x86 also removes the disabled CPU from cpu_online_map and then re-enables interrupts for 1ms, presumably to handle any pending interrupts: arch/x86/kernel/irq_32.c (and irq_64.c): cpu_disable_common: [remove cpu from cpu_online_map] fixup_irqs(): for_each_irq: [break CPU affinities] local_irq_enable(); mdelay(1); local_irq_disable(); So they are doing implicitly what ia64 is doing explicitly. Signed-off-by: Alex Chiang Signed-off-by: Tony Luck --- arch/ia64/kernel/smpboot.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/ia64/kernel') diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 11463994a7d..2ec5bbff461 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -736,14 +736,16 @@ int __cpu_disable(void) return -EBUSY; } + cpu_clear(cpu, cpu_online_map); + if (migrate_platform_irqs(cpu)) { cpu_set(cpu, cpu_online_map); return (-EBUSY); } remove_siblinginfo(cpu); - fixup_irqs(); cpu_clear(cpu, cpu_online_map); + fixup_irqs(); local_flush_tlb_all(); cpu_clear(cpu, cpu_callin_map); return 0; -- cgit v1.2.3 From c0acdea21437eff134cc3486bdc52907d9086af1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Mon, 9 Feb 2009 11:16:57 -0700 Subject: [IA64] Remove redundant cpu_clear() in __cpu_disable path The second call to cpu_clear() is redundant, as we've already removed the CPU from cpu_online_map before calling migrate_platform_irqs(). Signed-off-by: Alex Chiang Signed-off-by: Tony Luck --- arch/ia64/kernel/smpboot.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/ia64/kernel') diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 2ec5bbff461..52290547c85 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -740,11 +740,10 @@ int __cpu_disable(void) if (migrate_platform_irqs(cpu)) { cpu_set(cpu, cpu_online_map); - return (-EBUSY); + return -EBUSY; } remove_siblinginfo(cpu); - cpu_clear(cpu, cpu_online_map); fixup_irqs(); local_flush_tlb_all(); cpu_clear(cpu, cpu_callin_map); -- cgit v1.2.3 From aa2f63c95439a11dfac35c60d9160dcd0189aed3 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 22 Feb 2009 02:33:28 +0100 Subject: [IA64] Do not go beyond ARRAY_SIZE of unw.hash static struct { ... :114 unsigned short hash[UNW_HASH_SIZE]; ... :2152 for (index = 0; index <= UNW_HASH_SIZE; ++index) { This is a bug, isn't it? s/<=/ Signed-off-by: Tony Luck --- arch/ia64/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/ia64/kernel') diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index 67810b77d99..b6c0e63a0bf 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -2149,7 +2149,7 @@ unw_remove_unwind_table (void *handle) /* next, remove hash table entries for this table */ - for (index = 0; index <= UNW_HASH_SIZE; ++index) { + for (index = 0; index < UNW_HASH_SIZE; ++index) { tmp = unw.cache + unw.hash[index]; if (unw.hash[index] >= UNW_CACHE_SIZE || tmp->ip < table->start || tmp->ip >= table->end) -- cgit v1.2.3 From 5b5923975f07836fc7a5388f9fa5f459828ae4ee Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 21 Feb 2009 23:40:27 +0100 Subject: [IA64] Don't go beyond iosapic_intr_info's arraysize vi arch/ia64/kernel/iosapic.c +142 static struct iosapic_intr_info { ... } iosapic_intr_info[NR_IRQS]; But at line 510 we have: for (i = 0; i <= NR_IRQS; i++) { s/<=/ Signed-off-by: Tony Luck --- arch/ia64/kernel/iosapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/ia64/kernel') diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 5cfd3d91001..e13125058be 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c @@ -507,7 +507,7 @@ static int iosapic_find_sharable_irq(unsigned long trigger, unsigned long pol) if (trigger == IOSAPIC_EDGE) return -EINVAL; - for (i = 0; i <= NR_IRQS; i++) { + for (i = 0; i < NR_IRQS; i++) { info = &iosapic_intr_info[i]; if (info->trigger == trigger && info->polarity == pol && (info->dmode == IOSAPIC_FIXED || -- cgit v1.2.3