aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorAshok Raj <ashok.raj@intel.com>2005-06-25 17:55:03 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-25 19:24:31 -0400
commita02c4cb67e4ccd5ce7a13c7f04c2fedb06c35431 (patch)
treee3e78625efbded773190a02566b46ed71d717740 /arch/x86_64
parent884d9e40b4089014f40c49e86ac6505842db2b53 (diff)
[PATCH] x86_64: Provide ability to choose using shortcuts for IPI in flat mode.
This patch provides an option to switch broadcast or use mask version for sending IPI's. If CONFIG_HOTPLUG_CPU is defined, we choose not to use broadcast shortcuts by default, otherwise we choose broadcast mode as default. both cases, one can change this via startup cmd line option, to choose no-broadcast mode. no_ipi_broadcast=1 This is provided on request from Andi Kleen, since he doesnt agree with replacing IPI shortcuts as a solution for CPU hotplug. Without removing broadcast IPI's, it would mean lots of new code for __cpu_up() path, which would acheive the same results. Signed-off-by: Ashok Raj <ashok.raj@intel.com> Acked-by: Andi Kleen <ak@muc.de> Acked-by: Zwane Mwaikambo <zwane@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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);