[SPARC64]: Add initial code to twiddle %gl on trap entry/exit.
[powerpc.git] / arch / sparc64 / kernel / setup.c
index bf1849d..aaab319 100644 (file)
@@ -490,6 +490,79 @@ void register_prom_callbacks(void)
                   "' linux-.soft2 to .soft2");
 }
 
+static void __init per_cpu_patch(void)
+{
+#ifdef CONFIG_SMP
+       struct cpuid_patch_entry *p;
+       unsigned long ver;
+       int is_jbus;
+
+       if (tlb_type == spitfire && !this_is_starfire)
+               return;
+
+       __asm__ ("rdpr %%ver, %0" : "=r" (ver));
+       is_jbus = ((ver >> 32) == __JALAPENO_ID ||
+                  (ver >> 32) == __SERRANO_ID);
+
+       p = &__cpuid_patch;
+       while (p < &__cpuid_patch_end) {
+               unsigned long addr = p->addr;
+               unsigned int *insns;
+
+               switch (tlb_type) {
+               case spitfire:
+                       insns = &p->starfire[0];
+                       break;
+               case cheetah:
+               case cheetah_plus:
+                       if (is_jbus)
+                               insns = &p->cheetah_jbus[0];
+                       else
+                               insns = &p->cheetah_safari[0];
+                       break;
+               case hypervisor:
+                       insns = &p->sun4v[0];
+                       break;
+               default:
+                       prom_printf("Unknown cpu type, halting.\n");
+                       prom_halt();
+               };
+
+               *(unsigned int *) (addr +  0) = insns[0];
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+
+               *(unsigned int *) (addr +  4) = insns[1];
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
+
+               *(unsigned int *) (addr +  8) = insns[2];
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  8));
+
+               *(unsigned int *) (addr + 12) = insns[3];
+               __asm__ __volatile__("flush     %0" : : "r" (addr + 12));
+
+               p++;
+       }
+#endif
+}
+
+static void __init gl_patch(void)
+{
+       struct gl_1insn_patch_entry *p;
+
+       if (tlb_type != hypervisor)
+               return;
+
+       p = &__gl_1insn_patch;
+       while (p < &__gl_1insn_patch_end) {
+               unsigned long addr = p->addr;
+
+               *(unsigned int *) (addr +  0) = p->insn;
+               __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
+
+               p++;
+       }
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        /* Initialize PROM console and command line. */
@@ -507,6 +580,13 @@ void __init setup_arch(char **cmdline_p)
        /* Work out if we are starfire early on */
        check_if_starfire();
 
+       /* Now we know enough to patch the get_cpuid sequences
+        * used by trap code.
+        */
+       per_cpu_patch();
+
+       gl_patch();
+
        boot_flags_init(*cmdline_p);
 
        idprom_init();
@@ -520,7 +600,7 @@ void __init setup_arch(char **cmdline_p)
        rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);     
 #endif
 
-       init_task.thread_info->kregs = &fake_swapper_regs;
+       task_thread_info(&init_task)->kregs = &fake_swapper_regs;
 
 #ifdef CONFIG_IP_PNP
        if (!ic_set_manually) {
@@ -542,7 +622,12 @@ void __init setup_arch(char **cmdline_p)
        }
 #endif
 
+       smp_setup_cpu_possible_map();
+
        paging_init();
+
+       /* Get boot processor trap_block[] setup.  */
+       init_cur_cpu_trap();
 }
 
 static int __init set_preferred_console(void)
@@ -561,6 +646,8 @@ static int __init set_preferred_console(void)
                serial_console = 1;
        } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
                serial_console = 2;
+       } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) {
+               serial_console = 3;
        } else {
                prom_printf("Inconsistent console: "
                            "input %d, output %d\n",
@@ -587,6 +674,8 @@ extern void mmu_info(struct seq_file *);
 unsigned int dcache_parity_tl1_occurred;
 unsigned int icache_parity_tl1_occurred;
 
+static int ncpus_probed;
+
 static int show_cpuinfo(struct seq_file *m, void *__unused)
 {
        seq_printf(m, 
@@ -595,8 +684,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   "promlib\t\t: Version 3 Revision %d\n"
                   "prom\t\t: %d.%d.%d\n"
                   "type\t\t: sun4u\n"
-                  "ncpus probed\t: %ld\n"
-                  "ncpus active\t: %ld\n"
+                  "ncpus probed\t: %d\n"
+                  "ncpus active\t: %d\n"
                   "D$ parity tl1\t: %u\n"
                   "I$ parity tl1\t: %u\n"
 #ifndef CONFIG_SMP
@@ -610,8 +699,8 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
                   prom_prev >> 16,
                   (prom_prev >> 8) & 0xff,
                   prom_prev & 0xff,
-                  (long)num_possible_cpus(),
-                  (long)num_online_cpus(),
+                  ncpus_probed,
+                  num_online_cpus(),
                   dcache_parity_tl1_occurred,
                   icache_parity_tl1_occurred
 #ifndef CONFIG_SMP
@@ -677,6 +766,15 @@ static int __init topology_init(void)
        int i, err;
 
        err = -ENOMEM;
+
+       /* Count the number of physically present processors in
+        * the machine, even on uniprocessor, so that /proc/cpuinfo
+        * output is consistent with 2.4.x
+        */
+       ncpus_probed = 0;
+       while (!cpu_find_by_instance(ncpus_probed, NULL, NULL))
+               ncpus_probed++;
+
        for (i = 0; i < NR_CPUS; i++) {
                if (cpu_possible(i)) {
                        struct cpu *p = kmalloc(sizeof(*p), GFP_KERNEL);