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