xref: /openbmc/linux/arch/x86/kernel/apic/ipi.c (revision 521b82fe)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/cpumask.h>
4 
5 #include <asm/apic.h>
6 #include <asm/ipi.h>
7 
8 void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
9 {
10 	/*
11 	 * Subtle. In the case of the 'never do double writes' workaround
12 	 * we have to lock out interrupts to be safe.  As we don't care
13 	 * of the value read we use an atomic rmw access to avoid costly
14 	 * cli/sti.  Otherwise we use an even cheaper single atomic write
15 	 * to the APIC.
16 	 */
17 	unsigned int cfg;
18 
19 	/*
20 	 * Wait for idle.
21 	 */
22 	__xapic_wait_icr_idle();
23 
24 	/*
25 	 * No need to touch the target chip field
26 	 */
27 	cfg = __prepare_ICR(shortcut, vector, dest);
28 
29 	/*
30 	 * Send the IPI. The write to APIC_ICR fires this off.
31 	 */
32 	native_apic_mem_write(APIC_ICR, cfg);
33 }
34 
35 /*
36  * This is used to send an IPI with no shorthand notation (the destination is
37  * specified in bits 56 to 63 of the ICR).
38  */
39 void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest)
40 {
41 	unsigned long cfg;
42 
43 	/*
44 	 * Wait for idle.
45 	 */
46 	if (unlikely(vector == NMI_VECTOR))
47 		safe_apic_wait_icr_idle();
48 	else
49 		__xapic_wait_icr_idle();
50 
51 	/*
52 	 * prepare target chip field
53 	 */
54 	cfg = __prepare_ICR2(mask);
55 	native_apic_mem_write(APIC_ICR2, cfg);
56 
57 	/*
58 	 * program the ICR
59 	 */
60 	cfg = __prepare_ICR(0, vector, dest);
61 
62 	/*
63 	 * Send the IPI. The write to APIC_ICR fires this off.
64 	 */
65 	native_apic_mem_write(APIC_ICR, cfg);
66 }
67 
68 void default_send_IPI_single_phys(int cpu, int vector)
69 {
70 	unsigned long flags;
71 
72 	local_irq_save(flags);
73 	__default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, cpu),
74 				      vector, APIC_DEST_PHYSICAL);
75 	local_irq_restore(flags);
76 }
77 
78 void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector)
79 {
80 	unsigned long query_cpu;
81 	unsigned long flags;
82 
83 	/*
84 	 * Hack. The clustered APIC addressing mode doesn't allow us to send
85 	 * to an arbitrary mask, so I do a unicast to each CPU instead.
86 	 * - mbligh
87 	 */
88 	local_irq_save(flags);
89 	for_each_cpu(query_cpu, mask) {
90 		__default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid,
91 				query_cpu), vector, APIC_DEST_PHYSICAL);
92 	}
93 	local_irq_restore(flags);
94 }
95 
96 void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
97 						 int vector)
98 {
99 	unsigned int this_cpu = smp_processor_id();
100 	unsigned int query_cpu;
101 	unsigned long flags;
102 
103 	/* See Hack comment above */
104 
105 	local_irq_save(flags);
106 	for_each_cpu(query_cpu, mask) {
107 		if (query_cpu == this_cpu)
108 			continue;
109 		__default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid,
110 				 query_cpu), vector, APIC_DEST_PHYSICAL);
111 	}
112 	local_irq_restore(flags);
113 }
114 
115 /*
116  * Helper function for APICs which insist on cpumasks
117  */
118 void default_send_IPI_single(int cpu, int vector)
119 {
120 	apic->send_IPI_mask(cpumask_of(cpu), vector);
121 }
122 
123 #ifdef CONFIG_X86_32
124 
125 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
126 						 int vector)
127 {
128 	unsigned long flags;
129 	unsigned int query_cpu;
130 
131 	/*
132 	 * Hack. The clustered APIC addressing mode doesn't allow us to send
133 	 * to an arbitrary mask, so I do a unicasts to each CPU instead. This
134 	 * should be modified to do 1 message per cluster ID - mbligh
135 	 */
136 
137 	local_irq_save(flags);
138 	for_each_cpu(query_cpu, mask)
139 		__default_send_IPI_dest_field(
140 			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
141 			vector, apic->dest_logical);
142 	local_irq_restore(flags);
143 }
144 
145 void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
146 						 int vector)
147 {
148 	unsigned long flags;
149 	unsigned int query_cpu;
150 	unsigned int this_cpu = smp_processor_id();
151 
152 	/* See Hack comment above */
153 
154 	local_irq_save(flags);
155 	for_each_cpu(query_cpu, mask) {
156 		if (query_cpu == this_cpu)
157 			continue;
158 		__default_send_IPI_dest_field(
159 			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
160 			vector, apic->dest_logical);
161 		}
162 	local_irq_restore(flags);
163 }
164 
165 /*
166  * This is only used on smaller machines.
167  */
168 void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector)
169 {
170 	unsigned long mask = cpumask_bits(cpumask)[0];
171 	unsigned long flags;
172 
173 	if (!mask)
174 		return;
175 
176 	local_irq_save(flags);
177 	WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]);
178 	__default_send_IPI_dest_field(mask, vector, apic->dest_logical);
179 	local_irq_restore(flags);
180 }
181 
182 void default_send_IPI_allbutself(int vector)
183 {
184 	/*
185 	 * if there are no other CPUs in the system then we get an APIC send
186 	 * error if we try to broadcast, thus avoid sending IPIs in this case.
187 	 */
188 	if (num_online_cpus() < 2)
189 		return;
190 
191 	if (no_broadcast || vector == NMI_VECTOR) {
192 		apic->send_IPI_mask_allbutself(cpu_online_mask, vector);
193 	} else {
194 		__default_send_IPI_shortcut(APIC_DEST_ALLBUT, vector,
195 					    apic->dest_logical);
196 	}
197 }
198 
199 void default_send_IPI_all(int vector)
200 {
201 	if (no_broadcast || vector == NMI_VECTOR) {
202 		apic->send_IPI_mask(cpu_online_mask, vector);
203 	} else {
204 		__default_send_IPI_shortcut(APIC_DEST_ALLINC, vector,
205 					    apic->dest_logical);
206 	}
207 }
208 
209 void default_send_IPI_self(int vector)
210 {
211 	__default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical);
212 }
213 
214 /* must come after the send_IPI functions above for inlining */
215 static int convert_apicid_to_cpu(int apic_id)
216 {
217 	int i;
218 
219 	for_each_possible_cpu(i) {
220 		if (per_cpu(x86_cpu_to_apicid, i) == apic_id)
221 			return i;
222 	}
223 	return -1;
224 }
225 
226 int safe_smp_processor_id(void)
227 {
228 	int apicid, cpuid;
229 
230 	if (!boot_cpu_has(X86_FEATURE_APIC))
231 		return 0;
232 
233 	apicid = hard_smp_processor_id();
234 	if (apicid == BAD_APICID)
235 		return 0;
236 
237 	cpuid = convert_apicid_to_cpu(apicid);
238 
239 	return cpuid >= 0 ? cpuid : 0;
240 }
241 #endif
242