aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/genapic_flat.c96
1 files changed, 82 insertions, 14 deletions
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index 00f3fa6df714..282846965080 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -20,6 +20,46 @@
20#include <asm/smp.h> 20#include <asm/smp.h>
21#include <asm/ipi.h> 21#include <asm/ipi.h>
22 22
23/*
24 * The following permit choosing broadcast IPI shortcut v.s sending IPI only
25 * to online cpus via the send_IPI_mask varient.
26 * The mask version is my preferred option, since it eliminates a lot of
27 * other extra code that would need to be written to cleanup intrs sent
28 * to a CPU while offline.
29 *
30 * Sending broadcast introduces lots of trouble in CPU hotplug situations.
31 * These IPI's are delivered to cpu's irrespective of their offline status
32 * and could pickup stale intr data when these CPUS are turned online.
33 *
34 * Not using broadcast is a cleaner approach IMO, but Andi Kleen disagrees with
35 * the idea of not using broadcast IPI's anymore. Hence the run time check
36 * is introduced, on his request so we can choose an alternate mechanism.
37 *
38 * Initial wacky performance tests that collect cycle counts show
39 * no increase in using mask v.s broadcast version. In fact they seem
40 * identical in terms of cycle counts.
41 *
42 * if we need to use broadcast, we need to do the following.
43 *
44 * cli;
45 * hold call_lock;
46 * clear any pending IPI, just ack and clear all pending intr
47 * set cpu_online_map;
48 * release call_lock;
49 * sti;
50 *
51 * The complicated dummy irq processing shown above is not required if
52 * we didnt sent IPI's to wrong CPU's in the first place.
53 *
54 * - Ashok Raj <ashok.raj@intel.com>
55 */
56#ifdef CONFIG_HOTPLUG_CPU
57#define DEFAULT_SEND_IPI (1)
58#else
59#define DEFAULT_SEND_IPI (0)
60#endif
61
62static int no_broadcast=DEFAULT_SEND_IPI;
23 63
24static cpumask_t flat_target_cpus(void) 64static cpumask_t flat_target_cpus(void)
25{ 65{
@@ -79,28 +119,37 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
79 local_irq_restore(flags); 119 local_irq_restore(flags);
80} 120}
81 121
82static void flat_send_IPI_allbutself(int vector) 122static inline void __local_flat_send_IPI_allbutself(int vector)
83{ 123{
84 cpumask_t mask; 124 if (no_broadcast) {
85 /* 125 cpumask_t mask = cpu_online_map;
86 * if there are no other CPUs in the system then 126 int this_cpu = get_cpu();
87 * we get an APIC send error if we try to broadcast.
88 * thus we have to avoid sending IPIs in this case.
89 */
90 int this_cpu = get_cpu();
91
92 mask = cpu_online_map;
93 cpu_clear(this_cpu, mask);
94 127
95 if (cpus_weight(mask) >= 1) 128 cpu_clear(this_cpu, mask);
96 flat_send_IPI_mask(mask, vector); 129 flat_send_IPI_mask(mask, vector);
130 put_cpu();
131 }
132 else
133 __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
134}
97 135
98 put_cpu(); 136static inline void __local_flat_send_IPI_all(int vector)
137{
138 if (no_broadcast)
139 flat_send_IPI_mask(cpu_online_map, vector);
140 else
141 __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
142}
143
144static void flat_send_IPI_allbutself(int vector)
145{
146 if (((num_online_cpus()) - 1) >= 1)
147 __local_flat_send_IPI_allbutself(vector);
99} 148}
100 149
101static void flat_send_IPI_all(int vector) 150static void flat_send_IPI_all(int vector)
102{ 151{
103 flat_send_IPI_mask(cpu_online_map, vector); 152 __local_flat_send_IPI_all(vector);
104} 153}
105 154
106static int flat_apic_id_registered(void) 155static int flat_apic_id_registered(void)
@@ -121,6 +170,16 @@ static unsigned int phys_pkg_id(int index_msb)
121 return ((ebx >> 24) & 0xFF) >> index_msb; 170 return ((ebx >> 24) & 0xFF) >> index_msb;
122} 171}
123 172
173static __init int no_ipi_broadcast(char *str)
174{
175 get_option(&str, &no_broadcast);
176 printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
177 "IPI Broadcast");
178 return 1;
179}
180
181__setup("no_ipi_broadcast", no_ipi_broadcast);
182
124struct genapic apic_flat = { 183struct genapic apic_flat = {
125 .name = "flat", 184 .name = "flat",
126 .int_delivery_mode = dest_LowestPrio, 185 .int_delivery_mode = dest_LowestPrio,
@@ -135,3 +194,12 @@ struct genapic apic_flat = {
135 .cpu_mask_to_apicid = flat_cpu_mask_to_apicid, 194 .cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
136 .phys_pkg_id = phys_pkg_id, 195 .phys_pkg_id = phys_pkg_id,
137}; 196};
197
198static int __init print_ipi_mode(void)
199{
200 printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
201 "Shortcut");
202 return 0;
203}
204
205late_initcall(print_ipi_mode);