[SPARC64]: Pass multiple CPUs at once to hypervisor cross-call API.
[powerpc.git] / arch / sparc64 / kernel / smp.c
index f553264..356d423 100644 (file)
@@ -78,7 +78,7 @@ void smp_bogo(struct seq_file *m)
 
 void __init smp_store_cpu_info(int id)
 {
-       int cpu_node;
+       int cpu_node, def;
 
        /* multiplier and counter set by
           smp_setup_percpu_timer()  */
@@ -90,18 +90,32 @@ void __init smp_store_cpu_info(int id)
 
        cpu_data(id).idle_volume                = 1;
 
+       def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
        cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
-                                                     16 * 1024);
+                                                     def);
+
+       def = 32;
        cpu_data(id).dcache_line_size =
-               prom_getintdefault(cpu_node, "dcache-line-size", 32);
+               prom_getintdefault(cpu_node, "dcache-line-size", def);
+
+       def = 16 * 1024;
        cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
-                                                     16 * 1024);
+                                                     def);
+
+       def = 32;
        cpu_data(id).icache_line_size =
-               prom_getintdefault(cpu_node, "icache-line-size", 32);
+               prom_getintdefault(cpu_node, "icache-line-size", def);
+
+       def = ((tlb_type == hypervisor) ?
+              (3 * 1024 * 1024) :
+              (4 * 1024 * 1024));
        cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
-                                                     4 * 1024 * 1024);
+                                                     def);
+
+       def = 64;
        cpu_data(id).ecache_line_size =
-               prom_getintdefault(cpu_node, "ecache-line-size", 64);
+               prom_getintdefault(cpu_node, "ecache-line-size", def);
+
        printk("CPU[%d]: Caches "
               "D[sz(%d):line_sz(%d)] "
               "I[sz(%d):line_sz(%d)] "
@@ -123,7 +137,7 @@ void __init smp_callin(void)
        __local_per_cpu_offset = __per_cpu_offset(cpuid);
 
        if (tlb_type == hypervisor)
-               sun4v_register_fault_status();
+               sun4v_ktsb_register();
 
        __flush_tlb_all();
 
@@ -302,6 +316,8 @@ static void smp_synchronize_one_tick(int cpu)
        spin_unlock_irqrestore(&itc_sync_lock, flags);
 }
 
+extern void sun4v_init_mondo_queues(int use_bootmem, int cpu, int alloc, int load);
+
 extern unsigned long sparc64_cpu_startup;
 
 /* The OBP cpu startup callback truncates the 3rd arg cookie to
@@ -317,21 +333,31 @@ static int __devinit smp_boot_one_cpu(unsigned int cpu)
        unsigned long cookie =
                (unsigned long)(&cpu_new_thread);
        struct task_struct *p;
-       int timeout, ret, cpu_node;
+       int timeout, ret;
 
        p = fork_idle(cpu);
        callin_flag = 0;
        cpu_new_thread = task_thread_info(p);
        cpu_set(cpu, cpu_callout_map);
 
-       cpu_find_by_mid(cpu, &cpu_node);
-       prom_startcpu(cpu_node, entry, cookie);
+       if (tlb_type == hypervisor) {
+               /* Alloc the mondo queues, cpu will load them.  */
+               sun4v_init_mondo_queues(0, cpu, 1, 0);
+
+               prom_startcpu_cpuid(cpu, entry, cookie);
+       } else {
+               int cpu_node;
+
+               cpu_find_by_mid(cpu, &cpu_node);
+               prom_startcpu(cpu_node, entry, cookie);
+       }
 
        for (timeout = 0; timeout < 5000000; timeout++) {
                if (callin_flag)
                        break;
                udelay(100);
        }
+
        if (callin_flag) {
                ret = 0;
        } else {
@@ -531,7 +557,6 @@ retry:
        }
 }
 
-#if 0
 /* Multi-cpu list version.  */
 static int init_cpu_list(u16 *list, cpumask_t mask)
 {
@@ -589,7 +614,7 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t
                                       "2" (arg1), "3" (arg2),
                                       "i" (HV_FAST_TRAP)
                                     : "memory");
-               if (likely(func == HV_EOK))
+               if (likely(arg0 == HV_EOK))
                        break;
 
                if (unlikely(++retries > 100)) {
@@ -605,59 +630,6 @@ static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t
 
        put_cpu();
 }
-#else
-/* Single-cpu list version.  */
-static void hypervisor_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
-{
-       int this_cpu = get_cpu();
-       struct trap_per_cpu *tb = &trap_block[this_cpu];
-       u64 *mondo = __va(tb->cpu_mondo_block_pa);
-       u16 *cpu_list = __va(tb->cpu_list_pa);
-       int i;
-
-       mondo[0] = data0;
-       mondo[1] = data1;
-       mondo[2] = data2;
-       wmb();
-
-       for_each_cpu_mask(i, mask) {
-               int retries = 0;
-
-               do {
-                       register unsigned long func __asm__("%o5");
-                       register unsigned long arg0 __asm__("%o0");
-                       register unsigned long arg1 __asm__("%o1");
-                       register unsigned long arg2 __asm__("%o2");
-
-                       cpu_list[0] = i;
-                       func = HV_FAST_CPU_MONDO_SEND;
-                       arg0 = 1;
-                       arg1 = tb->cpu_list_pa;
-                       arg2 = tb->cpu_mondo_block_pa;
-
-                       __asm__ __volatile__("ta        %8"
-                                            : "=&r" (func), "=&r" (arg0),
-                                              "=&r" (arg1), "=&r" (arg2)
-                                            : "0" (func), "1" (arg0),
-                                              "2" (arg1), "3" (arg2),
-                                              "i" (HV_FAST_TRAP)
-                                            : "memory");
-                       if (likely(func == HV_EOK))
-                               break;
-
-                       if (unlikely(++retries > 100)) {
-                               printk("CPU[%d]: sun4v mondo error %lu\n",
-                                      this_cpu, func);
-                               break;
-                       }
-
-                       udelay(2 * i);
-               } while (1);
-       }
-
-       put_cpu();
-}
-#endif
 
 /* Send cross call to all processors mentioned in MASK
  * except self.
@@ -1276,7 +1248,11 @@ int __devinit __cpu_up(unsigned int cpu)
                if (!cpu_isset(cpu, cpu_online_map)) {
                        ret = -ENODEV;
                } else {
-                       smp_synchronize_one_tick(cpu);
+                       /* On SUN4V, writes to %tick and %stick are
+                        * not allowed.
+                        */
+                       if (tlb_type != hypervisor)
+                               smp_synchronize_one_tick(cpu);
                }
        }
        return ret;