[POWERPC] Make sure smp_processor_id works very early in boot
[safe/jmp/linux-2.6] / arch / powerpc / kernel / setup_64.c
index c4b7696..175539c 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/unistd.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/bootmem.h>
 #include <asm/io.h>
 #include <asm/kdump.h>
 #include <asm/prom.h>
 #define DBG(fmt...)
 #endif
 
-/*
- * Here are some early debugging facilities. You can enable one
- * but your kernel will not boot on anything else if you do so
- */
-
-/* This one is for use on LPAR machines that support an HVC console
- * on vterm 0
- */
-extern void udbg_init_debug_lpar(void);
-/* This one is for use on Apple G5 machines
- */
-extern void udbg_init_pmac_realmode(void);
-/* That's RTAS panel debug */
-extern void call_rtas_display_status_delay(unsigned char c);
-/* Here's maple real mode debug */
-extern void udbg_init_maple_realmode(void);
-
-#define EARLY_DEBUG_INIT() do {} while(0)
-
-#if 0
-#define EARLY_DEBUG_INIT() udbg_init_debug_lpar()
-#define EARLY_DEBUG_INIT() udbg_init_maple_realmode()
-#define EARLY_DEBUG_INIT() udbg_init_pmac_realmode()
-#define EARLY_DEBUG_INIT()                                             \
-       do { udbg_putc = call_rtas_display_status_delay; } while(0)
-#endif
-
 int have_of = 1;
 int boot_cpuid = 0;
-int boot_cpuid_phys = 0;
 dev_t boot_dev;
 u64 ppc64_pft_size;
 
@@ -122,22 +95,11 @@ int dcache_bsize;
 int icache_bsize;
 int ucache_bsize;
 
-/* The main machine-dep calls structure
- */
-struct machdep_calls ppc_md;
-EXPORT_SYMBOL(ppc_md);
-
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
 #endif /* CONFIG_MAGIC_SYSRQ */
 
 
-static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-static struct notifier_block ppc64_panic_block = {
-       .notifier_call = ppc64_panic_event,
-       .priority = INT_MIN /* may not return; must be done last */
-};
-
 #ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
@@ -187,31 +149,12 @@ early_param("smt-enabled", early_smt_enabled);
 #define check_smt_enabled()
 #endif /* CONFIG_SMP */
 
-extern struct machdep_calls pSeries_md;
-extern struct machdep_calls pmac_md;
-extern struct machdep_calls maple_md;
-extern struct machdep_calls cell_md;
-extern struct machdep_calls iseries_md;
-
-/* Ultimately, stuff them in an elf section like initcalls... */
-static struct machdep_calls __initdata *machines[] = {
-#ifdef CONFIG_PPC_PSERIES
-       &pSeries_md,
-#endif /* CONFIG_PPC_PSERIES */
-#ifdef CONFIG_PPC_PMAC
-       &pmac_md,
-#endif /* CONFIG_PPC_PMAC */
-#ifdef CONFIG_PPC_MAPLE
-       &maple_md,
-#endif /* CONFIG_PPC_MAPLE */
-#ifdef CONFIG_PPC_CELL
-       &cell_md,
-#endif
-#ifdef CONFIG_PPC_ISERIES
-       &iseries_md,
-#endif
-       NULL
-};
+/* Put the paca pointer into r13 and SPRG3 */
+void __init setup_paca(int cpu)
+{
+       local_paca = &paca[cpu];
+       mtspr(SPRN_SPRG3, local_paca);
+}
 
 /*
  * Early initialization entry point. This is called by head.S
@@ -234,16 +177,13 @@ static struct machdep_calls __initdata *machines[] = {
 
 void __init early_setup(unsigned long dt_ptr)
 {
-       struct paca_struct *lpaca = get_paca();
-       static struct machdep_calls **mach;
+       /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
+       setup_paca(0);
 
-       /*
-        * Enable early debugging if any specified (see top of
-        * this file)
-        */
-       EARLY_DEBUG_INIT();
+       /* Enable early debugging if any specified (see udbg.h) */
+       udbg_early_init();
 
-       DBG(" -> early_setup()\n");
+       DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr);
 
        /*
         * Do early initializations using the flattened device
@@ -252,26 +192,18 @@ void __init early_setup(unsigned long dt_ptr)
         */
        early_init_devtree(__va(dt_ptr));
 
-       /*
-        * Iterate all ppc_md structures until we find the proper
-        * one for the current machine type
-        */
-       DBG("Probing machine type for platform %x...\n", _machine);
+       /* Now we know the logical id of our boot cpu, setup the paca. */
+       setup_paca(boot_cpuid);
 
-       for (mach = machines; *mach; mach++) {
-               if ((*mach)->probe(_machine))
-                       break;
-       }
-       /* What can we do if we didn't find ? */
-       if (*mach == NULL) {
-               DBG("No suitable machine found !\n");
-               for (;;);
-       }
-       ppc_md = **mach;
+       /* Fix up paca fields required for the boot cpu */
+       get_paca()->cpu_start = 1;
+       get_paca()->stab_real = __pa((u64)&initial_stab);
+       get_paca()->stab_addr = (u64)&initial_stab;
 
-#ifdef CONFIG_CRASH_DUMP
-       kdump_setup();
-#endif
+       /* Probe the machine type */
+       probe_machine();
+
+       setup_kdump_trampoline();
 
        DBG("Found, Initializing memory management...\n");
 
@@ -285,12 +217,10 @@ void __init early_setup(unsigned long dt_ptr)
        /*
         * Initialize stab / SLB management except on iSeries
         */
-       if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
-               if (cpu_has_feature(CPU_FTR_SLB))
-                       slb_initialize();
-               else
-                       stab_initialize(lpaca->stab_real);
-       }
+       if (cpu_has_feature(CPU_FTR_SLB))
+               slb_initialize();
+       else if (!firmware_has_feature(FW_FEATURE_ISERIES))
+               stab_initialize(get_paca()->stab_real);
 
        DBG(" <- early_setup()\n");
 }
@@ -340,8 +270,6 @@ void smp_release_cpus(void)
 
        DBG(" <- smp_release_cpus()\n");
 }
-#else
-#define smp_release_cpus()
 #endif /* CONFIG_SMP || CONFIG_KEXEC */
 
 /*
@@ -371,7 +299,7 @@ static void __init initialize_cache_info(void)
                        const char *dc, *ic;
 
                        /* Then read cache informations */
-                       if (_machine == PLATFORM_POWERMAC) {
+                       if (machine_is(powermac)) {
                                dc = "d-cache-block-size";
                                ic = "i-cache-block-size";
                        } else {
@@ -432,19 +360,11 @@ void __init setup_system(void)
         */
        unflatten_device_tree();
 
-#ifdef CONFIG_KEXEC
-       kexec_setup();  /* requires unflattened device tree. */
-#endif
-
        /*
         * Fill the ppc64_caches & systemcfg structures with informations
         * retrieved from the device-tree. Need to be called before
         * finish_device_tree() since the later requires some of the
-        * informations filled up here to properly parse the interrupt
-        * tree.
-        * It also sets up the cache line sizes which allows to call
-        * routines like flush_icache_range (used by the hash init
-        * later on).
+        * informations filled up here to properly parse the interrupt tree.
         */
        initialize_cache_info();
 
@@ -491,18 +411,18 @@ void __init setup_system(void)
         */
        register_early_udbg_console();
 
-       /* Save unparsed command line copy for /proc/cmdline */
-       strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-       parse_early_param();
+       if (do_early_xmon)
+               debugger(NULL);
 
        check_smt_enabled();
        smp_setup_cpu_maps();
 
+#ifdef CONFIG_SMP
        /* Release secondary cpus out of their spinloops at 0x60 now that
         * we can map physical -> logical CPU ids
         */
        smp_release_cpus();
+#endif
 
        printk("Starting Linux PPC64 %s\n", system_utsname.version);
 
@@ -510,7 +430,6 @@ void __init setup_system(void)
        printk("ppc64_pft_size                = 0x%lx\n", ppc64_pft_size);
        printk("ppc64_interrupt_controller    = 0x%ld\n",
               ppc64_interrupt_controller);
-       printk("platform                      = 0x%x\n", _machine);
        printk("physicalMemorySize            = 0x%lx\n", lmb_phys_mem_size());
        printk("ppc64_caches.dcache_line_size = 0x%x\n",
               ppc64_caches.dline_size);
@@ -523,18 +442,9 @@ void __init setup_system(void)
 #endif
        printk("-----------------------------------------------------\n");
 
-       mm_init_ppc64();
-
        DBG(" <- setup_system()\n");
 }
 
-static int ppc64_panic_event(struct notifier_block *this,
-                             unsigned long event, void *ptr)
-{
-       ppc_md.panic((char *)ptr);  /* May not return */
-       return NOTIFY_DONE;
-}
-
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
@@ -544,7 +454,7 @@ static void __init irqstack_early_init(void)
         * interrupt stacks must be under 256MB, we cannot afford to take
         * SLB misses on them.
         */
-       for_each_cpu(i) {
+       for_each_possible_cpu(i) {
                softirq_ctx[i] = (struct thread_info *)
                        __va(lmb_alloc_base(THREAD_SIZE,
                                            THREAD_SIZE, 0x10000000));
@@ -577,7 +487,7 @@ static void __init emergency_stack_init(void)
         */
        limit = min(0x10000000UL, lmb.rmo_size);
 
-       for_each_cpu(i)
+       for_each_possible_cpu(i)
                paca[i].emergency_sp =
                __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE;
 }
@@ -589,8 +499,6 @@ static void __init emergency_stack_init(void)
  */
 void __init setup_arch(char **cmdline_p)
 {
-       extern void do_init_bootmem(void);
-
        ppc64_boot_msg(0x12, "Setup Arch");
 
        *cmdline_p = cmd_line;
@@ -607,7 +515,7 @@ void __init setup_arch(char **cmdline_p)
        panic_timeout = 180;
 
        if (ppc_md.panic)
-               notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);
+               setup_panic();
 
        init_mm.start_code = PAGE_OFFSET;
        init_mm.end_code = (unsigned long) _etext;
@@ -629,12 +537,6 @@ void __init setup_arch(char **cmdline_p)
 
        ppc_md.setup_arch();
 
-       /* Use the default idle loop if the platform hasn't provided one. */
-       if (NULL == ppc_md.idle_loop) {
-               ppc_md.idle_loop = default_idle;
-               printk(KERN_INFO "Using default idle loop\n");
-       }
-
        paging_init();
        ppc64_boot_msg(0x15, "Setup Done");
 }
@@ -671,16 +573,33 @@ void ppc64_terminate_msg(unsigned int src, const char *msg)
        printk("[terminate]%04x %s\n", src, msg);
 }
 
-int check_legacy_ioport(unsigned long base_port)
-{
-       if (ppc_md.check_legacy_ioport == NULL)
-               return 0;
-       return ppc_md.check_legacy_ioport(base_port);
-}
-EXPORT_SYMBOL(check_legacy_ioport);
-
 void cpu_die(void)
 {
        if (ppc_md.cpu_die)
                ppc_md.cpu_die();
 }
+
+#ifdef CONFIG_SMP
+void __init setup_per_cpu_areas(void)
+{
+       int i;
+       unsigned long size;
+       char *ptr;
+
+       /* Copy section for each CPU (we discard the original) */
+       size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
+#ifdef CONFIG_MODULES
+       if (size < PERCPU_ENOUGH_ROOM)
+               size = PERCPU_ENOUGH_ROOM;
+#endif
+
+       for_each_possible_cpu(i) {
+               ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size);
+               if (!ptr)
+                       panic("Cannot allocate cpu data for CPU %d\n", i);
+
+               paca[i].data_offset = ptr - __per_cpu_start;
+               memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+       }
+}
+#endif