LCOV - code coverage report
Current view: top level - arch/x86/kernel - smp.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 66 0.0 %
Date: 2022-03-28 16:04:14 Functions: 0 7 0.0 %
Branches: 0 30 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *      Intel SMP support routines.
       4                 :            :  *
       5                 :            :  *      (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
       6                 :            :  *      (c) 1998-99, 2000, 2009 Ingo Molnar <mingo@redhat.com>
       7                 :            :  *      (c) 2002,2003 Andi Kleen, SuSE Labs.
       8                 :            :  *
       9                 :            :  *      i386 and x86_64 integration by Glauber Costa <gcosta@redhat.com>
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/init.h>
      13                 :            : 
      14                 :            : #include <linux/mm.h>
      15                 :            : #include <linux/delay.h>
      16                 :            : #include <linux/spinlock.h>
      17                 :            : #include <linux/export.h>
      18                 :            : #include <linux/kernel_stat.h>
      19                 :            : #include <linux/mc146818rtc.h>
      20                 :            : #include <linux/cache.h>
      21                 :            : #include <linux/interrupt.h>
      22                 :            : #include <linux/cpu.h>
      23                 :            : #include <linux/gfp.h>
      24                 :            : 
      25                 :            : #include <asm/mtrr.h>
      26                 :            : #include <asm/tlbflush.h>
      27                 :            : #include <asm/mmu_context.h>
      28                 :            : #include <asm/proto.h>
      29                 :            : #include <asm/apic.h>
      30                 :            : #include <asm/nmi.h>
      31                 :            : #include <asm/mce.h>
      32                 :            : #include <asm/trace/irq_vectors.h>
      33                 :            : #include <asm/kexec.h>
      34                 :            : #include <asm/virtext.h>
      35                 :            : 
      36                 :            : /*
      37                 :            :  *      Some notes on x86 processor bugs affecting SMP operation:
      38                 :            :  *
      39                 :            :  *      Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
      40                 :            :  *      The Linux implications for SMP are handled as follows:
      41                 :            :  *
      42                 :            :  *      Pentium III / [Xeon]
      43                 :            :  *              None of the E1AP-E3AP errata are visible to the user.
      44                 :            :  *
      45                 :            :  *      E1AP.   see PII A1AP
      46                 :            :  *      E2AP.   see PII A2AP
      47                 :            :  *      E3AP.   see PII A3AP
      48                 :            :  *
      49                 :            :  *      Pentium II / [Xeon]
      50                 :            :  *              None of the A1AP-A3AP errata are visible to the user.
      51                 :            :  *
      52                 :            :  *      A1AP.   see PPro 1AP
      53                 :            :  *      A2AP.   see PPro 2AP
      54                 :            :  *      A3AP.   see PPro 7AP
      55                 :            :  *
      56                 :            :  *      Pentium Pro
      57                 :            :  *              None of 1AP-9AP errata are visible to the normal user,
      58                 :            :  *      except occasional delivery of 'spurious interrupt' as trap #15.
      59                 :            :  *      This is very rare and a non-problem.
      60                 :            :  *
      61                 :            :  *      1AP.    Linux maps APIC as non-cacheable
      62                 :            :  *      2AP.    worked around in hardware
      63                 :            :  *      3AP.    fixed in C0 and above steppings microcode update.
      64                 :            :  *              Linux does not use excessive STARTUP_IPIs.
      65                 :            :  *      4AP.    worked around in hardware
      66                 :            :  *      5AP.    symmetric IO mode (normal Linux operation) not affected.
      67                 :            :  *              'noapic' mode has vector 0xf filled out properly.
      68                 :            :  *      6AP.    'noapic' mode might be affected - fixed in later steppings
      69                 :            :  *      7AP.    We do not assume writes to the LVT deassering IRQs
      70                 :            :  *      8AP.    We do not enable low power mode (deep sleep) during MP bootup
      71                 :            :  *      9AP.    We do not use mixed mode
      72                 :            :  *
      73                 :            :  *      Pentium
      74                 :            :  *              There is a marginal case where REP MOVS on 100MHz SMP
      75                 :            :  *      machines with B stepping processors can fail. XXX should provide
      76                 :            :  *      an L1cache=Writethrough or L1cache=off option.
      77                 :            :  *
      78                 :            :  *              B stepping CPUs may hang. There are hardware work arounds
      79                 :            :  *      for this. We warn about it in case your board doesn't have the work
      80                 :            :  *      arounds. Basically that's so I can tell anyone with a B stepping
      81                 :            :  *      CPU and SMP problems "tough".
      82                 :            :  *
      83                 :            :  *      Specific items [From Pentium Processor Specification Update]
      84                 :            :  *
      85                 :            :  *      1AP.    Linux doesn't use remote read
      86                 :            :  *      2AP.    Linux doesn't trust APIC errors
      87                 :            :  *      3AP.    We work around this
      88                 :            :  *      4AP.    Linux never generated 3 interrupts of the same priority
      89                 :            :  *              to cause a lost local interrupt.
      90                 :            :  *      5AP.    Remote read is never used
      91                 :            :  *      6AP.    not affected - worked around in hardware
      92                 :            :  *      7AP.    not affected - worked around in hardware
      93                 :            :  *      8AP.    worked around in hardware - we get explicit CS errors if not
      94                 :            :  *      9AP.    only 'noapic' mode affected. Might generate spurious
      95                 :            :  *              interrupts, we log only the first one and count the
      96                 :            :  *              rest silently.
      97                 :            :  *      10AP.   not affected - worked around in hardware
      98                 :            :  *      11AP.   Linux reads the APIC between writes to avoid this, as per
      99                 :            :  *              the documentation. Make sure you preserve this as it affects
     100                 :            :  *              the C stepping chips too.
     101                 :            :  *      12AP.   not affected - worked around in hardware
     102                 :            :  *      13AP.   not affected - worked around in hardware
     103                 :            :  *      14AP.   we always deassert INIT during bootup
     104                 :            :  *      15AP.   not affected - worked around in hardware
     105                 :            :  *      16AP.   not affected - worked around in hardware
     106                 :            :  *      17AP.   not affected - worked around in hardware
     107                 :            :  *      18AP.   not affected - worked around in hardware
     108                 :            :  *      19AP.   not affected - worked around in BIOS
     109                 :            :  *
     110                 :            :  *      If this sounds worrying believe me these bugs are either ___RARE___,
     111                 :            :  *      or are signal timing bugs worked around in hardware and there's
     112                 :            :  *      about nothing of note with C stepping upwards.
     113                 :            :  */
     114                 :            : 
     115                 :            : static atomic_t stopping_cpu = ATOMIC_INIT(-1);
     116                 :            : static bool smp_no_nmi_ipi = false;
     117                 :            : 
     118                 :          0 : static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs)
     119                 :            : {
     120                 :            :         /* We are registered on stopping cpu too, avoid spurious NMI */
     121         [ #  # ]:          0 :         if (raw_smp_processor_id() == atomic_read(&stopping_cpu))
     122                 :            :                 return NMI_HANDLED;
     123                 :            : 
     124                 :          0 :         cpu_emergency_vmxoff();
     125                 :          0 :         stop_this_cpu(NULL);
     126                 :            : 
     127                 :          0 :         return NMI_HANDLED;
     128                 :            : }
     129                 :            : 
     130                 :            : /*
     131                 :            :  * this function calls the 'stop' function on all other CPUs in the system.
     132                 :            :  */
     133                 :            : 
     134                 :          0 : asmlinkage __visible void smp_reboot_interrupt(void)
     135                 :            : {
     136                 :          0 :         ipi_entering_ack_irq();
     137                 :          0 :         cpu_emergency_vmxoff();
     138                 :          0 :         stop_this_cpu(NULL);
     139                 :          0 :         irq_exit();
     140                 :          0 : }
     141                 :            : 
     142                 :          0 : static int register_stop_handler(void)
     143                 :            : {
     144                 :          0 :         return register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback,
     145                 :            :                                     NMI_FLAG_FIRST, "smp_stop");
     146                 :            : }
     147                 :            : 
     148                 :          0 : static void native_stop_other_cpus(int wait)
     149                 :            : {
     150                 :          0 :         unsigned long flags;
     151                 :          0 :         unsigned long timeout;
     152                 :            : 
     153         [ #  # ]:          0 :         if (reboot_force)
     154                 :            :                 return;
     155                 :            : 
     156                 :            :         /*
     157                 :            :          * Use an own vector here because smp_call_function
     158                 :            :          * does lots of things not suitable in a panic situation.
     159                 :            :          */
     160                 :            : 
     161                 :            :         /*
     162                 :            :          * We start by using the REBOOT_VECTOR irq.
     163                 :            :          * The irq is treated as a sync point to allow critical
     164                 :            :          * regions of code on other cpus to release their spin locks
     165                 :            :          * and re-enable irqs.  Jumping straight to an NMI might
     166                 :            :          * accidentally cause deadlocks with further shutdown/panic
     167                 :            :          * code.  By syncing, we give the cpus up to one second to
     168                 :            :          * finish their work before we force them off with the NMI.
     169                 :            :          */
     170         [ #  # ]:          0 :         if (num_online_cpus() > 1) {
     171                 :            :                 /* did someone beat us here? */
     172         [ #  # ]:          0 :                 if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1)
     173                 :            :                         return;
     174                 :            : 
     175                 :            :                 /* sync above data before sending IRQ */
     176                 :          0 :                 wmb();
     177                 :            : 
     178                 :          0 :                 apic_send_IPI_allbutself(REBOOT_VECTOR);
     179                 :            : 
     180                 :            :                 /*
     181                 :            :                  * Don't wait longer than a second for IPI completion. The
     182                 :            :                  * wait request is not checked here because that would
     183                 :            :                  * prevent an NMI shutdown attempt in case that not all
     184                 :            :                  * CPUs reach shutdown state.
     185                 :            :                  */
     186                 :          0 :                 timeout = USEC_PER_SEC;
     187   [ #  #  #  # ]:          0 :                 while (num_online_cpus() > 1 && timeout--)
     188                 :          0 :                         udelay(1);
     189                 :            :         }
     190                 :            : 
     191                 :            :         /* if the REBOOT_VECTOR didn't work, try with the NMI */
     192         [ #  # ]:          0 :         if (num_online_cpus() > 1) {
     193                 :            :                 /*
     194                 :            :                  * If NMI IPI is enabled, try to register the stop handler
     195                 :            :                  * and send the IPI. In any case try to wait for the other
     196                 :            :                  * CPUs to stop.
     197                 :            :                  */
     198   [ #  #  #  # ]:          0 :                 if (!smp_no_nmi_ipi && !register_stop_handler()) {
     199                 :            :                         /* Sync above data before sending IRQ */
     200                 :          0 :                         wmb();
     201                 :            : 
     202                 :          0 :                         pr_emerg("Shutting down cpus with NMI\n");
     203                 :            : 
     204                 :          0 :                         apic_send_IPI_allbutself(NMI_VECTOR);
     205                 :            :                 }
     206                 :            :                 /*
     207                 :            :                  * Don't wait longer than 10 ms if the caller didn't
     208                 :            :                  * reqeust it. If wait is true, the machine hangs here if
     209                 :            :                  * one or more CPUs do not reach shutdown state.
     210                 :            :                  */
     211                 :            :                 timeout = USEC_PER_MSEC * 10;
     212   [ #  #  #  #  :          0 :                 while (num_online_cpus() > 1 && (wait || timeout--))
                   #  # ]
     213                 :          0 :                         udelay(1);
     214                 :            :         }
     215                 :            : 
     216                 :          0 :         local_irq_save(flags);
     217                 :          0 :         disable_local_APIC();
     218                 :          0 :         mcheck_cpu_clear(this_cpu_ptr(&cpu_info));
     219                 :          0 :         local_irq_restore(flags);
     220                 :            : }
     221                 :            : 
     222                 :            : /*
     223                 :            :  * Reschedule call back. KVM uses this interrupt to force a cpu out of
     224                 :            :  * guest mode
     225                 :            :  */
     226                 :          0 : __visible void __irq_entry smp_reschedule_interrupt(struct pt_regs *regs)
     227                 :            : {
     228                 :          0 :         ack_APIC_irq();
     229                 :          0 :         inc_irq_stat(irq_resched_count);
     230         [ #  # ]:          0 :         kvm_set_cpu_l1tf_flush_l1d();
     231                 :            : 
     232   [ #  #  #  # ]:          0 :         if (trace_resched_ipi_enabled()) {
     233                 :            :                 /*
     234                 :            :                  * scheduler_ipi() might call irq_enter() as well, but
     235                 :            :                  * nested calls are fine.
     236                 :            :                  */
     237                 :          0 :                 irq_enter();
     238                 :          0 :                 trace_reschedule_entry(RESCHEDULE_VECTOR);
     239                 :          0 :                 scheduler_ipi();
     240                 :          0 :                 trace_reschedule_exit(RESCHEDULE_VECTOR);
     241                 :          0 :                 irq_exit();
     242                 :          0 :                 return;
     243                 :            :         }
     244                 :          0 :         scheduler_ipi();
     245                 :            : }
     246                 :            : 
     247                 :          0 : __visible void __irq_entry smp_call_function_interrupt(struct pt_regs *regs)
     248                 :            : {
     249                 :          0 :         ipi_entering_ack_irq();
     250                 :          0 :         trace_call_function_entry(CALL_FUNCTION_VECTOR);
     251                 :          0 :         inc_irq_stat(irq_call_count);
     252                 :          0 :         generic_smp_call_function_interrupt();
     253                 :          0 :         trace_call_function_exit(CALL_FUNCTION_VECTOR);
     254                 :          0 :         exiting_irq();
     255                 :          0 : }
     256                 :            : 
     257                 :          0 : __visible void __irq_entry smp_call_function_single_interrupt(struct pt_regs *r)
     258                 :            : {
     259                 :          0 :         ipi_entering_ack_irq();
     260                 :          0 :         trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR);
     261                 :          0 :         inc_irq_stat(irq_call_count);
     262                 :          0 :         generic_smp_call_function_single_interrupt();
     263                 :          0 :         trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR);
     264                 :          0 :         exiting_irq();
     265                 :          0 : }
     266                 :            : 
     267                 :          0 : static int __init nonmi_ipi_setup(char *str)
     268                 :            : {
     269                 :          0 :         smp_no_nmi_ipi = true;
     270                 :          0 :         return 1;
     271                 :            : }
     272                 :            : 
     273                 :            : __setup("nonmi_ipi", nonmi_ipi_setup);
     274                 :            : 
     275                 :            : struct smp_ops smp_ops = {
     276                 :            :         .smp_prepare_boot_cpu   = native_smp_prepare_boot_cpu,
     277                 :            :         .smp_prepare_cpus       = native_smp_prepare_cpus,
     278                 :            :         .smp_cpus_done          = native_smp_cpus_done,
     279                 :            : 
     280                 :            :         .stop_other_cpus        = native_stop_other_cpus,
     281                 :            : #if defined(CONFIG_KEXEC_CORE)
     282                 :            :         .crash_stop_other_cpus  = kdump_nmi_shootdown_cpus,
     283                 :            : #endif
     284                 :            :         .smp_send_reschedule    = native_smp_send_reschedule,
     285                 :            : 
     286                 :            :         .cpu_up                 = native_cpu_up,
     287                 :            :         .cpu_die                = native_cpu_die,
     288                 :            :         .cpu_disable            = native_cpu_disable,
     289                 :            :         .play_dead              = native_play_dead,
     290                 :            : 
     291                 :            :         .send_call_func_ipi     = native_send_call_func_ipi,
     292                 :            :         .send_call_func_single_ipi = native_send_call_func_single_ipi,
     293                 :            : };
     294                 :            : EXPORT_SYMBOL_GPL(smp_ops);

Generated by: LCOV version 1.14