• Thomas Gleixner's avatar
    tick: Clear broadcast pending bit when switching to oneshot · dbd51587
    Thomas Gleixner authored
    commit dd5fd9b9 upstream.
    
    AMD systems which use the C1E workaround in the amd_e400_idle routine
    trigger the WARN_ON_ONCE in the broadcast code when onlining a CPU.
    
    The reason is that the idle routine of those AMD systems switches the
    cpu into forced broadcast mode early on before the newly brought up
    CPU can switch over to high resolution / NOHZ mode. The timer related
    CPU1 bringup looks like this:
    
      clockevent_register_device(local_apic);
      tick_setup(local_apic);
      ...
      idle()
    	tick_broadcast_on_off(FORCE);
    	tick_broadcast_oneshot_control(ENTER)
    	  cpumask_set(cpu, broadcast_oneshot_mask);
    	halt();
    
    Now the broadcast interrupt on CPU0 sets CPU1 in the
    broadcast_pending_mask and wakes CPU1. So CPU1 continues:
    
    	local_apic_timer_interrupt()
    	   tick_handle_periodic();
    	   softirq()
    	     tick_init_highres();
    	       cpumask_clr(cpu, broadcast_oneshot_mask);
    
    	tick_broadcast_oneshot_control(ENTER)
    	   WARN_ON(cpumask_test(cpu, broadcast_pending_mask);
    
    So while we remove CPU1 from the broadcast_oneshot_mask when we switch
    over to highres mode, we do not clear the pending bit, which then
    triggers the warning when we go back to idle.
    
    The reason why this is only visible on C1E affected AMD systems is
    that the other machines enter the deep sleep states via
    acpi_idle/intel_idle and exit the broadcast mode before executing the
    remote triggered local_apic_timer_interrupt. So the pending bit is
    already cleared when the switch over to highres mode is clearing the
    oneshot mask.
    
    The solution is simple: Clear the pending bit together with the mask
    bit when we switch over to highres mode.
    
    Stanislaw came up independently with the same patch by enforcing the
    C1E workaround and debugging the fallout. I picked mine, because mine
    has a changelog :)
    Reported-by: default avatarpoma <pomidorabelisima@gmail.com>
    Debugged-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: Olaf Hering <olaf@aepfle.de>
    Cc: Dave Jones <davej@redhat.com>
    Cc: Justin M. Forbes <jforbes@redhat.com>
    Cc: Josh Boyer <jwboyer@redhat.com>
    Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1402111434180.21991@ionos.tec.linutronix.deSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    dbd51587
tick-broadcast.c 22.6 KB