aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/smp.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-02-08 19:41:20 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:12:02 -0500
commit1d2f1f90a1e004b0c1b8a73ed4394a93f09104b3 (patch)
tree2fcc0840b52218631020311d7b6d785e9a15db6a /arch/sparc64/kernel/smp.c
parent5b0c0572fcd6204675c5f7ddfa572b5017f817dd (diff)
[SPARC64]: Sun4v cross-call sending support.
Technically the hypervisor call supports sending in a list of all cpus to get the cross-call, but I only pass in one cpu at a time for now. The multi-cpu support is there, just ifdef'd out so it's easy to enable or delete it later. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/smp.c')
-rw-r--r--arch/sparc64/kernel/smp.c125
1 files changed, 124 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 223cc6bd369a..c10a3a8639e8 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -531,10 +531,133 @@ retry:
531 } 531 }
532} 532}
533 533
534#if 0
535/* Multi-cpu list version. */
536static int init_cpu_list(u16 *list, cpumask_t mask)
537{
538 int i, cnt;
539
540 cnt = 0;
541 for_each_cpu_mask(i, mask)
542 list[cnt++] = i;
543
544 return cnt;
545}
546
547static int update_cpu_list(u16 *list, int orig_cnt, cpumask_t mask)
548{
549 int i;
550
551 for (i = 0; i < orig_cnt; i++) {
552 if (list[i] == 0xffff)
553 cpu_clear(i, mask);
554 }
555
556 return init_cpu_list(list, mask);
557}
558
559static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
560{
561 int this_cpu = get_cpu();
562 struct trap_per_cpu *tb = &trap_block[this_cpu];
563 u64 *mondo = __va(tb->cpu_mondo_block_pa);
564 u16 *cpu_list = __va(tb->cpu_list_pa);
565 int cnt, retries;
566
567 mondo[0] = data0;
568 mondo[1] = data1;
569 mondo[2] = data2;
570 wmb();
571
572 retries = 0;
573 cnt = init_cpu_list(cpu_list, mask);
574 do {
575 register unsigned long func __asm__("%o0");
576 register unsigned long arg0 __asm__("%o1");
577 register unsigned long arg1 __asm__("%o2");
578 register unsigned long arg2 __asm__("%o3");
579
580 func = HV_FAST_CPU_MONDO_SEND;
581 arg0 = cnt;
582 arg1 = tb->cpu_list_pa;
583 arg2 = tb->cpu_mondo_block_pa;
584
585 __asm__ __volatile__("ta %8"
586 : "=&r" (func), "=&r" (arg0),
587 "=&r" (arg1), "=&r" (arg2)
588 : "0" (func), "1" (arg0),
589 "2" (arg1), "3" (arg2),
590 "i" (HV_FAST_TRAP)
591 : "memory");
592 if (likely(func == HV_EOK))
593 break;
594
595 if (unlikely(++retries > 100)) {
596 printk("CPU[%d]: sun4v mondo error %lu\n",
597 this_cpu, func);
598 break;
599 }
600
601 cnt = update_cpu_list(cpu_list, cnt, mask);
602
603 udelay(2 * cnt);
604 } while (1);
605
606 put_cpu();
607}
608#else
609/* Single-cpu list version. */
534static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) 610static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
535{ 611{
536 /* XXX implement me */ 612 int this_cpu = get_cpu();
613 struct trap_per_cpu *tb = &trap_block[this_cpu];
614 u64 *mondo = __va(tb->cpu_mondo_block_pa);
615 u16 *cpu_list = __va(tb->cpu_list_pa);
616 int i;
617
618 mondo[0] = data0;
619 mondo[1] = data1;
620 mondo[2] = data2;
621 wmb();
622
623 for_each_cpu_mask(i, mask) {
624 int retries = 0;
625
626 do {
627 register unsigned long func __asm__("%o0");
628 register unsigned long arg0 __asm__("%o1");
629 register unsigned long arg1 __asm__("%o2");
630 register unsigned long arg2 __asm__("%o3");
631
632 cpu_list[0] = i;
633 func = HV_FAST_CPU_MONDO_SEND;
634 arg0 = 1;
635 arg1 = tb->cpu_list_pa;
636 arg2 = tb->cpu_mondo_block_pa;
637
638 __asm__ __volatile__("ta %8"
639 : "=&r" (func), "=&r" (arg0),
640 "=&r" (arg1), "=&r" (arg2)
641 : "0" (func), "1" (arg0),
642 "2" (arg1), "3" (arg2),
643 "i" (HV_FAST_TRAP)
644 : "memory");
645 if (likely(func == HV_EOK))
646 break;
647
648 if (unlikely(++retries > 100)) {
649 printk("CPU[%d]: sun4v mondo error %lu\n",
650 this_cpu, func);
651 break;
652 }
653
654 udelay(2 * i);
655 } while (1);
656 }
657
658 put_cpu();
537} 659}
660#endif
538 661
539/* Send cross call to all processors mentioned in MASK 662/* Send cross call to all processors mentioned in MASK
540 * except self. 663 * except self.