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/processor.h>
53#include <asm/ptrace.h>
54#include <asm/sal.h>
55#include <asm/tlbflush.h>
56#include <asm/unistd.h>
57
58#define SMP_DEBUG 0
59
60#if SMP_DEBUG
61#define Dprintk(x...) printk(x)
62#else
63#define Dprintk(x...)
64#endif
65
66#ifdef CONFIG_HOTPLUG_CPU
67#ifdef CONFIG_PERMIT_BSP_REMOVE
68#define bsp_remove_ok 1
69#else
70#define bsp_remove_ok 0
71#endif
72
73
74
75
76struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
77
78
79
80
81
82struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
83
84#define set_brendez_area(x) (sal_state_for_booting_cpu = &sal_boot_rendez_state[(x)]);
85
86#else
87#define set_brendez_area(x)
88#endif
89
90
91
92
93
94#define MASTER (0)
95#define SLAVE (SMP_CACHE_BYTES/8)
96
97#define NUM_ROUNDS 64
98#define NUM_ITERS 5
99
100static DEFINE_SPINLOCK(itc_sync_lock);
101static volatile unsigned long go[SLAVE + 1];
102
103#define DEBUG_ITC_SYNC 0
104
105extern void start_ap (void);
106extern unsigned long ia64_iobase;
107
108struct task_struct *task_for_booting_cpu;
109
110
111
112
113DEFINE_PER_CPU(int, cpu_state);
114
115cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
116EXPORT_SYMBOL(cpu_core_map);
117DEFINE_PER_CPU_SHARED_ALIGNED(cpumask_t, cpu_sibling_map);
118EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
119
120int smp_num_siblings = 1;
121
122
123volatile int ia64_cpu_to_sapicid[NR_CPUS];
124EXPORT_SYMBOL(ia64_cpu_to_sapicid);
125
126static cpumask_t cpu_callin_map;
127
128struct smp_boot_data smp_boot_data __initdata;
129
130unsigned long ap_wakeup_vector = -1;
131
132char __initdata no_int_routing;
133
134unsigned char smp_int_redirect;
135
136#ifdef CONFIG_FORCE_CPEI_RETARGET
137#define CPEI_OVERRIDE_DEFAULT (1)
138#else
139#define CPEI_OVERRIDE_DEFAULT (0)
140#endif
141
142unsigned int force_cpei_retarget = CPEI_OVERRIDE_DEFAULT;
143
144static int __init
145cmdl_force_cpei(char *str)
146{
147 int value=0;
148
149 get_option (&str, &value);
150 force_cpei_retarget = value;
151
152 return 1;
153}
154
155__setup("force_cpei=", cmdl_force_cpei);
156
157static int __init
158nointroute (char *str)
159{
160 no_int_routing = 1;
161 printk ("no_int_routing on\n");
162 return 1;
163}
164
165__setup("nointroute", nointroute);
166
167static void fix_b0_for_bsp(void)
168{
169#ifdef CONFIG_HOTPLUG_CPU
170 int cpuid;
171 static int fix_bsp_b0 = 1;
172
173 cpuid = smp_processor_id();
174
175
176
177
178 if (!(fix_bsp_b0 && cpuid))
179 return;
180
181 sal_boot_rendez_state[0].br[0] = sal_boot_rendez_state[cpuid].br[0];
182 printk ("Fixed BSP b0 value from CPU %d\n", cpuid);
183
184 fix_bsp_b0 = 0;
185#endif
186}
187
188void
189sync_master (void *arg)
190{
191 unsigned long flags, i;
192
193 go[MASTER] = 0;
194
195 local_irq_save(flags);
196 {
197 for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
198 while (!go[MASTER])
199 cpu_relax();
200 go[MASTER] = 0;
201 go[SLAVE] = ia64_get_itc();
202 }
203 }
204 local_irq_restore(flags);
205}
206
207
208
209
210
211
212static inline long
213get_delta (long *rt, long *master)
214{
215 unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
216 unsigned long tcenter, t0, t1, tm;
217 long i;
218
219 for (i = 0; i < NUM_ITERS; ++i) {
220 t0 = ia64_get_itc();
221 go[MASTER] = 1;
222 while (!(tm = go[SLAVE]))
223 cpu_relax();
224 go[SLAVE] = 0;
225 t1 = ia64_get_itc();
226
227 if (t1 - t0 < best_t1 - best_t0)
228 best_t0 = t0, best_t1 = t1, best_tm = tm;
229 }
230
231 *rt = best_t1 - best_t0;
232 *master = best_tm - best_t0;
233
234
235 tcenter = (best_t0/2 + best_t1/2);
236 if (best_t0 % 2 + best_t1 % 2 == 2)
237 ++tcenter;
238 return tcenter - best_tm;
239}
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
273void
274ia64_sync_itc (unsigned int master)
275{
276 long i, delta, adj, adjust_latency = 0, done = 0;
277 unsigned long flags, rt, master_time_stamp, bound;
278#if DEBUG_ITC_SYNC
279 struct {
280 long rt;
281 long master;
282 long diff;
283 long lat;
284 } t[NUM_ROUNDS];
285#endif
286
287
288
289
290
291
292
293 BUG_ON((ia64_get_itv() & (1 << 16)) == 0);
294
295 go[MASTER] = 1;
296
297 if (smp_call_function_single(master, sync_master, NULL, 0) < 0) {
298 printk(KERN_ERR "sync_itc: failed to get attention of CPU %u!\n", master);
299 return;
300 }
301
302 while (go[MASTER])
303 cpu_relax();
304
305 spin_lock_irqsave(&itc_sync_lock, flags);
306 {
307 for (i = 0; i < NUM_ROUNDS; ++i) {
308 delta = get_delta(&rt, &master_time_stamp);
309 if (delta == 0) {
310 done = 1;
311 bound = rt;
312 }
313
314 if (!done) {
315 if (i > 0) {
316 adjust_latency += -delta;
317 adj = -delta + adjust_latency/4;
318 } else
319 adj = -delta;
320
321 ia64_set_itc(ia64_get_itc() + adj);
322 }
323#if DEBUG_ITC_SYNC
324 t[i].rt = rt;
325 t[i].master = master_time_stamp;
326 t[i].diff = delta;
327 t[i].lat = adjust_latency/4;
328#endif
329 }
330 }
331 spin_unlock_irqrestore(&itc_sync_lock, flags);
332
333#if DEBUG_ITC_SYNC
334 for (i = 0; i < NUM_ROUNDS; ++i)
335 printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
336 t[i].rt, t[i].master, t[i].diff, t[i].lat);
337#endif
338
339 printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, "
340 "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
341}
342
343
344
345
346static inline void smp_setup_percpu_timer(void)
347{
348}
349
350static void
351smp_callin (void)
352{
353 int cpuid, phys_id, itc_master;
354 struct cpuinfo_ia64 *last_cpuinfo, *this_cpuinfo;
355 extern void ia64_init_itm(void);
356 extern volatile int time_keeper_id;
357
358 cpuid = smp_processor_id();
359 phys_id = hard_smp_processor_id();
360 itc_master = time_keeper_id;
361
362 if (cpu_online(cpuid)) {
363 printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already present??\n",
364 phys_id, cpuid);
365 BUG();
366 }
367
368 fix_b0_for_bsp();
369
370
371
372
373 set_numa_node(cpu_to_node_map[cpuid]);
374 set_numa_mem(local_memory_node(cpu_to_node_map[cpuid]));
375
376 spin_lock(&vector_lock);
377
378 __setup_vector_irq(cpuid);
379 notify_cpu_starting(cpuid);
380 set_cpu_online(cpuid, true);
381 per_cpu(cpu_state, cpuid) = CPU_ONLINE;
382 spin_unlock(&vector_lock);
383
384 smp_setup_percpu_timer();
385
386 ia64_mca_cmc_vector_setup();
387
388 local_irq_enable();
389
390 if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
391
392
393
394
395
396
397 Dprintk("Going to syncup ITC with ITC Master.\n");
398 ia64_sync_itc(itc_master);
399 }
400
401
402
403
404 ia64_init_itm();
405
406
407
408
409
410 last_cpuinfo = cpu_data(cpuid - 1);
411 this_cpuinfo = local_cpu_data;
412 if (last_cpuinfo->itc_freq != this_cpuinfo->itc_freq ||
413 last_cpuinfo->proc_freq != this_cpuinfo->proc_freq ||
414 last_cpuinfo->features != this_cpuinfo->features ||
415 last_cpuinfo->revision != this_cpuinfo->revision ||
416 last_cpuinfo->family != this_cpuinfo->family ||
417 last_cpuinfo->archrev != this_cpuinfo->archrev ||
418 last_cpuinfo->model != this_cpuinfo->model)
419 calibrate_delay();
420 local_cpu_data->loops_per_jiffy = loops_per_jiffy;
421
422
423
424
425 cpumask_set_cpu(cpuid, &cpu_callin_map);
426 Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
427}
428
429
430
431
432
433int
434start_secondary (void *unused)
435{
436
437 ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
438#ifndef CONFIG_PRINTK_TIME
439 Dprintk("start_secondary: starting CPU 0x%x\n", hard_smp_processor_id());
440#endif
441 efi_map_pal_code();
442 cpu_init();
443 preempt_disable();
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