vserver 1.9.3
[linux-2.6.git] / arch / i386 / kernel / smpboot.c
index 1a9b081..016a070 100644 (file)
@@ -17,7 +17,7 @@
  *     Fixes
  *             Felix Koop      :       NR_CPUS used properly
  *             Jose Renau      :       Handle single CPU case.
- *             Alan Cox        :       By repeated request 8) - Total BogoMIP report.
+ *             Alan Cox        :       By repeated request 8) - Total BogoMIPS report.
  *             Greg Wright     :       Fix for kernel stacks panic.
  *             Erich Boleyn    :       MP v1.4 and additional changes.
  *     Matthias Sattler        :       Changes for 2.1 kernel map.
@@ -72,6 +72,10 @@ static cpumask_t smp_commenced_mask;
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
 
+u8 x86_cpu_to_apicid[NR_CPUS] =
+                       { [0 ... NR_CPUS-1] = 0xff };
+EXPORT_SYMBOL(x86_cpu_to_apicid);
+
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
@@ -187,34 +191,6 @@ static unsigned long long tsc_values[NR_CPUS];
 
 #define NR_LOOPS 5
 
-/*
- * accurate 64-bit/32-bit division, expanded to 32-bit divisions and 64-bit
- * multiplication. Not terribly optimized but we need it at boot time only
- * anyway.
- *
- * result == a / b
- *     == (a1 + a2*(2^32)) / b
- *     == a1/b + a2*(2^32/b)
- *     == a1/b + a2*((2^32-1)/b) + a2/b + (a2*((2^32-1) % b))/b
- *                 ^---- (this multiplication can overflow)
- */
-
-static unsigned long long __init div64 (unsigned long long a, unsigned long b0)
-{
-       unsigned int a1, a2;
-       unsigned long long res;
-
-       a1 = ((unsigned int*)&a)[0];
-       a2 = ((unsigned int*)&a)[1];
-
-       res = a1/b0 +
-               (unsigned long long)a2 * (unsigned long long)(0xffffffff/b0) +
-               a2 / b0 +
-               (a2 * (0xffffffff % b0)) / b0;
-
-       return res;
-}
-
 static void __init synchronize_tsc_bp (void)
 {
        int i;
@@ -224,7 +200,7 @@ static void __init synchronize_tsc_bp (void)
        unsigned long one_usec;
        int buggy = 0;
 
-       printk("checking TSC synchronization across %u CPUs: ", num_booting_cpus());
+       printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
 
        /* convert from kcyc/sec to cyc/usec */
        one_usec = cpu_khz / 1000;
@@ -279,7 +255,8 @@ static void __init synchronize_tsc_bp (void)
                        sum += t0;
                }
        }
-       avg = div64(sum, num_booting_cpus());
+       avg = sum;
+       do_div(avg, num_booting_cpus());
 
        sum = 0;
        for (i = 0; i < NR_CPUS; i++) {
@@ -297,18 +274,18 @@ static void __init synchronize_tsc_bp (void)
                                buggy = 1;
                                printk("\n");
                        }
-                       realdelta = div64(delta, one_usec);
+                       realdelta = delta;
+                       do_div(realdelta, one_usec);
                        if (tsc_values[i] < avg)
                                realdelta = -realdelta;
 
-                       printk("BIOS BUG: CPU#%d improperly initialized, has %ld usecs TSC skew! FIXED.\n", i, realdelta);
+                       printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
                }
 
                sum += delta;
        }
        if (!buggy)
                printk("passed.\n");
-               ;
 }
 
 static void __init synchronize_tsc_ap (void)
@@ -492,16 +469,6 @@ extern struct {
        unsigned short ss;
 } stack_start;
 
-static struct task_struct * __init fork_by_hand(void)
-{
-       struct pt_regs regs;
-       /*
-        * don't care about the eip and regs settings since
-        * we'll never reschedule the forked task.
-        */
-       return copy_process(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
-}
-
 #ifdef CONFIG_NUMA
 
 /* which logical CPUs are on which nodes */
@@ -797,21 +764,10 @@ static int __init do_boot_cpu(int apicid)
         * We can't use kernel_thread since we must avoid to
         * reschedule the child.
         */
-       idle = fork_by_hand();
+       idle = fork_idle(cpu);
        if (IS_ERR(idle))
                panic("failed fork for CPU %d", cpu);
-       wake_up_forked_process(idle);
-
-       /*
-        * We remove it from the pidhash and the runqueue
-        * once we got the process:
-        */
-       init_idle(idle, cpu);
-
        idle->thread.eip = (unsigned long) start_secondary;
-
-       unhash_process(idle);
-
        /* start_eip had better be page-aligned! */
        start_eip = setup_trampoline();
 
@@ -875,6 +831,7 @@ static int __init do_boot_cpu(int apicid)
                        inquire_remote_apic(apicid);
                }
        }
+       x86_cpu_to_apicid[cpu] = apicid;
        if (boot_error) {
                /* Try to put things back the way they were before ... */
                unmap_cpu_to_logical_apicid(cpu);
@@ -957,6 +914,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
 
        boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
        boot_cpu_logical_apicid = logical_smp_processor_id();
+       x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 
        current_thread_info()->cpu = 0;
        smp_tune_scheduling();
@@ -1132,213 +1090,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
                synchronize_tsc_bp();
 }
 
-#ifdef CONFIG_SCHED_SMT
-#ifdef CONFIG_NUMA
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static DEFINE_PER_CPU(struct sched_domain, node_domains);
-__init void arch_init_sched_domains(void)
-{
-       int i;
-       struct sched_group *first = NULL, *last = NULL;
-
-       /* Set up domains */
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-               struct sched_domain *node_domain = &per_cpu(node_domains, i);
-               int node = cpu_to_node(i);
-               cpumask_t nodemask = node_to_cpumask(node);
-
-               *cpu_domain = SD_SIBLING_INIT;
-               cpu_domain->span = cpu_sibling_map[i];
-               cpu_domain->parent = phys_domain;
-               cpu_domain->groups = &sched_group_cpus[i];
-
-               *phys_domain = SD_CPU_INIT;
-               phys_domain->span = nodemask;
-               phys_domain->parent = node_domain;
-               phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-
-               *node_domain = SD_NODE_INIT;
-               node_domain->span = cpu_possible_map;
-               node_domain->groups = &sched_group_nodes[cpu_to_node(i)];
-       }
-
-       /* Set up CPU (sibling) groups */
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               int j;
-               first = last = NULL;
-
-               if (i != first_cpu(cpu_domain->span))
-                       continue;
-
-               for_each_cpu_mask(j, cpu_domain->span) {
-                       struct sched_group *cpu = &sched_group_cpus[j];
-
-                       cpu->cpumask = CPU_MASK_NONE;
-                       cpu_set(j, cpu->cpumask);
-                       cpu->cpu_power = SCHED_LOAD_SCALE;
-
-                       if (!first)
-                               first = cpu;
-                       if (last)
-                               last->next = cpu;
-                       last = cpu;
-               }
-               last->next = first;
-       }
-
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               int j;
-               cpumask_t nodemask;
-               struct sched_group *node = &sched_group_nodes[i];
-               cpumask_t node_cpumask = node_to_cpumask(i);
-
-               cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-               if (cpus_empty(nodemask))
-                       continue;
-
-               first = last = NULL;
-               /* Set up physical groups */
-               for_each_cpu_mask(j, nodemask) {
-                       struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j);
-                       struct sched_group *cpu = &sched_group_phys[j];
-
-                       if (j != first_cpu(cpu_domain->span))
-                               continue;
-
-                       cpu->cpumask = cpu_domain->span;
-                       /*
-                        * Make each extra sibling increase power by 10% of
-                        * the basic CPU. This is very arbitrary.
-                        */
-                       cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-                       node->cpu_power += cpu->cpu_power;
-
-                       if (!first)
-                               first = cpu;
-                       if (last)
-                               last->next = cpu;
-                       last = cpu;
-               }
-               last->next = first;
-       }
-
-       /* Set up nodes */
-       first = last = NULL;
-       for (i = 0; i < MAX_NUMNODES; i++) {
-               struct sched_group *cpu = &sched_group_nodes[i];
-               cpumask_t nodemask;
-               cpumask_t node_cpumask = node_to_cpumask(i);
-
-               cpus_and(nodemask, node_cpumask, cpu_possible_map);
-
-               if (cpus_empty(nodemask))
-                       continue;
-
-               cpu->cpumask = nodemask;
-               /* ->cpu_power already setup */
-
-               if (!first)
-                       first = cpu;
-               if (last)
-                       last->next = cpu;
-               last = cpu;
-       }
-       last->next = first;
-
-       mb();
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               cpu_attach_domain(cpu_domain, i);
-       }
-}
-#else /* !CONFIG_NUMA */
-static struct sched_group sched_group_cpus[NR_CPUS];
-static struct sched_group sched_group_phys[NR_CPUS];
-static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
-static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-__init void arch_init_sched_domains(void)
-{
-       int i;
-       struct sched_group *first = NULL, *last = NULL;
-
-       /* Set up domains */
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               struct sched_domain *phys_domain = &per_cpu(phys_domains, i);
-
-               *cpu_domain = SD_SIBLING_INIT;
-               cpu_domain->span = cpu_sibling_map[i];
-               cpu_domain->parent = phys_domain;
-               cpu_domain->groups = &sched_group_cpus[i];
-
-               *phys_domain = SD_CPU_INIT;
-               phys_domain->span = cpu_possible_map;
-               phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)];
-       }
-
-       /* Set up CPU (sibling) groups */
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               int j;
-               first = last = NULL;
-
-               if (i != first_cpu(cpu_domain->span))
-                       continue;
-
-               for_each_cpu_mask(j, cpu_domain->span) {
-                       struct sched_group *cpu = &sched_group_cpus[j];
-
-                       cpus_clear(cpu->cpumask);
-                       cpu_set(j, cpu->cpumask);
-                       cpu->cpu_power = SCHED_LOAD_SCALE;
-
-                       if (!first)
-                               first = cpu;
-                       if (last)
-                               last->next = cpu;
-                       last = cpu;
-               }
-               last->next = first;
-       }
-
-       first = last = NULL;
-       /* Set up physical groups */
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               struct sched_group *cpu = &sched_group_phys[i];
-
-               if (i != first_cpu(cpu_domain->span))
-                       continue;
-
-               cpu->cpumask = cpu_domain->span;
-               /* See SMT+NUMA setup for comment */
-               cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10;
-
-               if (!first)
-                       first = cpu;
-               if (last)
-                       last->next = cpu;
-               last = cpu;
-       }
-       last->next = first;
-
-       mb();
-       for_each_cpu(i) {
-               struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i);
-               cpu_attach_domain(cpu_domain, i);
-       }
-}
-#endif /* CONFIG_NUMA */
-#endif /* CONFIG_SCHED_SMT */
-
 /* These are wrappers to interface to the new boot process.  Someone
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
 void __init smp_prepare_cpus(unsigned int max_cpus)