[SPARC64]: Detect sun4v early in boot process.
[cascardo/linux.git] / arch / sparc64 / kernel / setup.c
index aaab319..7f02c8f 100644 (file)
@@ -189,26 +189,30 @@ int prom_callback(long *args)
                }
 
                if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) {
-                       extern unsigned long sparc64_kern_pri_context;
-
-                       /* Spitfire Errata #32 workaround */
-                       __asm__ __volatile__("stxa      %0, [%1] %2\n\t"
-                                            "flush     %%g6"
-                                            : /* No outputs */
-                                            : "r" (sparc64_kern_pri_context),
-                                              "r" (PRIMARY_CONTEXT),
-                                              "i" (ASI_DMMU));
+                       if (tlb_type == spitfire) {
+                               extern unsigned long sparc64_kern_pri_context;
+
+                               /* Spitfire Errata #32 workaround */
+                               __asm__ __volatile__(
+                                       "stxa   %0, [%1] %2\n\t"
+                                       "flush  %%g6"
+                                       : /* No outputs */
+                                       : "r" (sparc64_kern_pri_context),
+                                         "r" (PRIMARY_CONTEXT),
+                                         "i" (ASI_DMMU));
+                       }
 
                        /*
                         * Locked down tlb entry.
                         */
 
-                       if (tlb_type == spitfire)
+                       if (tlb_type == spitfire) {
                                tte = spitfire_get_dtlb_data(SPITFIRE_HIGHEST_LOCKED_TLBENT);
-                       else if (tlb_type == cheetah || tlb_type == cheetah_plus)
+                               res = PROM_TRUE;
+                       } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
                                tte = cheetah_get_ldtlb_data(CHEETAH_HIGHEST_LOCKED_TLBENT);
-
-                       res = PROM_TRUE;
+                               res = PROM_TRUE;
+                       }
                        goto done;
                }
 
@@ -500,9 +504,12 @@ static void __init per_cpu_patch(void)
        if (tlb_type == spitfire && !this_is_starfire)
                return;
 
-       __asm__ ("rdpr %%ver, %0" : "=r" (ver));
-       is_jbus = ((ver >> 32) == __JALAPENO_ID ||
-                  (ver >> 32) == __SERRANO_ID);
+       is_jbus = 0;
+       if (tlb_type != hypervisor) {
+               __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+               is_jbus = ((ver >> 32) == __JALAPENO_ID ||
+                          (ver >> 32) == __SERRANO_ID);
+       }
 
        p = &__cpuid_patch;
        while (p < &__cpuid_patch_end) {
@@ -529,15 +536,19 @@ static void __init per_cpu_patch(void)
                };
 
                *(unsigned int *) (addr +  0) = insns[0];
+               wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
                *(unsigned int *) (addr +  4) = insns[1];
+               wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
 
                *(unsigned int *) (addr +  8) = insns[2];
+               wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  8));
 
                *(unsigned int *) (addr + 12) = insns[3];
+               wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr + 12));
 
                p++;
@@ -545,21 +556,38 @@ static void __init per_cpu_patch(void)
 #endif
 }
 
-static void __init gl_patch(void)
+static void __init sun4v_patch(void)
 {
-       struct gl_1insn_patch_entry *p;
+       struct sun4v_1insn_patch_entry *p1;
+       struct sun4v_2insn_patch_entry *p2;
 
        if (tlb_type != hypervisor)
                return;
 
-       p = &__gl_1insn_patch;
-       while (p < &__gl_1insn_patch_end) {
-               unsigned long addr = p->addr;
+       p1 = &__sun4v_1insn_patch;
+       while (p1 < &__sun4v_1insn_patch_end) {
+               unsigned long addr = p1->addr;
 
-               *(unsigned int *) (addr +  0) = p->insn;
+               *(unsigned int *) (addr +  0) = p1->insn;
+               wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
-               p++;
+               p1++;
+       }
+
+       p2 = &__sun4v_2insn_patch;
+       while (p2 < &__sun4v_2insn_patch_end) {
+               unsigned long addr = p2->addr;
+
+               *(unsigned int *) (addr +  0) = p2->insns[0];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+
+               *(unsigned int *) (addr +  3) = p2->insns[1];
+               wmb();
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
+
+               p2++;
        }
 }
 
@@ -585,7 +613,7 @@ void __init setup_arch(char **cmdline_p)
         */
        per_cpu_patch();
 
-       gl_patch();
+       sun4v_patch();
 
        boot_flags_init(*cmdline_p);