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