1
2
3
4
5
6
7
8
9
10
11#include <linux/init.h>
12
13#include <linux/mm.h>
14#include <linux/irq.h>
15#include <linux/delay.h>
16#include <linux/spinlock.h>
17#include <linux/smp_lock.h>
18#include <linux/kernel_stat.h>
19#include <linux/mc146818rtc.h>
20#include <linux/cache.h>
21
22#include <asm/mtrr.h>
23#include <asm/pgalloc.h>
24#include <asm/smpboot.h>
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106spinlock_cacheline_t kernel_flag_cacheline = {SPIN_LOCK_UNLOCKED};
107
108struct tlb_state cpu_tlbstate[NR_CPUS] __cacheline_aligned = {[0 ... NR_CPUS-1] = { &init_mm, 0, }};
109
110
111
112
113
114
115
116static inline int __prepare_ICR (unsigned int shortcut, int vector)
117{
118 return APIC_DM_FIXED | shortcut | vector | INT_DEST_ADDR_MODE;
119}
120
121static inline int __prepare_ICR2 (unsigned int mask)
122{
123 return SET_APIC_DEST_FIELD(mask);
124}
125
126static inline void __send_IPI_shortcut(unsigned int shortcut, int vector)
127{
128
129
130
131
132
133
134
135 unsigned int cfg;
136
137
138
139
140 apic_wait_icr_idle();
141
142
143
144
145 cfg = __prepare_ICR(shortcut, vector);
146
147
148
149
150 apic_write_around(APIC_ICR, cfg);
151}
152
153void send_IPI_self(int vector)
154{
155 __send_IPI_shortcut(APIC_DEST_SELF, vector);
156}
157
158static inline void send_IPI_mask_bitmask(int mask, int vector)
159{
160 unsigned long cfg;
161 unsigned long flags;
162
163 __save_flags(flags);
164 __cli();
165
166
167
168
169
170 apic_wait_icr_idle();
171
172
173
174
175 cfg = __prepare_ICR2(mask);
176 apic_write_around(APIC_ICR2, cfg);
177
178
179
180
181 cfg = __prepare_ICR(0, vector);
182
183
184
185
186 apic_write_around(APIC_ICR, cfg);
187
188 __restore_flags(flags);
189}
190
191static inline void send_IPI_mask_sequence(int mask, int vector)
192{
193 unsigned long cfg, flags;
194 unsigned int query_cpu, query_mask;
195
196
197
198
199
200
201
202 __save_flags(flags);
203 __cli();
204
205 for (query_cpu = 0; query_cpu < NR_CPUS; ++query_cpu) {
206 query_mask = 1 << query_cpu;
207 if (query_mask & mask) {
208
209
210
211
212 apic_wait_icr_idle();
213
214
215
216
217 if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
218 cfg = __prepare_ICR2(cpu_to_physical_apicid(query_cpu));
219 else
220 cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu));
221 apic_write_around(APIC_ICR2, cfg);
222
223
224
225
226 cfg = __prepare_ICR(0, vector);
227
228
229
230
231 apic_write_around(APIC_ICR, cfg);
232 }
233 }
234 __restore_flags(flags);
235}
236
237static inline void send_IPI_mask(int mask, int vector)
238{
239 if (clustered_apic_mode)
240 send_IPI_mask_sequence(mask, vector);
241 else
242 send_IPI_mask_bitmask(mask, vector);
243}
244
245static inline void send_IPI_allbutself(int vector)
246{
247
248
249
250
251
252 if (!(smp_num_cpus > 1))
253 return;
254
255 if (clustered_apic_mode) {
256
257 int cpu;
258
259 if (smp_num_cpus > 1) {
260 for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
261 if (cpu != smp_processor_id())
262 send_IPI_mask(1 << cpu, vector);
263 }
264 }
265 } else {
266 __send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
267 return;
268 }
269}
270
271static inline void send_IPI_all(int vector)
272{
273 if (clustered_apic_mode) {
274
275 int cpu;
276
277 for (cpu = 0; cpu < smp_num_cpus; ++cpu) {
278 send_IPI_mask(1 << cpu, vector);
279 }
280 } else {
281 __send_IPI_shortcut(APIC_DEST_ALLINC, vector);
282 }
283}
284
285
286
287
288
289
290
291
292
293
294
295static volatile unsigned long flush_cpumask;
296static struct mm_struct * flush_mm;
297static unsigned long flush_va;
298static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
299#define FLUSH_ALL 0xffffffff
300
301
302
303
304
305
306
307
308static void inline leave_mm (unsigned long cpu)
309{
310 BUG_ON(cpu_tlbstate[cpu].state == TLBSTATE_OK);
311 clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask);
312 load_cr3(swapper_pg_dir);
313}
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361asmlinkage void smp_invalidate_interrupt (void)
362{
363 unsigned long cpu = smp_processor_id();
364
365 if (!test_bit(cpu, &flush_cpumask))
366 return;
367
368
369
370
371
372
373
374
375
376 if (flush_mm == cpu_tlbstate[cpu].active_mm) {
377 if (cpu_tlbstate[cpu].state == TLBSTATE_OK) {
378 if (flush_va == FLUSH_ALL)
379 local_flush_tlb();
380 else
381 __flush_tlb_one(flush_va);
382 } else
383 leave_mm(cpu);
384 }
385 ack_APIC_irq();
386 clear_bit(cpu, &flush_cpumask);
387}
388
389static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
390 unsigned long va)
391{
392
393
394
395
396
397
398
399 if (!cpumask)
400 BUG();
401 if ((cpumask & cpu_online_map) != cpumask)
402 BUG();
403 if (cpumask & (1 << smp_processor_id()))
404 BUG();
405 if (!mm)
406 BUG();
407
408
409
410
411
412
413
414 spin_lock(&tlbstate_lock);
415
416 flush_mm = mm;
417 flush_va = va;
418 atomic_set_mask(cpumask, &flush_cpumask);
419
420
421
422
423 send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
424
425 while (flush_cpumask)
426 ;
427
428 flush_mm = NULL;
429 flush_va = 0;
430 spin_unlock(&tlbstate_lock);
431}
432
433void flush_tlb_current_task(void)
434{
435 struct mm_struct *mm = current->mm;
436 unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
437
438 local_flush_tlb();
439 if (cpu_mask)
440 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
441}
442
443void flush_tlb_mm (struct mm_struct * mm)
444{
445 unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
446
447 if (current->active_mm == mm) {
448 if (current->mm)
449 local_flush_tlb();
450 else
451 leave_mm(smp_processor_id());
452 }
453 if (cpu_mask)
454 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
455}
456
457void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
458{
459 struct mm_struct *mm = vma->vm_mm;
460 unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
461
462 if (current->active_mm == mm) {
463 if(current->mm)
464 __flush_tlb_one(va);
465 else
466 leave_mm(smp_processor_id());
467 }
468
469 if (cpu_mask)
470 flush_tlb_others(cpu_mask, mm, va);
471}
472
473static inline void do_flush_tlb_all_local(void)
474{
475 unsigned long cpu = smp_processor_id();
476
477 __flush_tlb_all();
478 if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY)
479 leave_mm(cpu);
480}
481
482static void flush_tlb_all_ipi(void* info)
483{
484 do_flush_tlb_all_local();
485}
486
487void flush_tlb_all(void)
488{
489 smp_call_function (flush_tlb_all_ipi,0,1,1);
490
491 do_flush_tlb_all_local();
492}
493
494
495
496
497
498
499
500void smp_send_reschedule(int cpu)
501{
502 send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR);
503}
504
505
506
507
508
509static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
510
511struct call_data_struct {
512 void (*func) (void *info);
513 void *info;
514 atomic_t started;
515 atomic_t finished;
516 int wait;
517};
518
519static struct call_data_struct * call_data;
520
521
522
523
524
525
526int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
527 int wait)
528
529
530
531
532
533
534
535
536
537
538
539
540{
541 struct call_data_struct data;
542 int cpus = smp_num_cpus-1;
543
544 if (!cpus)
545 return 0;
546
547 data.func = func;
548 data.info = info;
549 atomic_set(&data.started, 0);
550 data.wait = wait;
551 if (wait)
552 atomic_set(&data.finished, 0);
553
554 spin_lock(&call_lock);
555 call_data = &data;
556 wmb();
557
558 send_IPI_allbutself(CALL_FUNCTION_VECTOR);
559
560
561 while (atomic_read(&data.started) != cpus)
562 barrier();
563
564 if (wait)
565 while (atomic_read(&data.finished) != cpus)
566 barrier();
567 spin_unlock(&call_lock);
568
569 return 0;
570}
571
572static void stop_this_cpu (void * dummy)
573{
574
575
576
577 clear_bit(smp_processor_id(), &cpu_online_map);
578 __cli();
579 disable_local_APIC();
580 if (cpu_data[smp_processor_id()].hlt_works_ok)
581 for(;;) __asm__("hlt");
582 for (;;);
583}
584
585
586
587
588
589void smp_send_stop(void)
590{
591 smp_call_function(stop_this_cpu, NULL, 1, 0);
592 smp_num_cpus = 1;
593
594 __cli();
595 disable_local_APIC();
596 __sti();
597}
598
599
600
601
602
603
604asmlinkage void smp_reschedule_interrupt(void)
605{
606 ack_APIC_irq();
607}
608
609asmlinkage void smp_call_function_interrupt(void)
610{
611 void (*func) (void *info) = call_data->func;
612 void *info = call_data->info;
613 int wait = call_data->wait;
614
615 ack_APIC_irq();
616
617
618
619
620 mb();
621 atomic_inc(&call_data->started);
622
623
624
625 (*func)(info);
626 if (wait) {
627 mb();
628 atomic_inc(&call_data->finished);
629 }
630}
631
632