cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ipi.c (7657B)


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