LCOV - code coverage report
Current view: top level - arch/x86/kernel/apic - ipi.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 7 93 7.5 %
Date: 2022-04-01 14:17:54 Functions: 2 16 12.5 %
Branches: 3 64 4.7 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : 
       3                 :            : #include <linux/cpumask.h>
       4                 :            : #include <linux/smp.h>
       5                 :            : 
       6                 :            : #include "local.h"
       7                 :            : 
       8                 :            : DEFINE_STATIC_KEY_FALSE(apic_use_ipi_shorthand);
       9                 :            : 
      10                 :            : #ifdef CONFIG_SMP
      11                 :            : static int apic_ipi_shorthand_off __ro_after_init;
      12                 :            : 
      13                 :          0 : static __init int apic_ipi_shorthand(char *str)
      14                 :            : {
      15                 :          0 :         get_option(&str, &apic_ipi_shorthand_off);
      16                 :          0 :         return 1;
      17                 :            : }
      18                 :            : __setup("no_ipi_broadcast=", apic_ipi_shorthand);
      19                 :            : 
      20                 :         11 : static int __init print_ipi_mode(void)
      21                 :            : {
      22         [ +  - ]:         22 :         pr_info("IPI shorthand broadcast: %s\n",
      23                 :            :                 apic_ipi_shorthand_off ? "disabled" : "enabled");
      24                 :         11 :         return 0;
      25                 :            : }
      26                 :            : late_initcall(print_ipi_mode);
      27                 :            : 
      28                 :         11 : void apic_smt_update(void)
      29                 :            : {
      30                 :            :         /*
      31                 :            :          * Do not switch to broadcast mode if:
      32                 :            :          * - Disabled on the command line
      33                 :            :          * - Only a single CPU is online
      34                 :            :          * - Not all present CPUs have been at least booted once
      35                 :            :          *
      36                 :            :          * The latter is important as the local APIC might be in some
      37                 :            :          * random state and a broadcast might cause havoc. That's
      38                 :            :          * especially true for NMI broadcasting.
      39                 :            :          */
      40   [ +  -  -  +  :         22 :         if (apic_ipi_shorthand_off || num_online_cpus() == 1 ||
                   -  - ]
      41                 :            :             !cpumask_equal(cpu_present_mask, &cpus_booted_once_mask)) {
      42                 :         11 :                 static_branch_disable(&apic_use_ipi_shorthand);
      43                 :            :         } else {
      44                 :          0 :                 static_branch_enable(&apic_use_ipi_shorthand);
      45                 :            :         }
      46                 :         11 : }
      47                 :            : 
      48                 :          0 : void apic_send_IPI_allbutself(unsigned int vector)
      49                 :            : {
      50         [ #  # ]:          0 :         if (num_online_cpus() < 2)
      51                 :            :                 return;
      52                 :            : 
      53   [ #  #  #  # ]:          0 :         if (static_branch_likely(&apic_use_ipi_shorthand))
      54                 :          0 :                 apic->send_IPI_allbutself(vector);
      55                 :            :         else
      56                 :          0 :                 apic->send_IPI_mask_allbutself(cpu_online_mask, vector);
      57                 :            : }
      58                 :            : 
      59                 :            : /*
      60                 :            :  * Send a 'reschedule' IPI to another CPU. It goes straight through and
      61                 :            :  * wastes no time serializing anything. Worst case is that we lose a
      62                 :            :  * reschedule ...
      63                 :            :  */
      64                 :          0 : void native_smp_send_reschedule(int cpu)
      65                 :            : {
      66         [ #  # ]:          0 :         if (unlikely(cpu_is_offline(cpu))) {
      67                 :          0 :                 WARN(1, "sched: Unexpected reschedule of offline CPU#%d!\n", cpu);
      68                 :          0 :                 return;
      69                 :            :         }
      70                 :          0 :         apic->send_IPI(cpu, RESCHEDULE_VECTOR);
      71                 :            : }
      72                 :            : 
      73                 :          0 : void native_send_call_func_single_ipi(int cpu)
      74                 :            : {
      75                 :          0 :         apic->send_IPI(cpu, CALL_FUNCTION_SINGLE_VECTOR);
      76                 :          0 : }
      77                 :            : 
      78                 :          0 : void native_send_call_func_ipi(const struct cpumask *mask)
      79                 :            : {
      80   [ #  #  #  # ]:          0 :         if (static_branch_likely(&apic_use_ipi_shorthand)) {
      81         [ #  # ]:          0 :                 unsigned int cpu = smp_processor_id();
      82                 :            : 
      83         [ #  # ]:          0 :                 if (!cpumask_or_equal(mask, cpumask_of(cpu), cpu_online_mask))
      84                 :          0 :                         goto sendmask;
      85                 :            : 
      86         [ #  # ]:          0 :                 if (cpumask_test_cpu(cpu, mask))
      87                 :          0 :                         apic->send_IPI_all(CALL_FUNCTION_VECTOR);
      88         [ #  # ]:          0 :                 else if (num_online_cpus() > 1)
      89                 :          0 :                         apic->send_IPI_allbutself(CALL_FUNCTION_VECTOR);
      90                 :          0 :                 return;
      91                 :            :         }
      92                 :            : 
      93                 :          0 : sendmask:
      94                 :          0 :         apic->send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
      95                 :            : }
      96                 :            : 
      97                 :            : #endif /* CONFIG_SMP */
      98                 :            : 
      99                 :          0 : static inline int __prepare_ICR2(unsigned int mask)
     100                 :            : {
     101                 :          0 :         return SET_APIC_DEST_FIELD(mask);
     102                 :            : }
     103                 :            : 
     104                 :            : static inline void __xapic_wait_icr_idle(void)
     105                 :            : {
     106   [ #  #  #  #  :          0 :         while (native_apic_mem_read(APIC_ICR) & APIC_ICR_BUSY)
          #  #  #  #  #  
                      # ]
     107                 :          0 :                 cpu_relax();
     108                 :            : }
     109                 :            : 
     110                 :          0 : void __default_send_IPI_shortcut(unsigned int shortcut, int vector)
     111                 :            : {
     112                 :            :         /*
     113                 :            :          * Subtle. In the case of the 'never do double writes' workaround
     114                 :            :          * we have to lock out interrupts to be safe.  As we don't care
     115                 :            :          * of the value read we use an atomic rmw access to avoid costly
     116                 :            :          * cli/sti.  Otherwise we use an even cheaper single atomic write
     117                 :            :          * to the APIC.
     118                 :            :          */
     119                 :          0 :         unsigned int cfg;
     120                 :            : 
     121                 :            :         /*
     122                 :            :          * Wait for idle.
     123                 :            :          */
     124         [ #  # ]:          0 :         if (unlikely(vector == NMI_VECTOR))
     125                 :          0 :                 safe_apic_wait_icr_idle();
     126                 :            :         else
     127                 :            :                 __xapic_wait_icr_idle();
     128                 :            : 
     129                 :            :         /*
     130                 :            :          * No need to touch the target chip field. Also the destination
     131                 :            :          * mode is ignored when a shorthand is used.
     132                 :            :          */
     133   [ #  #  #  #  :          0 :         cfg = __prepare_ICR(shortcut, vector, 0);
             #  #  #  # ]
     134                 :            : 
     135                 :            :         /*
     136                 :            :          * Send the IPI. The write to APIC_ICR fires this off.
     137                 :            :          */
     138                 :          0 :         native_apic_mem_write(APIC_ICR, cfg);
     139                 :          0 : }
     140                 :            : 
     141                 :            : /*
     142                 :            :  * This is used to send an IPI with no shorthand notation (the destination is
     143                 :            :  * specified in bits 56 to 63 of the ICR).
     144                 :            :  */
     145                 :          0 : void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
     146                 :            : {
     147                 :          0 :         unsigned long cfg;
     148                 :            : 
     149                 :            :         /*
     150                 :            :          * Wait for idle.
     151                 :            :          */
     152         [ #  # ]:          0 :         if (unlikely(vector == NMI_VECTOR))
     153                 :          0 :                 safe_apic_wait_icr_idle();
     154                 :            :         else
     155                 :            :                 __xapic_wait_icr_idle();
     156                 :            : 
     157                 :            :         /*
     158                 :            :          * prepare target chip field
     159                 :            :          */
     160                 :          0 :         cfg = __prepare_ICR2(mask);
     161                 :          0 :         native_apic_mem_write(APIC_ICR2, cfg);
     162                 :            : 
     163                 :            :         /*
     164                 :            :          * program the ICR
     165                 :            :          */
     166         [ #  # ]:          0 :         cfg = __prepare_ICR(0, vector, dest);
     167                 :            : 
     168                 :            :         /*
     169                 :            :          * Send the IPI. The write to APIC_ICR fires this off.
     170                 :            :          */
     171                 :          0 :         native_apic_mem_write(APIC_ICR, cfg);
     172                 :          0 : }
     173                 :            : 
     174                 :          0 : void default_send_IPI_single_phys(int cpu, int vector)
     175                 :            : {
     176                 :          0 :         unsigned long flags;
     177                 :            : 
     178                 :          0 :         local_irq_save(flags);
     179                 :          0 :         __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, cpu),
     180                 :            :                                       vector, APIC_DEST_PHYSICAL);
     181                 :          0 :         local_irq_restore(flags);
     182                 :          0 : }
     183                 :            : 
     184                 :          0 : void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector)
     185                 :            : {
     186                 :          0 :         unsigned long query_cpu;
     187                 :          0 :         unsigned long flags;
     188                 :            : 
     189                 :            :         /*
     190                 :            :          * Hack. The clustered APIC addressing mode doesn't allow us to send
     191                 :            :          * to an arbitrary mask, so I do a unicast to each CPU instead.
     192                 :            :          * - mbligh
     193                 :            :          */
     194                 :          0 :         local_irq_save(flags);
     195         [ #  # ]:          0 :         for_each_cpu(query_cpu, mask) {
     196                 :          0 :                 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid,
     197                 :            :                                 query_cpu), vector, APIC_DEST_PHYSICAL);
     198                 :            :         }
     199                 :          0 :         local_irq_restore(flags);
     200                 :          0 : }
     201                 :            : 
     202                 :          0 : void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
     203                 :            :                                                  int vector)
     204                 :            : {
     205                 :          0 :         unsigned int this_cpu = smp_processor_id();
     206                 :          0 :         unsigned int query_cpu;
     207                 :          0 :         unsigned long flags;
     208                 :            : 
     209                 :            :         /* See Hack comment above */
     210                 :            : 
     211                 :          0 :         local_irq_save(flags);
     212         [ #  # ]:          0 :         for_each_cpu(query_cpu, mask) {
     213         [ #  # ]:          0 :                 if (query_cpu == this_cpu)
     214                 :          0 :                         continue;
     215                 :          0 :                 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid,
     216                 :            :                                  query_cpu), vector, APIC_DEST_PHYSICAL);
     217                 :            :         }
     218                 :          0 :         local_irq_restore(flags);
     219                 :          0 : }
     220                 :            : 
     221                 :            : /*
     222                 :            :  * Helper function for APICs which insist on cpumasks
     223                 :            :  */
     224                 :          0 : void default_send_IPI_single(int cpu, int vector)
     225                 :            : {
     226                 :          0 :         apic->send_IPI_mask(cpumask_of(cpu), vector);
     227                 :          0 : }
     228                 :            : 
     229                 :          0 : void default_send_IPI_allbutself(int vector)
     230                 :            : {
     231         [ #  # ]:          0 :         __default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
     232                 :          0 : }
     233                 :            : 
     234                 :          0 : void default_send_IPI_all(int vector)
     235                 :            : {
     236         [ #  # ]:          0 :         __default_send_IPI_shortcut(APIC_DEST_ALLINC, vector);
     237                 :          0 : }
     238                 :            : 
     239                 :          0 : void default_send_IPI_self(int vector)
     240                 :            : {
     241         [ #  # ]:          0 :         __default_send_IPI_shortcut(APIC_DEST_SELF, vector);
     242                 :          0 : }
     243                 :            : 
     244                 :            : #ifdef CONFIG_X86_32
     245                 :            : 
     246                 :            : void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
     247                 :            :                                                  int vector)
     248                 :            : {
     249                 :            :         unsigned long flags;
     250                 :            :         unsigned int query_cpu;
     251                 :            : 
     252                 :            :         /*
     253                 :            :          * Hack. The clustered APIC addressing mode doesn't allow us to send
     254                 :            :          * to an arbitrary mask, so I do a unicasts to each CPU instead. This
     255                 :            :          * should be modified to do 1 message per cluster ID - mbligh
     256                 :            :          */
     257                 :            : 
     258                 :            :         local_irq_save(flags);
     259                 :            :         for_each_cpu(query_cpu, mask)
     260                 :            :                 __default_send_IPI_dest_field(
     261                 :            :                         early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
     262                 :            :                         vector, apic->dest_logical);
     263                 :            :         local_irq_restore(flags);
     264                 :            : }
     265                 :            : 
     266                 :            : void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
     267                 :            :                                                  int vector)
     268                 :            : {
     269                 :            :         unsigned long flags;
     270                 :            :         unsigned int query_cpu;
     271                 :            :         unsigned int this_cpu = smp_processor_id();
     272                 :            : 
     273                 :            :         /* See Hack comment above */
     274                 :            : 
     275                 :            :         local_irq_save(flags);
     276                 :            :         for_each_cpu(query_cpu, mask) {
     277                 :            :                 if (query_cpu == this_cpu)
     278                 :            :                         continue;
     279                 :            :                 __default_send_IPI_dest_field(
     280                 :            :                         early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
     281                 :            :                         vector, apic->dest_logical);
     282                 :            :                 }
     283                 :            :         local_irq_restore(flags);
     284                 :            : }
     285                 :            : 
     286                 :            : /*
     287                 :            :  * This is only used on smaller machines.
     288                 :            :  */
     289                 :            : void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
     290                 :            : {
     291                 :            :         unsigned long mask = cpumask_bits(cpumask)[0];
     292                 :            :         unsigned long flags;
     293                 :            : 
     294                 :            :         if (!mask)
     295                 :            :                 return;
     296                 :            : 
     297                 :            :         local_irq_save(flags);
     298                 :            :         WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
     299                 :            :         __default_send_IPI_dest_field(mask, vector, apic->dest_logical);
     300                 :            :         local_irq_restore(flags);
     301                 :            : }
     302                 :            : 
     303                 :            : /* must come after the send_IPI functions above for inlining */
     304                 :            : static int convert_apicid_to_cpu(int apic_id)
     305                 :            : {
     306                 :            :         int i;
     307                 :            : 
     308                 :            :         for_each_possible_cpu(i) {
     309                 :            :                 if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
     310                 :            :                         return i;
     311                 :            :         }
     312                 :            :         return -1;
     313                 :            : }
     314                 :            : 
     315                 :            : int safe_smp_processor_id(void)
     316                 :            : {
     317                 :            :         int apicid, cpuid;
     318                 :            : 
     319                 :            :         if (!boot_cpu_has(X86_FEATURE_APIC))
     320                 :            :                 return 0;
     321                 :            : 
     322                 :            :         apicid = hard_smp_processor_id();
     323                 :            :         if (apicid == BAD_APICID)
     324                 :            :                 return 0;
     325                 :            : 
     326                 :            :         cpuid = convert_apicid_to_cpu(apicid);
     327                 :            : 
     328                 :            :         return cpuid >= 0 ? cpuid : 0;
     329                 :            : }
     330                 :            : #endif

Generated by: LCOV version 1.14