While testing CPU offline/online, we hit various preempt_count related bugs. Various hacks have been employed for several theoretical corner cases. One situation however is perfectly repeatable on 2.6.33.6 with CONFIG_PREEMPT=y.
BUG: scheduling while atomic: swapper/0/0x00000065 Modules linked in: autofs4 sunrpc ipv6 dm_mirror dm_region_hash dm_log dm_mod ehea sg ext4 jbd2 mbcache sd_mod crc_t10dif ibmvscsic scsi_transport_srp scsi_tgt [last unloaded: scsi_wait_scan] Call Trace: [c00000010e9e39f0] [c0000000000144d4] .show_stack+0x74/0x1c0 (unreliable) [c00000010e9e3aa0] [c00000000007a680] .__schedule_bug+0xa0/0xb0 [c00000010e9e3b30] [c00000000056dea4] .schedule+0x7a4/0xd60 [c00000010e9e3cd0] [c000000000016be8] .cpu_idle+0x1f8/0x220 [c00000010e9e3d80] [c00000000057d858] .start_secondary+0x388/0x3c0 [c00000010e9e3e30] [c000000000008278] .start_secondary_resume+0x10/0x14 With some instrumentation we were able to determine that the preempt_count() appears to change across the extended_cede_processor() call. Specifically across the plpar_hcall_norets(H_CEDE) call. On PREEMPT_RT we call this with preempt_count=1 and return with preempt_count=0xffffffff. On mainline with CONFIG_PREEMPT=y, the value is different (0x65) but is still incorrect. Also of interest is that this path cpu_idle()->cpu_die()->pseries_mach_cpu_die() to start_secondary() enters with a preempt_count=1 if it wasn't corrupted across the hcall. The early boot path from _start however appears to call start_secondary() with a preempt_count of 0. The following patch is most certainly not correct, but it does eliminate the situation on mainline 100% of the time (there is still a 25% reproduction rate on PREEMPT_RT). Can someone comment on: 1) How can the preempt_count() get mangled across the H_CEDE hcall? 2) Should we call preempt_enable() in cpu_idle() prior to cpu_die() ? Hacked-up-by: Darren Hart <dvh...@us.ibm.com> Index: linux-2.6.33.6/arch/powerpc/platforms/pseries/hotplug-cpu.c =================================================================== --- linux-2.6.33.6.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ linux-2.6.33.6/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -138,6 +138,7 @@ static void pseries_mach_cpu_die(void) * Kernel stack will be reset and start_secondary() * will be called to continue the online operation. */ + preempt_count() = 0; start_secondary_resume(); } } -- Darren Hart IBM Linux Technology Center Real-Time Linux Team _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev