ia64/xen-unstable

changeset 6105:d95ea17567c6

The following patch provides x86_64 SMP support for xen linux. Many,
many thanks to the help for bug fixes, cleanups, good domU support,
and more from Jun and Xin. I've tested this on a couple different
machines, and made sure the UP build still boots and works. dom0 and
domU smp both work. There's still some cleanups to do, but we'd prefer
to do the last bit in tree. This doesn't update defconfigs just yet.
That'll be a follow-on patch shortly, so for now, you'll have to manually
enable CONFIG_SMP if you'd like to test.

Signed-off-by: Chris Wright <chrisw@osdl.org>
Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Aug 11 08:59:47 2005 +0000 (2005-08-11)
parents c66cac10524a
children a64ac7fafbf0
files linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile linux-2.6-xen-sparse/arch/xen/x86_64/kernel/apic.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c linux-2.6-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig	Thu Aug 11 08:58:40 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/Kconfig	Thu Aug 11 08:59:47 2005 +0000
     1.3 @@ -126,6 +126,10 @@ config X86_IO_APIC
     1.4  	bool
     1.5  	default XEN_PRIVILEGED_GUEST
     1.6  
     1.7 +config X86_XEN_GENAPIC
     1.8 +	bool
     1.9 +	default XEN_PRIVILEGED_GUEST || SMP
    1.10 +
    1.11  config X86_LOCAL_APIC
    1.12  	bool
    1.13  	default XEN_PRIVILEGED_GUEST
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile	Thu Aug 11 08:58:40 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/Makefile	Thu Aug 11 08:59:47 2005 +0000
     2.3 @@ -25,11 +25,12 @@ obj-$(CONFIG_ACPI_BOOT)		+= acpi/
     2.4  c-obj-$(CONFIG_X86_MSR)		+= msr.o
     2.5  obj-$(CONFIG_MICROCODE)		+= microcode.o
     2.6  obj-$(CONFIG_X86_CPUID)		+= cpuid.o
     2.7 -#obj-$(CONFIG_SMP)		+= smp.o smpboot.o trampoline.o
     2.8 +obj-$(CONFIG_SMP)		+= smp.o smpboot.o
     2.9  obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o
    2.10  c-obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
    2.11  obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o
    2.12 -c-obj-$(CONFIG_X86_IO_APIC)	+= genapic.o genapic_cluster.o genapic_flat.o
    2.13 +obj-$(CONFIG_X86_XEN_GENAPIC)	+= genapic.o genapic_xen.o
    2.14 +c-obj-$(CONFIG_X86_IO_APIC)	+= genapic_cluster.o genapic_flat.o
    2.15  #obj-$(CONFIG_PM)		+= suspend.o
    2.16  #obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
    2.17  #obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/apic.c	Thu Aug 11 08:58:40 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/apic.c	Thu Aug 11 08:59:47 2005 +0000
     3.3 @@ -48,7 +48,7 @@ void smp_local_timer_interrupt(struct pt
     3.4  	int cpu = smp_processor_id();
     3.5  
     3.6  	profile_tick(CPU_PROFILING, regs);
     3.7 -#if 0
     3.8 +#ifndef CONFIG_XEN
     3.9  	if (--per_cpu(prof_counter, cpu) <= 0) {
    3.10  		/*
    3.11  		 * The multiplier may have changed since the last time we got
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic.c	Thu Aug 11 08:59:47 2005 +0000
     4.3 @@ -0,0 +1,123 @@
     4.4 +/*
     4.5 + * Copyright 2004 James Cleverdon, IBM.
     4.6 + * Subject to the GNU Public License, v.2
     4.7 + *
     4.8 + * Generic APIC sub-arch probe layer.
     4.9 + *
    4.10 + * Hacked for x86-64 by James Cleverdon from i386 architecture code by
    4.11 + * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
    4.12 + * James Cleverdon.
    4.13 + */
    4.14 +#include <linux/config.h>
    4.15 +#include <linux/threads.h>
    4.16 +#include <linux/cpumask.h>
    4.17 +#include <linux/string.h>
    4.18 +#include <linux/kernel.h>
    4.19 +#include <linux/ctype.h>
    4.20 +#include <linux/init.h>
    4.21 +#include <linux/module.h>
    4.22 +
    4.23 +#include <asm/smp.h>
    4.24 +#include <asm/ipi.h>
    4.25 +
    4.26 +#if defined(CONFIG_ACPI_BUS)
    4.27 +#include <acpi/acpi_bus.h>
    4.28 +#endif
    4.29 +
    4.30 +/* which logical CPU number maps to which CPU (physical APIC ID) */
    4.31 +u8 x86_cpu_to_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    4.32 +EXPORT_SYMBOL(x86_cpu_to_apicid);
    4.33 +u8 x86_cpu_to_log_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
    4.34 +
    4.35 +extern struct genapic apic_cluster;
    4.36 +extern struct genapic apic_flat;
    4.37 +
    4.38 +#ifndef CONFIG_XEN
    4.39 +struct genapic *genapic = &apic_flat;
    4.40 +#else
    4.41 +extern struct genapic apic_xen;
    4.42 +struct genapic *genapic = &apic_xen;
    4.43 +#endif
    4.44 +
    4.45 +
    4.46 +/*
    4.47 + * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
    4.48 + */
    4.49 +void __init clustered_apic_check(void)
    4.50 +{
    4.51 +#ifndef CONFIG_XEN
    4.52 +	long i;
    4.53 +	u8 clusters, max_cluster;
    4.54 +	u8 id;
    4.55 +	u8 cluster_cnt[NUM_APIC_CLUSTERS];
    4.56 +
    4.57 +	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
    4.58 +		/* AMD always uses flat mode right now */
    4.59 +		genapic = &apic_flat;
    4.60 +		goto print;
    4.61 +	}
    4.62 +
    4.63 +#if defined(CONFIG_ACPI_BUS)
    4.64 +	/*
    4.65 +	 * Some x86_64 machines use physical APIC mode regardless of how many
    4.66 +	 * procs/clusters are present (x86_64 ES7000 is an example).
    4.67 +	 */
    4.68 +	if (acpi_fadt.revision > FADT2_REVISION_ID)
    4.69 +		if (acpi_fadt.force_apic_physical_destination_mode) {
    4.70 +			genapic = &apic_cluster;
    4.71 +			goto print;
    4.72 +		}
    4.73 +#endif
    4.74 +
    4.75 +	memset(cluster_cnt, 0, sizeof(cluster_cnt));
    4.76 +
    4.77 +	for (i = 0; i < NR_CPUS; i++) {
    4.78 +		id = bios_cpu_apicid[i];
    4.79 +		if (id != BAD_APICID)
    4.80 +			cluster_cnt[APIC_CLUSTERID(id)]++;
    4.81 +	}
    4.82 +
    4.83 +	clusters = 0;
    4.84 +	max_cluster = 0;
    4.85 +	for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
    4.86 +		if (cluster_cnt[i] > 0) {
    4.87 +			++clusters;
    4.88 +			if (cluster_cnt[i] > max_cluster)
    4.89 +				max_cluster = cluster_cnt[i];
    4.90 +		}
    4.91 +	}
    4.92 +
    4.93 +	/*
    4.94 +	 * If we have clusters <= 1 and CPUs <= 8 in cluster 0, then flat mode,
    4.95 +	 * else if max_cluster <= 4 and cluster_cnt[15] == 0, clustered logical
    4.96 +	 * else physical mode.
    4.97 +	 * (We don't use lowest priority delivery + HW APIC IRQ steering, so
    4.98 +	 * can ignore the clustered logical case and go straight to physical.)
    4.99 +	 */
   4.100 +	if (clusters <= 1 && max_cluster <= 8 && cluster_cnt[0] == max_cluster)
   4.101 +		genapic = &apic_flat;
   4.102 +	else
   4.103 +		genapic = &apic_cluster;
   4.104 +
   4.105 +print:
   4.106 +#else
   4.107 +	/* hardcode to xen apic functions */
   4.108 +	genapic = &apic_xen;
   4.109 +#endif
   4.110 +	printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
   4.111 +}
   4.112 +
   4.113 +/* Same for both flat and clustered. */
   4.114 +
   4.115 +#ifdef CONFIG_XEN
   4.116 +extern void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest);
   4.117 +#endif
   4.118 +
   4.119 +void send_IPI_self(int vector)
   4.120 +{
   4.121 +#ifndef CONFIG_XEN
   4.122 +	__send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
   4.123 +#else
   4.124 +	xen_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
   4.125 +#endif
   4.126 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/genapic_xen.c	Thu Aug 11 08:59:47 2005 +0000
     5.3 @@ -0,0 +1,167 @@
     5.4 +/*
     5.5 + * Copyright 2004 James Cleverdon, IBM.
     5.6 + * Subject to the GNU Public License, v.2
     5.7 + *
     5.8 + * Xen APIC subarch code.  Maximum 8 CPUs, logical delivery.
     5.9 + *
    5.10 + * Hacked for x86-64 by James Cleverdon from i386 architecture code by
    5.11 + * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
    5.12 + * James Cleverdon.
    5.13 + *
    5.14 + * Hacked to pieces for Xen by Chris Wright.
    5.15 + */
    5.16 +#include <linux/config.h>
    5.17 +#include <linux/threads.h>
    5.18 +#include <linux/cpumask.h>
    5.19 +#include <linux/string.h>
    5.20 +#include <linux/kernel.h>
    5.21 +#include <linux/ctype.h>
    5.22 +#include <linux/init.h>
    5.23 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
    5.24 +#include <asm/smp.h>
    5.25 +#include <asm/ipi.h>
    5.26 +#else
    5.27 +#include <asm/apic.h>
    5.28 +#include <asm/apicdef.h>
    5.29 +#include <asm/genapic.h>
    5.30 +#endif
    5.31 +#include <asm-xen/evtchn.h>
    5.32 +
    5.33 +DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
    5.34 +
    5.35 +static inline void __send_IPI_one(unsigned int cpu, int vector)
    5.36 +{
    5.37 +	unsigned int evtchn;
    5.38 +	Dprintk("%s\n", __FUNCTION__);
    5.39 +
    5.40 +	evtchn = per_cpu(ipi_to_evtchn, cpu)[vector];
    5.41 +	if (evtchn)
    5.42 +		notify_via_evtchn(evtchn);
    5.43 +	else
    5.44 +		printk("send_IPI to unbound port %d/%d", cpu, vector);
    5.45 +}
    5.46 +
    5.47 +void xen_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
    5.48 +{
    5.49 +	int cpu;
    5.50 +
    5.51 +	switch (shortcut) {
    5.52 +	case APIC_DEST_SELF:
    5.53 +		__send_IPI_one(smp_processor_id(), vector);
    5.54 +		break;
    5.55 +	case APIC_DEST_ALLBUT:
    5.56 +		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
    5.57 +			if (cpu == smp_processor_id())
    5.58 +				continue;
    5.59 +			if (cpu_isset(cpu, cpu_online_map)) {
    5.60 +				__send_IPI_one(cpu, vector);
    5.61 +			}
    5.62 +		}
    5.63 +		break;
    5.64 +	case APIC_DEST_ALLINC:
    5.65 +		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
    5.66 +			if (cpu_isset(cpu, cpu_online_map)) {
    5.67 +				__send_IPI_one(cpu, vector);
    5.68 +			}
    5.69 +		}
    5.70 +		break;
    5.71 +	default:
    5.72 +		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
    5.73 +		       vector);
    5.74 +		break;
    5.75 +	}
    5.76 +}
    5.77 +
    5.78 +static cpumask_t xen_target_cpus(void)
    5.79 +{
    5.80 +	return cpu_online_map;
    5.81 +}
    5.82 +
    5.83 +/*
    5.84 + * Set up the logical destination ID.
    5.85 + * Do nothing, not called now.
    5.86 + */
    5.87 +static void xen_init_apic_ldr(void)
    5.88 +{
    5.89 +	Dprintk("%s\n", __FUNCTION__);
    5.90 +	return;
    5.91 +}
    5.92 +
    5.93 +static void xen_send_IPI_allbutself(int vector)
    5.94 +{
    5.95 +	/*
    5.96 +	 * if there are no other CPUs in the system then
    5.97 +	 * we get an APIC send error if we try to broadcast.
    5.98 +	 * thus we have to avoid sending IPIs in this case.
    5.99 +	 */
   5.100 +	Dprintk("%s\n", __FUNCTION__);
   5.101 +	if (num_online_cpus() > 1)
   5.102 +		xen_send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
   5.103 +}
   5.104 +
   5.105 +static void xen_send_IPI_all(int vector)
   5.106 +{
   5.107 +	Dprintk("%s\n", __FUNCTION__);
   5.108 +	xen_send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
   5.109 +}
   5.110 +
   5.111 +static void xen_send_IPI_mask(cpumask_t cpumask, int vector)
   5.112 +{
   5.113 +	unsigned long mask = cpus_addr(cpumask)[0];
   5.114 +	unsigned int cpu;
   5.115 +	unsigned long flags;
   5.116 +
   5.117 +	Dprintk("%s\n", __FUNCTION__);
   5.118 +	local_irq_save(flags);
   5.119 +	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
   5.120 +
   5.121 +	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
   5.122 +		if (cpu_isset(cpu, cpumask)) {
   5.123 +			__send_IPI_one(cpu, vector);
   5.124 +		}
   5.125 +	}
   5.126 +	local_irq_restore(flags);
   5.127 +}
   5.128 +
   5.129 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
   5.130 +static int xen_apic_id_registered(void)
   5.131 +{
   5.132 +	/* better be set */
   5.133 +	Dprintk("%s\n", __FUNCTION__);
   5.134 +	return physid_isset(smp_processor_id(), phys_cpu_present_map);
   5.135 +}
   5.136 +#endif
   5.137 +
   5.138 +static unsigned int xen_cpu_mask_to_apicid(cpumask_t cpumask)
   5.139 +{
   5.140 +	Dprintk("%s\n", __FUNCTION__);
   5.141 +	return cpus_addr(cpumask)[0] & APIC_ALL_CPUS;
   5.142 +}
   5.143 +
   5.144 +static unsigned int phys_pkg_id(int index_msb)
   5.145 +{
   5.146 +	u32 ebx;
   5.147 +
   5.148 +	Dprintk("%s\n", __FUNCTION__);
   5.149 +	ebx = cpuid_ebx(1);
   5.150 +	return ((ebx >> 24) & 0xFF) >> index_msb;
   5.151 +}
   5.152 +
   5.153 +struct genapic apic_xen =  {
   5.154 +	.name = "xen",
   5.155 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
   5.156 +	.int_delivery_mode = dest_LowestPrio,
   5.157 +#endif
   5.158 +	.int_dest_mode = (APIC_DEST_LOGICAL != 0),
   5.159 +	.int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
   5.160 +	.target_cpus = xen_target_cpus,
   5.161 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
   5.162 +	.apic_id_registered = xen_apic_id_registered,
   5.163 +#endif
   5.164 +	.init_apic_ldr = xen_init_apic_ldr,
   5.165 +	.send_IPI_all = xen_send_IPI_all,
   5.166 +	.send_IPI_allbutself = xen_send_IPI_allbutself,
   5.167 +	.send_IPI_mask = xen_send_IPI_mask,
   5.168 +	.cpu_mask_to_apicid = xen_cpu_mask_to_apicid,
   5.169 +	.phys_pkg_id = phys_pkg_id,
   5.170 +};
     6.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S	Thu Aug 11 08:58:40 2005 +0000
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/head.S	Thu Aug 11 08:59:47 2005 +0000
     6.3 @@ -41,7 +41,6 @@
     6.4  startup_64:
     6.5  ENTRY(_start)
     6.6          cld                
     6.7 -	movq init_rsp(%rip),%rsp
     6.8  	/* Copy the necessary stuff from xen_start_info structure. */
     6.9  	movq  $xen_start_info_union,%rdi
    6.10  	movq  $64,%rcx          /* sizeof (union xen_start_info_union) / sizeof (long) */
    6.11 @@ -52,6 +51,7 @@ ENTRY(_start)
    6.12  	cld
    6.13  #endif /* CONFIG_SMP */
    6.14  
    6.15 +	movq init_rsp(%rip),%rsp
    6.16  	/* zero EFLAGS after setting rsp */
    6.17  	pushq $0
    6.18  	popfq
    6.19 @@ -204,6 +204,7 @@ ENTRY(cpu_gdt_table)
    6.20  	.quad	0,0			/* TSS */
    6.21  	.quad	0,0			/* LDT */
    6.22  	.quad   0,0,0			/* three TLS descriptors */ 
    6.23 +	.quad	0			/* unused now?   __KERNEL16_CS - 16bit PM for S3 wakeup. */
    6.24  
    6.25  gdt_end:	
    6.26  	/* asm/segment.h:GDT_ENTRIES must match this */	
     7.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c	Thu Aug 11 08:58:40 2005 +0000
     7.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/irq.c	Thu Aug 11 08:59:47 2005 +0000
     7.3 @@ -21,6 +21,11 @@
     7.4  
     7.5  atomic_t irq_err_count;
     7.6  
     7.7 +#ifdef CONFIG_X86_IO_APIC
     7.8 +#ifdef APIC_MISMATCH_DEBUG
     7.9 +atomic_t irq_mis_count;
    7.10 +#endif
    7.11 +#endif
    7.12  
    7.13  /*
    7.14   * Generic, controller-independent functions:
     8.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c	Thu Aug 11 08:58:40 2005 +0000
     8.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c	Thu Aug 11 08:59:47 2005 +0000
     8.3 @@ -200,12 +200,14 @@ static struct resource adapter_rom_resou
     8.4  #define ADAPTER_ROM_RESOURCES \
     8.5  	(sizeof adapter_rom_resources / sizeof adapter_rom_resources[0])
     8.6  
     8.7 +#ifdef CONFIG_XEN_PRIVILEGED_GUEST
     8.8  static struct resource video_rom_resource = {
     8.9  	.name = "Video ROM",
    8.10  	.start = 0xc0000,
    8.11  	.end = 0xc7fff,
    8.12  	.flags = IORESOURCE_ROM,
    8.13  };
    8.14 +#endif
    8.15  
    8.16  static struct resource video_ram_resource = {
    8.17  	.name = "Video RAM area",
    8.18 @@ -599,6 +601,19 @@ static void __init print_memory_map(char
    8.19          }
    8.20  }
    8.21  
    8.22 +#ifdef CONFIG_XEN
    8.23 +void __init smp_alloc_memory(void)
    8.24 +{
    8.25 +	int cpu;
    8.26 +
    8.27 +	for (cpu = 1; cpu < NR_CPUS; cpu++) {
    8.28 +		cpu_gdt_descr[cpu].address = (unsigned long)
    8.29 +			alloc_bootmem_low_pages(PAGE_SIZE);
    8.30 +		/* XXX free unused pages later */
    8.31 +	}
    8.32 +}
    8.33 +#endif
    8.34 +
    8.35  void __init setup_arch(char **cmdline_p)
    8.36  {
    8.37  	int i, j;
    8.38 @@ -740,6 +755,11 @@ void __init setup_arch(char **cmdline_p)
    8.39  		}
    8.40  	}
    8.41  #endif
    8.42 +#ifdef CONFIG_SMP
    8.43 +#ifdef CONFIG_XEN
    8.44 +	smp_alloc_memory();
    8.45 +#endif
    8.46 +#endif
    8.47  	paging_init();
    8.48  #ifdef CONFIG_X86_LOCAL_APIC
    8.49  	/*
     9.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c	Thu Aug 11 08:58:40 2005 +0000
     9.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c	Thu Aug 11 08:59:47 2005 +0000
     9.3 @@ -276,9 +276,11 @@ void __init cpu_init (void)
     9.4  	 * Initialize the per-CPU GDT with the boot GDT,
     9.5  	 * and set up the GDT descriptor:
     9.6  	 */
     9.7 +#ifndef CONFIG_XEN 
     9.8  	if (cpu) {
     9.9  		memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
    9.10  	}	
    9.11 +#endif
    9.12  
    9.13  	cpu_gdt_descr[cpu].size = GDT_SIZE;
    9.14  	cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
    10.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c	Thu Aug 11 08:58:40 2005 +0000
    10.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smp.c	Thu Aug 11 08:59:47 2005 +0000
    10.3 @@ -28,7 +28,12 @@
    10.4  #include <asm/mmu_context.h>
    10.5  #include <asm/proto.h>
    10.6  #include <asm/apicdef.h>
    10.7 +#ifdef CONFIG_XEN
    10.8 +#include <asm-xen/evtchn.h>
    10.9  
   10.10 +#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
   10.11 +
   10.12 +#else
   10.13  /*
   10.14   *	Smarter SMP flushing macros. 
   10.15   *		c/o Linus Torvalds.
   10.16 @@ -44,6 +49,7 @@ static struct mm_struct * flush_mm;
   10.17  static unsigned long flush_va;
   10.18  static DEFINE_SPINLOCK(tlbstate_lock);
   10.19  #define FLUSH_ALL	-1ULL
   10.20 +#endif
   10.21  
   10.22  /*
   10.23   * We cannot call mmdrop() because we are in interrupt context, 
   10.24 @@ -57,6 +63,7 @@ static inline void leave_mm (unsigned lo
   10.25  	load_cr3(swapper_pg_dir);
   10.26  }
   10.27  
   10.28 +#ifndef CONFIG_XEN
   10.29  /*
   10.30   *
   10.31   * The flush IPI assumes that a thread switch happens in this order:
   10.32 @@ -250,6 +257,18 @@ void flush_tlb_all(void)
   10.33  {
   10.34  	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
   10.35  }
   10.36 +#else
   10.37 +asmlinkage void smp_invalidate_interrupt (void)
   10.38 +{ return; }
   10.39 +void flush_tlb_current_task(void)
   10.40 +{ xen_tlb_flush_mask(&current->mm->cpu_vm_mask); }
   10.41 +void flush_tlb_mm (struct mm_struct * mm)
   10.42 +{ xen_tlb_flush_mask(&mm->cpu_vm_mask); }
   10.43 +void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
   10.44 +{ xen_invlpg_mask(&vma->vm_mm->cpu_vm_mask, va); }
   10.45 +void flush_tlb_all(void)
   10.46 +{ xen_tlb_flush_all(); }
   10.47 +#endif /* Xen */
   10.48  
   10.49  void smp_kdb_stop(void)
   10.50  {
   10.51 @@ -310,13 +329,21 @@ static void __smp_call_function (void (*
   10.52  
   10.53  	/* Wait for response */
   10.54  	while (atomic_read(&data.started) != cpus)
   10.55 +#ifndef CONFIG_XEN
   10.56  		cpu_relax();
   10.57 +#else
   10.58 +		barrier();
   10.59 +#endif
   10.60  
   10.61  	if (!wait)
   10.62  		return;
   10.63  
   10.64  	while (atomic_read(&data.finished) != cpus)
   10.65 +#ifndef CONFIG_XEN
   10.66  		cpu_relax();
   10.67 +#else
   10.68 +		barrier();
   10.69 +#endif
   10.70  }
   10.71  
   10.72  /*
   10.73 @@ -350,7 +377,11 @@ void smp_stop_cpu(void)
   10.74  	 */
   10.75  	cpu_clear(smp_processor_id(), cpu_online_map);
   10.76  	local_irq_disable();
   10.77 +#ifndef CONFIG_XEN
   10.78  	disable_local_APIC();
   10.79 +#else
   10.80 +	xxprint("stop_this_cpu disable_local_APIC\n");
   10.81 +#endif
   10.82  	local_irq_enable(); 
   10.83  }
   10.84  
   10.85 @@ -364,8 +395,10 @@ static void smp_really_stop_cpu(void *du
   10.86  void smp_send_stop(void)
   10.87  {
   10.88  	int nolock = 0;
   10.89 +#ifndef CONFIG_XEN
   10.90  	if (reboot_force)
   10.91  		return;
   10.92 +#endif
   10.93  	/* Don't deadlock on the call lock in panic */
   10.94  	if (!spin_trylock(&call_lock)) {
   10.95  		/* ignore locking because we have paniced anyways */
   10.96 @@ -376,7 +409,11 @@ void smp_send_stop(void)
   10.97  		spin_unlock(&call_lock);
   10.98  
   10.99  	local_irq_disable();
  10.100 +#ifdef CONFIG_XEN
  10.101 +	xxprint("stop_this_cpu disable_local_APIC\n");
  10.102 +#else
  10.103  	disable_local_APIC();
  10.104 +#endif
  10.105  	local_irq_enable();
  10.106  }
  10.107  
  10.108 @@ -385,18 +422,32 @@ void smp_send_stop(void)
  10.109   * all the work is done automatically when
  10.110   * we return from the interrupt.
  10.111   */
  10.112 +#ifndef CONFIG_XEN
  10.113  asmlinkage void smp_reschedule_interrupt(void)
  10.114 +#else
  10.115 +asmlinkage irqreturn_t smp_reschedule_interrupt(void)
  10.116 +#endif
  10.117  {
  10.118 +#ifndef CONFIG_XEN
  10.119  	ack_APIC_irq();
  10.120 +#else
  10.121 +	return IRQ_HANDLED;
  10.122 +#endif
  10.123  }
  10.124  
  10.125 +#ifndef CONFIG_XEN
  10.126  asmlinkage void smp_call_function_interrupt(void)
  10.127 +#else
  10.128 +asmlinkage irqreturn_t smp_call_function_interrupt(void)
  10.129 +#endif
  10.130  {
  10.131  	void (*func) (void *info) = call_data->func;
  10.132  	void *info = call_data->info;
  10.133  	int wait = call_data->wait;
  10.134  
  10.135 +#ifndef CONFIG_XEN
  10.136  	ack_APIC_irq();
  10.137 +#endif
  10.138  	/*
  10.139  	 * Notify initiating CPU that I've grabbed the data and am
  10.140  	 * about to execute the function
  10.141 @@ -413,10 +464,16 @@ asmlinkage void smp_call_function_interr
  10.142  		mb();
  10.143  		atomic_inc(&call_data->finished);
  10.144  	}
  10.145 +#ifdef CONFIG_XEN
  10.146 +	return IRQ_HANDLED;
  10.147 +#endif
  10.148  }
  10.149  
  10.150  int safe_smp_processor_id(void)
  10.151  {
  10.152 +#ifdef CONFIG_XEN
  10.153 +	return smp_processor_id();
  10.154 +#else
  10.155  	int apicid, i;
  10.156  
  10.157  	if (disable_apic)
  10.158 @@ -437,4 +494,5 @@ int safe_smp_processor_id(void)
  10.159  		return 0;
  10.160  
  10.161  	return 0; /* Should not happen */
  10.162 +#endif
  10.163  }
    11.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Thu Aug 11 08:58:40 2005 +0000
    11.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c	Thu Aug 11 08:59:47 2005 +0000
    11.3 @@ -47,6 +47,9 @@
    11.4  #include <linux/bootmem.h>
    11.5  #include <linux/thread_info.h>
    11.6  #include <linux/module.h>
    11.7 +#ifdef CONFIG_XEN
    11.8 +#include <linux/interrupt.h>
    11.9 +#endif
   11.10  
   11.11  #include <linux/delay.h>
   11.12  #include <linux/mc146818rtc.h>
   11.13 @@ -57,12 +60,21 @@
   11.14  #include <asm/tlbflush.h>
   11.15  #include <asm/proto.h>
   11.16  #include <asm/nmi.h>
   11.17 +#ifdef CONFIG_XEN
   11.18 +#include <asm/arch_hooks.h>
   11.19 +
   11.20 +#include <asm-xen/evtchn.h>
   11.21 +#endif
   11.22  
   11.23  /* Change for real CPU hotplug. Note other files need to be fixed
   11.24     first too. */
   11.25  #define __cpuinit __init
   11.26  #define __cpuinitdata __initdata
   11.27  
   11.28 +#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
   11.29 +	unsigned int maxcpus = NR_CPUS;
   11.30 +#endif
   11.31 +
   11.32  /* Number of siblings per CPU package */
   11.33  int smp_num_siblings = 1;
   11.34  /* Package ID of each logical CPU */
   11.35 @@ -96,6 +108,7 @@ cpumask_t cpu_sibling_map[NR_CPUS] __cac
   11.36  cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
   11.37  EXPORT_SYMBOL(cpu_core_map);
   11.38  
   11.39 +#ifndef CONFIG_XEN
   11.40  /*
   11.41   * Trampoline 80x86 program as an array.
   11.42   */
   11.43 @@ -115,6 +128,7 @@ static unsigned long __cpuinit setup_tra
   11.44  	memcpy(tramp, trampoline_data, trampoline_end - trampoline_data);
   11.45  	return virt_to_phys(tramp);
   11.46  }
   11.47 +#endif
   11.48  
   11.49  /*
   11.50   * The bootstrap kernel entry code has set these up. Save them for
   11.51 @@ -130,6 +144,7 @@ static void __cpuinit smp_store_cpu_info
   11.52  	print_cpu_info(c);
   11.53  }
   11.54  
   11.55 +#ifndef CONFIG_XEN
   11.56  /*
   11.57   * New Funky TSC sync algorithm borrowed from IA64.
   11.58   * Main advantage is that it doesn't reset the TSCs fully and
   11.59 @@ -331,6 +346,7 @@ static __init int notscsync_setup(char *
   11.60  	return 0;
   11.61  }
   11.62  __setup("notscsync", notscsync_setup);
   11.63 +#endif
   11.64  
   11.65  static atomic_t init_deasserted __cpuinitdata;
   11.66  
   11.67 @@ -343,6 +359,7 @@ void __cpuinit smp_callin(void)
   11.68  	int cpuid, phys_id;
   11.69  	unsigned long timeout;
   11.70  
   11.71 +#ifndef CONFIG_XEN
   11.72  	/*
   11.73  	 * If waken up by an INIT in an 82489DX configuration
   11.74  	 * we may get here before an INIT-deassert IPI reaches
   11.75 @@ -352,10 +369,15 @@ void __cpuinit smp_callin(void)
   11.76  	while (!atomic_read(&init_deasserted))
   11.77  		cpu_relax();
   11.78  
   11.79 +#endif
   11.80  	/*
   11.81  	 * (This works even if the APIC is not enabled.)
   11.82  	 */
   11.83 +#ifndef CONFIG_XEN
   11.84  	phys_id = GET_APIC_ID(apic_read(APIC_ID));
   11.85 +#else
   11.86 +	phys_id = smp_processor_id();
   11.87 +#endif
   11.88  	cpuid = smp_processor_id();
   11.89  	if (cpu_isset(cpuid, cpu_callin_map)) {
   11.90  		panic("smp_callin: phys CPU#%d, CPU#%d already present??\n",
   11.91 @@ -389,6 +411,7 @@ void __cpuinit smp_callin(void)
   11.92  			cpuid);
   11.93  	}
   11.94  
   11.95 +#ifndef CONFIG_XEN
   11.96  	/*
   11.97  	 * the boot CPU has finished the init stage and is spinning
   11.98  	 * on callin_map until we finish. We are free to set up this
   11.99 @@ -398,6 +421,7 @@ void __cpuinit smp_callin(void)
  11.100  
  11.101  	Dprintk("CALLIN, before setup_local_APIC().\n");
  11.102  	setup_local_APIC();
  11.103 +#endif
  11.104  
  11.105  	/*
  11.106  	 * Get our bogomips.
  11.107 @@ -405,7 +429,9 @@ void __cpuinit smp_callin(void)
  11.108  	calibrate_delay();
  11.109  	Dprintk("Stack at about %p\n",&cpuid);
  11.110  
  11.111 +#ifndef CONFIG_XEN
  11.112  	disable_APIC_timer();
  11.113 +#endif
  11.114  
  11.115  	/*
  11.116  	 * Save our processor parameters
  11.117 @@ -418,6 +444,29 @@ void __cpuinit smp_callin(void)
  11.118  	cpu_set(cpuid, cpu_callin_map);
  11.119  }
  11.120  
  11.121 +#ifdef CONFIG_XEN
  11.122 +static irqreturn_t ldebug_interrupt(
  11.123 +	int irq, void *dev_id, struct pt_regs *regs)
  11.124 +{
  11.125 +	return IRQ_HANDLED;
  11.126 +}
  11.127 +
  11.128 +static DEFINE_PER_CPU(int, ldebug_irq);
  11.129 +static char ldebug_name[NR_CPUS][15];
  11.130 +
  11.131 +void ldebug_setup(void)
  11.132 +{
  11.133 +	int cpu = smp_processor_id();
  11.134 +
  11.135 +	per_cpu(ldebug_irq, cpu) = bind_virq_to_irq(VIRQ_DEBUG);
  11.136 +	sprintf(ldebug_name[cpu], "ldebug%d", cpu);
  11.137 +	BUG_ON(request_irq(per_cpu(ldebug_irq, cpu), ldebug_interrupt,
  11.138 +	                   SA_INTERRUPT, ldebug_name[cpu], NULL));
  11.139 +}
  11.140 +
  11.141 +extern void local_setup_timer(void);
  11.142 +#endif
  11.143 +
  11.144  /*
  11.145   * Setup code on secondary processor (after comming out of the trampoline)
  11.146   */
  11.147 @@ -434,6 +483,7 @@ void __cpuinit start_secondary(void)
  11.148  	/* otherwise gcc will move up the smp_processor_id before the cpu_init */
  11.149  	barrier();
  11.150  
  11.151 +#ifndef CONFIG_XEN
  11.152  	Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); 	
  11.153  	setup_secondary_APIC_clock();
  11.154  
  11.155 @@ -446,6 +496,12 @@ void __cpuinit start_secondary(void)
  11.156  	}
  11.157  
  11.158  	enable_APIC_timer();
  11.159 +#else
  11.160 +	local_setup_timer();
  11.161 +	ldebug_setup();
  11.162 +	smp_intr_init();
  11.163 +	local_irq_enable();
  11.164 +#endif
  11.165  
  11.166  	/*
  11.167  	 * Allow the master to continue.
  11.168 @@ -453,10 +509,12 @@ void __cpuinit start_secondary(void)
  11.169  	cpu_set(smp_processor_id(), cpu_online_map);
  11.170  	mb();
  11.171  
  11.172 +#ifndef CONFIG_XEN
  11.173  	/* Wait for TSC sync to not schedule things before.
  11.174  	   We still process interrupts, which could see an inconsistent
  11.175  	   time in that window unfortunately. */
  11.176  	tsc_sync_wait();
  11.177 +#endif
  11.178  
  11.179  	cpu_idle();
  11.180  }
  11.181 @@ -464,6 +522,7 @@ void __cpuinit start_secondary(void)
  11.182  extern volatile unsigned long init_rsp;
  11.183  extern void (*initial_code)(void);
  11.184  
  11.185 +#ifndef CONFIG_XEN
  11.186  #if APIC_DEBUG
  11.187  static void inquire_remote_apic(int apicid)
  11.188  {
  11.189 @@ -627,6 +686,7 @@ static int __cpuinit wakeup_secondary_vi
  11.190  
  11.191  	return (send_status | accept_status);
  11.192  }
  11.193 +#endif
  11.194  
  11.195  /*
  11.196   * Boot one CPU.
  11.197 @@ -637,6 +697,14 @@ static int __cpuinit do_boot_cpu(int cpu
  11.198  	unsigned long boot_error;
  11.199  	int timeout;
  11.200  	unsigned long start_rip;
  11.201 +#ifdef CONFIG_XEN
  11.202 +	vcpu_guest_context_t ctxt;
  11.203 +	extern void startup_64_smp(void);
  11.204 +	extern void hypervisor_callback(void);
  11.205 +	extern void failsafe_callback(void);
  11.206 +	extern void smp_trap_init(trap_info_t *);
  11.207 +	int i;
  11.208 +#endif
  11.209  	/*
  11.210  	 * We can't use kernel_thread since we must avoid to
  11.211  	 * reschedule the child.
  11.212 @@ -649,7 +717,11 @@ static int __cpuinit do_boot_cpu(int cpu
  11.213  
  11.214  	cpu_pda[cpu].pcurrent = idle;
  11.215  
  11.216 +#ifndef CONFIG_XEN
  11.217  	start_rip = setup_trampoline();
  11.218 +#else
  11.219 +	start_rip = (unsigned long)startup_64_smp;
  11.220 +#endif
  11.221  
  11.222  	init_rsp = idle->thread.rsp;
  11.223  	per_cpu(init_tss,cpu).rsp0 = init_rsp;
  11.224 @@ -666,6 +738,93 @@ static int __cpuinit do_boot_cpu(int cpu
  11.225  
  11.226  	atomic_set(&init_deasserted, 0);
  11.227  
  11.228 +#ifdef CONFIG_XEN
  11.229 +	if (cpu_gdt_descr[0].size > PAGE_SIZE)
  11.230 +		BUG();
  11.231 +	cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
  11.232 +	memcpy((void *)cpu_gdt_descr[cpu].address,
  11.233 +		(void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
  11.234 +
  11.235 +	memset(&ctxt, 0, sizeof(ctxt));
  11.236 +
  11.237 +	ctxt.flags = VGCF_IN_KERNEL;
  11.238 +	ctxt.user_regs.ds = __USER_DS;
  11.239 +	ctxt.user_regs.es = __USER_DS;
  11.240 +	ctxt.user_regs.fs = 0;
  11.241 +	ctxt.user_regs.gs = 0;
  11.242 +	ctxt.user_regs.ss = __KERNEL_DS|0x3;
  11.243 +	ctxt.user_regs.cs = __KERNEL_CS|0x3;
  11.244 +	ctxt.user_regs.rip = start_rip;
  11.245 +	ctxt.user_regs.rsp = idle->thread.rsp;
  11.246 +#define X86_EFLAGS_IOPL_RING3 0x3000
  11.247 +	ctxt.user_regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_IOPL_RING3;
  11.248 +
  11.249 +	/* FPU is set up to default initial state. */
  11.250 +	memset(&ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
  11.251 +
  11.252 +	/* Virtual IDT is empty at start-of-day. */
  11.253 +	for ( i = 0; i < 256; i++ )
  11.254 +	{
  11.255 +		ctxt.trap_ctxt[i].vector = i;
  11.256 +		ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
  11.257 +	}
  11.258 +	smp_trap_init(ctxt.trap_ctxt);
  11.259 +
  11.260 +	/* No LDT. */
  11.261 +	ctxt.ldt_ents = 0;
  11.262 +
  11.263 +	{
  11.264 +		unsigned long va;
  11.265 +		int f;
  11.266 +
  11.267 +		for (va = cpu_gdt_descr[cpu].address, f = 0;
  11.268 +		     va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
  11.269 +		     va += PAGE_SIZE, f++) {
  11.270 +			ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
  11.271 +			make_page_readonly((void *)va);
  11.272 +		}
  11.273 +		ctxt.gdt_ents = GDT_ENTRIES;
  11.274 +	}
  11.275 +
  11.276 +	/* Ring 1 stack is the initial stack. */
  11.277 +	ctxt.kernel_ss = __KERNEL_DS;
  11.278 +	ctxt.kernel_sp = idle->thread.rsp;
  11.279 +
  11.280 +	/* Callback handlers. */
  11.281 +	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
  11.282 +	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
  11.283 +	ctxt.syscall_callback_eip  = (unsigned long)system_call;
  11.284 +
  11.285 +	ctxt.ctrlreg[3] = (unsigned long)virt_to_machine(init_level4_pgt);
  11.286 +
  11.287 +	boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt);
  11.288 +
  11.289 +	if (!boot_error) {
  11.290 +		/*
  11.291 +		 * allow APs to start initializing.
  11.292 +		 */
  11.293 +		Dprintk("Before Callout %d.\n", cpu);
  11.294 +		cpu_set(cpu, cpu_callout_map);
  11.295 +		Dprintk("After Callout %d.\n", cpu);
  11.296 +
  11.297 +		/*
  11.298 +		 * Wait 5s total for a response
  11.299 +		 */
  11.300 +		for (timeout = 0; timeout < 50000; timeout++) {
  11.301 +			if (cpu_isset(cpu, cpu_callin_map))
  11.302 +				break;	/* It has booted */
  11.303 +			udelay(100);
  11.304 +		}
  11.305 +
  11.306 +		if (cpu_isset(cpu, cpu_callin_map)) {
  11.307 +			/* number CPUs logically, starting from 1 (BSP is 0) */
  11.308 +			Dprintk("CPU has booted.\n");
  11.309 +		} else {
  11.310 +			boot_error= 1;
  11.311 +		}
  11.312 +	}
  11.313 +	x86_cpu_to_apicid[cpu] = apicid;
  11.314 +#else
  11.315  	Dprintk("Setting warm reset code and vector.\n");
  11.316  
  11.317  	CMOS_WRITE(0xa, 0xf);
  11.318 @@ -729,6 +888,7 @@ static int __cpuinit do_boot_cpu(int cpu
  11.319  #endif
  11.320  		}
  11.321  	}
  11.322 +#endif
  11.323  	if (boot_error) {
  11.324  		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
  11.325  		clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
  11.326 @@ -790,6 +950,7 @@ static __cpuinit void detect_siblings(vo
  11.327  	}
  11.328  }
  11.329  
  11.330 +#ifndef CONFIG_XEN
  11.331  /*
  11.332   * Cleanup possible dangling ends...
  11.333   */
  11.334 @@ -817,6 +978,7 @@ static __cpuinit void smp_cleanup_boot(v
  11.335  	free_page((unsigned long) __va(SMP_TRAMPOLINE_BASE));
  11.336  #endif
  11.337  }
  11.338 +#endif
  11.339  
  11.340  /*
  11.341   * Fall back to non SMP mode after errors.
  11.342 @@ -827,10 +989,12 @@ static __cpuinit void disable_smp(void)
  11.343  {
  11.344  	cpu_present_map = cpumask_of_cpu(0);
  11.345  	cpu_possible_map = cpumask_of_cpu(0);
  11.346 +#ifndef CONFIG_XEN
  11.347  	if (smp_found_config)
  11.348  		phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
  11.349  	else
  11.350  		phys_cpu_present_map = physid_mask_of_physid(0);
  11.351 +#endif
  11.352  	cpu_set(0, cpu_sibling_map[0]);
  11.353  	cpu_set(0, cpu_core_map[0]);
  11.354  }
  11.355 @@ -857,6 +1021,7 @@ static __cpuinit void enforce_max_cpus(u
  11.356   */
  11.357  static int __cpuinit smp_sanity_check(unsigned max_cpus)
  11.358  {
  11.359 +#ifndef CONFIG_XEN
  11.360  	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
  11.361  		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
  11.362  		       hard_smp_processor_id());
  11.363 @@ -896,13 +1061,19 @@ static int __cpuinit smp_sanity_check(un
  11.364  		nr_ioapics = 0;
  11.365  		return -1;
  11.366  	}
  11.367 +#endif
  11.368  
  11.369  	/*
  11.370  	 * If SMP should be disabled, then really disable it!
  11.371  	 */
  11.372  	if (!max_cpus) {
  11.373 +#ifdef CONFIG_XEN
  11.374 +		HYPERVISOR_shared_info->n_vcpu = 1;
  11.375 +#endif
  11.376  		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
  11.377 +#ifndef CONFIG_XEN
  11.378  		nr_ioapics = 0;
  11.379 +#endif
  11.380  		return -1;
  11.381  	}
  11.382  
  11.383 @@ -917,7 +1088,10 @@ void __cpuinit smp_prepare_cpus(unsigned
  11.384  {
  11.385  	int i;
  11.386  
  11.387 +#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
  11.388 +#else
  11.389  	nmi_watchdog_default();
  11.390 +#endif
  11.391  	current_cpu_data = boot_cpu_data;
  11.392  	current_thread_info()->cpu = 0;  /* needed? */
  11.393  
  11.394 @@ -927,8 +1101,12 @@ void __cpuinit smp_prepare_cpus(unsigned
  11.395  	 * Fill in cpu_present_mask
  11.396  	 */
  11.397  	for (i = 0; i < NR_CPUS; i++) {
  11.398 +#ifndef CONFIG_XEN
  11.399  		int apicid = cpu_present_to_apicid(i);
  11.400  		if (physid_isset(apicid, phys_cpu_present_map)) {
  11.401 +#else
  11.402 +		if (i < HYPERVISOR_shared_info->n_vcpu) {
  11.403 +#endif
  11.404  			cpu_set(i, cpu_present_map);
  11.405  			/* possible map would be different if we supported real
  11.406  			   CPU hotplug. */
  11.407 @@ -942,6 +1120,9 @@ void __cpuinit smp_prepare_cpus(unsigned
  11.408  		return;
  11.409  	}
  11.410  
  11.411 +#ifdef CONFIG_XEN
  11.412 +	smp_intr_init();
  11.413 +#else
  11.414  
  11.415  	/*
  11.416  	 * Switch from PIC to APIC mode.
  11.417 @@ -954,20 +1135,26 @@ void __cpuinit smp_prepare_cpus(unsigned
  11.418  		      GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
  11.419  		/* Or can we switch back to PIC here? */
  11.420  	}
  11.421 +#endif
  11.422  
  11.423  	/*
  11.424  	 * Now start the IO-APICs
  11.425  	 */
  11.426 +#if defined(CONFIG_XEN) && !defined(CONFIG_XEN_PRIVILEGED_GUEST)
  11.427 +#else
  11.428  	if (!skip_ioapic_setup && nr_ioapics)
  11.429  		setup_IO_APIC();
  11.430  	else
  11.431  		nr_ioapics = 0;
  11.432 +#endif
  11.433  
  11.434  	/*
  11.435  	 * Set up local APIC timer on boot CPU.
  11.436  	 */
  11.437  
  11.438 +#ifndef CONFIG_XEN
  11.439  	setup_boot_APIC_clock();
  11.440 +#endif
  11.441  }
  11.442  
  11.443  /*
  11.444 @@ -989,17 +1176,23 @@ void __init smp_prepare_boot_cpu(void)
  11.445  int __cpuinit __cpu_up(unsigned int cpu)
  11.446  {
  11.447  	int err;
  11.448 +#ifndef CONFIG_XEN
  11.449  	int apicid = cpu_present_to_apicid(cpu);
  11.450 +#else
  11.451 +	int apicid = cpu;
  11.452 +#endif
  11.453  
  11.454  	WARN_ON(irqs_disabled());
  11.455  
  11.456  	Dprintk("++++++++++++++++++++=_---CPU UP  %u\n", cpu);
  11.457  
  11.458 +#ifndef CONFIG_XEN
  11.459  	if (apicid == BAD_APICID || apicid == boot_cpu_id ||
  11.460  	    !physid_isset(apicid, phys_cpu_present_map)) {
  11.461  		printk("__cpu_up: bad cpu %d\n", cpu);
  11.462  		return -EINVAL;
  11.463  	}
  11.464 +#endif
  11.465  
  11.466  	/* Boot it! */
  11.467  	err = do_boot_cpu(cpu, apicid);
  11.468 @@ -1021,15 +1214,76 @@ int __cpuinit __cpu_up(unsigned int cpu)
  11.469   */
  11.470  void __cpuinit smp_cpus_done(unsigned int max_cpus)
  11.471  {
  11.472 +#ifndef CONFIG_XEN
  11.473  	zap_low_mappings();
  11.474  	smp_cleanup_boot();
  11.475  
  11.476  #ifdef CONFIG_X86_IO_APIC
  11.477  	setup_ioapic_dest();
  11.478  #endif
  11.479 +#endif
  11.480  
  11.481  	detect_siblings();
  11.482 +#ifndef CONFIG_XEN
  11.483  	time_init_gtod();
  11.484  
  11.485  	check_nmi_watchdog();
  11.486 +#endif
  11.487  }
  11.488 +
  11.489 +#ifdef CONFIG_XEN
  11.490 +extern int bind_ipi_to_irq(int ipi);
  11.491 +extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
  11.492 +extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
  11.493 +
  11.494 +static DEFINE_PER_CPU(int, resched_irq);
  11.495 +static DEFINE_PER_CPU(int, callfunc_irq);
  11.496 +static char resched_name[NR_CPUS][15];
  11.497 +static char callfunc_name[NR_CPUS][15];
  11.498 +
  11.499 +void smp_intr_init(void)
  11.500 +{
  11.501 +	int cpu = smp_processor_id();
  11.502 +
  11.503 +	per_cpu(resched_irq, cpu) =
  11.504 +		bind_ipi_to_irq(RESCHEDULE_VECTOR);
  11.505 +	sprintf(resched_name[cpu], "resched%d", cpu);
  11.506 +	BUG_ON(request_irq(per_cpu(resched_irq, cpu), smp_reschedule_interrupt,
  11.507 +	                   SA_INTERRUPT, resched_name[cpu], NULL));
  11.508 +
  11.509 +	per_cpu(callfunc_irq, cpu) =
  11.510 +		bind_ipi_to_irq(CALL_FUNCTION_VECTOR);
  11.511 +	sprintf(callfunc_name[cpu], "callfunc%d", cpu);
  11.512 +	BUG_ON(request_irq(per_cpu(callfunc_irq, cpu),
  11.513 +	                   smp_call_function_interrupt,
  11.514 +	                   SA_INTERRUPT, callfunc_name[cpu], NULL));
  11.515 +}
  11.516 +
  11.517 +static void smp_intr_exit(void)
  11.518 +{
  11.519 +	int cpu = smp_processor_id();
  11.520 +
  11.521 +	free_irq(per_cpu(resched_irq, cpu), NULL);
  11.522 +	unbind_ipi_from_irq(RESCHEDULE_VECTOR);
  11.523 +
  11.524 +	free_irq(per_cpu(callfunc_irq, cpu), NULL);
  11.525 +	unbind_ipi_from_irq(CALL_FUNCTION_VECTOR);
  11.526 +}
  11.527 +
  11.528 +extern void local_setup_timer_irq(void);
  11.529 +extern void local_teardown_timer_irq(void);
  11.530 +
  11.531 +void smp_suspend(void)
  11.532 +{
  11.533 +	/* XXX todo: take down time and ipi's on all cpus */
  11.534 +	local_teardown_timer_irq();
  11.535 +	smp_intr_exit();
  11.536 +}
  11.537 +
  11.538 +void smp_resume(void)
  11.539 +{
  11.540 +	/* XXX todo: restore time and ipi's on all cpus */
  11.541 +	smp_intr_init();
  11.542 +	local_setup_timer_irq();
  11.543 +}
  11.544 +#endif
    12.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c	Thu Aug 11 08:58:40 2005 +0000
    12.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/traps.c	Thu Aug 11 08:59:47 2005 +0000
    12.3 @@ -953,6 +953,17 @@ void __init trap_init(void)
    12.4  	cpu_init();
    12.5  }
    12.6  
    12.7 +void smp_trap_init(trap_info_t *trap_ctxt)
    12.8 +{
    12.9 +	trap_info_t *t = trap_table;
   12.10 +
   12.11 +	for (t = trap_table; t->address; t++) {
   12.12 +		trap_ctxt[t->vector].flags = t->flags;
   12.13 +		trap_ctxt[t->vector].cs = t->cs;
   12.14 +		trap_ctxt[t->vector].address = t->address;
   12.15 +	}
   12.16 +}
   12.17 +
   12.18  
   12.19  /* Actual parsing is done early in setup.c. */
   12.20  static int __init oops_dummy(char *s)
    13.1 --- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S	Thu Aug 11 08:58:40 2005 +0000
    13.2 +++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/xen_entry.S	Thu Aug 11 08:59:47 2005 +0000
    13.3 @@ -8,11 +8,14 @@
    13.4  #define sizeof_vcpu_shift		3
    13.5  
    13.6  #ifdef CONFIG_SMP
    13.7 -#define preempt_disable(reg)	incl threadinfo_preempt_count(reg)
    13.8 -#define preempt_enable(reg)	decl threadinfo_preempt_count(reg)
    13.9 +//#define preempt_disable(reg)	incl threadinfo_preempt_count(reg)
   13.10 +//#define preempt_enable(reg)	decl threadinfo_preempt_count(reg)
   13.11 +#define preempt_disable(reg)
   13.12 +#define preempt_enable(reg)
   13.13  #define XEN_GET_VCPU_INFO(reg)	preempt_disable(%rbp)			; \
   13.14  				movq %gs:pda_cpunumber,reg		; \
   13.15 -				shl  $sizeof_vcpu_shift,reg		; \
   13.16 +				shl  $32, reg				; \
   13.17 +				shr  $32-sizeof_vcpu_shift,reg		; \
   13.18  				addq HYPERVISOR_shared_info,reg
   13.19  #define XEN_PUT_VCPU_INFO(reg)	preempt_enable(%rbp)			; \
   13.20  #define XEN_PUT_VCPU_INFO_fixup .byte 0xff,0xff,0xff