This source file includes following definitions.
- cmdl_force_cpei
- nointroute
- fix_b0_for_bsp
- sync_master
- get_delta
- ia64_sync_itc
- smp_setup_percpu_timer
- smp_callin
- start_secondary
- do_boot_cpu
- decay
- smp_build_cpu_map
- smp_prepare_cpus
- smp_prepare_boot_cpu
- clear_cpu_sibling_map
- remove_siblinginfo
- migrate_platform_irqs
- __cpu_disable
- __cpu_die
- smp_cpus_done
- set_cpu_sibling_map
- __cpu_up
- init_smp_config
- identify_siblings
- is_multithreading_enabled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <linux/module.h>
27 #include <linux/acpi.h>
28 #include <linux/memblock.h>
29 #include <linux/cpu.h>
30 #include <linux/delay.h>
31 #include <linux/init.h>
32 #include <linux/interrupt.h>
33 #include <linux/irq.h>
34 #include <linux/kernel.h>
35 #include <linux/kernel_stat.h>
36 #include <linux/mm.h>
37 #include <linux/notifier.h>
38 #include <linux/smp.h>
39 #include <linux/spinlock.h>
40 #include <linux/efi.h>
41 #include <linux/percpu.h>
42 #include <linux/bitops.h>
43
44 #include <linux/atomic.h>
45 #include <asm/cache.h>
46 #include <asm/current.h>
47 #include <asm/delay.h>
48 #include <asm/io.h>
49 #include <asm/irq.h>
50 #include <asm/mca.h>
51 #include <asm/page.h>
52 #include <asm/pgalloc.h>
53 #include <asm/pgtable.h>
54 #include <asm/processor.h>
55 #include <asm/ptrace.h>
56 #include <asm/sal.h>
57 #include <asm/tlbflush.h>
58 #include <asm/unistd.h>
59
60 #define SMP_DEBUG 0
61
62 #if SMP_DEBUG
63 #define Dprintk(x...) printk(x)
64 #else
65 #define Dprintk(x...)
66 #endif
67
68 #ifdef CONFIG_HOTPLUG_CPU
69 #ifdef CONFIG_PERMIT_BSP_REMOVE
70 #define bsp_remove_ok 1
71 #else
72 #define bsp_remove_ok 0
73 #endif
74
75
76
77
78 struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
79
80
81
82
83
84 struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
85
86 #define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
87
88 #else
89 #define set_brendez_area(x)
90 #endif
91
92
93
94
95
96 #define MASTER (0)
97 #define SLAVE (SMP_CACHE_BYTES/8)
98
99 #define NUM_ROUNDS 64
100 #define NUM_ITERS 5
101
102 static DEFINE_SPINLOCK(itc_sync_lock);
103 static volatile unsigned long go[SLAVE + 1];
104
105 #define DEBUG_ITC_SYNC 0
106
107 extern void start_ap (void);
108 extern unsigned long ia64_iobase;
109
110 struct task_struct *task_for_booting_cpu;
111
112
113
114
115 DEFINE_PER_CPU(int, cpu_state);
116
117 cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
118 EXPORT_SYMBOL(cpu_core_map);
119 DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
120 EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
121
122 int smp_num_siblings = 1;
123
124
125 volatile int ia64_cpu_to_sapicid[NR_CPUS];
126 EXPORT_SYMBOL(ia64_cpu_to_sapicid);
127
128 static cpumask_t cpu_callin_map;
129
130 struct smp_boot_data smp_boot_data __initdata;
131
132 unsigned long ap_wakeup_vector = -1;
133
134 char __initdata no_int_routing;
135
136 unsigned char smp_int_redirect;
137
138 #ifdef CONFIG_FORCE_CPEI_RETARGET
139 #define CPEI_OVERRIDE_DEFAULT (1)
140 #else
141 #define CPEI_OVERRIDE_DEFAULT (0)
142 #endif
143
144 unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT;
145
146 static int __init
147 cmdl_force_cpei(char *str)
148 {
149 int value=0;
150
151 get_option (&str, &value);
152 force_cpei_retarget = value;
153
154 return 1;
155 }
156
157 __setup("force_cpei=", cmdl_force_cpei);
158
159 static int __init
160 nointroute (char *str)
161 {
162 no_int_routing = 1;
163 printk ("no_int_routing on\n");
164 return 1;
165 }
166
167 __setup("nointroute", nointroute);
168
169 static void fix_b0_for_bsp(void)
170 {
171 #ifdef CONFIG_HOTPLUG_CPU
172 int cpuid;
173 static int fix_bsp_b0 = 1;
174
175 cpuid = smp_processor_id();
176
177
178
179
180 if (!(fix_bsp_b0 && cpuid))
181 return;
182
183 sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0];
184 printk ("Fixed BSP b0 value from CPU %d\n", cpuid);
185
186 fix_bsp_b0 = 0;
187 #endif
188 }
189
190 void
191 sync_master (void *arg)
192 {
193 unsigned long flags, i;
194
195 go[MASTER] = 0;
196
197 local_irq_save(flags);
198 {
199 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
200 while (!go[MASTER])
201 cpu_relax();
202 go[MASTER] = 0;
203 go[SLAVE] = ia64_get_itc();
204 }
205 }
206 local_irq_restore(flags);
207 }
208
209
210
211
212
213
214 static inline long
215 get_delta (long *rt, long *master)
216 {
217 unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
218 unsigned long tcenter, t0, t1, tm;
219 long i;
220
221 for (i = 0; i < NUM_ITERS; ++i) {
222 t0 = ia64_get_itc();
223 go[MASTER] = 1;
224 while (!(tm = go[SLAVE]))
225 cpu_relax();
226 go[SLAVE] = 0;
227 t1 = ia64_get_itc();
228
229 if (t1 - t0 < best_t1 - best_t0)
230 best_t0 = t0, best_t1 = t1, best_tm = tm;
231 }
232
233 *rt = best_t1 - best_t0;
234 *master = best_tm - best_t0;
235
236
237 tcenter = (best_t0/2 + best_t1/2);
238 if (best_t0 % 2 + best_t1 % 2 == 2)
239 ++tcenter;
240 return tcenter - best_tm;
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 void
276 ia64_sync_itc (unsigned int master)
277 {
278 long i, delta, adj, adjust_latency = 0, done = 0;
279 unsigned long flags, rt, master_time_stamp, bound;
280 #if DEBUG_ITC_SYNC
281 struct {
282 long rt;
283 long master;
284 long diff;
285 long lat;
286 } t[NUM_ROUNDS];
287 #endif
288
289
290
291
292
293
294
295 BUG_ON((ia64_get_itv() & (1 << 16)) == 0);
296
297 go[MASTER] = 1;
298
299 if (smp_call_function_single(master, sync_master, NULL, 0) < 0) {
300 printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master);
301 return;
302 }
303
304 while (go[MASTER])
305 cpu_relax();
306
307 spin_lock_irqsave(&itc_sync_lock, flags);
308 {
309 for (i = 0; i < NUM_ROUNDS; ++i) {
310 delta = get_delta(&rt, &master_time_stamp);
311 if (delta == 0) {
312 done = 1;
313 bound = rt;
314 }
315
316 if (!done) {
317 if (i > 0) {
318 adjust_latency += -delta;
319 adj = -delta + adjust_latency/4;
320 } else
321 adj = -delta;
322
323 ia64_set_itc(ia64_get_itc() + adj);
324 }
325 #if DEBUG_ITC_SYNC
326 t[i].rt = rt;
327 t[i].master = master_time_stamp;
328 t[i].diff = delta;
329 t[i].lat = adjust_latency/4;
330 #endif
331 }
332 }
333 spin_unlock_irqrestore(&itc_sync_lock, flags);
334
335 #if DEBUG_ITC_SYNC
336 for (i = 0; i < NUM_ROUNDS; ++i)
337 printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
338 t[i].rt, t[i].master, t[i].diff, t[i].lat);
339 #endif
340
341 printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, "
342 "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
343 }
344
345
346
347
348 static inline void smp_setup_percpu_timer(void)
349 {
350 }
351
352 static void
353 smp_callin (void)
354 {
355 int cpuid, phys_id, itc_master;
356 struct cpuinfo_ia64 *last_cpuinfo, *this_cpuinfo;
357 extern void ia64_init_itm(void);
358 extern volatile int time_keeper_id;
359
360 #ifdef CONFIG_PERFMON
361 extern void pfm_init_percpu(void);
362 #endif
363
364 cpuid = smp_processor_id();
365 phys_id = hard_smp_processor_id();
366 itc_master = time_keeper_id;
367
368 if (cpu_online(cpuid)) {
369 printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
370 phys_id, cpuid);
371 BUG();
372 }
373
374 fix_b0_for_bsp();
375
376
377
378
379 set_numa_node(cpu_to_node_map[cpuid]);
380 set_numa_mem(local_memory_node(cpu_to_node_map[cpuid]));
381
382 spin_lock(&vector_lock);
383
384 __setup_vector_irq(cpuid);
385 notify_cpu_starting(cpuid);
386 set_cpu_online(cpuid, true);
387 per_cpu(cpu_state, cpuid) = CPU_ONLINE;
388 spin_unlock(&vector_lock);
389
390 smp_setup_percpu_timer();
391
392 ia64_mca_cmc_vector_setup();
393
394 #ifdef CONFIG_PERFMON
395 pfm_init_percpu();
396 #endif
397
398 local_irq_enable();
399
400 if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
401
402
403
404
405
406
407 Dprintk("Going to syncup ITC with ITC Master.\n");
408 ia64_sync_itc(itc_master);
409 }
410
411
412
413
414 ia64_init_itm();
415
416
417
418
419
420 last_cpuinfo = cpu_data(cpuid - 1);
421 this_cpuinfo = local_cpu_data;
422 if (last_cpuinfo->itc_freq != this_cpuinfo->itc_freq ||
423 last_cpuinfo->proc_freq != this_cpuinfo->proc_freq ||
424 last_cpuinfo->features != this_cpuinfo->features ||
425 last_cpuinfo->revision != this_cpuinfo->revision ||
426 last_cpuinfo->family != this_cpuinfo->family ||
427 last_cpuinfo->archrev != this_cpuinfo->archrev ||
428 last_cpuinfo->model != this_cpuinfo->model)
429 calibrate_delay();
430 local_cpu_data->loops_per_jiffy = loops_per_jiffy;
431
432
433
434
435 cpumask_set_cpu(cpuid, &cpu_callin_map);
436 Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
437 }
438
439
440
441
442
443 int
444 start_secondary (void *unused)
445 {
446
447 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
448 #ifndef CONFIG_PRINTK_TIME
449 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
450 #endif
451 efi_map_pal_code();
452 cpu_init();
453 preempt_disable();
454 smp_callin();
455
456 cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
457 return 0;
458 }
459
460 static int
461 do_boot_cpu (int sapicid, int cpu, struct task_struct *idle)
462 {
463 int timeout;
464
465 task_for_booting_cpu = idle;
466 Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
467
468 set_brendez_area(cpu);
469 ia64_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
470
471
472
473
474 Dprintk("Waiting on callin_map ...");
475 for (timeout = 0; timeout < 100000; timeout++) {
476 if (cpumask_test_cpu(cpu, &cpu_callin_map))
477 break;
478 barrier();
479 udelay(100);
480 }
481 Dprintk("\n");
482
483 if (!cpumask_test_cpu(cpu, &cpu_callin_map)) {
484 printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid);
485 ia64_cpu_to_sapicid[cpu] = -1;
486 set_cpu_online(cpu, false);
487 return -EINVAL;
488 }
489 return 0;
490 }
491
492 static int __init
493 decay (char *str)
494 {
495 int ticks;
496 get_option (&str, &ticks);
497 return 1;
498 }
499
500 __setup("decay=", decay);
501
502
503
504
505 void __init
506 smp_build_cpu_map (void)
507 {
508 int sapicid, cpu, i;
509 int boot_cpu_id = hard_smp_processor_id();
510
511 for (cpu = 0; cpu < NR_CPUS; cpu++) {
512 ia64_cpu_to_sapicid[cpu] = -1;
513 }
514
515 ia64_cpu_to_sapicid[0] = boot_cpu_id;
516 init_cpu_present(cpumask_of(0));
517 set_cpu_possible(0, true);
518 for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
519 sapicid = smp_boot_data.cpu_phys_id[i];
520 if (sapicid == boot_cpu_id)
521 continue;
522 set_cpu_present(cpu, true);
523 set_cpu_possible(cpu, true);
524 ia64_cpu_to_sapicid[cpu] = sapicid;
525 cpu++;
526 }
527 }
528
529
530
531
532 void __init
533 smp_prepare_cpus (unsigned int max_cpus)
534 {
535 int boot_cpu_id = hard_smp_processor_id();
536
537
538
539
540
541 smp_setup_percpu_timer();
542
543 cpumask_set_cpu(0, &cpu_callin_map);
544
545 local_cpu_data->loops_per_jiffy = loops_per_jiffy;
546 ia64_cpu_to_sapicid[0] = boot_cpu_id;
547
548 printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
549
550 current_thread_info()->cpu = 0;
551
552
553
554
555 if (!max_cpus) {
556 printk(KERN_INFO "SMP mode deactivated.\n");
557 init_cpu_online(cpumask_of(0));
558 init_cpu_present(cpumask_of(0));
559 init_cpu_possible(cpumask_of(0));
560 return;
561 }
562 }
563
564 void smp_prepare_boot_cpu(void)
565 {
566 set_cpu_online(smp_processor_id(), true);
567 cpumask_set_cpu(smp_processor_id(), &cpu_callin_map);
568 set_numa_node(cpu_to_node_map[smp_processor_id()]);
569 per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
570 }
571
572 #ifdef CONFIG_HOTPLUG_CPU
573 static inline void
574 clear_cpu_sibling_map(int cpu)
575 {
576 int i;
577
578 for_each_cpu(i, &per_cpu(cpu_sibling_map, cpu))
579 cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, i));
580 for_each_cpu(i, &cpu_core_map[cpu])
581 cpumask_clear_cpu(cpu, &cpu_core_map[i]);
582
583 per_cpu(cpu_sibling_map, cpu) = cpu_core_map[cpu] = CPU_MASK_NONE;
584 }
585
586 static void
587 remove_siblinginfo(int cpu)
588 {
589 int last = 0;
590
591 if (cpu_data(cpu)->threads_per_core == 1 &&
592 cpu_data(cpu)->cores_per_socket == 1) {
593 cpumask_clear_cpu(cpu, &cpu_core_map[cpu]);
594 cpumask_clear_cpu(cpu, &per_cpu(cpu_sibling_map, cpu));
595 return;
596 }
597
598 last = (cpumask_weight(&cpu_core_map[cpu]) == 1 ? 1 : 0);
599
600
601 clear_cpu_sibling_map(cpu);
602 }
603
604 extern void fixup_irqs(void);
605
606 int migrate_platform_irqs(unsigned int cpu)
607 {
608 int new_cpei_cpu;
609 struct irq_data *data = NULL;
610 const struct cpumask *mask;
611 int retval = 0;
612
613
614
615
616 if (cpe_vector > 0 && is_cpu_cpei_target(cpu)) {
617 printk ("CPU (%d) is CPEI Target\n", cpu);
618 if (can_cpei_retarget()) {
619
620
621
622 new_cpei_cpu = cpumask_any(cpu_online_mask);
623 mask = cpumask_of(new_cpei_cpu);
624 set_cpei_target_cpu(new_cpei_cpu);
625 data = irq_get_irq_data(ia64_cpe_irq);
626
627
628
629
630
631 if (data && data->chip) {
632 data->chip->irq_disable(data);
633 data->chip->irq_set_affinity(data, mask, false);
634 data->chip->irq_enable(data);
635 printk ("Re-targeting CPEI to cpu %d\n", new_cpei_cpu);
636 }
637 }
638 if (!data) {
639 printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
640 retval = -EBUSY;
641 }
642 }
643 return retval;
644 }
645
646
647 int __cpu_disable(void)
648 {
649 int cpu = smp_processor_id();
650
651
652
653
654 if (cpu == 0 && !bsp_remove_ok) {
655 printk ("Your platform does not support removal of BSP\n");
656 return (-EBUSY);
657 }
658
659 set_cpu_online(cpu, false);
660
661 if (migrate_platform_irqs(cpu)) {
662 set_cpu_online(cpu, true);
663 return -EBUSY;
664 }
665
666 remove_siblinginfo(cpu);
667 fixup_irqs();
668 local_flush_tlb_all();
669 cpumask_clear_cpu(cpu, &cpu_callin_map);
670 return 0;
671 }
672
673 void __cpu_die(unsigned int cpu)
674 {
675 unsigned int i;
676
677 for (i = 0; i < 100; i++) {
678
679 if (per_cpu(cpu_state, cpu) == CPU_DEAD)
680 {
681 printk ("CPU %d is now offline\n", cpu);
682 return;
683 }
684 msleep(100);
685 }
686 printk(KERN_ERR "CPU %u didn't die...\n", cpu);
687 }
688 #endif
689
690 void
691 smp_cpus_done (unsigned int dummy)
692 {
693 int cpu;
694 unsigned long bogosum = 0;
695
696
697
698
699
700 for_each_online_cpu(cpu) {
701 bogosum += cpu_data(cpu)->loops_per_jiffy;
702 }
703
704 printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
705 (int)num_online_cpus(), bogosum/(500000/HZ), (bogosum/(5000/HZ))%100);
706 }
707
708 static inline void set_cpu_sibling_map(int cpu)
709 {
710 int i;
711
712 for_each_online_cpu(i) {
713 if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
714 cpumask_set_cpu(i, &cpu_core_map[cpu]);
715 cpumask_set_cpu(cpu, &cpu_core_map[i]);
716 if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
717 cpumask_set_cpu(i,
718 &per_cpu(cpu_sibling_map, cpu));
719 cpumask_set_cpu(cpu,
720 &per_cpu(cpu_sibling_map, i));
721 }
722 }
723 }
724 }
725
726 int
727 __cpu_up(unsigned int cpu, struct task_struct *tidle)
728 {
729 int ret;
730 int sapicid;
731
732 sapicid = ia64_cpu_to_sapicid[cpu];
733 if (sapicid == -1)
734 return -EINVAL;
735
736
737
738
739
740 if (cpumask_test_cpu(cpu, &cpu_callin_map))
741 return -EINVAL;
742
743 per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
744
745 ret = do_boot_cpu(sapicid, cpu, tidle);
746 if (ret < 0)
747 return ret;
748
749 if (cpu_data(cpu)->threads_per_core == 1 &&
750 cpu_data(cpu)->cores_per_socket == 1) {
751 cpumask_set_cpu(cpu, &per_cpu(cpu_sibling_map, cpu));
752 cpumask_set_cpu(cpu, &cpu_core_map[cpu]);
753 return 0;
754 }
755
756 set_cpu_sibling_map(cpu);
757
758 return 0;
759 }
760
761
762
763
764
765
766
767 void __init
768 init_smp_config(void)
769 {
770 struct fptr {
771 unsigned long fp;
772 unsigned long gp;
773 } *ap_startup;
774 long sal_ret;
775
776
777 ap_startup = (struct fptr *) start_ap;
778 sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
779 ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0);
780 if (sal_ret < 0)
781 printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n",
782 ia64_sal_strerror(sal_ret));
783 }
784
785
786
787
788
789 void identify_siblings(struct cpuinfo_ia64 *c)
790 {
791 long status;
792 u16 pltid;
793 pal_logical_to_physical_t info;
794
795 status = ia64_pal_logical_to_phys(-1, &info);
796 if (status != PAL_STATUS_SUCCESS) {
797 if (status != PAL_STATUS_UNIMPLEMENTED) {
798 printk(KERN_ERR
799 "ia64_pal_logical_to_phys failed with %ld\n",
800 status);
801 return;
802 }
803
804 info.overview_ppid = 0;
805 info.overview_cpp = 1;
806 info.overview_tpc = 1;
807 }
808
809 status = ia64_sal_physical_id_info(&pltid);
810 if (status != PAL_STATUS_SUCCESS) {
811 if (status != PAL_STATUS_UNIMPLEMENTED)
812 printk(KERN_ERR
813 "ia64_sal_pltid failed with %ld\n",
814 status);
815 return;
816 }
817
818 c->socket_id = (pltid << 8) | info.overview_ppid;
819
820 if (info.overview_cpp == 1 && info.overview_tpc == 1)
821 return;
822
823 c->cores_per_socket = info.overview_cpp;
824 c->threads_per_core = info.overview_tpc;
825 c->num_log = info.overview_num_log;
826
827 c->core_id = info.log1_cid;
828 c->thread_id = info.log1_tid;
829 }
830
831
832
833
834
835
836
837 int is_multithreading_enabled(void)
838 {
839 int i, j;
840
841 for_each_present_cpu(i) {
842 for_each_present_cpu(j) {
843 if (j == i)
844 continue;
845 if ((cpu_data(j)->socket_id == cpu_data(i)->socket_id)) {
846 if (cpu_data(j)->core_id == cpu_data(i)->core_id)
847 return 1;
848 }
849 }
850 }
851 return 0;
852 }
853 EXPORT_SYMBOL_GPL(is_multithreading_enabled);