ia64/xen-unstable

changeset 7425:3d27ee7da0c1

Merge i386/x86_64 smpboot.c into a simplified common Xen version.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Oct 18 17:40:31 2005 +0100 (2005-10-18)
parents 7169e31606bd
children 377b64f085d0
files linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S linux-2.6-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c linux-2.6-xen-sparse/arch/xen/kernel/Makefile linux-2.6-xen-sparse/arch/xen/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile linux-2.6-xen-sparse/arch/xen/x86_64/kernel/x8664_ksyms.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/smp.h linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/smp.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile	Tue Oct 18 15:40:29 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/Makefile	Tue Oct 18 17:40:31 2005 +0100
     1.3 @@ -27,7 +27,7 @@ c-obj-$(CONFIG_X86_MSR)		+= msr.o
     1.4  c-obj-$(CONFIG_X86_CPUID)	+= cpuid.o
     1.5  obj-$(CONFIG_MICROCODE)		+= microcode.o
     1.6  c-obj-$(CONFIG_APM)		+= apm.o
     1.7 -obj-$(CONFIG_X86_SMP)		+= smp.o smpboot.o
     1.8 +obj-$(CONFIG_X86_SMP)		+= smp.o
     1.9  #obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
    1.10  obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
    1.11  obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S	Tue Oct 18 15:40:29 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/head.S	Tue Oct 18 17:40:31 2005 +0100
     2.3 @@ -40,7 +40,7 @@
     2.4  ENTRY(startup_32)
     2.5  	movl %esi,xen_start_info
     2.6  
     2.7 -#ifdef CONFIG_SMP
     2.8 +#if 0
     2.9  ENTRY(startup_32_smp)
    2.10  #endif /* CONFIG_SMP */
    2.11  
    2.12 @@ -78,7 +78,7 @@ checkCPUtype:
    2.13  	movl %eax,%gs
    2.14  	cld			# gcc2 wants the direction flag cleared at all times
    2.15  
    2.16 -#ifdef CONFIG_SMP
    2.17 +#if 0
    2.18  	movb ready, %cl	
    2.19  	cmpb $1,%cl
    2.20  	je 1f			# the first CPU calls start_kernel
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c	Tue Oct 18 15:40:29 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c	Tue Oct 18 17:40:31 2005 +0100
     3.3 @@ -136,9 +136,6 @@ EXPORT_SYMBOL(cpu_sibling_map);
     3.4  #endif
     3.5  
     3.6  #ifdef CONFIG_SMP
     3.7 -EXPORT_SYMBOL(cpu_data);
     3.8 -EXPORT_SYMBOL(cpu_online_map);
     3.9 -EXPORT_SYMBOL(cpu_callout_map);
    3.10  EXPORT_SYMBOL(__write_lock_failed);
    3.11  EXPORT_SYMBOL(__read_lock_failed);
    3.12  
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Tue Oct 18 15:40:29 2005 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,1520 +0,0 @@
     4.4 -/*
     4.5 - *	x86 SMP booting functions
     4.6 - *
     4.7 - *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
     4.8 - *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
     4.9 - *
    4.10 - *	Much of the core SMP work is based on previous work by Thomas Radke, to
    4.11 - *	whom a great many thanks are extended.
    4.12 - *
    4.13 - *	Thanks to Intel for making available several different Pentium,
    4.14 - *	Pentium Pro and Pentium-II/Xeon MP machines.
    4.15 - *	Original development of Linux SMP code supported by Caldera.
    4.16 - *
    4.17 - *	This code is released under the GNU General Public License version 2 or
    4.18 - *	later.
    4.19 - *
    4.20 - *	Fixes
    4.21 - *		Felix Koop	:	NR_CPUS used properly
    4.22 - *		Jose Renau	:	Handle single CPU case.
    4.23 - *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
    4.24 - *		Greg Wright	:	Fix for kernel stacks panic.
    4.25 - *		Erich Boleyn	:	MP v1.4 and additional changes.
    4.26 - *	Matthias Sattler	:	Changes for 2.1 kernel map.
    4.27 - *	Michel Lespinasse	:	Changes for 2.1 kernel map.
    4.28 - *	Michael Chastain	:	Change trampoline.S to gnu as.
    4.29 - *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
    4.30 - *		Ingo Molnar	:	Added APIC timers, based on code
    4.31 - *					from Jose Renau
    4.32 - *		Ingo Molnar	:	various cleanups and rewrites
    4.33 - *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
    4.34 - *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
    4.35 - *		Martin J. Bligh	: 	Added support for multi-quad systems
    4.36 - *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
    4.37 -*		Rusty Russell	:	Hacked into shape for new "hotplug" boot process. */
    4.38 -
    4.39 -#include <linux/module.h>
    4.40 -#include <linux/config.h>
    4.41 -#include <linux/init.h>
    4.42 -#include <linux/kernel.h>
    4.43 -
    4.44 -#include <linux/mm.h>
    4.45 -#include <linux/sched.h>
    4.46 -#include <linux/kernel_stat.h>
    4.47 -#include <linux/smp_lock.h>
    4.48 -#include <linux/irq.h>
    4.49 -#include <linux/bootmem.h>
    4.50 -#include <linux/notifier.h>
    4.51 -#include <linux/cpu.h>
    4.52 -#include <linux/percpu.h>
    4.53 -
    4.54 -#include <linux/delay.h>
    4.55 -#include <linux/mc146818rtc.h>
    4.56 -#include <asm/tlbflush.h>
    4.57 -#include <asm/desc.h>
    4.58 -#include <asm/arch_hooks.h>
    4.59 -
    4.60 -#include <asm/smp_alt.h>
    4.61 -
    4.62 -#ifndef CONFIG_X86_IO_APIC
    4.63 -#define Dprintk(args...)
    4.64 -#endif
    4.65 -#include <mach_wakecpu.h>
    4.66 -#include <smpboot_hooks.h>
    4.67 -
    4.68 -#include <asm-xen/evtchn.h>
    4.69 -#include <asm-xen/xen-public/vcpu.h>
    4.70 -#include <asm-xen/xenbus.h>
    4.71 -
    4.72 -static void xen_smp_intr_init(unsigned int cpu);
    4.73 -static void xen_smp_intr_exit(unsigned int cpu);
    4.74 -
    4.75 -/* Set if we find a B stepping CPU */
    4.76 -static int __initdata smp_b_stepping;
    4.77 -
    4.78 -/* Number of siblings per CPU package */
    4.79 -int smp_num_siblings = 1;
    4.80 -int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
    4.81 -EXPORT_SYMBOL(phys_proc_id);
    4.82 -int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
    4.83 -EXPORT_SYMBOL(cpu_core_id);
    4.84 -
    4.85 -/* bitmap of online cpus */
    4.86 -cpumask_t cpu_online_map;
    4.87 -
    4.88 -cpumask_t cpu_callin_map;
    4.89 -cpumask_t cpu_callout_map;
    4.90 -static cpumask_t smp_commenced_mask;
    4.91 -
    4.92 -/* Per CPU bogomips and other parameters */
    4.93 -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
    4.94 -
    4.95 -u8 x86_cpu_to_apicid[NR_CPUS] =
    4.96 -			{ [0 ... NR_CPUS-1] = 0xff };
    4.97 -EXPORT_SYMBOL(x86_cpu_to_apicid);
    4.98 -
    4.99 -#if 0
   4.100 -/*
   4.101 - * Trampoline 80x86 program as an array.
   4.102 - */
   4.103 -
   4.104 -extern unsigned char trampoline_data [];
   4.105 -extern unsigned char trampoline_end  [];
   4.106 -static unsigned char *trampoline_base;
   4.107 -static int trampoline_exec;
   4.108 -#endif
   4.109 -
   4.110 -#ifdef CONFIG_HOTPLUG_CPU
   4.111 -/* State of each CPU. */
   4.112 -DEFINE_PER_CPU(int, cpu_state) = { 0 };
   4.113 -#endif
   4.114 -
   4.115 -static DEFINE_PER_CPU(int, resched_irq);
   4.116 -static DEFINE_PER_CPU(int, callfunc_irq);
   4.117 -static char resched_name[NR_CPUS][15];
   4.118 -static char callfunc_name[NR_CPUS][15];
   4.119 -
   4.120 -#if 0
   4.121 -/*
   4.122 - * Currently trivial. Write the real->protected mode
   4.123 - * bootstrap into the page concerned. The caller
   4.124 - * has made sure it's suitably aligned.
   4.125 - */
   4.126 -
   4.127 -static unsigned long __init setup_trampoline(void)
   4.128 -{
   4.129 -	memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
   4.130 -	return virt_to_phys(trampoline_base);
   4.131 -}
   4.132 -#endif
   4.133 -
   4.134 -static void map_cpu_to_logical_apicid(void);
   4.135 -
   4.136 -/*
   4.137 - * We are called very early to get the low memory for the
   4.138 - * SMP bootup trampoline page.
   4.139 - */
   4.140 -void __init smp_alloc_memory(void)
   4.141 -{
   4.142 -#if 0
   4.143 -	trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE);
   4.144 -	/*
   4.145 -	 * Has to be in very low memory so we can execute
   4.146 -	 * real-mode AP code.
   4.147 -	 */
   4.148 -	if (__pa(trampoline_base) >= 0x9F000)
   4.149 -		BUG();
   4.150 -	/*
   4.151 -	 * Make the SMP trampoline executable:
   4.152 -	 */
   4.153 -	trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1);
   4.154 -#endif
   4.155 -}
   4.156 -
   4.157 -/*
   4.158 - * The bootstrap kernel entry code has set these up. Save them for
   4.159 - * a given CPU
   4.160 - */
   4.161 -
   4.162 -static void __init smp_store_cpu_info(int id)
   4.163 -{
   4.164 -	struct cpuinfo_x86 *c = cpu_data + id;
   4.165 -
   4.166 -	*c = boot_cpu_data;
   4.167 -	if (id!=0)
   4.168 -		identify_cpu(c);
   4.169 -	/*
   4.170 -	 * Mask B, Pentium, but not Pentium MMX
   4.171 -	 */
   4.172 -	if (c->x86_vendor == X86_VENDOR_INTEL &&
   4.173 -	    c->x86 == 5 &&
   4.174 -	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
   4.175 -	    c->x86_model <= 3)
   4.176 -		/*
   4.177 -		 * Remember we have B step Pentia with bugs
   4.178 -		 */
   4.179 -		smp_b_stepping = 1;
   4.180 -
   4.181 -	/*
   4.182 -	 * Certain Athlons might work (for various values of 'work') in SMP
   4.183 -	 * but they are not certified as MP capable.
   4.184 -	 */
   4.185 -	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
   4.186 -
   4.187 -		/* Athlon 660/661 is valid. */	
   4.188 -		if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
   4.189 -			goto valid_k7;
   4.190 -
   4.191 -		/* Duron 670 is valid */
   4.192 -		if ((c->x86_model==7) && (c->x86_mask==0))
   4.193 -			goto valid_k7;
   4.194 -
   4.195 -		/*
   4.196 -		 * Athlon 662, Duron 671, and Athlon >model 7 have capability bit.
   4.197 -		 * It's worth noting that the A5 stepping (662) of some Athlon XP's
   4.198 -		 * have the MP bit set.
   4.199 -		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more.
   4.200 -		 */
   4.201 -		if (((c->x86_model==6) && (c->x86_mask>=2)) ||
   4.202 -		    ((c->x86_model==7) && (c->x86_mask>=1)) ||
   4.203 -		     (c->x86_model> 7))
   4.204 -			if (cpu_has_mp)
   4.205 -				goto valid_k7;
   4.206 -
   4.207 -		/* If we get here, it's not a certified SMP capable AMD system. */
   4.208 -		tainted |= TAINT_UNSAFE_SMP;
   4.209 -	}
   4.210 -
   4.211 -valid_k7:
   4.212 -	;
   4.213 -}
   4.214 -
   4.215 -#if 0
   4.216 -/*
   4.217 - * TSC synchronization.
   4.218 - *
   4.219 - * We first check whether all CPUs have their TSC's synchronized,
   4.220 - * then we print a warning if not, and always resync.
   4.221 - */
   4.222 -
   4.223 -static atomic_t tsc_start_flag = ATOMIC_INIT(0);
   4.224 -static atomic_t tsc_count_start = ATOMIC_INIT(0);
   4.225 -static atomic_t tsc_count_stop = ATOMIC_INIT(0);
   4.226 -static unsigned long long tsc_values[NR_CPUS];
   4.227 -
   4.228 -#define NR_LOOPS 5
   4.229 -
   4.230 -static void __init synchronize_tsc_bp (void)
   4.231 -{
   4.232 -	int i;
   4.233 -	unsigned long long t0;
   4.234 -	unsigned long long sum, avg;
   4.235 -	long long delta;
   4.236 -	unsigned long one_usec;
   4.237 -	int buggy = 0;
   4.238 -
   4.239 -	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
   4.240 -
   4.241 -	/* convert from kcyc/sec to cyc/usec */
   4.242 -	one_usec = cpu_khz / 1000;
   4.243 -
   4.244 -	atomic_set(&tsc_start_flag, 1);
   4.245 -	wmb();
   4.246 -
   4.247 -	/*
   4.248 -	 * We loop a few times to get a primed instruction cache,
   4.249 -	 * then the last pass is more or less synchronized and
   4.250 -	 * the BP and APs set their cycle counters to zero all at
   4.251 -	 * once. This reduces the chance of having random offsets
   4.252 -	 * between the processors, and guarantees that the maximum
   4.253 -	 * delay between the cycle counters is never bigger than
   4.254 -	 * the latency of information-passing (cachelines) between
   4.255 -	 * two CPUs.
   4.256 -	 */
   4.257 -	for (i = 0; i < NR_LOOPS; i++) {
   4.258 -		/*
   4.259 -		 * all APs synchronize but they loop on '== num_cpus'
   4.260 -		 */
   4.261 -		while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
   4.262 -			mb();
   4.263 -		atomic_set(&tsc_count_stop, 0);
   4.264 -		wmb();
   4.265 -		/*
   4.266 -		 * this lets the APs save their current TSC:
   4.267 -		 */
   4.268 -		atomic_inc(&tsc_count_start);
   4.269 -
   4.270 -		rdtscll(tsc_values[smp_processor_id()]);
   4.271 -		/*
   4.272 -		 * We clear the TSC in the last loop:
   4.273 -		 */
   4.274 -		if (i == NR_LOOPS-1)
   4.275 -			write_tsc(0, 0);
   4.276 -
   4.277 -		/*
   4.278 -		 * Wait for all APs to leave the synchronization point:
   4.279 -		 */
   4.280 -		while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
   4.281 -			mb();
   4.282 -		atomic_set(&tsc_count_start, 0);
   4.283 -		wmb();
   4.284 -		atomic_inc(&tsc_count_stop);
   4.285 -	}
   4.286 -
   4.287 -	sum = 0;
   4.288 -	for (i = 0; i < NR_CPUS; i++) {
   4.289 -		if (cpu_isset(i, cpu_callout_map)) {
   4.290 -			t0 = tsc_values[i];
   4.291 -			sum += t0;
   4.292 -		}
   4.293 -	}
   4.294 -	avg = sum;
   4.295 -	do_div(avg, num_booting_cpus());
   4.296 -
   4.297 -	sum = 0;
   4.298 -	for (i = 0; i < NR_CPUS; i++) {
   4.299 -		if (!cpu_isset(i, cpu_callout_map))
   4.300 -			continue;
   4.301 -		delta = tsc_values[i] - avg;
   4.302 -		if (delta < 0)
   4.303 -			delta = -delta;
   4.304 -		/*
   4.305 -		 * We report bigger than 2 microseconds clock differences.
   4.306 -		 */
   4.307 -		if (delta > 2*one_usec) {
   4.308 -			long realdelta;
   4.309 -			if (!buggy) {
   4.310 -				buggy = 1;
   4.311 -				printk("\n");
   4.312 -			}
   4.313 -			realdelta = delta;
   4.314 -			do_div(realdelta, one_usec);
   4.315 -			if (tsc_values[i] < avg)
   4.316 -				realdelta = -realdelta;
   4.317 -
   4.318 -			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
   4.319 -		}
   4.320 -
   4.321 -		sum += delta;
   4.322 -	}
   4.323 -	if (!buggy)
   4.324 -		printk("passed.\n");
   4.325 -}
   4.326 -
   4.327 -static void __init synchronize_tsc_ap (void)
   4.328 -{
   4.329 -	int i;
   4.330 -
   4.331 -	/*
   4.332 -	 * Not every cpu is online at the time
   4.333 -	 * this gets called, so we first wait for the BP to
   4.334 -	 * finish SMP initialization:
   4.335 -	 */
   4.336 -	while (!atomic_read(&tsc_start_flag)) mb();
   4.337 -
   4.338 -	for (i = 0; i < NR_LOOPS; i++) {
   4.339 -		atomic_inc(&tsc_count_start);
   4.340 -		while (atomic_read(&tsc_count_start) != num_booting_cpus())
   4.341 -			mb();
   4.342 -
   4.343 -		rdtscll(tsc_values[smp_processor_id()]);
   4.344 -		if (i == NR_LOOPS-1)
   4.345 -			write_tsc(0, 0);
   4.346 -
   4.347 -		atomic_inc(&tsc_count_stop);
   4.348 -		while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb();
   4.349 -	}
   4.350 -}
   4.351 -#undef NR_LOOPS
   4.352 -#endif
   4.353 -
   4.354 -extern void calibrate_delay(void);
   4.355 -
   4.356 -static atomic_t init_deasserted;
   4.357 -
   4.358 -static void __init smp_callin(void)
   4.359 -{
   4.360 -	int cpuid, phys_id;
   4.361 -#if 0
   4.362 -	unsigned long timeout;
   4.363 -
   4.364 -	/*
   4.365 -	 * If waken up by an INIT in an 82489DX configuration
   4.366 -	 * we may get here before an INIT-deassert IPI reaches
   4.367 -	 * our local APIC.  We have to wait for the IPI or we'll
   4.368 -	 * lock up on an APIC access.
   4.369 -	 */
   4.370 -	wait_for_init_deassert(&init_deasserted);
   4.371 -#endif
   4.372 -
   4.373 -	/*
   4.374 -	 * (This works even if the APIC is not enabled.)
   4.375 -	 */
   4.376 -	phys_id = smp_processor_id();
   4.377 -	cpuid = smp_processor_id();
   4.378 -	if (cpu_isset(cpuid, cpu_callin_map)) {
   4.379 -		printk("huh, phys CPU#%d, CPU#%d already present??\n",
   4.380 -					phys_id, cpuid);
   4.381 -		BUG();
   4.382 -	}
   4.383 -	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
   4.384 -
   4.385 -#if 0
   4.386 -	/*
   4.387 -	 * STARTUP IPIs are fragile beasts as they might sometimes
   4.388 -	 * trigger some glue motherboard logic. Complete APIC bus
   4.389 -	 * silence for 1 second, this overestimates the time the
   4.390 -	 * boot CPU is spending to send the up to 2 STARTUP IPIs
   4.391 -	 * by a factor of two. This should be enough.
   4.392 -	 */
   4.393 -
   4.394 -	/*
   4.395 -	 * Waiting 2s total for startup (udelay is not yet working)
   4.396 -	 */
   4.397 -	timeout = jiffies + 2*HZ;
   4.398 -	while (time_before(jiffies, timeout)) {
   4.399 -		/*
   4.400 -		 * Has the boot CPU finished it's STARTUP sequence?
   4.401 -		 */
   4.402 -		if (cpu_isset(cpuid, cpu_callout_map))
   4.403 -			break;
   4.404 -		rep_nop();
   4.405 -	}
   4.406 -
   4.407 -	if (!time_before(jiffies, timeout)) {
   4.408 -		printk("BUG: CPU%d started up but did not get a callout!\n",
   4.409 -			cpuid);
   4.410 -		BUG();
   4.411 -	}
   4.412 -
   4.413 -	/*
   4.414 -	 * the boot CPU has finished the init stage and is spinning
   4.415 -	 * on callin_map until we finish. We are free to set up this
   4.416 -	 * CPU, first the APIC. (this is probably redundant on most
   4.417 -	 * boards)
   4.418 -	 */
   4.419 -
   4.420 -	Dprintk("CALLIN, before setup_local_APIC().\n");
   4.421 -	smp_callin_clear_local_apic();
   4.422 -	setup_local_APIC();
   4.423 -#endif
   4.424 -	map_cpu_to_logical_apicid();
   4.425 -
   4.426 -	/*
   4.427 -	 * Get our bogomips.
   4.428 -	 */
   4.429 -	calibrate_delay();
   4.430 -	Dprintk("Stack at about %p\n",&cpuid);
   4.431 -
   4.432 -	/*
   4.433 -	 * Save our processor parameters
   4.434 -	 */
   4.435 - 	smp_store_cpu_info(cpuid);
   4.436 -
   4.437 -#if 0
   4.438 -	disable_APIC_timer();
   4.439 -#endif
   4.440 -
   4.441 -	/*
   4.442 -	 * Allow the master to continue.
   4.443 -	 */
   4.444 -	cpu_set(cpuid, cpu_callin_map);
   4.445 -
   4.446 -#if 0
   4.447 -	/*
   4.448 -	 *      Synchronize the TSC with the BP
   4.449 -	 */
   4.450 -	if (cpu_has_tsc && cpu_khz)
   4.451 -		synchronize_tsc_ap();
   4.452 -#endif
   4.453 -}
   4.454 -
   4.455 -static int cpucount;
   4.456 -
   4.457 -/*
   4.458 - * Activate a secondary processor.
   4.459 - */
   4.460 -static void __init start_secondary(void *unused)
   4.461 -{
   4.462 -	/*
   4.463 -	 * Dont put anything before smp_callin(), SMP
   4.464 -	 * booting is too fragile that we want to limit the
   4.465 -	 * things done here to the most necessary things.
   4.466 -	 */
   4.467 -	cpu_init();
   4.468 -	smp_callin();
   4.469 -	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
   4.470 -		rep_nop();
   4.471 -	local_irq_enable();
   4.472 -	/*
   4.473 -	 * low-memory mappings have been cleared, flush them from
   4.474 -	 * the local TLBs too.
   4.475 -	 */
   4.476 -	local_flush_tlb();
   4.477 -	cpu_set(smp_processor_id(), cpu_online_map);
   4.478 -
   4.479 -	/* We can take interrupts now: we're officially "up". */
   4.480 -	local_irq_enable();
   4.481 -
   4.482 -	wmb();
   4.483 -	cpu_idle();
   4.484 -}
   4.485 -
   4.486 -/*
   4.487 - * Everything has been set up for the secondary
   4.488 - * CPUs - they just need to reload everything
   4.489 - * from the task structure
   4.490 - * This function must not return.
   4.491 - */
   4.492 -void __init initialize_secondary(void)
   4.493 -{
   4.494 -	/*
   4.495 -	 * We don't actually need to load the full TSS,
   4.496 -	 * basically just the stack pointer and the eip.
   4.497 -	 */
   4.498 -
   4.499 -	asm volatile(
   4.500 -		"movl %0,%%esp\n\t"
   4.501 -		"jmp *%1"
   4.502 -		:
   4.503 -		:"r" (current->thread.esp),"r" (current->thread.eip));
   4.504 -}
   4.505 -
   4.506 -extern struct {
   4.507 -	void * esp;
   4.508 -	unsigned short ss;
   4.509 -} stack_start;
   4.510 -
   4.511 -#ifdef CONFIG_NUMA
   4.512 -
   4.513 -/* which logical CPUs are on which nodes */
   4.514 -cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
   4.515 -				{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
   4.516 -/* which node each logical CPU is on */
   4.517 -int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
   4.518 -EXPORT_SYMBOL(cpu_2_node);
   4.519 -
   4.520 -/* set up a mapping between cpu and node. */
   4.521 -static inline void map_cpu_to_node(int cpu, int node)
   4.522 -{
   4.523 -	printk("Mapping cpu %d to node %d\n", cpu, node);
   4.524 -	cpu_set(cpu, node_2_cpu_mask[node]);
   4.525 -	cpu_2_node[cpu] = node;
   4.526 -}
   4.527 -
   4.528 -/* undo a mapping between cpu and node. */
   4.529 -static inline void unmap_cpu_to_node(int cpu)
   4.530 -{
   4.531 -	int node;
   4.532 -
   4.533 -	printk("Unmapping cpu %d from all nodes\n", cpu);
   4.534 -	for (node = 0; node < MAX_NUMNODES; node ++)
   4.535 -		cpu_clear(cpu, node_2_cpu_mask[node]);
   4.536 -	cpu_2_node[cpu] = 0;
   4.537 -}
   4.538 -#else /* !CONFIG_NUMA */
   4.539 -
   4.540 -#define map_cpu_to_node(cpu, node)	({})
   4.541 -#define unmap_cpu_to_node(cpu)	({})
   4.542 -
   4.543 -#endif /* CONFIG_NUMA */
   4.544 -
   4.545 -u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
   4.546 -
   4.547 -static void map_cpu_to_logical_apicid(void)
   4.548 -{
   4.549 -	int cpu = smp_processor_id();
   4.550 -	int apicid = smp_processor_id();
   4.551 -
   4.552 -	cpu_2_logical_apicid[cpu] = apicid;
   4.553 -	map_cpu_to_node(cpu, apicid_to_node(apicid));
   4.554 -}
   4.555 -
   4.556 -static void unmap_cpu_to_logical_apicid(int cpu)
   4.557 -{
   4.558 -	cpu_2_logical_apicid[cpu] = BAD_APICID;
   4.559 -	unmap_cpu_to_node(cpu);
   4.560 -}
   4.561 -
   4.562 -#if APIC_DEBUG
   4.563 -static inline void __inquire_remote_apic(int apicid)
   4.564 -{
   4.565 -	int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
   4.566 -	char *names[] = { "ID", "VERSION", "SPIV" };
   4.567 -	int timeout, status;
   4.568 -
   4.569 -	printk("Inquiring remote APIC #%d...\n", apicid);
   4.570 -
   4.571 -	for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
   4.572 -		printk("... APIC #%d %s: ", apicid, names[i]);
   4.573 -
   4.574 -		/*
   4.575 -		 * Wait for idle.
   4.576 -		 */
   4.577 -		apic_wait_icr_idle();
   4.578 -
   4.579 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
   4.580 -		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
   4.581 -
   4.582 -		timeout = 0;
   4.583 -		do {
   4.584 -			udelay(100);
   4.585 -			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
   4.586 -		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
   4.587 -
   4.588 -		switch (status) {
   4.589 -		case APIC_ICR_RR_VALID:
   4.590 -			status = apic_read(APIC_RRR);
   4.591 -			printk("%08x\n", status);
   4.592 -			break;
   4.593 -		default:
   4.594 -			printk("failed\n");
   4.595 -		}
   4.596 -	}
   4.597 -}
   4.598 -#endif
   4.599 -
   4.600 -#if 0
   4.601 -#ifdef WAKE_SECONDARY_VIA_NMI
   4.602 -/* 
   4.603 - * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
   4.604 - * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
   4.605 - * won't ... remember to clear down the APIC, etc later.
   4.606 - */
   4.607 -static int __init
   4.608 -wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
   4.609 -{
   4.610 -	unsigned long send_status = 0, accept_status = 0;
   4.611 -	int timeout, maxlvt;
   4.612 -
   4.613 -	/* Target chip */
   4.614 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
   4.615 -
   4.616 -	/* Boot on the stack */
   4.617 -	/* Kick the second */
   4.618 -	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
   4.619 -
   4.620 -	Dprintk("Waiting for send to finish...\n");
   4.621 -	timeout = 0;
   4.622 -	do {
   4.623 -		Dprintk("+");
   4.624 -		udelay(100);
   4.625 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.626 -	} while (send_status && (timeout++ < 1000));
   4.627 -
   4.628 -	/*
   4.629 -	 * Give the other CPU some time to accept the IPI.
   4.630 -	 */
   4.631 -	udelay(200);
   4.632 -	/*
   4.633 -	 * Due to the Pentium erratum 3AP.
   4.634 -	 */
   4.635 -	maxlvt = get_maxlvt();
   4.636 -	if (maxlvt > 3) {
   4.637 -		apic_read_around(APIC_SPIV);
   4.638 -		apic_write(APIC_ESR, 0);
   4.639 -	}
   4.640 -	accept_status = (apic_read(APIC_ESR) & 0xEF);
   4.641 -	Dprintk("NMI sent.\n");
   4.642 -
   4.643 -	if (send_status)
   4.644 -		printk("APIC never delivered???\n");
   4.645 -	if (accept_status)
   4.646 -		printk("APIC delivery error (%lx).\n", accept_status);
   4.647 -
   4.648 -	return (send_status | accept_status);
   4.649 -}
   4.650 -#endif	/* WAKE_SECONDARY_VIA_NMI */
   4.651 -
   4.652 -#ifdef WAKE_SECONDARY_VIA_INIT
   4.653 -static int __init
   4.654 -wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
   4.655 -{
   4.656 -	unsigned long send_status = 0, accept_status = 0;
   4.657 -	int maxlvt, timeout, num_starts, j;
   4.658 -
   4.659 -	/*
   4.660 -	 * Be paranoid about clearing APIC errors.
   4.661 -	 */
   4.662 -	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
   4.663 -		apic_read_around(APIC_SPIV);
   4.664 -		apic_write(APIC_ESR, 0);
   4.665 -		apic_read(APIC_ESR);
   4.666 -	}
   4.667 -
   4.668 -	Dprintk("Asserting INIT.\n");
   4.669 -
   4.670 -	/*
   4.671 -	 * Turn INIT on target chip
   4.672 -	 */
   4.673 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.674 -
   4.675 -	/*
   4.676 -	 * Send IPI
   4.677 -	 */
   4.678 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
   4.679 -				| APIC_DM_INIT);
   4.680 -
   4.681 -	Dprintk("Waiting for send to finish...\n");
   4.682 -	timeout = 0;
   4.683 -	do {
   4.684 -		Dprintk("+");
   4.685 -		udelay(100);
   4.686 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.687 -	} while (send_status && (timeout++ < 1000));
   4.688 -
   4.689 -	mdelay(10);
   4.690 -
   4.691 -	Dprintk("Deasserting INIT.\n");
   4.692 -
   4.693 -	/* Target chip */
   4.694 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.695 -
   4.696 -	/* Send IPI */
   4.697 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
   4.698 -
   4.699 -	Dprintk("Waiting for send to finish...\n");
   4.700 -	timeout = 0;
   4.701 -	do {
   4.702 -		Dprintk("+");
   4.703 -		udelay(100);
   4.704 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.705 -	} while (send_status && (timeout++ < 1000));
   4.706 -
   4.707 -	atomic_set(&init_deasserted, 1);
   4.708 -
   4.709 -	/*
   4.710 -	 * Should we send STARTUP IPIs ?
   4.711 -	 *
   4.712 -	 * Determine this based on the APIC version.
   4.713 -	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
   4.714 -	 */
   4.715 -	if (APIC_INTEGRATED(apic_version[phys_apicid]))
   4.716 -		num_starts = 2;
   4.717 -	else
   4.718 -		num_starts = 0;
   4.719 -
   4.720 -	/*
   4.721 -	 * Run STARTUP IPI loop.
   4.722 -	 */
   4.723 -	Dprintk("#startup loops: %d.\n", num_starts);
   4.724 -
   4.725 -	maxlvt = get_maxlvt();
   4.726 -
   4.727 -	for (j = 1; j <= num_starts; j++) {
   4.728 -		Dprintk("Sending STARTUP #%d.\n",j);
   4.729 -		apic_read_around(APIC_SPIV);
   4.730 -		apic_write(APIC_ESR, 0);
   4.731 -		apic_read(APIC_ESR);
   4.732 -		Dprintk("After apic_write.\n");
   4.733 -
   4.734 -		/*
   4.735 -		 * STARTUP IPI
   4.736 -		 */
   4.737 -
   4.738 -		/* Target chip */
   4.739 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.740 -
   4.741 -		/* Boot on the stack */
   4.742 -		/* Kick the second */
   4.743 -		apic_write_around(APIC_ICR, APIC_DM_STARTUP
   4.744 -					| (start_eip >> 12));
   4.745 -
   4.746 -		/*
   4.747 -		 * Give the other CPU some time to accept the IPI.
   4.748 -		 */
   4.749 -		udelay(300);
   4.750 -
   4.751 -		Dprintk("Startup point 1.\n");
   4.752 -
   4.753 -		Dprintk("Waiting for send to finish...\n");
   4.754 -		timeout = 0;
   4.755 -		do {
   4.756 -			Dprintk("+");
   4.757 -			udelay(100);
   4.758 -			send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.759 -		} while (send_status && (timeout++ < 1000));
   4.760 -
   4.761 -		/*
   4.762 -		 * Give the other CPU some time to accept the IPI.
   4.763 -		 */
   4.764 -		udelay(200);
   4.765 -		/*
   4.766 -		 * Due to the Pentium erratum 3AP.
   4.767 -		 */
   4.768 -		if (maxlvt > 3) {
   4.769 -			apic_read_around(APIC_SPIV);
   4.770 -			apic_write(APIC_ESR, 0);
   4.771 -		}
   4.772 -		accept_status = (apic_read(APIC_ESR) & 0xEF);
   4.773 -		if (send_status || accept_status)
   4.774 -			break;
   4.775 -	}
   4.776 -	Dprintk("After Startup.\n");
   4.777 -
   4.778 -	if (send_status)
   4.779 -		printk("APIC never delivered???\n");
   4.780 -	if (accept_status)
   4.781 -		printk("APIC delivery error (%lx).\n", accept_status);
   4.782 -
   4.783 -	return (send_status | accept_status);
   4.784 -}
   4.785 -#endif	/* WAKE_SECONDARY_VIA_INIT */
   4.786 -#endif
   4.787 -
   4.788 -extern cpumask_t cpu_initialized;
   4.789 -
   4.790 -static int __init do_boot_cpu(int apicid)
   4.791 -/*
   4.792 - * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
   4.793 - * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
   4.794 - * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
   4.795 - */
   4.796 -{
   4.797 -	struct task_struct *idle;
   4.798 -	unsigned long boot_error;
   4.799 -	int timeout, cpu;
   4.800 -	unsigned long start_eip;
   4.801 -#if 0
   4.802 -	unsigned short nmi_high = 0, nmi_low = 0;
   4.803 -#endif
   4.804 -	vcpu_guest_context_t ctxt;
   4.805 -	extern void startup_32_smp(void);
   4.806 -	extern void hypervisor_callback(void);
   4.807 -	extern void failsafe_callback(void);
   4.808 -	extern void smp_trap_init(trap_info_t *);
   4.809 -
   4.810 -	cpu = ++cpucount;
   4.811 -	/*
   4.812 -	 * We can't use kernel_thread since we must avoid to
   4.813 -	 * reschedule the child.
   4.814 -	 */
   4.815 -	idle = fork_idle(cpu);
   4.816 -	if (IS_ERR(idle))
   4.817 -		panic("failed fork for CPU %d", cpu);
   4.818 -	idle->thread.eip = (unsigned long) start_secondary;
   4.819 -	/* start_eip had better be page-aligned! */
   4.820 -	start_eip = (unsigned long)startup_32_smp;
   4.821 -
   4.822 -	/* So we see what's up   */
   4.823 -	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
   4.824 -	/* Stack for startup_32 can be just as for start_secondary onwards */
   4.825 -	stack_start.esp = (void *) idle->thread.esp;
   4.826 -
   4.827 -	irq_ctx_init(cpu);
   4.828 -
   4.829 -	/*
   4.830 -	 * This grunge runs the startup process for
   4.831 -	 * the targeted processor.
   4.832 -	 */
   4.833 -
   4.834 -	atomic_set(&init_deasserted, 0);
   4.835 -
   4.836 -#if 1
   4.837 -	cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL|__GFP_ZERO);
   4.838 -	BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
   4.839 -	cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
   4.840 -	memcpy((void *)cpu_gdt_descr[cpu].address,
   4.841 -	       (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
   4.842 -
   4.843 -	memset(&ctxt, 0, sizeof(ctxt));
   4.844 -
   4.845 -	ctxt.user_regs.ds = __USER_DS;
   4.846 -	ctxt.user_regs.es = __USER_DS;
   4.847 -	ctxt.user_regs.fs = 0;
   4.848 -	ctxt.user_regs.gs = 0;
   4.849 -	ctxt.user_regs.ss = __KERNEL_DS;
   4.850 -	ctxt.user_regs.cs = __KERNEL_CS;
   4.851 -	ctxt.user_regs.eip = start_eip;
   4.852 -	ctxt.user_regs.esp = idle->thread.esp;
   4.853 -#define X86_EFLAGS_IOPL_RING1 0x1000
   4.854 -	ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1;
   4.855 -
   4.856 -	/* FPU is set up to default initial state. */
   4.857 -	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
   4.858 -
   4.859 -	smp_trap_init(ctxt.trap_ctxt);
   4.860 -
   4.861 -	/* No LDT. */
   4.862 -	ctxt.ldt_ents = 0;
   4.863 -
   4.864 -	{
   4.865 -		unsigned long va;
   4.866 -		int f;
   4.867 -
   4.868 -		for (va = cpu_gdt_descr[cpu].address, f = 0;
   4.869 -		     va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
   4.870 -		     va += PAGE_SIZE, f++) {
   4.871 -			ctxt.gdt_frames[f] = virt_to_mfn(va);
   4.872 -			make_page_readonly((void *)va);
   4.873 -		}
   4.874 -		ctxt.gdt_ents = cpu_gdt_descr[cpu].size / 8;
   4.875 -	}
   4.876 -
   4.877 -	/* Ring 1 stack is the initial stack. */
   4.878 -	ctxt.kernel_ss = __KERNEL_DS;
   4.879 -	ctxt.kernel_sp = idle->thread.esp;
   4.880 -
   4.881 -	/* Callback handlers. */
   4.882 -	ctxt.event_callback_cs     = __KERNEL_CS;
   4.883 -	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   4.884 -	ctxt.failsafe_callback_cs  = __KERNEL_CS;
   4.885 -	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   4.886 -
   4.887 -	ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
   4.888 -
   4.889 -	boot_error = HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt);
   4.890 -	if (boot_error)
   4.891 -		printk("boot error: %ld\n", boot_error);
   4.892 -
   4.893 -	if (!boot_error) {
   4.894 -		HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
   4.895 -
   4.896 -		/*
   4.897 -		 * allow APs to start initializing.
   4.898 -		 */
   4.899 -		Dprintk("Before Callout %d.\n", cpu);
   4.900 -		cpu_set(cpu, cpu_callout_map);
   4.901 -		Dprintk("After Callout %d.\n", cpu);
   4.902 -
   4.903 -		/*
   4.904 -		 * Wait 5s total for a response
   4.905 -		 */
   4.906 -		for (timeout = 0; timeout < 50000; timeout++) {
   4.907 -			if (cpu_isset(cpu, cpu_callin_map))
   4.908 -				break;	/* It has booted */
   4.909 -			udelay(100);
   4.910 -		}
   4.911 -
   4.912 -		if (cpu_isset(cpu, cpu_callin_map)) {
   4.913 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   4.914 -			Dprintk("OK.\n");
   4.915 -			printk("CPU%d: ", cpu);
   4.916 -			print_cpu_info(&cpu_data[cpu]);
   4.917 -			Dprintk("CPU has booted.\n");
   4.918 -		} else {
   4.919 -			boot_error= 1;
   4.920 -		}
   4.921 -	}
   4.922 -	x86_cpu_to_apicid[cpu] = apicid;
   4.923 -	if (boot_error) {
   4.924 -		/* Try to put things back the way they were before ... */
   4.925 -		unmap_cpu_to_logical_apicid(cpu);
   4.926 -		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
   4.927 -		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
   4.928 -		cpucount--;
   4.929 -	}
   4.930 -
   4.931 -#else
   4.932 -	Dprintk("Setting warm reset code and vector.\n");
   4.933 -
   4.934 -	store_NMI_vector(&nmi_high, &nmi_low);
   4.935 -
   4.936 -	smpboot_setup_warm_reset_vector(start_eip);
   4.937 -
   4.938 -	/*
   4.939 -	 * Starting actual IPI sequence...
   4.940 -	 */
   4.941 -	boot_error = wakeup_secondary_cpu(apicid, start_eip);
   4.942 -
   4.943 -	if (!boot_error) {
   4.944 -		/*
   4.945 -		 * allow APs to start initializing.
   4.946 -		 */
   4.947 -		Dprintk("Before Callout %d.\n", cpu);
   4.948 -		cpu_set(cpu, cpu_callout_map);
   4.949 -		Dprintk("After Callout %d.\n", cpu);
   4.950 -
   4.951 -		/*
   4.952 -		 * Wait 5s total for a response
   4.953 -		 */
   4.954 -		for (timeout = 0; timeout < 50000; timeout++) {
   4.955 -			if (cpu_isset(cpu, cpu_callin_map))
   4.956 -				break;	/* It has booted */
   4.957 -			udelay(100);
   4.958 -		}
   4.959 -
   4.960 -		if (cpu_isset(cpu, cpu_callin_map)) {
   4.961 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   4.962 -			Dprintk("OK.\n");
   4.963 -			printk("CPU%d: ", cpu);
   4.964 -			print_cpu_info(&cpu_data[cpu]);
   4.965 -			Dprintk("CPU has booted.\n");
   4.966 -		} else {
   4.967 -			boot_error= 1;
   4.968 -			if (*((volatile unsigned char *)trampoline_base)
   4.969 -					== 0xA5)
   4.970 -				/* trampoline started but...? */
   4.971 -				printk("Stuck ??\n");
   4.972 -			else
   4.973 -				/* trampoline code not run */
   4.974 -				printk("Not responding.\n");
   4.975 -			inquire_remote_apic(apicid);
   4.976 -		}
   4.977 -	}
   4.978 -	x86_cpu_to_apicid[cpu] = apicid;
   4.979 -	if (boot_error) {
   4.980 -		/* Try to put things back the way they were before ... */
   4.981 -		unmap_cpu_to_logical_apicid(cpu);
   4.982 -		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
   4.983 -		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
   4.984 -		cpucount--;
   4.985 -	}
   4.986 -
   4.987 -	/* mark "stuck" area as not stuck */
   4.988 -	*((volatile unsigned long *)trampoline_base) = 0;
   4.989 -#endif
   4.990 -
   4.991 -	return boot_error;
   4.992 -}
   4.993 -
   4.994 -static void smp_tune_scheduling (void)
   4.995 -{
   4.996 -	unsigned long cachesize;       /* kB   */
   4.997 -	unsigned long bandwidth = 350; /* MB/s */
   4.998 -	/*
   4.999 -	 * Rough estimation for SMP scheduling, this is the number of
  4.1000 -	 * cycles it takes for a fully memory-limited process to flush
  4.1001 -	 * the SMP-local cache.
  4.1002 -	 *
  4.1003 -	 * (For a P5 this pretty much means we will choose another idle
  4.1004 -	 *  CPU almost always at wakeup time (this is due to the small
  4.1005 -	 *  L1 cache), on PIIs it's around 50-100 usecs, depending on
  4.1006 -	 *  the cache size)
  4.1007 -	 */
  4.1008 -
  4.1009 -	if (!cpu_khz) {
  4.1010 -		/*
  4.1011 -		 * this basically disables processor-affinity
  4.1012 -		 * scheduling on SMP without a TSC.
  4.1013 -		 */
  4.1014 -		return;
  4.1015 -	} else {
  4.1016 -		cachesize = boot_cpu_data.x86_cache_size;
  4.1017 -		if (cachesize == -1) {
  4.1018 -			cachesize = 16; /* Pentiums, 2x8kB cache */
  4.1019 -			bandwidth = 100;
  4.1020 -		}
  4.1021 -	}
  4.1022 -}
  4.1023 -
  4.1024 -/*
  4.1025 - * Cycle through the processors sending APIC IPIs to boot each.
  4.1026 - */
  4.1027 -
  4.1028 -#if 0
  4.1029 -static int boot_cpu_logical_apicid;
  4.1030 -#endif
  4.1031 -/* Where the IO area was mapped on multiquad, always 0 otherwise */
  4.1032 -void *xquad_portio;
  4.1033 -
  4.1034 -cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
  4.1035 -cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
  4.1036 -EXPORT_SYMBOL(cpu_core_map);
  4.1037 -
  4.1038 -static void __init smp_boot_cpus(unsigned int max_cpus)
  4.1039 -{
  4.1040 -	int cpu, kicked;
  4.1041 -	unsigned long bogosum = 0;
  4.1042 -#if 0
  4.1043 -	int apicid, bit;
  4.1044 -#endif
  4.1045 -
  4.1046 -	/*
  4.1047 -	 * Setup boot CPU information
  4.1048 -	 */
  4.1049 -	smp_store_cpu_info(0); /* Final full version of the data */
  4.1050 -	printk("CPU%d: ", 0);
  4.1051 -	print_cpu_info(&cpu_data[0]);
  4.1052 -
  4.1053 -#if 0
  4.1054 -	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
  4.1055 -	boot_cpu_logical_apicid = logical_smp_processor_id();
  4.1056 -	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
  4.1057 -#else
  4.1058 -	// boot_cpu_physical_apicid = 0;
  4.1059 -	// boot_cpu_logical_apicid = 0;
  4.1060 -	x86_cpu_to_apicid[0] = 0;
  4.1061 -#endif
  4.1062 -
  4.1063 -	current_thread_info()->cpu = 0;
  4.1064 -	smp_tune_scheduling();
  4.1065 -	cpus_clear(cpu_sibling_map[0]);
  4.1066 -	cpu_set(0, cpu_sibling_map[0]);
  4.1067 -
  4.1068 -	cpus_clear(cpu_core_map[0]);
  4.1069 -	cpu_set(0, cpu_core_map[0]);
  4.1070 -
  4.1071 -#ifdef CONFIG_X86_IO_APIC
  4.1072 -	/*
  4.1073 -	 * If we couldn't find an SMP configuration at boot time,
  4.1074 -	 * get out of here now!
  4.1075 -	 */
  4.1076 -	if (!smp_found_config && !acpi_lapic) {
  4.1077 -		printk(KERN_NOTICE "SMP motherboard not detected.\n");
  4.1078 -		smpboot_clear_io_apic_irqs();
  4.1079 -#if 0
  4.1080 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1081 -#endif
  4.1082 -#ifdef CONFIG_X86_LOCAL_APIC
  4.1083 -		if (APIC_init_uniprocessor())
  4.1084 -			printk(KERN_NOTICE "Local APIC not detected."
  4.1085 -					   " Using dummy APIC emulation.\n");
  4.1086 -#endif
  4.1087 -		map_cpu_to_logical_apicid();
  4.1088 -		cpu_set(0, cpu_sibling_map[0]);
  4.1089 -		cpu_set(0, cpu_core_map[0]);
  4.1090 -		return;
  4.1091 -	}
  4.1092 -#endif
  4.1093 -
  4.1094 -#if 0
  4.1095 -	/*
  4.1096 -	 * Should not be necessary because the MP table should list the boot
  4.1097 -	 * CPU too, but we do it for the sake of robustness anyway.
  4.1098 -	 * Makes no sense to do this check in clustered apic mode, so skip it
  4.1099 -	 */
  4.1100 -	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
  4.1101 -		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
  4.1102 -				boot_cpu_physical_apicid);
  4.1103 -		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
  4.1104 -	}
  4.1105 -
  4.1106 -	/*
  4.1107 -	 * If we couldn't find a local APIC, then get out of here now!
  4.1108 -	 */
  4.1109 -	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
  4.1110 -		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
  4.1111 -			boot_cpu_physical_apicid);
  4.1112 -		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
  4.1113 -		smpboot_clear_io_apic_irqs();
  4.1114 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1115 -		cpu_set(0, cpu_sibling_map[0]);
  4.1116 -		cpu_set(0, cpu_core_map[0]);
  4.1117 -		cpu_set(0, cpu_sibling_map[0]);
  4.1118 -		cpu_set(0, cpu_core_map[0]);
  4.1119 -		return;
  4.1120 -	}
  4.1121 -
  4.1122 -	verify_local_APIC();
  4.1123 -#endif
  4.1124 -
  4.1125 -	/*
  4.1126 -	 * If SMP should be disabled, then really disable it!
  4.1127 -	 */
  4.1128 -	if (!max_cpus) {
  4.1129 -		xen_start_info->n_vcpu = 1;
  4.1130 -		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
  4.1131 -		smpboot_clear_io_apic_irqs();
  4.1132 -#if 0
  4.1133 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1134 -#endif
  4.1135 -		return;
  4.1136 -	}
  4.1137 -
  4.1138 -	xen_smp_intr_init(0);
  4.1139 -
  4.1140 -#if 0
  4.1141 -	connect_bsp_APIC();
  4.1142 -	setup_local_APIC();
  4.1143 -#endif
  4.1144 -	map_cpu_to_logical_apicid();
  4.1145 -#if 0
  4.1146 -
  4.1147 -
  4.1148 -	setup_portio_remap();
  4.1149 -
  4.1150 -	/*
  4.1151 -	 * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
  4.1152 -	 *
  4.1153 -	 * In clustered apic mode, phys_cpu_present_map is a constructed thus:
  4.1154 -	 * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the 
  4.1155 -	 * clustered apic ID.
  4.1156 -	 */
  4.1157 -	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
  4.1158 -#endif
  4.1159 -	Dprintk("CPU present map: %lx\n", (1UL << xen_start_info->n_vcpu) - 1);
  4.1160 -
  4.1161 -	kicked = 1;
  4.1162 -	for (cpu = 1; kicked < NR_CPUS && cpu < xen_start_info->n_vcpu; cpu++) {
  4.1163 -		if (max_cpus <= cpucount+1)
  4.1164 -			continue;
  4.1165 -
  4.1166 -#ifdef CONFIG_SMP_ALTERNATIVES
  4.1167 -		if (kicked == 1)
  4.1168 -			prepare_for_smp();
  4.1169 -#endif
  4.1170 -		if (do_boot_cpu(cpu))
  4.1171 -			printk("CPU #%d not responding - cannot use it.\n",
  4.1172 -								cpu);
  4.1173 -		else
  4.1174 -			++kicked;
  4.1175 -	}
  4.1176 -
  4.1177 -#if 0
  4.1178 -	/*
  4.1179 -	 * Cleanup possible dangling ends...
  4.1180 -	 */
  4.1181 -	smpboot_restore_warm_reset_vector();
  4.1182 -#endif
  4.1183 -
  4.1184 -	/*
  4.1185 -	 * Allow the user to impress friends.
  4.1186 -	 */
  4.1187 -	Dprintk("Before bogomips.\n");
  4.1188 -	for (cpu = 0; cpu < NR_CPUS; cpu++)
  4.1189 -		if (cpu_isset(cpu, cpu_callout_map))
  4.1190 -			bogosum += cpu_data[cpu].loops_per_jiffy;
  4.1191 -	printk(KERN_INFO
  4.1192 -		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
  4.1193 -		cpucount+1,
  4.1194 -		bogosum/(500000/HZ),
  4.1195 -		(bogosum/(5000/HZ))%100);
  4.1196 -	
  4.1197 -	Dprintk("Before bogocount - setting activated=1.\n");
  4.1198 -
  4.1199 -	if (smp_b_stepping)
  4.1200 -		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
  4.1201 -
  4.1202 -	/*
  4.1203 -	 * Don't taint if we are running SMP kernel on a single non-MP
  4.1204 -	 * approved Athlon
  4.1205 -	 */
  4.1206 -	if (tainted & TAINT_UNSAFE_SMP) {
  4.1207 -		if (cpucount)
  4.1208 -			printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
  4.1209 -		else
  4.1210 -			tainted &= ~TAINT_UNSAFE_SMP;
  4.1211 -	}
  4.1212 -
  4.1213 -	Dprintk("Boot done.\n");
  4.1214 -
  4.1215 -	/*
  4.1216 -	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
  4.1217 -	 * efficiently.
  4.1218 -	 */
  4.1219 -	for (cpu = 0; cpu < NR_CPUS; cpu++) {
  4.1220 -		cpus_clear(cpu_sibling_map[cpu]);
  4.1221 -		cpus_clear(cpu_core_map[cpu]);
  4.1222 -	}
  4.1223 -
  4.1224 -	for (cpu = 0; cpu < NR_CPUS; cpu++) {
  4.1225 -		struct cpuinfo_x86 *c = cpu_data + cpu;
  4.1226 -		int siblings = 0;
  4.1227 -		int i;
  4.1228 -		if (!cpu_isset(cpu, cpu_callout_map))
  4.1229 -			continue;
  4.1230 -
  4.1231 -		if (smp_num_siblings > 1) {
  4.1232 -			for (i = 0; i < NR_CPUS; i++) {
  4.1233 -				if (!cpu_isset(i, cpu_callout_map))
  4.1234 -					continue;
  4.1235 -				if (cpu_core_id[cpu] == cpu_core_id[i]) {
  4.1236 -					siblings++;
  4.1237 -					cpu_set(i, cpu_sibling_map[cpu]);
  4.1238 -				}
  4.1239 -			}
  4.1240 -		} else {
  4.1241 -			siblings++;
  4.1242 -			cpu_set(cpu, cpu_sibling_map[cpu]);
  4.1243 -		}
  4.1244 -
  4.1245 -		if (siblings != smp_num_siblings) {
  4.1246 -			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
  4.1247 -			smp_num_siblings = siblings;
  4.1248 -		}
  4.1249 -
  4.1250 -		if (c->x86_num_cores > 1) {
  4.1251 -			for (i = 0; i < NR_CPUS; i++) {
  4.1252 -				if (!cpu_isset(i, cpu_callout_map))
  4.1253 -					continue;
  4.1254 -				if (phys_proc_id[cpu] == phys_proc_id[i]) {
  4.1255 -					cpu_set(i, cpu_core_map[cpu]);
  4.1256 -				}
  4.1257 -			}
  4.1258 -		} else {
  4.1259 -			cpu_core_map[cpu] = cpu_sibling_map[cpu];
  4.1260 -		}
  4.1261 -	}
  4.1262 -
  4.1263 -	smpboot_setup_io_apic();
  4.1264 -
  4.1265 -#if 0
  4.1266 -	setup_boot_APIC_clock();
  4.1267 -
  4.1268 -	/*
  4.1269 -	 * Synchronize the TSC with the AP
  4.1270 -	 */
  4.1271 -	if (cpu_has_tsc && cpucount && cpu_khz)
  4.1272 -		synchronize_tsc_bp();
  4.1273 -#endif
  4.1274 -}
  4.1275 -
  4.1276 -/* These are wrappers to interface to the new boot process.  Someone
  4.1277 -   who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
  4.1278 -void __init smp_prepare_cpus(unsigned int max_cpus)
  4.1279 -{
  4.1280 -	smp_commenced_mask = cpumask_of_cpu(0);
  4.1281 -	cpu_callin_map = cpumask_of_cpu(0);
  4.1282 -	mb();
  4.1283 -	smp_boot_cpus(max_cpus);
  4.1284 -}
  4.1285 -
  4.1286 -void __devinit smp_prepare_boot_cpu(void)
  4.1287 -{
  4.1288 -	cpu_set(smp_processor_id(), cpu_online_map);
  4.1289 -	cpu_set(smp_processor_id(), cpu_callout_map);
  4.1290 -}
  4.1291 -
  4.1292 -#ifdef CONFIG_HOTPLUG_CPU
  4.1293 -
  4.1294 -static void handle_vcpu_hotplug_event(
  4.1295 -	struct xenbus_watch *watch, const char **vec, unsigned int len)
  4.1296 -{
  4.1297 -	int err, cpu;
  4.1298 -	char dir[32], state[32];
  4.1299 -	char *cpustr;
  4.1300 -	const char *node = vec[XS_WATCH_PATH];
  4.1301 -
  4.1302 -	if ((cpustr = strstr(node, "cpu/")) == NULL)
  4.1303 -		return;
  4.1304 -
  4.1305 -	sscanf(cpustr, "cpu/%d", &cpu);
  4.1306 -
  4.1307 -	sprintf(dir, "cpu/%d", cpu);
  4.1308 -	err = xenbus_scanf(NULL, dir, "availability", "%s", state);
  4.1309 -	if (err != 1) {
  4.1310 -		printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
  4.1311 -		return;
  4.1312 -	}
  4.1313 -
  4.1314 -	if (strcmp(state, "online") == 0)
  4.1315 -		(void)cpu_up(cpu);
  4.1316 -	else if (strcmp(state, "offline") == 0)
  4.1317 -		(void)cpu_down(cpu);
  4.1318 -	else
  4.1319 -		printk(KERN_ERR "XENBUS: unknown state(%s) on node(%s)\n",
  4.1320 -		       state, node);
  4.1321 -}
  4.1322 -
  4.1323 -static int setup_cpu_watcher(struct notifier_block *notifier,
  4.1324 -			      unsigned long event, void *data)
  4.1325 -{
  4.1326 -	static struct xenbus_watch cpu_watch = {
  4.1327 -		.node = "cpu",
  4.1328 -		.callback = handle_vcpu_hotplug_event };
  4.1329 -	(void)register_xenbus_watch(&cpu_watch);
  4.1330 -	return NOTIFY_DONE;
  4.1331 -}
  4.1332 -
  4.1333 -static int __init setup_vcpu_hotplug_event(void)
  4.1334 -{
  4.1335 -	static struct notifier_block xsn_cpu = {
  4.1336 -		.notifier_call = setup_cpu_watcher };
  4.1337 -	register_xenstore_notifier(&xsn_cpu);
  4.1338 -	return 0;
  4.1339 -}
  4.1340 -
  4.1341 -subsys_initcall(setup_vcpu_hotplug_event);
  4.1342 -
  4.1343 -int __cpu_disable(void)
  4.1344 -{
  4.1345 -	cpumask_t map = cpu_online_map;
  4.1346 -	int cpu = smp_processor_id();
  4.1347 -
  4.1348 -	/*
  4.1349 -	 * Perhaps use cpufreq to drop frequency, but that could go
  4.1350 -	 * into generic code.
  4.1351 - 	 *
  4.1352 -	 * We won't take down the boot processor on i386 due to some
  4.1353 -	 * interrupts only being able to be serviced by the BSP.
  4.1354 -	 * Especially so if we're not using an IOAPIC	-zwane
  4.1355 -	 */
  4.1356 -	if (cpu == 0)
  4.1357 -		return -EBUSY;
  4.1358 -
  4.1359 -	cpu_clear(cpu, map);
  4.1360 -	fixup_irqs(map);
  4.1361 -
  4.1362 -	/* It's now safe to remove this processor from the online map */
  4.1363 -	cpu_clear(cpu, cpu_online_map);
  4.1364 -
  4.1365 -	return 0;
  4.1366 -}
  4.1367 -
  4.1368 -void __cpu_die(unsigned int cpu)
  4.1369 -{
  4.1370 -	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
  4.1371 -		current->state = TASK_UNINTERRUPTIBLE;
  4.1372 -		schedule_timeout(HZ/10);
  4.1373 -	}
  4.1374 -
  4.1375 -	xen_smp_intr_exit(cpu);
  4.1376 -
  4.1377 -#ifdef CONFIG_SMP_ALTERNATIVES
  4.1378 -	if (num_online_cpus() == 1)
  4.1379 -		unprepare_for_smp();
  4.1380 -#endif
  4.1381 -}
  4.1382 -
  4.1383 -#else /* ... !CONFIG_HOTPLUG_CPU */
  4.1384 -int __cpu_disable(void)
  4.1385 -{
  4.1386 -	return -ENOSYS;
  4.1387 -}
  4.1388 -
  4.1389 -void __cpu_die(unsigned int cpu)
  4.1390 -{
  4.1391 -	/* We said "no" in __cpu_disable */
  4.1392 -	BUG();
  4.1393 -}
  4.1394 -#endif /* CONFIG_HOTPLUG_CPU */
  4.1395 -
  4.1396 -int __devinit __cpu_up(unsigned int cpu)
  4.1397 -{
  4.1398 -	/* In case one didn't come up */
  4.1399 -	if (!cpu_isset(cpu, cpu_callin_map)) {
  4.1400 -		printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
  4.1401 -		local_irq_enable();
  4.1402 -		return -EIO;
  4.1403 -	}
  4.1404 -
  4.1405 -#ifdef CONFIG_SMP_ALTERNATIVES
  4.1406 -	if (num_online_cpus() == 1)
  4.1407 -		prepare_for_smp();
  4.1408 -#endif
  4.1409 -
  4.1410 -	xen_smp_intr_init(cpu);
  4.1411 -	cpu_set(cpu, smp_commenced_mask);
  4.1412 -	cpu_set(cpu, cpu_online_map);
  4.1413 -	HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
  4.1414 -
  4.1415 -	return 0;
  4.1416 -}
  4.1417 -
  4.1418 -void __init smp_cpus_done(unsigned int max_cpus)
  4.1419 -{
  4.1420 -#if 1
  4.1421 -#else
  4.1422 -#ifdef CONFIG_X86_IO_APIC
  4.1423 -	setup_ioapic_dest();
  4.1424 -#endif
  4.1425 -	zap_low_mappings();
  4.1426 -	/*
  4.1427 -	 * Disable executability of the SMP trampoline:
  4.1428 -	 */
  4.1429 -	set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
  4.1430 -#endif
  4.1431 -}
  4.1432 -
  4.1433 -extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
  4.1434 -extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
  4.1435 -
  4.1436 -extern void local_setup_timer(unsigned int cpu);
  4.1437 -extern void local_teardown_timer(unsigned int cpu);
  4.1438 -
  4.1439 -static void xen_smp_intr_init(unsigned int cpu)
  4.1440 -{
  4.1441 -	per_cpu(resched_irq, cpu) =
  4.1442 -		bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu);
  4.1443 -	sprintf(resched_name[cpu], "resched%d", cpu);
  4.1444 -	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
  4.1445 -	                   SA_INTERRUPT, resched_name[cpu], NULL));
  4.1446 -
  4.1447 -	per_cpu(callfunc_irq, cpu) =
  4.1448 -		bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu);
  4.1449 -	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
  4.1450 -	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
  4.1451 -	                   smp_call_function_interrupt,
  4.1452 -	                   SA_INTERRUPT, callfunc_name[cpu], NULL));
  4.1453 -
  4.1454 -	if (cpu != 0)
  4.1455 -		local_setup_timer(cpu);
  4.1456 -}
  4.1457 -
  4.1458 -static void xen_smp_intr_exit(unsigned int cpu)
  4.1459 -{
  4.1460 -	if (cpu != 0)
  4.1461 -		local_teardown_timer(cpu);
  4.1462 -
  4.1463 -	free_irq(per_cpu(resched_irq, cpu), NULL);
  4.1464 -	unbind_ipi_from_irq(RESCHEDULE_VECTOR, cpu);
  4.1465 -
  4.1466 -	free_irq(per_cpu(callfunc_irq, cpu), NULL);
  4.1467 -	unbind_ipi_from_irq(CALL_FUNCTION_VECTOR, cpu);
  4.1468 -}
  4.1469 -
  4.1470 -void vcpu_prepare(int vcpu)
  4.1471 -{
  4.1472 -	extern void hypervisor_callback(void);
  4.1473 -	extern void failsafe_callback(void);
  4.1474 -	extern void smp_trap_init(trap_info_t *);
  4.1475 -	vcpu_guest_context_t ctxt;
  4.1476 -	struct task_struct *idle = idle_task(vcpu);
  4.1477 -
  4.1478 -	if (vcpu == 0)
  4.1479 -		return;
  4.1480 -
  4.1481 -	memset(&ctxt, 0, sizeof(ctxt));
  4.1482 -
  4.1483 -	ctxt.user_regs.ds = __USER_DS;
  4.1484 -	ctxt.user_regs.es = __USER_DS;
  4.1485 -	ctxt.user_regs.fs = 0;
  4.1486 -	ctxt.user_regs.gs = 0;
  4.1487 -	ctxt.user_regs.ss = __KERNEL_DS;
  4.1488 -	ctxt.user_regs.cs = __KERNEL_CS;
  4.1489 -	ctxt.user_regs.eip = (unsigned long)cpu_idle;
  4.1490 -	ctxt.user_regs.esp = idle->thread.esp;
  4.1491 -	ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING1;
  4.1492 -
  4.1493 -	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
  4.1494 -
  4.1495 -	smp_trap_init(ctxt.trap_ctxt);
  4.1496 -
  4.1497 -	ctxt.ldt_ents = 0;
  4.1498 -
  4.1499 -	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address);
  4.1500 -	ctxt.gdt_ents      = cpu_gdt_descr[vcpu].size / 8;
  4.1501 -
  4.1502 -	ctxt.kernel_ss = __KERNEL_DS;
  4.1503 -	ctxt.kernel_sp = idle->thread.esp0;
  4.1504 -
  4.1505 -	ctxt.event_callback_cs     = __KERNEL_CS;
  4.1506 -	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
  4.1507 -	ctxt.failsafe_callback_cs  = __KERNEL_CS;
  4.1508 -	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
  4.1509 -
  4.1510 -	ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
  4.1511 -
  4.1512 -	(void)HYPERVISOR_vcpu_op(VCPUOP_initialise, vcpu, &ctxt);
  4.1513 -}
  4.1514 -
  4.1515 -/*
  4.1516 - * Local variables:
  4.1517 - *  c-file-style: "linux"
  4.1518 - *  indent-tabs-mode: t
  4.1519 - *  c-indent-level: 8
  4.1520 - *  c-basic-offset: 8
  4.1521 - *  tab-width: 8
  4.1522 - * End:
  4.1523 - */
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/Makefile	Tue Oct 18 15:40:29 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/Makefile	Tue Oct 18 17:40:31 2005 +0100
     5.3 @@ -15,4 +15,4 @@ obj-y   := evtchn.o fixup.o reboot.o gnt
     5.4  
     5.5  obj-$(CONFIG_PROC_FS) += xen_proc.o
     5.6  obj-$(CONFIG_NET)     += skbuff.o
     5.7 -obj-$(CONFIG_SMP)     += smp.o
     5.8 +obj-$(CONFIG_SMP)     += smp.o smpboot.o
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/smpboot.c	Tue Oct 18 17:40:31 2005 +0100
     6.3 @@ -0,0 +1,381 @@
     6.4 +/*
     6.5 + *	Xen SMP booting functions
     6.6 + *
     6.7 + *	See arch/i386/kernel/smpboot.c for copyright and credits for derived
     6.8 + *	portions of this file.
     6.9 + */
    6.10 +
    6.11 +#include <linux/module.h>
    6.12 +#include <linux/config.h>
    6.13 +#include <linux/init.h>
    6.14 +#include <linux/kernel.h>
    6.15 +#include <linux/mm.h>
    6.16 +#include <linux/sched.h>
    6.17 +#include <linux/kernel_stat.h>
    6.18 +#include <linux/smp_lock.h>
    6.19 +#include <linux/irq.h>
    6.20 +#include <linux/bootmem.h>
    6.21 +#include <linux/notifier.h>
    6.22 +#include <linux/cpu.h>
    6.23 +#include <linux/percpu.h>
    6.24 +#include <asm/desc.h>
    6.25 +#include <asm/arch_hooks.h>
    6.26 +#include <asm/pgalloc.h>
    6.27 +#include <asm-xen/evtchn.h>
    6.28 +#include <asm-xen/xen-public/vcpu.h>
    6.29 +#include <asm-xen/xenbus.h>
    6.30 +
    6.31 +#ifdef CONFIG_SMP_ALTERNATIVES
    6.32 +#include <asm/smp_alt.h>
    6.33 +#endif
    6.34 +
    6.35 +extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
    6.36 +extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
    6.37 +
    6.38 +extern void local_setup_timer(unsigned int cpu);
    6.39 +extern void local_teardown_timer(unsigned int cpu);
    6.40 +
    6.41 +extern void hypervisor_callback(void);
    6.42 +extern void failsafe_callback(void);
    6.43 +extern void system_call(void);
    6.44 +extern void smp_trap_init(trap_info_t *);
    6.45 +
    6.46 +extern cpumask_t cpu_initialized;
    6.47 +
    6.48 +/* Number of siblings per CPU package */
    6.49 +int smp_num_siblings = 1;
    6.50 +int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
    6.51 +EXPORT_SYMBOL(phys_proc_id);
    6.52 +int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
    6.53 +EXPORT_SYMBOL(cpu_core_id);
    6.54 +
    6.55 +cpumask_t cpu_online_map;
    6.56 +EXPORT_SYMBOL(cpu_online_map);
    6.57 +cpumask_t cpu_possible_map;
    6.58 +EXPORT_SYMBOL(cpu_possible_map);
    6.59 +
    6.60 +struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
    6.61 +EXPORT_SYMBOL(cpu_data);
    6.62 +
    6.63 +#ifdef CONFIG_HOTPLUG_CPU
    6.64 +DEFINE_PER_CPU(int, cpu_state) = { 0 };
    6.65 +#endif
    6.66 +
    6.67 +static DEFINE_PER_CPU(int, resched_irq);
    6.68 +static DEFINE_PER_CPU(int, callfunc_irq);
    6.69 +static char resched_name[NR_CPUS][15];
    6.70 +static char callfunc_name[NR_CPUS][15];
    6.71 +
    6.72 +u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    6.73 +
    6.74 +void *xquad_portio;
    6.75 +
    6.76 +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
    6.77 +cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
    6.78 +EXPORT_SYMBOL(cpu_core_map);
    6.79 +
    6.80 +#ifdef __i386__
    6.81 +u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = 0xff };
    6.82 +EXPORT_SYMBOL(x86_cpu_to_apicid);
    6.83 +#else
    6.84 +unsigned int maxcpus = NR_CPUS;
    6.85 +#endif
    6.86 +
    6.87 +void __init smp_alloc_memory(void)
    6.88 +{
    6.89 +}
    6.90 +
    6.91 +static void xen_smp_intr_init(unsigned int cpu)
    6.92 +{
    6.93 +	per_cpu(resched_irq, cpu) =
    6.94 +		bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu);
    6.95 +	sprintf(resched_name[cpu], "resched%d", cpu);
    6.96 +	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
    6.97 +	                   SA_INTERRUPT, resched_name[cpu], NULL));
    6.98 +
    6.99 +	per_cpu(callfunc_irq, cpu) =
   6.100 +		bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu);
   6.101 +	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
   6.102 +	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
   6.103 +	                   smp_call_function_interrupt,
   6.104 +	                   SA_INTERRUPT, callfunc_name[cpu], NULL));
   6.105 +
   6.106 +	if (cpu != 0)
   6.107 +		local_setup_timer(cpu);
   6.108 +}
   6.109 +
   6.110 +#ifdef CONFIG_HOTPLUG_CPU
   6.111 +static void xen_smp_intr_exit(unsigned int cpu)
   6.112 +{
   6.113 +	if (cpu != 0)
   6.114 +		local_teardown_timer(cpu);
   6.115 +
   6.116 +	free_irq(per_cpu(resched_irq, cpu), NULL);
   6.117 +	unbind_ipi_from_irq(RESCHEDULE_VECTOR, cpu);
   6.118 +
   6.119 +	free_irq(per_cpu(callfunc_irq, cpu), NULL);
   6.120 +	unbind_ipi_from_irq(CALL_FUNCTION_VECTOR, cpu);
   6.121 +}
   6.122 +#endif
   6.123 +
   6.124 +static void cpu_bringup(void)
   6.125 +{
   6.126 +	if (!cpu_isset(smp_processor_id(), cpu_initialized))
   6.127 +		cpu_init();
   6.128 +	local_irq_enable();
   6.129 +	cpu_idle();
   6.130 +}
   6.131 +
   6.132 +void vcpu_prepare(int vcpu)
   6.133 +{
   6.134 +	vcpu_guest_context_t ctxt;
   6.135 +	struct task_struct *idle = idle_task(vcpu);
   6.136 +
   6.137 +	if (vcpu == 0)
   6.138 +		return;
   6.139 +
   6.140 +	memset(&ctxt, 0, sizeof(ctxt));
   6.141 +
   6.142 +	ctxt.flags = VGCF_IN_KERNEL;
   6.143 +	ctxt.user_regs.ds = __USER_DS;
   6.144 +	ctxt.user_regs.es = __USER_DS;
   6.145 +	ctxt.user_regs.fs = 0;
   6.146 +	ctxt.user_regs.gs = 0;
   6.147 +	ctxt.user_regs.ss = __KERNEL_DS;
   6.148 +	ctxt.user_regs.eip = (unsigned long)cpu_bringup;
   6.149 +	ctxt.user_regs.eflags = X86_EFLAGS_IF | 0x1000; /* IOPL_RING1 */
   6.150 +
   6.151 +	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
   6.152 +
   6.153 +	smp_trap_init(ctxt.trap_ctxt);
   6.154 +
   6.155 +	ctxt.ldt_ents = 0;
   6.156 +
   6.157 +	ctxt.gdt_frames[0] = virt_to_mfn(cpu_gdt_descr[vcpu].address);
   6.158 +	ctxt.gdt_ents      = cpu_gdt_descr[vcpu].size / 8;
   6.159 +
   6.160 +#ifdef __i386__
   6.161 +	ctxt.user_regs.cs = __KERNEL_CS;
   6.162 +	ctxt.user_regs.esp = idle->thread.esp;
   6.163 +
   6.164 +	ctxt.kernel_ss = __KERNEL_DS;
   6.165 +	ctxt.kernel_sp = idle->thread.esp0;
   6.166 +
   6.167 +	ctxt.event_callback_cs     = __KERNEL_CS;
   6.168 +	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   6.169 +	ctxt.failsafe_callback_cs  = __KERNEL_CS;
   6.170 +	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   6.171 +
   6.172 +	ctxt.ctrlreg[3] = virt_to_mfn(swapper_pg_dir) << PAGE_SHIFT;
   6.173 +#else
   6.174 +	ctxt.user_regs.cs = __KERNEL_CS | 3;
   6.175 +	ctxt.user_regs.esp = idle->thread.rsp;
   6.176 +
   6.177 +	ctxt.kernel_ss = __KERNEL_DS;
   6.178 +	ctxt.kernel_sp = idle->thread.rsp0;
   6.179 +
   6.180 +	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   6.181 +	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   6.182 +	ctxt.syscall_callback_eip  = (unsigned long)system_call;
   6.183 +
   6.184 +	ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT;
   6.185 +#endif
   6.186 +
   6.187 +	BUG_ON(HYPERVISOR_vcpu_op(VCPUOP_initialise, vcpu, &ctxt));
   6.188 +}
   6.189 +
   6.190 +void __init smp_prepare_cpus(unsigned int max_cpus)
   6.191 +{
   6.192 +	int cpu;
   6.193 +	struct task_struct *idle;
   6.194 +
   6.195 +	if (max_cpus == 0) {
   6.196 +		xen_start_info->n_vcpu = 1;
   6.197 +		return;
   6.198 +	}
   6.199 +
   6.200 +	if (max_cpus < xen_start_info->n_vcpu)
   6.201 +		xen_start_info->n_vcpu = max_cpus;
   6.202 +
   6.203 +	xen_smp_intr_init(0);
   6.204 +
   6.205 +	for (cpu = 1; cpu < xen_start_info->n_vcpu; cpu++) {
   6.206 +		cpu_data[cpu] = boot_cpu_data;
   6.207 +		cpu_2_logical_apicid[cpu] = cpu;
   6.208 +		x86_cpu_to_apicid[cpu] = cpu;
   6.209 +
   6.210 +		idle = fork_idle(cpu);
   6.211 +		if (IS_ERR(idle))
   6.212 +			panic("failed fork for CPU %d", cpu);
   6.213 +
   6.214 +		irq_ctx_init(cpu);
   6.215 +
   6.216 +		cpu_gdt_descr[cpu].address =
   6.217 +			__get_free_page(GFP_KERNEL|__GFP_ZERO);
   6.218 +		BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
   6.219 +		cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
   6.220 +		memcpy((void *)cpu_gdt_descr[cpu].address,
   6.221 +		       (void *)cpu_gdt_descr[0].address,
   6.222 +		       cpu_gdt_descr[0].size);
   6.223 +		make_page_readonly((void *)cpu_gdt_descr[cpu].address);
   6.224 +
   6.225 +		cpu_set(cpu, cpu_possible_map);
   6.226 +
   6.227 +		vcpu_prepare(cpu);
   6.228 +	}
   6.229 +
   6.230 +	/* Currently, Xen gives no dynamic NUMA/HT info. */
   6.231 +	for (cpu = 0; cpu < NR_CPUS; cpu++) {
   6.232 +		cpus_clear(cpu_sibling_map[cpu]);
   6.233 +		cpus_clear(cpu_core_map[cpu]);
   6.234 +	}
   6.235 +
   6.236 +#ifdef CONFIG_X86_IO_APIC
   6.237 +	/*
   6.238 +	 * Here we can be sure that there is an IO-APIC in the system. Let's
   6.239 +	 * go and set it up:
   6.240 +	 */
   6.241 +	if (!skip_ioapic_setup && nr_ioapics)
   6.242 +		setup_IO_APIC();
   6.243 +#endif
   6.244 +}
   6.245 +
   6.246 +void __devinit smp_prepare_boot_cpu(void)
   6.247 +{
   6.248 +	cpu_possible_map = cpumask_of_cpu(0);
   6.249 +	cpu_online_map   = cpumask_of_cpu(0);
   6.250 +
   6.251 +	cpu_data[0] = boot_cpu_data;
   6.252 +	cpu_2_logical_apicid[0] = 0;
   6.253 +	x86_cpu_to_apicid[0] = 0;
   6.254 +
   6.255 +	current_thread_info()->cpu = 0;
   6.256 +	cpus_clear(cpu_sibling_map[0]);
   6.257 +	cpu_set(0, cpu_sibling_map[0]);
   6.258 +
   6.259 +	cpus_clear(cpu_core_map[0]);
   6.260 +	cpu_set(0, cpu_core_map[0]);
   6.261 +}
   6.262 +
   6.263 +#ifdef CONFIG_HOTPLUG_CPU
   6.264 +
   6.265 +static void handle_vcpu_hotplug_event(
   6.266 +	struct xenbus_watch *watch, const char **vec, unsigned int len)
   6.267 +{
   6.268 +	int err, cpu;
   6.269 +	char dir[32], state[32];
   6.270 +	char *cpustr;
   6.271 +	const char *node = vec[XS_WATCH_PATH];
   6.272 +
   6.273 +	if ((cpustr = strstr(node, "cpu/")) == NULL)
   6.274 +		return;
   6.275 +
   6.276 +	sscanf(cpustr, "cpu/%d", &cpu);
   6.277 +
   6.278 +	sprintf(dir, "cpu/%d", cpu);
   6.279 +	err = xenbus_scanf(NULL, dir, "availability", "%s", state);
   6.280 +	if (err != 1) {
   6.281 +		printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
   6.282 +		return;
   6.283 +	}
   6.284 +
   6.285 +	if (strcmp(state, "online") == 0)
   6.286 +		(void)cpu_up(cpu);
   6.287 +	else if (strcmp(state, "offline") == 0)
   6.288 +		(void)cpu_down(cpu);
   6.289 +	else
   6.290 +		printk(KERN_ERR "XENBUS: unknown state(%s) on node(%s)\n",
   6.291 +		       state, node);
   6.292 +}
   6.293 +
   6.294 +static int setup_cpu_watcher(struct notifier_block *notifier,
   6.295 +			      unsigned long event, void *data)
   6.296 +{
   6.297 +	static struct xenbus_watch cpu_watch = {
   6.298 +		.node = "cpu",
   6.299 +		.callback = handle_vcpu_hotplug_event };
   6.300 +	(void)register_xenbus_watch(&cpu_watch);
   6.301 +	return NOTIFY_DONE;
   6.302 +}
   6.303 +
   6.304 +static int __init setup_vcpu_hotplug_event(void)
   6.305 +{
   6.306 +	static struct notifier_block xsn_cpu = {
   6.307 +		.notifier_call = setup_cpu_watcher };
   6.308 +	register_xenstore_notifier(&xsn_cpu);
   6.309 +	return 0;
   6.310 +}
   6.311 +
   6.312 +subsys_initcall(setup_vcpu_hotplug_event);
   6.313 +
   6.314 +int __cpu_disable(void)
   6.315 +{
   6.316 +	cpumask_t map = cpu_online_map;
   6.317 +	int cpu = smp_processor_id();
   6.318 +
   6.319 +	if (cpu == 0)
   6.320 +		return -EBUSY;
   6.321 +
   6.322 +	cpu_clear(cpu, map);
   6.323 +	fixup_irqs(map);
   6.324 +	cpu_clear(cpu, cpu_online_map);
   6.325 +
   6.326 +	return 0;
   6.327 +}
   6.328 +
   6.329 +void __cpu_die(unsigned int cpu)
   6.330 +{
   6.331 +	while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
   6.332 +		current->state = TASK_UNINTERRUPTIBLE;
   6.333 +		schedule_timeout(HZ/10);
   6.334 +	}
   6.335 +
   6.336 +	xen_smp_intr_exit(cpu);
   6.337 +
   6.338 +#ifdef CONFIG_SMP_ALTERNATIVES
   6.339 +	if (num_online_cpus() == 1)
   6.340 +		unprepare_for_smp();
   6.341 +#endif
   6.342 +}
   6.343 +
   6.344 +#else /* ... !CONFIG_HOTPLUG_CPU */
   6.345 +
   6.346 +int __cpu_disable(void)
   6.347 +{
   6.348 +	return -ENOSYS;
   6.349 +}
   6.350 +
   6.351 +void __cpu_die(unsigned int cpu)
   6.352 +{
   6.353 +	BUG();
   6.354 +}
   6.355 +
   6.356 +#endif /* CONFIG_HOTPLUG_CPU */
   6.357 +
   6.358 +int __devinit __cpu_up(unsigned int cpu)
   6.359 +{
   6.360 +#ifdef CONFIG_SMP_ALTERNATIVES
   6.361 +	if (num_online_cpus() == 1)
   6.362 +		prepare_for_smp();
   6.363 +#endif
   6.364 +
   6.365 +	xen_smp_intr_init(cpu);
   6.366 +	cpu_set(cpu, cpu_online_map);
   6.367 +	HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
   6.368 +
   6.369 +	return 0;
   6.370 +}
   6.371 +
   6.372 +void __init smp_cpus_done(unsigned int max_cpus)
   6.373 +{
   6.374 +}
   6.375 +
   6.376 +/*
   6.377 + * Local variables:
   6.378 + *  c-file-style: "linux"
   6.379 + *  indent-tabs-mode: t
   6.380 + *  c-indent-level: 8
   6.381 + *  c-basic-offset: 8
   6.382 + *  tab-width: 8
   6.383 + * End:
   6.384 + */
     7.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile	Tue Oct 18 15:40:29 2005 +0100
     7.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile	Tue Oct 18 17:40:31 2005 +0100
     7.3 @@ -25,7 +25,7 @@ obj-$(CONFIG_ACPI_BOOT)		+= acpi/
     7.4  c-obj-$(CONFIG_X86_MSR)		+= msr.o
     7.5  obj-$(CONFIG_MICROCODE)		+= microcode.o
     7.6  obj-$(CONFIG_X86_CPUID)		+= cpuid.o
     7.7 -obj-$(CONFIG_SMP)		+= smp.o smpboot.o
     7.8 +obj-$(CONFIG_SMP)		+= smp.o
     7.9  obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
    7.10  c-obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
    7.11  obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
     8.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Tue Oct 18 15:40:29 2005 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,1253 +0,0 @@
     8.4 -/*
     8.5 - *	x86 SMP booting functions
     8.6 - *
     8.7 - *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
     8.8 - *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
     8.9 - *	Copyright 2001 Andi Kleen, SuSE Labs.
    8.10 - *
    8.11 - *	Much of the core SMP work is based on previous work by Thomas Radke, to
    8.12 - *	whom a great many thanks are extended.
    8.13 - *
    8.14 - *	Thanks to Intel for making available several different Pentium,
    8.15 - *	Pentium Pro and Pentium-II/Xeon MP machines.
    8.16 - *	Original development of Linux SMP code supported by Caldera.
    8.17 - *
    8.18 - *	This code is released under the GNU General Public License version 2
    8.19 - *
    8.20 - *	Fixes
    8.21 - *		Felix Koop	:	NR_CPUS used properly
    8.22 - *		Jose Renau	:	Handle single CPU case.
    8.23 - *		Alan Cox	:	By repeated request 8) - Total BogoMIP report.
    8.24 - *		Greg Wright	:	Fix for kernel stacks panic.
    8.25 - *		Erich Boleyn	:	MP v1.4 and additional changes.
    8.26 - *	Matthias Sattler	:	Changes for 2.1 kernel map.
    8.27 - *	Michel Lespinasse	:	Changes for 2.1 kernel map.
    8.28 - *	Michael Chastain	:	Change trampoline.S to gnu as.
    8.29 - *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
    8.30 - *		Ingo Molnar	:	Added APIC timers, based on code
    8.31 - *					from Jose Renau
    8.32 - *		Ingo Molnar	:	various cleanups and rewrites
    8.33 - *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
    8.34 - *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
    8.35 - *	Andi Kleen		:	Changed for SMP boot into long mode.
    8.36 - *		Rusty Russell	:	Hacked into shape for new "hotplug" boot process.
    8.37 - *      Andi Kleen              :       Converted to new state machine.
    8.38 - *					Various cleanups.
    8.39 - *					Probably mostly hotplug CPU ready now.
    8.40 - */
    8.41 -
    8.42 -
    8.43 -#include <linux/config.h>
    8.44 -#include <linux/init.h>
    8.45 -
    8.46 -#include <linux/mm.h>
    8.47 -#include <linux/kernel_stat.h>
    8.48 -#include <linux/smp_lock.h>
    8.49 -#include <linux/irq.h>
    8.50 -#include <linux/bootmem.h>
    8.51 -#include <linux/thread_info.h>
    8.52 -#include <linux/module.h>
    8.53 -#ifdef CONFIG_XEN
    8.54 -#include <linux/interrupt.h>
    8.55 -#endif
    8.56 -
    8.57 -#include <linux/delay.h>
    8.58 -#include <linux/mc146818rtc.h>
    8.59 -#include <asm/mtrr.h>
    8.60 -#include <asm/pgalloc.h>
    8.61 -#include <asm/desc.h>
    8.62 -#include <asm/kdebug.h>
    8.63 -#include <asm/tlbflush.h>
    8.64 -#include <asm/proto.h>
    8.65 -#include <asm/nmi.h>
    8.66 -#ifdef CONFIG_XEN
    8.67 -#include <asm/arch_hooks.h>
    8.68 -#include <asm-xen/evtchn.h>
    8.69 -#include <asm-xen/xen-public/vcpu.h>
    8.70 -#endif
    8.71 -
    8.72 -/* Change for real CPU hotplug. Note other files need to be fixed
    8.73 -   first too. */
    8.74 -#define __cpuinit __init
    8.75 -#define __cpuinitdata __initdata
    8.76 -
    8.77 -#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
    8.78 -	unsigned int maxcpus = NR_CPUS;
    8.79 -#endif
    8.80 -
    8.81 -/* Number of siblings per CPU package */
    8.82 -int smp_num_siblings = 1;
    8.83 -/* Package ID of each logical CPU */
    8.84 -u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    8.85 -u8 cpu_core_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    8.86 -EXPORT_SYMBOL(phys_proc_id);
    8.87 -EXPORT_SYMBOL(cpu_core_id);
    8.88 -
    8.89 -/* Bitmask of currently online CPUs */
    8.90 -cpumask_t cpu_online_map;
    8.91 -
    8.92 -EXPORT_SYMBOL(cpu_online_map);
    8.93 -
    8.94 -/*
    8.95 - * Private maps to synchronize booting between AP and BP.
    8.96 - * Probably not needed anymore, but it makes for easier debugging. -AK
    8.97 - */
    8.98 -cpumask_t cpu_callin_map;
    8.99 -cpumask_t cpu_callout_map;
   8.100 -
   8.101 -cpumask_t cpu_possible_map;
   8.102 -EXPORT_SYMBOL(cpu_possible_map);
   8.103 -
   8.104 -/* Per CPU bogomips and other parameters */
   8.105 -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
   8.106 -
   8.107 -/* Set when the idlers are all forked */
   8.108 -int smp_threads_ready;
   8.109 -
   8.110 -cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
   8.111 -cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
   8.112 -EXPORT_SYMBOL(cpu_core_map);
   8.113 -
   8.114 -#ifndef CONFIG_XEN
   8.115 -/*
   8.116 - * Trampoline 80x86 program as an array.
   8.117 - */
   8.118 -
   8.119 -extern unsigned char trampoline_data[];
   8.120 -extern unsigned char trampoline_end[];
   8.121 -
   8.122 -/*
   8.123 - * Currently trivial. Write the real->protected mode
   8.124 - * bootstrap into the page concerned. The caller
   8.125 - * has made sure it's suitably aligned.
   8.126 - */
   8.127 -
   8.128 -static unsigned long __cpuinit setup_trampoline(void)
   8.129 -{
   8.130 -	void *tramp = __va(SMP_TRAMPOLINE_BASE); 
   8.131 -	memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
   8.132 -	return virt_to_phys(tramp);
   8.133 -}
   8.134 -#endif
   8.135 -
   8.136 -/*
   8.137 - * The bootstrap kernel entry code has set these up. Save them for
   8.138 - * a given CPU
   8.139 - */
   8.140 -
   8.141 -static void __cpuinit smp_store_cpu_info(int id)
   8.142 -{
   8.143 -	struct cpuinfo_x86 *c = cpu_data + id;
   8.144 -
   8.145 -	*c = boot_cpu_data;
   8.146 -	identify_cpu(c);
   8.147 -	print_cpu_info(c);
   8.148 -}
   8.149 -
   8.150 -#ifndef CONFIG_XEN
   8.151 -/*
   8.152 - * New Funky TSC sync algorithm borrowed from IA64.
   8.153 - * Main advantage is that it doesn't reset the TSCs fully and
   8.154 - * in general looks more robust and it works better than my earlier
   8.155 - * attempts. I believe it was written by David Mosberger. Some minor
   8.156 - * adjustments for x86-64 by me -AK
   8.157 - *
   8.158 - * Original comment reproduced below.
   8.159 - *
   8.160 - * Synchronize TSC of the current (slave) CPU with the TSC of the
   8.161 - * MASTER CPU (normally the time-keeper CPU).  We use a closed loop to
   8.162 - * eliminate the possibility of unaccounted-for errors (such as
   8.163 - * getting a machine check in the middle of a calibration step).  The
   8.164 - * basic idea is for the slave to ask the master what itc value it has
   8.165 - * and to read its own itc before and after the master responds.  Each
   8.166 - * iteration gives us three timestamps:
   8.167 - *
   8.168 - *	slave		master
   8.169 - *
   8.170 - *	t0 ---\
   8.171 - *             ---\
   8.172 - *		   --->
   8.173 - *			tm
   8.174 - *		   /---
   8.175 - *	       /---
   8.176 - *	t1 <---
   8.177 - *
   8.178 - *
   8.179 - * The goal is to adjust the slave's TSC such that tm falls exactly
   8.180 - * half-way between t0 and t1.  If we achieve this, the clocks are
   8.181 - * synchronized provided the interconnect between the slave and the
   8.182 - * master is symmetric.  Even if the interconnect were asymmetric, we
   8.183 - * would still know that the synchronization error is smaller than the
   8.184 - * roundtrip latency (t0 - t1).
   8.185 - *
   8.186 - * When the interconnect is quiet and symmetric, this lets us
   8.187 - * synchronize the TSC to within one or two cycles.  However, we can
   8.188 - * only *guarantee* that the synchronization is accurate to within a
   8.189 - * round-trip time, which is typically in the range of several hundred
   8.190 - * cycles (e.g., ~500 cycles).  In practice, this means that the TSCs
   8.191 - * are usually almost perfectly synchronized, but we shouldn't assume
   8.192 - * that the accuracy is much better than half a micro second or so.
   8.193 - *
   8.194 - * [there are other errors like the latency of RDTSC and of the
   8.195 - * WRMSR. These can also account to hundreds of cycles. So it's
   8.196 - * probably worse. It claims 153 cycles error on a dual Opteron,
   8.197 - * but I suspect the numbers are actually somewhat worse -AK]
   8.198 - */
   8.199 -
   8.200 -#define MASTER	0
   8.201 -#define SLAVE	(SMP_CACHE_BYTES/8)
   8.202 -
   8.203 -/* Intentionally don't use cpu_relax() while TSC synchronization
   8.204 -   because we don't want to go into funky power save modi or cause
   8.205 -   hypervisors to schedule us away.  Going to sleep would likely affect
   8.206 -   latency and low latency is the primary objective here. -AK */
   8.207 -#define no_cpu_relax() barrier()
   8.208 -
   8.209 -static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
   8.210 -static volatile __cpuinitdata unsigned long go[SLAVE + 1];
   8.211 -static int notscsync __cpuinitdata;
   8.212 -
   8.213 -#undef DEBUG_TSC_SYNC
   8.214 -
   8.215 -#define NUM_ROUNDS	64	/* magic value */
   8.216 -#define NUM_ITERS	5	/* likewise */
   8.217 -
   8.218 -/* Callback on boot CPU */
   8.219 -static __cpuinit void sync_master(void *arg)
   8.220 -{
   8.221 -	unsigned long flags, i;
   8.222 -
   8.223 -	if (smp_processor_id() != boot_cpu_id)
   8.224 -		return;
   8.225 -
   8.226 -	go[MASTER] = 0;
   8.227 -
   8.228 -	local_irq_save(flags);
   8.229 -	{
   8.230 -		for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
   8.231 -			while (!go[MASTER])
   8.232 -				no_cpu_relax();
   8.233 -			go[MASTER] = 0;
   8.234 -			rdtscll(go[SLAVE]);
   8.235 -		}
   8.236 -	}
   8.237 -	local_irq_restore(flags);
   8.238 -}
   8.239 -
   8.240 -/*
   8.241 - * Return the number of cycles by which our tsc differs from the tsc
   8.242 - * on the master (time-keeper) CPU.  A positive number indicates our
   8.243 - * tsc is ahead of the master, negative that it is behind.
   8.244 - */
   8.245 -static inline long
   8.246 -get_delta(long *rt, long *master)
   8.247 -{
   8.248 -	unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
   8.249 -	unsigned long tcenter, t0, t1, tm;
   8.250 -	int i;
   8.251 -
   8.252 -	for (i = 0; i < NUM_ITERS; ++i) {
   8.253 -		rdtscll(t0);
   8.254 -		go[MASTER] = 1;
   8.255 -		while (!(tm = go[SLAVE]))
   8.256 -			no_cpu_relax();
   8.257 -		go[SLAVE] = 0;
   8.258 -		rdtscll(t1);
   8.259 -
   8.260 -		if (t1 - t0 < best_t1 - best_t0)
   8.261 -			best_t0 = t0, best_t1 = t1, best_tm = tm;
   8.262 -	}
   8.263 -
   8.264 -	*rt = best_t1 - best_t0;
   8.265 -	*master = best_tm - best_t0;
   8.266 -
   8.267 -	/* average best_t0 and best_t1 without overflow: */
   8.268 -	tcenter = (best_t0/2 + best_t1/2);
   8.269 -	if (best_t0 % 2 + best_t1 % 2 == 2)
   8.270 -		++tcenter;
   8.271 -	return tcenter - best_tm;
   8.272 -}
   8.273 -
   8.274 -static __cpuinit void sync_tsc(void)
   8.275 -{
   8.276 -	int i, done = 0;
   8.277 -	long delta, adj, adjust_latency = 0;
   8.278 -	unsigned long flags, rt, master_time_stamp, bound;
   8.279 -#if DEBUG_TSC_SYNC
   8.280 -	static struct syncdebug {
   8.281 -		long rt;	/* roundtrip time */
   8.282 -		long master;	/* master's timestamp */
   8.283 -		long diff;	/* difference between midpoint and master's timestamp */
   8.284 -		long lat;	/* estimate of tsc adjustment latency */
   8.285 -	} t[NUM_ROUNDS] __cpuinitdata;
   8.286 -#endif
   8.287 -
   8.288 -	go[MASTER] = 1;
   8.289 -
   8.290 -	smp_call_function(sync_master, NULL, 1, 0);
   8.291 -
   8.292 -	while (go[MASTER])	/* wait for master to be ready */
   8.293 -		no_cpu_relax();
   8.294 -
   8.295 -	spin_lock_irqsave(&tsc_sync_lock, flags);
   8.296 -	{
   8.297 -		for (i = 0; i < NUM_ROUNDS; ++i) {
   8.298 -			delta = get_delta(&rt, &master_time_stamp);
   8.299 -			if (delta == 0) {
   8.300 -				done = 1;	/* let's lock on to this... */
   8.301 -				bound = rt;
   8.302 -			}
   8.303 -
   8.304 -			if (!done) {
   8.305 -				unsigned long t;
   8.306 -				if (i > 0) {
   8.307 -					adjust_latency += -delta;
   8.308 -					adj = -delta + adjust_latency/4;
   8.309 -				} else
   8.310 -					adj = -delta;
   8.311 -
   8.312 -				rdtscll(t);
   8.313 -				wrmsrl(MSR_IA32_TSC, t + adj);
   8.314 -			}
   8.315 -#if DEBUG_TSC_SYNC
   8.316 -			t[i].rt = rt;
   8.317 -			t[i].master = master_time_stamp;
   8.318 -			t[i].diff = delta;
   8.319 -			t[i].lat = adjust_latency/4;
   8.320 -#endif
   8.321 -		}
   8.322 -	}
   8.323 -	spin_unlock_irqrestore(&tsc_sync_lock, flags);
   8.324 -
   8.325 -#if DEBUG_TSC_SYNC
   8.326 -	for (i = 0; i < NUM_ROUNDS; ++i)
   8.327 -		printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
   8.328 -		       t[i].rt, t[i].master, t[i].diff, t[i].lat);
   8.329 -#endif
   8.330 -
   8.331 -	printk(KERN_INFO
   8.332 -	       "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
   8.333 -	       "maxerr %lu cycles)\n",
   8.334 -	       smp_processor_id(), boot_cpu_id, delta, rt);
   8.335 -}
   8.336 -
   8.337 -static void __cpuinit tsc_sync_wait(void)
   8.338 -{
   8.339 -	if (notscsync || !cpu_has_tsc)
   8.340 -		return;
   8.341 -	printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
   8.342 -			boot_cpu_id);
   8.343 -	sync_tsc();
   8.344 -}
   8.345 -
   8.346 -static __init int notscsync_setup(char *s)
   8.347 -{
   8.348 -	notscsync = 1;
   8.349 -	return 0;
   8.350 -}
   8.351 -__setup("notscsync", notscsync_setup);
   8.352 -#endif
   8.353 -
   8.354 -static atomic_t init_deasserted __cpuinitdata;
   8.355 -
   8.356 -/*
   8.357 - * Report back to the Boot Processor.
   8.358 - * Running on AP.
   8.359 - */
   8.360 -void __cpuinit smp_callin(void)
   8.361 -{
   8.362 -	int cpuid, phys_id;
   8.363 -	unsigned long timeout;
   8.364 -
   8.365 -#ifndef CONFIG_XEN
   8.366 -	/*
   8.367 -	 * If waken up by an INIT in an 82489DX configuration
   8.368 -	 * we may get here before an INIT-deassert IPI reaches
   8.369 -	 * our local APIC.  We have to wait for the IPI or we'll
   8.370 -	 * lock up on an APIC access.
   8.371 -	 */
   8.372 -	while (!atomic_read(&init_deasserted))
   8.373 -		cpu_relax();
   8.374 -
   8.375 -#endif
   8.376 -	/*
   8.377 -	 * (This works even if the APIC is not enabled.)
   8.378 -	 */
   8.379 -#ifndef CONFIG_XEN
   8.380 -	phys_id = GET_APIC_ID(apic_read(APIC_ID));
   8.381 -#else
   8.382 -	phys_id = smp_processor_id();
   8.383 -#endif
   8.384 -	cpuid = smp_processor_id();
   8.385 -	if (cpu_isset(cpuid, cpu_callin_map)) {
   8.386 -		panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
   8.387 -					phys_id, cpuid);
   8.388 -	}
   8.389 -	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
   8.390 -
   8.391 -	/*
   8.392 -	 * STARTUP IPIs are fragile beasts as they might sometimes
   8.393 -	 * trigger some glue motherboard logic. Complete APIC bus
   8.394 -	 * silence for 1 second, this overestimates the time the
   8.395 -	 * boot CPU is spending to send the up to 2 STARTUP IPIs
   8.396 -	 * by a factor of two. This should be enough.
   8.397 -	 */
   8.398 -
   8.399 -	/*
   8.400 -	 * Waiting 2s total for startup (udelay is not yet working)
   8.401 -	 */
   8.402 -	timeout = jiffies + 2*HZ;
   8.403 -	while (time_before(jiffies, timeout)) {
   8.404 -		/*
   8.405 -		 * Has the boot CPU finished it's STARTUP sequence?
   8.406 -		 */
   8.407 -		if (cpu_isset(cpuid, cpu_callout_map))
   8.408 -			break;
   8.409 -		cpu_relax();
   8.410 -	}
   8.411 -
   8.412 -	if (!time_before(jiffies, timeout)) {
   8.413 -		panic("smp_callin: CPU%d started up but did not get a callout!\n",
   8.414 -			cpuid);
   8.415 -	}
   8.416 -
   8.417 -#ifndef CONFIG_XEN
   8.418 -	/*
   8.419 -	 * the boot CPU has finished the init stage and is spinning
   8.420 -	 * on callin_map until we finish. We are free to set up this
   8.421 -	 * CPU, first the APIC. (this is probably redundant on most
   8.422 -	 * boards)
   8.423 -	 */
   8.424 -
   8.425 -	Dprintk("CALLIN, before setup_local_APIC().\n");
   8.426 -	setup_local_APIC();
   8.427 -#endif
   8.428 -
   8.429 -	/*
   8.430 -	 * Get our bogomips.
   8.431 -	 */
   8.432 -	calibrate_delay();
   8.433 -	Dprintk("Stack at about %p\n",&cpuid);
   8.434 -
   8.435 -#ifndef CONFIG_XEN
   8.436 -	disable_APIC_timer();
   8.437 -#endif
   8.438 -
   8.439 -	/*
   8.440 -	 * Save our processor parameters
   8.441 -	 */
   8.442 - 	smp_store_cpu_info(cpuid);
   8.443 -
   8.444 -	/*
   8.445 -	 * Allow the master to continue.
   8.446 -	 */
   8.447 -	cpu_set(cpuid, cpu_callin_map);
   8.448 -}
   8.449 -
   8.450 -#ifdef CONFIG_XEN
   8.451 -extern void local_setup_timer(unsigned int cpu);
   8.452 -#endif
   8.453 -
   8.454 -/*
   8.455 - * Setup code on secondary processor (after comming out of the trampoline)
   8.456 - */
   8.457 -void __cpuinit start_secondary(void)
   8.458 -{
   8.459 -	/*
   8.460 -	 * Dont put anything before smp_callin(), SMP
   8.461 -	 * booting is too fragile that we want to limit the
   8.462 -	 * things done here to the most necessary things.
   8.463 -	 */
   8.464 -	cpu_init();
   8.465 -	smp_callin();
   8.466 -
   8.467 -	/* otherwise gcc will move up the smp_processor_id before the cpu_init */
   8.468 -	barrier();
   8.469 -
   8.470 -#ifndef CONFIG_XEN
   8.471 -	Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); 	
   8.472 -	setup_secondary_APIC_clock();
   8.473 -
   8.474 -	Dprintk("cpu %d: enabling apic timer\n", smp_processor_id());
   8.475 -
   8.476 -	if (nmi_watchdog == NMI_IO_APIC) {
   8.477 -		disable_8259A_irq(0);
   8.478 -		enable_NMI_through_LVT0(NULL);
   8.479 -		enable_8259A_irq(0);
   8.480 -	}
   8.481 -
   8.482 -	enable_APIC_timer();
   8.483 -#else
   8.484 -	local_setup_timer(smp_processor_id());
   8.485 -	smp_intr_init();
   8.486 -	local_irq_enable();
   8.487 -#endif
   8.488 -
   8.489 -	/*
   8.490 -	 * Allow the master to continue.
   8.491 -	 */
   8.492 -	cpu_set(smp_processor_id(), cpu_online_map);
   8.493 -	mb();
   8.494 -
   8.495 -#ifndef CONFIG_XEN
   8.496 -	/* Wait for TSC sync to not schedule things before.
   8.497 -	   We still process interrupts, which could see an inconsistent
   8.498 -	   time in that window unfortunately. */
   8.499 -	tsc_sync_wait();
   8.500 -#endif
   8.501 -
   8.502 -	cpu_idle();
   8.503 -}
   8.504 -
   8.505 -extern volatile unsigned long init_rsp;
   8.506 -extern void (*initial_code)(void);
   8.507 -
   8.508 -#ifndef CONFIG_XEN
   8.509 -#if APIC_DEBUG
   8.510 -static void inquire_remote_apic(int apicid)
   8.511 -{
   8.512 -	unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
   8.513 -	char *names[] = { "ID", "VERSION", "SPIV" };
   8.514 -	int timeout, status;
   8.515 -
   8.516 -	printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
   8.517 -
   8.518 -	for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
   8.519 -		printk("... APIC #%d %s: ", apicid, names[i]);
   8.520 -
   8.521 -		/*
   8.522 -		 * Wait for idle.
   8.523 -		 */
   8.524 -		apic_wait_icr_idle();
   8.525 -
   8.526 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
   8.527 -		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
   8.528 -
   8.529 -		timeout = 0;
   8.530 -		do {
   8.531 -			udelay(100);
   8.532 -			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
   8.533 -		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
   8.534 -
   8.535 -		switch (status) {
   8.536 -		case APIC_ICR_RR_VALID:
   8.537 -			status = apic_read(APIC_RRR);
   8.538 -			printk("%08x\n", status);
   8.539 -			break;
   8.540 -		default:
   8.541 -			printk("failed\n");
   8.542 -		}
   8.543 -	}
   8.544 -}
   8.545 -#endif
   8.546 -
   8.547 -/*
   8.548 - * Kick the secondary to wake up.
   8.549 - */
   8.550 -static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int start_rip)
   8.551 -{
   8.552 -	unsigned long send_status = 0, accept_status = 0;
   8.553 -	int maxlvt, timeout, num_starts, j;
   8.554 -
   8.555 -	Dprintk("Asserting INIT.\n");
   8.556 -
   8.557 -	/*
   8.558 -	 * Turn INIT on target chip
   8.559 -	 */
   8.560 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   8.561 -
   8.562 -	/*
   8.563 -	 * Send IPI
   8.564 -	 */
   8.565 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
   8.566 -				| APIC_DM_INIT);
   8.567 -
   8.568 -	Dprintk("Waiting for send to finish...\n");
   8.569 -	timeout = 0;
   8.570 -	do {
   8.571 -		Dprintk("+");
   8.572 -		udelay(100);
   8.573 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   8.574 -	} while (send_status && (timeout++ < 1000));
   8.575 -
   8.576 -	mdelay(10);
   8.577 -
   8.578 -	Dprintk("Deasserting INIT.\n");
   8.579 -
   8.580 -	/* Target chip */
   8.581 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   8.582 -
   8.583 -	/* Send IPI */
   8.584 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
   8.585 -
   8.586 -	Dprintk("Waiting for send to finish...\n");
   8.587 -	timeout = 0;
   8.588 -	do {
   8.589 -		Dprintk("+");
   8.590 -		udelay(100);
   8.591 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   8.592 -	} while (send_status && (timeout++ < 1000));
   8.593 -
   8.594 -	atomic_set(&init_deasserted, 1);
   8.595 -
   8.596 -	/*
   8.597 -	 * Should we send STARTUP IPIs ?
   8.598 -	 *
   8.599 -	 * Determine this based on the APIC version.
   8.600 -	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
   8.601 -	 */
   8.602 -	if (APIC_INTEGRATED(apic_version[phys_apicid]))
   8.603 -		num_starts = 2;
   8.604 -	else
   8.605 -		num_starts = 0;
   8.606 -
   8.607 -	/*
   8.608 -	 * Run STARTUP IPI loop.
   8.609 -	 */
   8.610 -	Dprintk("#startup loops: %d.\n", num_starts);
   8.611 -
   8.612 -	maxlvt = get_maxlvt();
   8.613 -
   8.614 -	for (j = 1; j <= num_starts; j++) {
   8.615 -		Dprintk("Sending STARTUP #%d.\n",j);
   8.616 -		apic_read_around(APIC_SPIV);
   8.617 -		apic_write(APIC_ESR, 0);
   8.618 -		apic_read(APIC_ESR);
   8.619 -		Dprintk("After apic_write.\n");
   8.620 -
   8.621 -		/*
   8.622 -		 * STARTUP IPI
   8.623 -		 */
   8.624 -
   8.625 -		/* Target chip */
   8.626 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   8.627 -
   8.628 -		/* Boot on the stack */
   8.629 -		/* Kick the second */
   8.630 -		apic_write_around(APIC_ICR, APIC_DM_STARTUP
   8.631 -					| (start_rip >> 12));
   8.632 -
   8.633 -		/*
   8.634 -		 * Give the other CPU some time to accept the IPI.
   8.635 -		 */
   8.636 -		udelay(300);
   8.637 -
   8.638 -		Dprintk("Startup point 1.\n");
   8.639 -
   8.640 -		Dprintk("Waiting for send to finish...\n");
   8.641 -		timeout = 0;
   8.642 -		do {
   8.643 -			Dprintk("+");
   8.644 -			udelay(100);
   8.645 -			send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   8.646 -		} while (send_status && (timeout++ < 1000));
   8.647 -
   8.648 -		/*
   8.649 -		 * Give the other CPU some time to accept the IPI.
   8.650 -		 */
   8.651 -		udelay(200);
   8.652 -		/*
   8.653 -		 * Due to the Pentium erratum 3AP.
   8.654 -		 */
   8.655 -		if (maxlvt > 3) {
   8.656 -			apic_read_around(APIC_SPIV);
   8.657 -			apic_write(APIC_ESR, 0);
   8.658 -		}
   8.659 -		accept_status = (apic_read(APIC_ESR) & 0xEF);
   8.660 -		if (send_status || accept_status)
   8.661 -			break;
   8.662 -	}
   8.663 -	Dprintk("After Startup.\n");
   8.664 -
   8.665 -	if (send_status)
   8.666 -		printk(KERN_ERR "APIC never delivered???\n");
   8.667 -	if (accept_status)
   8.668 -		printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
   8.669 -
   8.670 -	return (send_status | accept_status);
   8.671 -}
   8.672 -#endif
   8.673 -
   8.674 -/*
   8.675 - * Boot one CPU.
   8.676 - */
   8.677 -static int __cpuinit do_boot_cpu(int cpu, int apicid)
   8.678 -{
   8.679 -	struct task_struct *idle;
   8.680 -	unsigned long boot_error;
   8.681 -	int timeout;
   8.682 -	unsigned long start_rip;
   8.683 -#ifdef CONFIG_XEN
   8.684 -	vcpu_guest_context_t ctxt;
   8.685 -	extern void startup_64_smp(void);
   8.686 -	extern void hypervisor_callback(void);
   8.687 -	extern void failsafe_callback(void);
   8.688 -	extern void smp_trap_init(trap_info_t *);
   8.689 -#endif
   8.690 -	/*
   8.691 -	 * We can't use kernel_thread since we must avoid to
   8.692 -	 * reschedule the child.
   8.693 -	 */
   8.694 -	idle = fork_idle(cpu);
   8.695 -	if (IS_ERR(idle)) {
   8.696 -		printk("failed fork for CPU %d\n", cpu);
   8.697 -		return PTR_ERR(idle);
   8.698 -	}
   8.699 -
   8.700 -	cpu_pda[cpu].pcurrent = idle;
   8.701 -
   8.702 -#ifndef CONFIG_XEN
   8.703 -	start_rip = setup_trampoline();
   8.704 -#else
   8.705 -	start_rip = (unsigned long)startup_64_smp;
   8.706 -#endif
   8.707 -
   8.708 -	init_rsp = idle->thread.rsp;
   8.709 -	per_cpu(init_tss,cpu).rsp0 = init_rsp;
   8.710 -	initial_code = start_secondary;
   8.711 -	clear_ti_thread_flag(idle->thread_info, TIF_FORK);
   8.712 -
   8.713 -	printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid,
   8.714 -	       start_rip, init_rsp);
   8.715 -
   8.716 -	/*
   8.717 -	 * This grunge runs the startup process for
   8.718 -	 * the targeted processor.
   8.719 -	 */
   8.720 -
   8.721 -	atomic_set(&init_deasserted, 0);
   8.722 -
   8.723 -#ifdef CONFIG_XEN
   8.724 -	cpu_gdt_descr[cpu].address = __get_free_page(GFP_KERNEL|__GFP_ZERO);
   8.725 -	BUG_ON(cpu_gdt_descr[0].size > PAGE_SIZE);
   8.726 -	cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
   8.727 -	memcpy((void *)cpu_gdt_descr[cpu].address,
   8.728 -		(void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
   8.729 -
   8.730 -	memset(&ctxt, 0, sizeof(ctxt));
   8.731 -
   8.732 -	ctxt.flags = VGCF_IN_KERNEL;
   8.733 -	ctxt.user_regs.ds = __USER_DS;
   8.734 -	ctxt.user_regs.es = __USER_DS;
   8.735 -	ctxt.user_regs.fs = 0;
   8.736 -	ctxt.user_regs.gs = 0;
   8.737 -	ctxt.user_regs.ss = __KERNEL_DS|0x3;
   8.738 -	ctxt.user_regs.cs = __KERNEL_CS|0x3;
   8.739 -	ctxt.user_regs.rip = start_rip;
   8.740 -	ctxt.user_regs.rsp = idle->thread.rsp;
   8.741 -#define X86_EFLAGS_IOPL_RING3 0x3000
   8.742 -	ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING3;
   8.743 -
   8.744 -	/* FPU is set up to default initial state. */
   8.745 -	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
   8.746 -
   8.747 -	smp_trap_init(ctxt.trap_ctxt);
   8.748 -
   8.749 -	/* No LDT. */
   8.750 -	ctxt.ldt_ents = 0;
   8.751 -
   8.752 -	{
   8.753 -		unsigned long va;
   8.754 -		int f;
   8.755 -
   8.756 -		for (va = cpu_gdt_descr[cpu].address, f = 0;
   8.757 -		     va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
   8.758 -		     va += PAGE_SIZE, f++) {
   8.759 -			ctxt.gdt_frames[f] = virt_to_mfn(va);
   8.760 -			make_page_readonly((void *)va);
   8.761 -		}
   8.762 -		ctxt.gdt_ents = GDT_ENTRIES;
   8.763 -	}
   8.764 -
   8.765 -	/* Ring 1 stack is the initial stack. */
   8.766 -	ctxt.kernel_ss = __KERNEL_DS;
   8.767 -	ctxt.kernel_sp = idle->thread.rsp;
   8.768 -
   8.769 -	/* Callback handlers. */
   8.770 -	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   8.771 -	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   8.772 -	ctxt.syscall_callback_eip  = (unsigned long)system_call;
   8.773 -
   8.774 -	ctxt.ctrlreg[3] = virt_to_mfn(init_level4_pgt) << PAGE_SHIFT;
   8.775 -
   8.776 -	boot_error  = HYPERVISOR_vcpu_op(VCPUOP_initialise, cpu, &ctxt);
   8.777 -	if (boot_error)
   8.778 -		printk("boot error: %ld\n", boot_error);
   8.779 -
   8.780 -	if (!boot_error) {
   8.781 -		HYPERVISOR_vcpu_op(VCPUOP_up, cpu, NULL);
   8.782 -
   8.783 -		/*
   8.784 -		 * allow APs to start initializing.
   8.785 -		 */
   8.786 -		Dprintk("Before Callout %d.\n", cpu);
   8.787 -		cpu_set(cpu, cpu_callout_map);
   8.788 -		Dprintk("After Callout %d.\n", cpu);
   8.789 -
   8.790 -		/*
   8.791 -		 * Wait 5s total for a response
   8.792 -		 */
   8.793 -		for (timeout = 0; timeout < 50000; timeout++) {
   8.794 -			if (cpu_isset(cpu, cpu_callin_map))
   8.795 -				break;	/* It has booted */
   8.796 -			udelay(100);
   8.797 -		}
   8.798 -
   8.799 -		if (cpu_isset(cpu, cpu_callin_map)) {
   8.800 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   8.801 -			Dprintk("CPU has booted.\n");
   8.802 -		} else {
   8.803 -			boot_error= 1;
   8.804 -		}
   8.805 -	}
   8.806 -	x86_cpu_to_apicid[cpu] = apicid;
   8.807 -#else
   8.808 -	Dprintk("Setting warm reset code and vector.\n");
   8.809 -
   8.810 -	CMOS_WRITE(0xa, 0xf);
   8.811 -	local_flush_tlb();
   8.812 -	Dprintk("1.\n");
   8.813 -	*((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4;
   8.814 -	Dprintk("2.\n");
   8.815 -	*((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf;
   8.816 -	Dprintk("3.\n");
   8.817 -
   8.818 -	/*
   8.819 -	 * Be paranoid about clearing APIC errors.
   8.820 -	 */
   8.821 -	if (APIC_INTEGRATED(apic_version[apicid])) {
   8.822 -		apic_read_around(APIC_SPIV);
   8.823 -		apic_write(APIC_ESR, 0);
   8.824 -		apic_read(APIC_ESR);
   8.825 -	}
   8.826 -
   8.827 -	/*
   8.828 -	 * Status is now clean
   8.829 -	 */
   8.830 -	boot_error = 0;
   8.831 -
   8.832 -	/*
   8.833 -	 * Starting actual IPI sequence...
   8.834 -	 */
   8.835 -	boot_error = wakeup_secondary_via_INIT(apicid, start_rip);
   8.836 -
   8.837 -	if (!boot_error) {
   8.838 -		/*
   8.839 -		 * allow APs to start initializing.
   8.840 -		 */
   8.841 -		Dprintk("Before Callout %d.\n", cpu);
   8.842 -		cpu_set(cpu, cpu_callout_map);
   8.843 -		Dprintk("After Callout %d.\n", cpu);
   8.844 -
   8.845 -		/*
   8.846 -		 * Wait 5s total for a response
   8.847 -		 */
   8.848 -		for (timeout = 0; timeout < 50000; timeout++) {
   8.849 -			if (cpu_isset(cpu, cpu_callin_map))
   8.850 -				break;	/* It has booted */
   8.851 -			udelay(100);
   8.852 -		}
   8.853 -
   8.854 -		if (cpu_isset(cpu, cpu_callin_map)) {
   8.855 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   8.856 -			Dprintk("CPU has booted.\n");
   8.857 -		} else {
   8.858 -			boot_error = 1;
   8.859 -			if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
   8.860 -					== 0xA5)
   8.861 -				/* trampoline started but...? */
   8.862 -				printk("Stuck ??\n");
   8.863 -			else
   8.864 -				/* trampoline code not run */
   8.865 -				printk("Not responding.\n");
   8.866 -#if APIC_DEBUG
   8.867 -			inquire_remote_apic(apicid);
   8.868 -#endif
   8.869 -		}
   8.870 -	}
   8.871 -#endif
   8.872 -	if (boot_error) {
   8.873 -		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
   8.874 -		clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
   8.875 -		cpu_clear(cpu, cpu_present_map);
   8.876 -		cpu_clear(cpu, cpu_possible_map);
   8.877 -		x86_cpu_to_apicid[cpu] = BAD_APICID;
   8.878 -		x86_cpu_to_log_apicid[cpu] = BAD_APICID;
   8.879 -		return -EIO;
   8.880 -	}
   8.881 -
   8.882 -	return 0;
   8.883 -}
   8.884 -
   8.885 -cycles_t cacheflush_time;
   8.886 -unsigned long cache_decay_ticks;
   8.887 -
   8.888 -/*
   8.889 - * Construct cpu_sibling_map[], so that we can tell the sibling CPU
   8.890 - * on SMT systems efficiently.
   8.891 - */
   8.892 -static __cpuinit void detect_siblings(void)
   8.893 -{
   8.894 -	int cpu;
   8.895 -
   8.896 -	for (cpu = 0; cpu < NR_CPUS; cpu++) {
   8.897 -		cpus_clear(cpu_sibling_map[cpu]);
   8.898 -		cpus_clear(cpu_core_map[cpu]);
   8.899 -	}
   8.900 -
   8.901 -	for_each_online_cpu (cpu) {
   8.902 -		struct cpuinfo_x86 *c = cpu_data + cpu;
   8.903 -		int siblings = 0;
   8.904 -		int i;
   8.905 -		if (smp_num_siblings > 1) {
   8.906 -			for_each_online_cpu (i) {
   8.907 -				if (cpu_core_id[cpu] == cpu_core_id[i]) {
   8.908 -					siblings++;
   8.909 -					cpu_set(i, cpu_sibling_map[cpu]);
   8.910 -				}
   8.911 -			}
   8.912 -		} else {
   8.913 -			siblings++;
   8.914 -			cpu_set(cpu, cpu_sibling_map[cpu]);
   8.915 -		}
   8.916 -
   8.917 -		if (siblings != smp_num_siblings) {
   8.918 -			printk(KERN_WARNING
   8.919 -	       "WARNING: %d siblings found for CPU%d, should be %d\n",
   8.920 -			       siblings, cpu, smp_num_siblings);
   8.921 -			smp_num_siblings = siblings;
   8.922 -		}
   8.923 -		if (c->x86_num_cores > 1) {
   8.924 -			for_each_online_cpu(i) {
   8.925 -				if (phys_proc_id[cpu] == phys_proc_id[i])
   8.926 -					cpu_set(i, cpu_core_map[cpu]);
   8.927 -			}
   8.928 -		} else
   8.929 -			cpu_core_map[cpu] = cpu_sibling_map[cpu];
   8.930 -	}
   8.931 -}
   8.932 -
   8.933 -#ifndef CONFIG_XEN
   8.934 -/*
   8.935 - * Cleanup possible dangling ends...
   8.936 - */
   8.937 -static __cpuinit void smp_cleanup_boot(void)
   8.938 -{
   8.939 -	/*
   8.940 -	 * Paranoid:  Set warm reset code and vector here back
   8.941 -	 * to default values.
   8.942 -	 */
   8.943 -	CMOS_WRITE(0, 0xf);
   8.944 -
   8.945 -	/*
   8.946 -	 * Reset trampoline flag
   8.947 -	 */
   8.948 -	*((volatile int *) phys_to_virt(0x467)) = 0;
   8.949 -
   8.950 -#ifndef CONFIG_HOTPLUG_CPU
   8.951 -	/*
   8.952 -	 * Free pages reserved for SMP bootup.
   8.953 -	 * When you add hotplug CPU support later remove this
   8.954 -	 * Note there is more work to be done for later CPU bootup.
   8.955 -	 */
   8.956 -
   8.957 -	free_page((unsigned long) __va(PAGE_SIZE));
   8.958 -	free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
   8.959 -#endif
   8.960 -}
   8.961 -#endif
   8.962 -
   8.963 -/*
   8.964 - * Fall back to non SMP mode after errors.
   8.965 - *
   8.966 - * RED-PEN audit/test this more. I bet there is more state messed up here.
   8.967 - */
   8.968 -static __cpuinit void disable_smp(void)
   8.969 -{
   8.970 -	cpu_present_map = cpumask_of_cpu(0);
   8.971 -	cpu_possible_map = cpumask_of_cpu(0);
   8.972 -#ifndef CONFIG_XEN
   8.973 -	if (smp_found_config)
   8.974 -		phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
   8.975 -	else
   8.976 -		phys_cpu_present_map = physid_mask_of_physid(0);
   8.977 -#endif
   8.978 -	cpu_set(0, cpu_sibling_map[0]);
   8.979 -	cpu_set(0, cpu_core_map[0]);
   8.980 -}
   8.981 -
   8.982 -/*
   8.983 - * Handle user cpus=... parameter.
   8.984 - */
   8.985 -static __cpuinit void enforce_max_cpus(unsigned max_cpus)
   8.986 -{
   8.987 -	int i, k;
   8.988 -	k = 0;
   8.989 -	for (i = 0; i < NR_CPUS; i++) {
   8.990 -		if (!cpu_possible(i))
   8.991 -			continue;
   8.992 -		if (++k > max_cpus) {
   8.993 -			cpu_clear(i, cpu_possible_map);
   8.994 -			cpu_clear(i, cpu_present_map);
   8.995 -		}
   8.996 -	}
   8.997 -}
   8.998 -
   8.999 -/*
  8.1000 - * Various sanity checks.
  8.1001 - */
  8.1002 -static int __cpuinit smp_sanity_check(unsigned max_cpus)
  8.1003 -{
  8.1004 -#ifndef CONFIG_XEN
  8.1005 -	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
  8.1006 -		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
  8.1007 -		       hard_smp_processor_id());
  8.1008 -		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
  8.1009 -	}
  8.1010 -
  8.1011 -	/*
  8.1012 -	 * If we couldn't find an SMP configuration at boot time,
  8.1013 -	 * get out of here now!
  8.1014 -	 */
  8.1015 -	if (!smp_found_config) {
  8.1016 -		printk(KERN_NOTICE "SMP motherboard not detected.\n");
  8.1017 -		disable_smp();
  8.1018 -		if (APIC_init_uniprocessor())
  8.1019 -			printk(KERN_NOTICE "Local APIC not detected."
  8.1020 -					   " Using dummy APIC emulation.\n");
  8.1021 -		return -1;
  8.1022 -	}
  8.1023 -
  8.1024 -	/*
  8.1025 -	 * Should not be necessary because the MP table should list the boot
  8.1026 -	 * CPU too, but we do it for the sake of robustness anyway.
  8.1027 -	 */
  8.1028 -	if (!physid_isset(boot_cpu_id, phys_cpu_present_map)) {
  8.1029 -		printk(KERN_NOTICE "weird, boot CPU (#%d) not listed by the BIOS.\n",
  8.1030 -								 boot_cpu_id);
  8.1031 -		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
  8.1032 -	}
  8.1033 -
  8.1034 -	/*
  8.1035 -	 * If we couldn't find a local APIC, then get out of here now!
  8.1036 -	 */
  8.1037 -	if (APIC_INTEGRATED(apic_version[boot_cpu_id]) && !cpu_has_apic) {
  8.1038 -		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
  8.1039 -			boot_cpu_id);
  8.1040 -		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
  8.1041 -		nr_ioapics = 0;
  8.1042 -		return -1;
  8.1043 -	}
  8.1044 -#endif
  8.1045 -
  8.1046 -	/*
  8.1047 -	 * If SMP should be disabled, then really disable it!
  8.1048 -	 */
  8.1049 -	if (!max_cpus) {
  8.1050 -#ifdef CONFIG_XEN
  8.1051 -		xen_start_info->n_vcpu = 1;
  8.1052 -#endif
  8.1053 -		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
  8.1054 -#ifndef CONFIG_XEN
  8.1055 -		nr_ioapics = 0;
  8.1056 -#endif
  8.1057 -		return -1;
  8.1058 -	}
  8.1059 -
  8.1060 -	return 0;
  8.1061 -}
  8.1062 -
  8.1063 -/*
  8.1064 - * Prepare for SMP bootup.  The MP table or ACPI has been read
  8.1065 - * earlier.  Just do some sanity checking here and enable APIC mode.
  8.1066 - */
  8.1067 -void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
  8.1068 -{
  8.1069 -	int i;
  8.1070 -
  8.1071 -#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
  8.1072 -#else
  8.1073 -	nmi_watchdog_default();
  8.1074 -#endif
  8.1075 -	current_cpu_data = boot_cpu_data;
  8.1076 -	current_thread_info()->cpu = 0;  /* needed? */
  8.1077 -
  8.1078 -	enforce_max_cpus(max_cpus);
  8.1079 -
  8.1080 -	/*
  8.1081 -	 * Fill in cpu_present_mask
  8.1082 -	 */
  8.1083 -	for (i = 0; i < NR_CPUS; i++) {
  8.1084 -#ifndef CONFIG_XEN
  8.1085 -		int apicid = cpu_present_to_apicid(i);
  8.1086 -		if (physid_isset(apicid, phys_cpu_present_map)) {
  8.1087 -#else
  8.1088 -		if (i < xen_start_info->n_vcpu) {
  8.1089 -#endif
  8.1090 -			cpu_set(i, cpu_present_map);
  8.1091 -			/* possible map would be different if we supported real
  8.1092 -			   CPU hotplug. */
  8.1093 -			cpu_set(i, cpu_possible_map);
  8.1094 -		}
  8.1095 -	}
  8.1096 -
  8.1097 -	if (smp_sanity_check(max_cpus) < 0) {
  8.1098 -		printk(KERN_INFO "SMP disabled\n");
  8.1099 -		disable_smp();
  8.1100 -		return;
  8.1101 -	}
  8.1102 -
  8.1103 -#ifdef CONFIG_XEN
  8.1104 -	smp_intr_init();
  8.1105 -#else
  8.1106 -
  8.1107 -	/*
  8.1108 -	 * Switch from PIC to APIC mode.
  8.1109 -	 */
  8.1110 -	connect_bsp_APIC();
  8.1111 -	setup_local_APIC();
  8.1112 -
  8.1113 -	if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
  8.1114 -		panic("Boot APIC ID in local APIC unexpected (%d vs %d)",
  8.1115 -		      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
  8.1116 -		/* Or can we switch back to PIC here? */
  8.1117 -	}
  8.1118 -#endif
  8.1119 -
  8.1120 -	/*
  8.1121 -	 * Now start the IO-APICs
  8.1122 -	 */
  8.1123 -#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
  8.1124 -#else
  8.1125 -	if (!skip_ioapic_setup && nr_ioapics)
  8.1126 -		setup_IO_APIC();
  8.1127 -	else
  8.1128 -		nr_ioapics = 0;
  8.1129 -#endif
  8.1130 -
  8.1131 -	/*
  8.1132 -	 * Set up local APIC timer on boot CPU.
  8.1133 -	 */
  8.1134 -
  8.1135 -#ifndef CONFIG_XEN
  8.1136 -	setup_boot_APIC_clock();
  8.1137 -#endif
  8.1138 -}
  8.1139 -
  8.1140 -/*
  8.1141 - * Early setup to make printk work.
  8.1142 - */
  8.1143 -void __init smp_prepare_boot_cpu(void)
  8.1144 -{
  8.1145 -	int me = smp_processor_id();
  8.1146 -	cpu_set(me, cpu_online_map);
  8.1147 -	cpu_set(me, cpu_callout_map);
  8.1148 -}
  8.1149 -
  8.1150 -/*
  8.1151 - * Entry point to boot a CPU.
  8.1152 - *
  8.1153 - * This is all __cpuinit, not __devinit for now because we don't support
  8.1154 - * CPU hotplug (yet).
  8.1155 - */
  8.1156 -int __cpuinit __cpu_up(unsigned int cpu)
  8.1157 -{
  8.1158 -	int err;
  8.1159 -#ifndef CONFIG_XEN
  8.1160 -	int apicid = cpu_present_to_apicid(cpu);
  8.1161 -#else
  8.1162 -	int apicid = cpu;
  8.1163 -#endif
  8.1164 -
  8.1165 -	WARN_ON(irqs_disabled());
  8.1166 -
  8.1167 -	Dprintk("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
  8.1168 -
  8.1169 -#ifndef CONFIG_XEN
  8.1170 -	if (apicid == BAD_APICID || apicid == boot_cpu_id ||
  8.1171 -	    !physid_isset(apicid, phys_cpu_present_map)) {
  8.1172 -		printk("__cpu_up: bad cpu %d\n", cpu);
  8.1173 -		return -EINVAL;
  8.1174 -	}
  8.1175 -#endif
  8.1176 -
  8.1177 -	/* Boot it! */
  8.1178 -	err = do_boot_cpu(cpu, apicid);
  8.1179 -	if (err < 0) {
  8.1180 -		Dprintk("do_boot_cpu failed %d\n", err);
  8.1181 -		return err;
  8.1182 -	}
  8.1183 -
  8.1184 -	/* Unleash the CPU! */
  8.1185 -	Dprintk("waiting for cpu %d\n", cpu);
  8.1186 -
  8.1187 -	while (!cpu_isset(cpu, cpu_online_map))
  8.1188 -		cpu_relax();
  8.1189 -	return 0;
  8.1190 -}
  8.1191 -
  8.1192 -/*
  8.1193 - * Finish the SMP boot.
  8.1194 - */
  8.1195 -void __cpuinit smp_cpus_done(unsigned int max_cpus)
  8.1196 -{
  8.1197 -#ifndef CONFIG_XEN
  8.1198 -	zap_low_mappings();
  8.1199 -	smp_cleanup_boot();
  8.1200 -
  8.1201 -#ifdef CONFIG_X86_IO_APIC
  8.1202 -	setup_ioapic_dest();
  8.1203 -#endif
  8.1204 -#endif
  8.1205 -
  8.1206 -	detect_siblings();
  8.1207 -#ifndef CONFIG_XEN
  8.1208 -	time_init_gtod();
  8.1209 -
  8.1210 -	check_nmi_watchdog();
  8.1211 -#endif
  8.1212 -}
  8.1213 -
  8.1214 -#ifdef CONFIG_XEN
  8.1215 -extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
  8.1216 -extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
  8.1217 -
  8.1218 -static DEFINE_PER_CPU(int, resched_irq);
  8.1219 -static DEFINE_PER_CPU(int, callfunc_irq);
  8.1220 -static char resched_name[NR_CPUS][15];
  8.1221 -static char callfunc_name[NR_CPUS][15];
  8.1222 -
  8.1223 -void smp_intr_init(void)
  8.1224 -{
  8.1225 -	int cpu = smp_processor_id();
  8.1226 -
  8.1227 -	per_cpu(resched_irq, cpu) =
  8.1228 -		bind_ipi_to_irq(RESCHEDULE_VECTOR, cpu);
  8.1229 -	sprintf(resched_name[cpu], "resched%d", cpu);
  8.1230 -	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
  8.1231 -	                   SA_INTERRUPT, resched_name[cpu], NULL));
  8.1232 -
  8.1233 -	per_cpu(callfunc_irq, cpu) =
  8.1234 -		bind_ipi_to_irq(CALL_FUNCTION_VECTOR, cpu);
  8.1235 -	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
  8.1236 -	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
  8.1237 -	                   smp_call_function_interrupt,
  8.1238 -	                   SA_INTERRUPT, callfunc_name[cpu], NULL));
  8.1239 -}
  8.1240 -
  8.1241 -static void smp_intr_exit(void)
  8.1242 -{
  8.1243 -	int cpu = smp_processor_id();
  8.1244 -
  8.1245 -	free_irq(per_cpu(resched_irq, cpu), NULL);
  8.1246 -	unbind_ipi_from_irq(RESCHEDULE_VECTOR, cpu);
  8.1247 -
  8.1248 -	free_irq(per_cpu(callfunc_irq, cpu), NULL);
  8.1249 -	unbind_ipi_from_irq(CALL_FUNCTION_VECTOR, cpu);
  8.1250 -}
  8.1251 -
  8.1252 -void vcpu_prepare(int vcpu)
  8.1253 -{
  8.1254 -}
  8.1255 -
  8.1256 -#endif
     9.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/x8664_ksyms.c	Tue Oct 18 15:40:29 2005 +0100
     9.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/x8664_ksyms.c	Tue Oct 18 17:40:31 2005 +0100
     9.3 @@ -113,14 +113,11 @@ EXPORT_SYMBOL(clear_page);
     9.4  
     9.5  EXPORT_SYMBOL(cpu_pda);
     9.6  #ifdef CONFIG_SMP
     9.7 -EXPORT_SYMBOL(cpu_data);
     9.8 -EXPORT_SYMBOL(cpu_online_map);
     9.9  EXPORT_SYMBOL(__write_lock_failed);
    9.10  EXPORT_SYMBOL(__read_lock_failed);
    9.11  
    9.12  EXPORT_SYMBOL(synchronize_irq);
    9.13  EXPORT_SYMBOL(smp_call_function);
    9.14 -EXPORT_SYMBOL(cpu_callout_map);
    9.15  #endif
    9.16  
    9.17  #ifdef CONFIG_VT
    10.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h	Tue Oct 18 15:40:29 2005 +0100
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,55 +0,0 @@
    10.4 -/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
    10.5 - * which needs to alter them. */
    10.6 -
    10.7 -static inline void smpboot_clear_io_apic_irqs(void)
    10.8 -{
    10.9 -#ifdef CONFIG_X86_IO_APIC
   10.10 -	io_apic_irqs = 0;
   10.11 -#endif
   10.12 -}
   10.13 -
   10.14 -static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
   10.15 -{
   10.16 -#if 1
   10.17 -	printk("smpboot_setup_warm_reset_vector\n");
   10.18 -#else
   10.19 -	CMOS_WRITE(0xa, 0xf);
   10.20 -	local_flush_tlb();
   10.21 -	Dprintk("1.\n");
   10.22 -	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
   10.23 -	Dprintk("2.\n");
   10.24 -	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
   10.25 -	Dprintk("3.\n");
   10.26 -#endif
   10.27 -}
   10.28 -
   10.29 -static inline void smpboot_restore_warm_reset_vector(void)
   10.30 -{
   10.31 -	/*
   10.32 -	 * Install writable page 0 entry to set BIOS data area.
   10.33 -	 */
   10.34 -	local_flush_tlb();
   10.35 -
   10.36 -	/*
   10.37 -	 * Paranoid:  Set warm reset code and vector here back
   10.38 -	 * to default values.
   10.39 -	 */
   10.40 -	CMOS_WRITE(0, 0xf);
   10.41 -
   10.42 -	*((volatile long *) phys_to_virt(0x467)) = 0;
   10.43 -}
   10.44 -
   10.45 -static inline void smpboot_setup_io_apic(void)
   10.46 -{
   10.47 -#ifdef CONFIG_X86_IO_APIC
   10.48 -	/*
   10.49 -	 * Here we can be sure that there is an IO-APIC in the system. Let's
   10.50 -	 * go and set it up:
   10.51 -	 */
   10.52 -	if (!skip_ioapic_setup && nr_ioapics)
   10.53 -		setup_IO_APIC();
   10.54 -#endif
   10.55 -}
   10.56 -
   10.57 -
   10.58 -#define	smp_found_config	(xen_start_info->n_vcpu > 1)
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/smp.h	Tue Oct 18 17:40:31 2005 +0100
    11.3 @@ -0,0 +1,92 @@
    11.4 +#ifndef __ASM_SMP_H
    11.5 +#define __ASM_SMP_H
    11.6 +
    11.7 +/*
    11.8 + * We need the APIC definitions automatically as part of 'smp.h'
    11.9 + */
   11.10 +#ifndef __ASSEMBLY__
   11.11 +#include <linux/config.h>
   11.12 +#include <linux/kernel.h>
   11.13 +#include <linux/threads.h>
   11.14 +#include <linux/cpumask.h>
   11.15 +#endif
   11.16 +
   11.17 +#ifdef CONFIG_X86_LOCAL_APIC
   11.18 +#ifndef __ASSEMBLY__
   11.19 +#include <asm/fixmap.h>
   11.20 +#include <asm/bitops.h>
   11.21 +#include <asm/mpspec.h>
   11.22 +#ifdef CONFIG_X86_IO_APIC
   11.23 +#include <asm/io_apic.h>
   11.24 +#endif
   11.25 +#include <asm/apic.h>
   11.26 +#endif
   11.27 +#endif
   11.28 +
   11.29 +#define BAD_APICID 0xFFu
   11.30 +#ifdef CONFIG_SMP
   11.31 +#ifndef __ASSEMBLY__
   11.32 +
   11.33 +/*
   11.34 + * Private routines/data
   11.35 + */
   11.36 + 
   11.37 +extern void smp_alloc_memory(void);
   11.38 +extern int pic_mode;
   11.39 +extern int smp_num_siblings;
   11.40 +extern cpumask_t cpu_sibling_map[];
   11.41 +extern cpumask_t cpu_core_map[];
   11.42 +
   11.43 +extern void smp_flush_tlb(void);
   11.44 +extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
   11.45 +extern void smp_invalidate_rcv(void);		/* Process an NMI */
   11.46 +extern void (*mtrr_hook) (void);
   11.47 +extern void zap_low_mappings (void);
   11.48 +
   11.49 +#define MAX_APICID 256
   11.50 +extern u8 x86_cpu_to_apicid[];
   11.51 +
   11.52 +/*
   11.53 + * This function is needed by all SMP systems. It must _always_ be valid
   11.54 + * from the initial startup. We map APIC_BASE very early in page_setup(),
   11.55 + * so this is correct in the x86 case.
   11.56 + */
   11.57 +#define __smp_processor_id() (current_thread_info()->cpu)
   11.58 +
   11.59 +extern cpumask_t cpu_possible_map;
   11.60 +
   11.61 +/* We don't mark CPUs online until __cpu_up(), so we need another measure */
   11.62 +static inline int num_booting_cpus(void)
   11.63 +{
   11.64 +	return cpus_weight(cpu_possible_map);
   11.65 +}
   11.66 +
   11.67 +#ifdef CONFIG_X86_LOCAL_APIC
   11.68 +
   11.69 +#ifdef APIC_DEFINITION
   11.70 +extern int hard_smp_processor_id(void);
   11.71 +#else
   11.72 +#include <mach_apicdef.h>
   11.73 +static inline int hard_smp_processor_id(void)
   11.74 +{
   11.75 +	/* we don't want to mark this access volatile - bad code generation */
   11.76 +	return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
   11.77 +}
   11.78 +#endif
   11.79 +
   11.80 +static __inline int logical_smp_processor_id(void)
   11.81 +{
   11.82 +	/* we don't want to mark this access volatile - bad code generation */
   11.83 +	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
   11.84 +}
   11.85 +
   11.86 +#endif
   11.87 +
   11.88 +extern int __cpu_disable(void);
   11.89 +extern void __cpu_die(unsigned int cpu);
   11.90 +#endif /* !__ASSEMBLY__ */
   11.91 +
   11.92 +#define NO_PROC_ID		0xFF		/* No processor magic marker */
   11.93 +
   11.94 +#endif
   11.95 +#endif
    12.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/smpboot_hooks.h	Tue Oct 18 15:40:29 2005 +0100
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,55 +0,0 @@
    12.4 -/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
    12.5 - * which needs to alter them. */
    12.6 -
    12.7 -static inline void smpboot_clear_io_apic_irqs(void)
    12.8 -{
    12.9 -#ifdef CONFIG_X86_IO_APIC
   12.10 -	io_apic_irqs = 0;
   12.11 -#endif
   12.12 -}
   12.13 -
   12.14 -static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
   12.15 -{
   12.16 -#if 1
   12.17 -	printk("smpboot_setup_warm_reset_vector\n");
   12.18 -#else
   12.19 -	CMOS_WRITE(0xa, 0xf);
   12.20 -	local_flush_tlb();
   12.21 -	Dprintk("1.\n");
   12.22 -	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
   12.23 -	Dprintk("2.\n");
   12.24 -	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
   12.25 -	Dprintk("3.\n");
   12.26 -#endif
   12.27 -}
   12.28 -
   12.29 -static inline void smpboot_restore_warm_reset_vector(void)
   12.30 -{
   12.31 -	/*
   12.32 -	 * Install writable page 0 entry to set BIOS data area.
   12.33 -	 */
   12.34 -	local_flush_tlb();
   12.35 -
   12.36 -	/*
   12.37 -	 * Paranoid:  Set warm reset code and vector here back
   12.38 -	 * to default values.
   12.39 -	 */
   12.40 -	CMOS_WRITE(0, 0xf);
   12.41 -
   12.42 -	*((volatile long *) phys_to_virt(0x467)) = 0;
   12.43 -}
   12.44 -
   12.45 -static inline void smpboot_setup_io_apic(void)
   12.46 -{
   12.47 -#ifdef CONFIG_X86_IO_APIC
   12.48 -	/*
   12.49 -	 * Here we can be sure that there is an IO-APIC in the system. Let's
   12.50 -	 * go and set it up:
   12.51 -	 */
   12.52 -	if (!skip_ioapic_setup && nr_ioapics)
   12.53 -		setup_IO_APIC();
   12.54 -#endif
   12.55 -}
   12.56 -
   12.57 -
   12.58 -#define	smp_found_config	(xen_start_info->n_vcpu > 1)
    13.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/smp.h	Tue Oct 18 15:40:29 2005 +0100
    13.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/smp.h	Tue Oct 18 17:40:31 2005 +0100
    13.3 @@ -34,7 +34,6 @@ struct pt_regs;
    13.4  extern cpumask_t cpu_present_mask;
    13.5  extern cpumask_t cpu_possible_map;
    13.6  extern cpumask_t cpu_online_map;
    13.7 -extern cpumask_t cpu_callout_map;
    13.8  
    13.9  /*
   13.10   * Private routines/data
   13.11 @@ -52,8 +51,8 @@ extern void zap_low_mappings(void);
   13.12  void smp_stop_cpu(void);
   13.13  extern cpumask_t cpu_sibling_map[NR_CPUS];
   13.14  extern cpumask_t cpu_core_map[NR_CPUS];
   13.15 -extern u8 phys_proc_id[NR_CPUS];
   13.16 -extern u8 cpu_core_id[NR_CPUS];
   13.17 +extern int phys_proc_id[NR_CPUS];
   13.18 +extern int cpu_core_id[NR_CPUS];
   13.19  
   13.20  #define SMP_TRAMPOLINE_BASE 0x6000
   13.21  
   13.22 @@ -65,7 +64,7 @@ extern u8 cpu_core_id[NR_CPUS];
   13.23  
   13.24  static inline int num_booting_cpus(void)
   13.25  {
   13.26 -	return cpus_weight(cpu_callout_map);
   13.27 +	return cpus_weight(cpu_possible_map);
   13.28  }
   13.29  
   13.30  #define __smp_processor_id() read_pda(cpunumber)