cregit-Linux how code gets into the kernel

Release 4.11 arch/x86/kernel/smp.c

Directory: arch/x86/kernel
/*
 *      Intel SMP support routines.
 *
 *      (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
 *      (c) 1998-99, 2000, 2009 Ingo Molnar <mingo@redhat.com>
 *      (c) 2002,2003 Andi Kleen, SuSE Labs.
 *
 *      i386 and x86_64 integration by Glauber Costa <gcosta@redhat.com>
 *
 *      This code is released under the GNU General Public License version 2 or
 *      later.
 */

#include <linux/init.h>

#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/export.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
#include <linux/cpu.h>
#include <linux/gfp.h>

#include <asm/mtrr.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/proto.h>
#include <asm/apic.h>
#include <asm/nmi.h>
#include <asm/mce.h>
#include <asm/trace/irq_vectors.h>
#include <asm/kexec.h>

/*
 *      Some notes on x86 processor bugs affecting SMP operation:
 *
 *      Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
 *      The Linux implications for SMP are handled as follows:
 *
 *      Pentium III / [Xeon]
 *              None of the E1AP-E3AP errata are visible to the user.
 *
 *      E1AP.   see PII A1AP
 *      E2AP.   see PII A2AP
 *      E3AP.   see PII A3AP
 *
 *      Pentium II / [Xeon]
 *              None of the A1AP-A3AP errata are visible to the user.
 *
 *      A1AP.   see PPro 1AP
 *      A2AP.   see PPro 2AP
 *      A3AP.   see PPro 7AP
 *
 *      Pentium Pro
 *              None of 1AP-9AP errata are visible to the normal user,
 *      except occasional delivery of 'spurious interrupt' as trap #15.
 *      This is very rare and a non-problem.
 *
 *      1AP.    Linux maps APIC as non-cacheable
 *      2AP.    worked around in hardware
 *      3AP.    fixed in C0 and above steppings microcode update.
 *              Linux does not use excessive STARTUP_IPIs.
 *      4AP.    worked around in hardware
 *      5AP.    symmetric IO mode (normal Linux operation) not affected.
 *              'noapic' mode has vector 0xf filled out properly.
 *      6AP.    'noapic' mode might be affected - fixed in later steppings
 *      7AP.    We do not assume writes to the LVT deassering IRQs
 *      8AP.    We do not enable low power mode (deep sleep) during MP bootup
 *      9AP.    We do not use mixed mode
 *
 *      Pentium
 *              There is a marginal case where REP MOVS on 100MHz SMP
 *      machines with B stepping processors can fail. XXX should provide
 *      an L1cache=Writethrough or L1cache=off option.
 *
 *              B stepping CPUs may hang. There are hardware work arounds
 *      for this. We warn about it in case your board doesn't have the work
 *      arounds. Basically that's so I can tell anyone with a B stepping
 *      CPU and SMP problems "tough".
 *
 *      Specific items [From Pentium Processor Specification Update]
 *
 *      1AP.    Linux doesn't use remote read
 *      2AP.    Linux doesn't trust APIC errors
 *      3AP.    We work around this
 *      4AP.    Linux never generated 3 interrupts of the same priority
 *              to cause a lost local interrupt.
 *      5AP.    Remote read is never used
 *      6AP.    not affected - worked around in hardware
 *      7AP.    not affected - worked around in hardware
 *      8AP.    worked around in hardware - we get explicit CS errors if not
 *      9AP.    only 'noapic' mode affected. Might generate spurious
 *              interrupts, we log only the first one and count the
 *              rest silently.
 *      10AP.   not affected - worked around in hardware
 *      11AP.   Linux reads the APIC between writes to avoid this, as per
 *              the documentation. Make sure you preserve this as it affects
 *              the C stepping chips too.
 *      12AP.   not affected - worked around in hardware
 *      13AP.   not affected - worked around in hardware
 *      14AP.   we always deassert INIT during bootup
 *      15AP.   not affected - worked around in hardware
 *      16AP.   not affected - worked around in hardware
 *      17AP.   not affected - worked around in hardware
 *      18AP.   not affected - worked around in hardware
 *      19AP.   not affected - worked around in BIOS
 *
 *      If this sounds worrying believe me these bugs are either ___RARE___,
 *      or are signal timing bugs worked around in hardware and there's
 *      about nothing of note with C stepping upwards.
 */


static atomic_t stopping_cpu = ATOMIC_INIT(-1);

static bool smp_no_nmi_ipi = false;

/*
 * this function sends a 'reschedule' IPI to another CPU.
 * it goes straight through and wastes no time serializing
 * anything. Worst case is that we lose a reschedule ...
 */

static void native_smp_send_reschedule(int cpu) { if (unlikely(cpu_is_offline(cpu))) { WARN_ON(1); return; } apic->send_IPI(cpu, RESCHEDULE_VECTOR); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa2261.11%133.33%
Gautham R. Shenoy1130.56%133.33%
Thomas Gleixner38.33%133.33%
Total36100.00%3100.00%


void native_send_call_func_single_ipi(int cpu) { apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa952.94%133.33%
Jens Axboe529.41%133.33%
Thomas Gleixner317.65%133.33%
Total17100.00%3100.00%


void native_send_call_func_ipi(const struct cpumask *mask) { cpumask_var_t allbutself; if (!alloc_cpumask_var(&allbutself, GFP_ATOMIC)) { apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); return; } cpumask_copy(allbutself, cpu_online_mask); cpumask_clear_cpu(smp_processor_id(), allbutself); if (cpumask_equal(mask, allbutself) && cpumask_equal(cpu_online_mask, cpu_callout_mask)) apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR); else apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR); free_cpumask_var(allbutself); }

Contributors

PersonTokensPropCommitsCommitProp
Mike Travis4145.56%342.86%
Glauber de Oliveira Costa3741.11%114.29%
Ingo Molnar66.67%114.29%
Hugh Dickins44.44%114.29%
Jens Axboe22.22%114.29%
Total90100.00%7100.00%


static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) { /* We are registered on stopping cpu too, avoid spurious NMI */ if (raw_smp_processor_id() == atomic_read(&stopping_cpu)) return NMI_HANDLED; stop_this_cpu(NULL); return NMI_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Don Zickus38100.00%1100.00%
Total38100.00%1100.00%

/* * this function calls the 'stop' function on all other CPUs in the system. */
asmlinkage __visible void smp_reboot_interrupt(void) { ipi_entering_ack_irq(); stop_this_cpu(NULL); irq_exit(); }

Contributors

PersonTokensPropCommitsCommitProp
Andi Kleen1995.00%266.67%
Thomas Gleixner15.00%133.33%
Total20100.00%3100.00%


static void native_stop_other_cpus(int wait) { unsigned long flags; unsigned long timeout; if (reboot_force) return; /* * Use an own vector here because smp_call_function * does lots of things not suitable in a panic situation. */ /* * We start by using the REBOOT_VECTOR irq. * The irq is treated as a sync point to allow critical * regions of code on other cpus to release their spin locks * and re-enable irqs. Jumping straight to an NMI might * accidentally cause deadlocks with further shutdown/panic * code. By syncing, we give the cpus up to one second to * finish their work before we force them off with the NMI. */ if (num_online_cpus() > 1) { /* did someone beat us here? */ if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1) return; /* sync above data before sending IRQ */ wmb(); apic->send_IPI_allbutself(REBOOT_VECTOR); /* * Don't wait longer than a second if the caller * didn't ask us to wait. */ timeout = USEC_PER_SEC; while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } /* if the REBOOT_VECTOR didn't work, try with the NMI */ if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) { if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback, NMI_FLAG_FIRST, "smp_stop")) /* Note: we ignore failures here */ /* Hope the REBOOT_IRQ is good enough */ goto finish; /* sync above data before sending IRQ */ wmb(); pr_emerg("Shutting down cpus with NMI\n"); apic->send_IPI_allbutself(NMI_VECTOR); /* * Don't wait longer than a 10 ms if the caller * didn't ask us to wait. */ timeout = USEC_PER_MSEC * 10; while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } finish: local_irq_save(flags); disable_local_APIC(); mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); local_irq_restore(flags); }

Contributors

PersonTokensPropCommitsCommitProp
Don Zickus10555.85%337.50%
Andi Kleen3418.09%112.50%
Glauber de Oliveira Costa2915.43%112.50%
Ashok Raj94.79%112.50%
Alok N Kataria94.79%112.50%
Jens Axboe21.06%112.50%
Total188100.00%8100.00%

/* * Reschedule call back. */
static inline void __smp_reschedule_interrupt(void) { inc_irq_stat(irq_resched_count); scheduler_ipi(); }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa952.94%125.00%
Seiji Aguchi423.53%125.00%
Peter Zijlstra317.65%125.00%
Hiroshi Shimamoto15.88%125.00%
Total17100.00%4100.00%


__visible void __irq_entry smp_reschedule_interrupt(struct pt_regs *regs) { ack_APIC_irq(); __smp_reschedule_interrupt(); /* * KVM uses this interrupt to force a cpu out of guest mode */ }

Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa1157.89%125.00%
Seiji Aguchi631.58%125.00%
Daniel Bristot de Oliveira15.26%125.00%
Andi Kleen15.26%125.00%
Total19100.00%4100.00%


__visible void __irq_entry smp_trace_reschedule_interrupt(struct pt_regs *regs) { /* * Need to call irq_enter() before calling the trace point. * __smp_reschedule_interrupt() calls irq_enter/exit() too (in * scheduler_ipi(). This is OK, since those functions are allowed * to nest. */ ipi_entering_ack_irq(); trace_reschedule_entry(RESCHEDULE_VECTOR); __smp_reschedule_interrupt(); trace_reschedule_exit(RESCHEDULE_VECTOR); exiting_irq(); /* * KVM uses this interrupt to force a cpu out of guest mode */ }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi2884.85%342.86%
Glauber de Oliveira Costa26.06%114.29%
Andi Kleen13.03%114.29%
Thomas Gleixner13.03%114.29%
Daniel Bristot de Oliveira13.03%114.29%
Total33100.00%7100.00%


static inline void __smp_call_function_interrupt(void) { generic_smp_call_function_interrupt(); inc_irq_stat(irq_call_count); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi847.06%125.00%
Glauber de Oliveira Costa529.41%125.00%
Jens Axboe317.65%125.00%
Hiroshi Shimamoto15.88%125.00%
Total17100.00%4100.00%


__visible void __irq_entry smp_call_function_interrupt(struct pt_regs *regs) { ipi_entering_ack_irq(); __smp_call_function_interrupt(); exiting_irq(); }

Contributors

PersonTokensPropCommitsCommitProp
Jens Axboe942.86%228.57%
Seiji Aguchi628.57%114.29%
Glauber de Oliveira Costa314.29%114.29%
Daniel Bristot de Oliveira14.76%114.29%
Thomas Gleixner14.76%114.29%
Andi Kleen14.76%114.29%
Total21100.00%7100.00%


__visible void __irq_entry smp_trace_call_function_interrupt(struct pt_regs *regs) { ipi_entering_ack_irq(); trace_call_function_entry(CALL_FUNCTION_VECTOR); __smp_call_function_interrupt(); trace_call_function_exit(CALL_FUNCTION_VECTOR); exiting_irq(); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi2890.32%125.00%
Andi Kleen13.23%125.00%
Thomas Gleixner13.23%125.00%
Daniel Bristot de Oliveira13.23%125.00%
Total31100.00%4100.00%


static inline void __smp_call_function_single_interrupt(void) { generic_smp_call_function_single_interrupt(); inc_irq_stat(irq_call_count); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi952.94%125.00%
Jens Axboe635.29%125.00%
Hiroshi Shimamoto15.88%125.00%
Glauber de Oliveira Costa15.88%125.00%
Total17100.00%4100.00%


__visible void __irq_entry smp_call_function_single_interrupt(struct pt_regs *regs) { ipi_entering_ack_irq(); __smp_call_function_single_interrupt(); exiting_irq(); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi1571.43%116.67%
Glauber de Oliveira Costa29.52%116.67%
Andi Kleen14.76%116.67%
Thomas Gleixner14.76%116.67%
Jens Axboe14.76%116.67%
Daniel Bristot de Oliveira14.76%116.67%
Total21100.00%6100.00%


__visible void __irq_entry smp_trace_call_function_single_interrupt(struct pt_regs *regs) { ipi_entering_ack_irq(); trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR); __smp_call_function_single_interrupt(); trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR); exiting_irq(); }

Contributors

PersonTokensPropCommitsCommitProp
Seiji Aguchi2890.32%125.00%
Thomas Gleixner13.23%125.00%
Andi Kleen13.23%125.00%
Daniel Bristot de Oliveira13.23%125.00%
Total31100.00%4100.00%


static int __init nonmi_ipi_setup(char *str) { smp_no_nmi_ipi = true; return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Don Zickus18100.00%2100.00%
Total18100.00%2100.00%

__setup("nonmi_ipi", nonmi_ipi_setup); struct smp_ops smp_ops = { .smp_prepare_boot_cpu = native_smp_prepare_boot_cpu, .smp_prepare_cpus = native_smp_prepare_cpus, .smp_cpus_done = native_smp_cpus_done, .stop_other_cpus = native_stop_other_cpus, #if defined(CONFIG_KEXEC_CORE) .crash_stop_other_cpus = kdump_nmi_shootdown_cpus, #endif .smp_send_reschedule = native_smp_send_reschedule, .cpu_up = native_cpu_up, .cpu_die = native_cpu_die, .cpu_disable = native_cpu_disable, .play_dead = native_play_dead, .send_call_func_ipi = native_send_call_func_ipi, .send_call_func_single_ipi = native_send_call_func_single_ipi, }; EXPORT_SYMBOL_GPL(smp_ops);

Overall Contributors

PersonTokensPropCommitsCommitProp
Glauber de Oliveira Costa21127.02%26.06%
Don Zickus18824.07%412.12%
Seiji Aguchi13517.29%39.09%
Andi Kleen597.55%39.09%
Mike Travis415.25%39.09%
Jens Axboe354.48%26.06%
Alex Nixon202.56%13.03%
Hidehiro Kawai162.05%13.03%
Thomas Gleixner121.54%26.06%
Ashok Raj121.54%13.03%
Gautham R. Shenoy111.41%13.03%
Alok N Kataria101.28%13.03%
Ingo Molnar81.02%39.09%
Daniel Bristot de Oliveira60.77%13.03%
Peter Zijlstra40.51%13.03%
Hugh Dickins40.51%13.03%
Tejun Heo30.38%13.03%
Hiroshi Shimamoto30.38%13.03%
Paul Gortmaker30.38%13.03%
Total781100.00%33100.00%
Directory: arch/x86/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.