diff options
-rw-r--r-- | arch/x86/include/asm/genapic_32.h | 7 | ||||
-rw-r--r-- | arch/x86/include/asm/genapic_64.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/uv/uv.h | 33 | ||||
-rw-r--r-- | arch/x86/include/asm/uv/uv_bau.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/genx2apic_uv_x.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/smpboot.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/tlb_64.c | 18 | ||||
-rw-r--r-- | arch/x86/kernel/tlb_uv.c | 68 |
9 files changed, 83 insertions, 54 deletions
diff --git a/arch/x86/include/asm/genapic_32.h b/arch/x86/include/asm/genapic_32.h index 2c05b737ee22..4334502d3664 100644 --- a/arch/x86/include/asm/genapic_32.h +++ b/arch/x86/include/asm/genapic_32.h | |||
@@ -138,11 +138,4 @@ struct genapic { | |||
138 | extern struct genapic *genapic; | 138 | extern struct genapic *genapic; |
139 | extern void es7000_update_genapic_to_cluster(void); | 139 | extern void es7000_update_genapic_to_cluster(void); |
140 | 140 | ||
141 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
142 | #define get_uv_system_type() UV_NONE | ||
143 | #define is_uv_system() 0 | ||
144 | #define uv_wakeup_secondary(a, b) 1 | ||
145 | #define uv_system_init() do {} while (0) | ||
146 | |||
147 | |||
148 | #endif /* _ASM_X86_GENAPIC_32_H */ | 141 | #endif /* _ASM_X86_GENAPIC_32_H */ |
diff --git a/arch/x86/include/asm/genapic_64.h b/arch/x86/include/asm/genapic_64.h index adf32fb56aa6..7bb092c59055 100644 --- a/arch/x86/include/asm/genapic_64.h +++ b/arch/x86/include/asm/genapic_64.h | |||
@@ -51,15 +51,9 @@ extern struct genapic apic_x2apic_phys; | |||
51 | extern int acpi_madt_oem_check(char *, char *); | 51 | extern int acpi_madt_oem_check(char *, char *); |
52 | 52 | ||
53 | extern void apic_send_IPI_self(int vector); | 53 | extern void apic_send_IPI_self(int vector); |
54 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
55 | extern enum uv_system_type get_uv_system_type(void); | ||
56 | extern int is_uv_system(void); | ||
57 | 54 | ||
58 | extern struct genapic apic_x2apic_uv_x; | 55 | extern struct genapic apic_x2apic_uv_x; |
59 | DECLARE_PER_CPU(int, x2apic_extra_bits); | 56 | DECLARE_PER_CPU(int, x2apic_extra_bits); |
60 | extern void uv_cpu_init(void); | ||
61 | extern void uv_system_init(void); | ||
62 | extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); | ||
63 | 57 | ||
64 | extern void setup_apic_routing(void); | 58 | extern void setup_apic_routing(void); |
65 | 59 | ||
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h new file mode 100644 index 000000000000..dce5fe350134 --- /dev/null +++ b/arch/x86/include/asm/uv/uv.h | |||
@@ -0,0 +1,33 @@ | |||
1 | #ifndef _ASM_X86_UV_UV_H | ||
2 | #define _ASM_X86_UV_UV_H | ||
3 | |||
4 | enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; | ||
5 | |||
6 | #ifdef CONFIG_X86_64 | ||
7 | |||
8 | extern enum uv_system_type get_uv_system_type(void); | ||
9 | extern int is_uv_system(void); | ||
10 | extern void uv_cpu_init(void); | ||
11 | extern void uv_system_init(void); | ||
12 | extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); | ||
13 | extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, | ||
14 | struct mm_struct *mm, | ||
15 | unsigned long va, | ||
16 | unsigned int cpu); | ||
17 | |||
18 | #else /* X86_64 */ | ||
19 | |||
20 | static inline enum uv_system_type get_uv_system_type(void) { return UV_NONE; } | ||
21 | static inline int is_uv_system(void) { return 0; } | ||
22 | static inline void uv_cpu_init(void) { } | ||
23 | static inline void uv_system_init(void) { } | ||
24 | static inline int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip) | ||
25 | { return 1; } | ||
26 | static inline const struct cpumask * | ||
27 | uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, | ||
28 | unsigned long va, unsigned int cpu) | ||
29 | { return cpumask; } | ||
30 | |||
31 | #endif /* X86_64 */ | ||
32 | |||
33 | #endif /* _ASM_X86_UV_UV_H */ | ||
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 74e6393bfddb..9b0e61bf7a88 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h | |||
@@ -325,8 +325,6 @@ static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) | |||
325 | #define cpubit_isset(cpu, bau_local_cpumask) \ | 325 | #define cpubit_isset(cpu, bau_local_cpumask) \ |
326 | test_bit((cpu), (bau_local_cpumask).bits) | 326 | test_bit((cpu), (bau_local_cpumask).bits) |
327 | 327 | ||
328 | extern int uv_flush_tlb_others(struct cpumask *, | ||
329 | struct mm_struct *, unsigned long); | ||
330 | extern void uv_bau_message_intr1(void); | 328 | extern void uv_bau_message_intr1(void); |
331 | extern void uv_bau_timeout_intr1(void); | 329 | extern void uv_bau_timeout_intr1(void); |
332 | 330 | ||
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fbebbcec001b..99904f288d6a 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/apic.h> | 28 | #include <asm/apic.h> |
29 | #include <mach_apic.h> | 29 | #include <mach_apic.h> |
30 | #include <asm/genapic.h> | 30 | #include <asm/genapic.h> |
31 | #include <asm/uv/uv.h> | ||
31 | #endif | 32 | #endif |
32 | 33 | ||
33 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index b193e082f6ce..bfe36249145c 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/ipi.h> | 25 | #include <asm/ipi.h> |
26 | #include <asm/genapic.h> | 26 | #include <asm/genapic.h> |
27 | #include <asm/pgtable.h> | 27 | #include <asm/pgtable.h> |
28 | #include <asm/uv/uv.h> | ||
28 | #include <asm/uv/uv_mmrs.h> | 29 | #include <asm/uv/uv_mmrs.h> |
29 | #include <asm/uv/uv_hub.h> | 30 | #include <asm/uv/uv_hub.h> |
30 | #include <asm/uv/bios.h> | 31 | #include <asm/uv/bios.h> |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 869b98840fd0..def770b57b5a 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <asm/vmi.h> | 62 | #include <asm/vmi.h> |
63 | #include <asm/genapic.h> | 63 | #include <asm/genapic.h> |
64 | #include <asm/setup.h> | 64 | #include <asm/setup.h> |
65 | #include <asm/uv/uv.h> | ||
65 | #include <linux/mc146818rtc.h> | 66 | #include <linux/mc146818rtc.h> |
66 | 67 | ||
67 | #include <mach_apic.h> | 68 | #include <mach_apic.h> |
diff --git a/arch/x86/kernel/tlb_64.c b/arch/x86/kernel/tlb_64.c index e64a32c48825..b8bed841ad67 100644 --- a/arch/x86/kernel/tlb_64.c +++ b/arch/x86/kernel/tlb_64.c | |||
@@ -15,8 +15,7 @@ | |||
15 | #include <asm/proto.h> | 15 | #include <asm/proto.h> |
16 | #include <asm/apicdef.h> | 16 | #include <asm/apicdef.h> |
17 | #include <asm/idle.h> | 17 | #include <asm/idle.h> |
18 | #include <asm/uv/uv_hub.h> | 18 | #include <asm/uv/uv.h> |
19 | #include <asm/uv/uv_bau.h> | ||
20 | 19 | ||
21 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) | 20 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) |
22 | = { &init_mm, 0, }; | 21 | = { &init_mm, 0, }; |
@@ -206,16 +205,13 @@ void native_flush_tlb_others(const struct cpumask *cpumask, | |||
206 | struct mm_struct *mm, unsigned long va) | 205 | struct mm_struct *mm, unsigned long va) |
207 | { | 206 | { |
208 | if (is_uv_system()) { | 207 | if (is_uv_system()) { |
209 | /* FIXME: could be an percpu_alloc'd thing */ | 208 | unsigned int cpu; |
210 | static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); | ||
211 | struct cpumask *after_uv_flush = &get_cpu_var(flush_tlb_mask); | ||
212 | 209 | ||
213 | cpumask_andnot(after_uv_flush, cpumask, | 210 | cpu = get_cpu(); |
214 | cpumask_of(smp_processor_id())); | 211 | cpumask = uv_flush_tlb_others(cpumask, mm, va, cpu); |
215 | if (!uv_flush_tlb_others(after_uv_flush, mm, va)) | 212 | if (cpumask) |
216 | flush_tlb_others_ipi(after_uv_flush, mm, va); | 213 | flush_tlb_others_ipi(cpumask, mm, va); |
217 | 214 | put_cpu(); | |
218 | put_cpu_var(flush_tlb_uv_cpumask); | ||
219 | return; | 215 | return; |
220 | } | 216 | } |
221 | flush_tlb_others_ipi(cpumask, mm, va); | 217 | flush_tlb_others_ipi(cpumask, mm, va); |
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 690dcf1a27d4..aae15dd72604 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | 12 | ||
13 | #include <asm/mmu_context.h> | 13 | #include <asm/mmu_context.h> |
14 | #include <asm/uv/uv.h> | ||
14 | #include <asm/uv/uv_mmrs.h> | 15 | #include <asm/uv/uv_mmrs.h> |
15 | #include <asm/uv/uv_hub.h> | 16 | #include <asm/uv/uv_hub.h> |
16 | #include <asm/uv/uv_bau.h> | 17 | #include <asm/uv/uv_bau.h> |
@@ -209,14 +210,15 @@ static int uv_wait_completion(struct bau_desc *bau_desc, | |||
209 | * | 210 | * |
210 | * Send a broadcast and wait for a broadcast message to complete. | 211 | * Send a broadcast and wait for a broadcast message to complete. |
211 | * | 212 | * |
212 | * The cpumaskp mask contains the cpus the broadcast was sent to. | 213 | * The flush_mask contains the cpus the broadcast was sent to. |
213 | * | 214 | * |
214 | * Returns 1 if all remote flushing was done. The mask is zeroed. | 215 | * Returns NULL if all remote flushing was done. The mask is zeroed. |
215 | * Returns 0 if some remote flushing remains to be done. The mask will have | 216 | * Returns @flush_mask if some remote flushing remains to be done. The |
216 | * some bits still set. | 217 | * mask will have some bits still set. |
217 | */ | 218 | */ |
218 | int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, | 219 | const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade, |
219 | struct cpumask *cpumaskp) | 220 | struct bau_desc *bau_desc, |
221 | struct cpumask *flush_mask) | ||
220 | { | 222 | { |
221 | int completion_status = 0; | 223 | int completion_status = 0; |
222 | int right_shift; | 224 | int right_shift; |
@@ -263,59 +265,69 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc, | |||
263 | * Success, so clear the remote cpu's from the mask so we don't | 265 | * Success, so clear the remote cpu's from the mask so we don't |
264 | * use the IPI method of shootdown on them. | 266 | * use the IPI method of shootdown on them. |
265 | */ | 267 | */ |
266 | for_each_cpu(bit, cpumaskp) { | 268 | for_each_cpu(bit, flush_mask) { |
267 | blade = uv_cpu_to_blade_id(bit); | 269 | blade = uv_cpu_to_blade_id(bit); |
268 | if (blade == this_blade) | 270 | if (blade == this_blade) |
269 | continue; | 271 | continue; |
270 | cpumask_clear_cpu(bit, cpumaskp); | 272 | cpumask_clear_cpu(bit, flush_mask); |
271 | } | 273 | } |
272 | if (!cpumask_empty(cpumaskp)) | 274 | if (!cpumask_empty(flush_mask)) |
273 | return 0; | 275 | return flush_mask; |
274 | return 1; | 276 | return NULL; |
275 | } | 277 | } |
276 | 278 | ||
277 | /** | 279 | /** |
278 | * uv_flush_tlb_others - globally purge translation cache of a virtual | 280 | * uv_flush_tlb_others - globally purge translation cache of a virtual |
279 | * address or all TLB's | 281 | * address or all TLB's |
280 | * @cpumaskp: mask of all cpu's in which the address is to be removed | 282 | * @cpumask: mask of all cpu's in which the address is to be removed |
281 | * @mm: mm_struct containing virtual address range | 283 | * @mm: mm_struct containing virtual address range |
282 | * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) | 284 | * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu) |
285 | * @cpu: the current cpu | ||
283 | * | 286 | * |
284 | * This is the entry point for initiating any UV global TLB shootdown. | 287 | * This is the entry point for initiating any UV global TLB shootdown. |
285 | * | 288 | * |
286 | * Purges the translation caches of all specified processors of the given | 289 | * Purges the translation caches of all specified processors of the given |
287 | * virtual address, or purges all TLB's on specified processors. | 290 | * virtual address, or purges all TLB's on specified processors. |
288 | * | 291 | * |
289 | * The caller has derived the cpumaskp from the mm_struct and has subtracted | 292 | * The caller has derived the cpumask from the mm_struct. This function |
290 | * the local cpu from the mask. This function is called only if there | 293 | * is called only if there are bits set in the mask. (e.g. flush_tlb_page()) |
291 | * are bits set in the mask. (e.g. flush_tlb_page()) | ||
292 | * | 294 | * |
293 | * The cpumaskp is converted into a nodemask of the nodes containing | 295 | * The cpumask is converted into a nodemask of the nodes containing |
294 | * the cpus. | 296 | * the cpus. |
295 | * | 297 | * |
296 | * Returns 1 if all remote flushing was done. | 298 | * Note that this function should be called with preemption disabled. |
297 | * Returns 0 if some remote flushing remains to be done. | 299 | * |
300 | * Returns NULL if all remote flushing was done. | ||
301 | * Returns pointer to cpumask if some remote flushing remains to be | ||
302 | * done. The returned pointer is valid till preemption is re-enabled. | ||
298 | */ | 303 | */ |
299 | int uv_flush_tlb_others(struct cpumask *cpumaskp, struct mm_struct *mm, | 304 | const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, |
300 | unsigned long va) | 305 | struct mm_struct *mm, |
306 | unsigned long va, unsigned int cpu) | ||
301 | { | 307 | { |
308 | static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask); | ||
309 | struct cpumask *flush_mask = &__get_cpu_var(flush_tlb_mask); | ||
302 | int i; | 310 | int i; |
303 | int bit; | 311 | int bit; |
304 | int blade; | 312 | int blade; |
305 | int cpu; | 313 | int uv_cpu; |
306 | int this_blade; | 314 | int this_blade; |
307 | int locals = 0; | 315 | int locals = 0; |
308 | struct bau_desc *bau_desc; | 316 | struct bau_desc *bau_desc; |
309 | 317 | ||
310 | cpu = uv_blade_processor_id(); | 318 | WARN_ON(!in_atomic()); |
319 | |||
320 | cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); | ||
321 | |||
322 | uv_cpu = uv_blade_processor_id(); | ||
311 | this_blade = uv_numa_blade_id(); | 323 | this_blade = uv_numa_blade_id(); |
312 | bau_desc = __get_cpu_var(bau_control).descriptor_base; | 324 | bau_desc = __get_cpu_var(bau_control).descriptor_base; |
313 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * cpu; | 325 | bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; |
314 | 326 | ||
315 | bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); | 327 | bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); |
316 | 328 | ||
317 | i = 0; | 329 | i = 0; |
318 | for_each_cpu(bit, cpumaskp) { | 330 | for_each_cpu(bit, flush_mask) { |
319 | blade = uv_cpu_to_blade_id(bit); | 331 | blade = uv_cpu_to_blade_id(bit); |
320 | BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); | 332 | BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1)); |
321 | if (blade == this_blade) { | 333 | if (blade == this_blade) { |
@@ -330,17 +342,17 @@ int uv_flush_tlb_others(struct cpumask *cpumaskp, struct mm_struct *mm, | |||
330 | * no off_node flushing; return status for local node | 342 | * no off_node flushing; return status for local node |
331 | */ | 343 | */ |
332 | if (locals) | 344 | if (locals) |
333 | return 0; | 345 | return flush_mask; |
334 | else | 346 | else |
335 | return 1; | 347 | return NULL; |
336 | } | 348 | } |
337 | __get_cpu_var(ptcstats).requestor++; | 349 | __get_cpu_var(ptcstats).requestor++; |
338 | __get_cpu_var(ptcstats).ntargeted += i; | 350 | __get_cpu_var(ptcstats).ntargeted += i; |
339 | 351 | ||
340 | bau_desc->payload.address = va; | 352 | bau_desc->payload.address = va; |
341 | bau_desc->payload.sending_cpu = smp_processor_id(); | 353 | bau_desc->payload.sending_cpu = cpu; |
342 | 354 | ||
343 | return uv_flush_send_and_wait(cpu, this_blade, bau_desc, cpumaskp); | 355 | return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask); |
344 | } | 356 | } |
345 | 357 | ||
346 | /* | 358 | /* |