WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Enable CONFIG_SMP compile and link

# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID f5c4042212b013d7750e5270d98c047c8419e5a7
# Parent  2b95125015a59eeb086b3748f9415ac440133b4d
Enable CONFIG_SMP compile and link

diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/hyperprivop.S
--- a/xen/arch/ia64/hyperprivop.S       Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/hyperprivop.S       Tue Aug 30 18:41:54 2005
@@ -25,6 +25,11 @@
 #define FAST_SSM_I
 #define FAST_PTC_GA
 #undef RFI_TO_INTERRUPT // not working yet
+#endif
+
+#ifdef CONFIG_SMP
+#warning "FIXME: ptc.ga instruction requires spinlock for SMP"
+#undef FAST_PTC_GA
 #endif
 
 // FIXME: turn off for now... but NaTs may crash Xen so re-enable soon!
@@ -1506,9 +1511,6 @@
 END(hyper_thash)
 
 ENTRY(hyper_ptc_ga)
-#ifdef CONFIG_SMP
-FIXME: ptc.ga instruction requires spinlock for SMP
-#endif
 #ifndef FAST_PTC_GA
        br.spnt.few dispatch_break_fault ;;
 #endif
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/irq.c
--- a/xen/arch/ia64/irq.c       Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/irq.c       Tue Aug 30 18:41:54 2005
@@ -266,8 +266,12 @@
 #ifdef CONFIG_SMP
 inline void synchronize_irq(unsigned int irq)
 {
-       while (irq_descp(irq)->status & IRQ_INPROGRESS)
+#ifndef XEN
+       struct irq_desc *desc = irq_desc + irq;
+
+       while (desc->status & IRQ_INPROGRESS)
                cpu_relax();
+#endif
 }
 EXPORT_SYMBOL(synchronize_irq);
 #endif
@@ -1012,6 +1016,8 @@
        return 0;
 }
 
+#ifndef XEN
+
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 
@@ -1121,6 +1127,7 @@
 
 
 #endif /* CONFIG_SMP */
+#endif
 
 #ifdef CONFIG_HOTPLUG_CPU
 unsigned int vectors_in_migration[NR_IRQS];
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux-xen/irq_ia64.c
--- a/xen/arch/ia64/linux-xen/irq_ia64.c        Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/linux-xen/irq_ia64.c        Tue Aug 30 18:41:54 2005
@@ -323,7 +323,9 @@
 
 static struct irqaction ipi_irqaction = {
        .handler =      handle_IPI,
+#ifndef XEN
        .flags =        SA_INTERRUPT,
+#endif
        .name =         "IPI"
 };
 #endif
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux-xen/mm_contig.c
--- a/xen/arch/ia64/linux-xen/mm_contig.c       Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/linux-xen/mm_contig.c       Tue Aug 30 18:41:54 2005
@@ -191,8 +191,13 @@
         * get_zeroed_page().
         */
        if (smp_processor_id() == 0) {
+#ifdef XEN
+               cpu_data = alloc_xenheap_pages(PERCPU_PAGE_SIZE -
+                       PAGE_SIZE + get_order(NR_CPUS));
+#else
                cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
                                           PERCPU_PAGE_SIZE, 
__pa(MAX_DMA_ADDRESS));
+#endif
                for (cpu = 0; cpu < NR_CPUS; cpu++) {
                        memcpy(cpu_data, __phys_per_cpu_start, __per_cpu_end - 
__per_cpu_start);
                        __per_cpu_offset[cpu] = (char *) cpu_data - 
__per_cpu_start;
@@ -204,6 +209,7 @@
 }
 #endif /* CONFIG_SMP */
 
+#ifndef XEN
 static int
 count_pages (u64 start, u64 end, void *arg)
 {
@@ -229,7 +235,6 @@
  * Set up the page tables.
  */
 
-#ifndef XEN
 void
 paging_init (void)
 {
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/process.c
--- a/xen/arch/ia64/process.c   Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/process.c   Tue Aug 30 18:41:54 2005
@@ -224,7 +224,7 @@
        regs->cr_iip = ((unsigned long) PSCBX(v,iva) + vector) & ~0xffUL;
        regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET;
 #ifdef CONFIG_SMP
-#error "sharedinfo doesn't handle smp yet"
+#warning "SMP FIXME: sharedinfo doesn't handle smp yet, need page per vcpu"
 #endif
        regs->r31 = &(((mapped_regs_t *)SHARED_ARCHINFO_ADDR)->ipsr);
 
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/xensetup.c
--- a/xen/arch/ia64/xensetup.c  Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/xensetup.c  Tue Aug 30 18:41:54 2005
@@ -26,6 +26,8 @@
 char saved_command_line[COMMAND_LINE_SIZE];
 
 struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
+
+cpumask_t cpu_present_map;
 
 #ifdef CLONE_DOMAIN0
 struct domain *clones[CLONE_DOMAIN0];
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/xentime.c
--- a/xen/arch/ia64/xentime.c   Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/xentime.c   Tue Aug 30 18:41:54 2005
@@ -31,6 +31,10 @@
 #include <linux/jiffies.h>     // not included by xen/sched.h
 #endif
 #include <xen/softirq.h>
+
+#ifdef XEN
+seqlock_t xtime_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED;
+#endif
 
 #define TIME_KEEPER_ID  0
 extern unsigned long wall_jiffies;
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/config.h
--- a/xen/include/asm-ia64/config.h     Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/config.h     Tue Aug 30 18:41:54 2005
@@ -20,6 +20,22 @@
 
 #define CONFIG_EFI_PCDP
 #define CONFIG_SERIAL_SGI_L1_CONSOLE
+
+#undef CONFIG_XEN_SMP
+
+#ifdef CONFIG_XEN_SMP
+#define CONFIG_SMP 1
+#define NR_CPUS 2
+#define CONFIG_NR_CPUS 2
+#else
+#undef CONFIG_SMP
+#define NR_CPUS 1
+#define CONFIG_NR_CPUS 1
+#endif
+//#define NR_CPUS 16
+//#define CONFIG_NR_CPUS 16
+//leave SMP for a later time
+//#undef CONFIG_SMP
 
 #ifndef __ASSEMBLY__
 
@@ -75,13 +91,16 @@
 //#define __cond_lock(x) (x)
 #define __must_check
 #define __deprecated
+#ifndef RELOC_HIDE
+# define RELOC_HIDE(ptr, off)                                  \
+  ({ unsigned long __ptr;                                      \
+     __ptr = (unsigned long) (ptr);                            \
+    (typeof(ptr)) (__ptr + (off)); })
+#endif
 
 // xen/include/asm/config.h
 #define HZ 100
-// leave SMP for a later time
-#define NR_CPUS 1
-//#define NR_CPUS 16
-//#define CONFIG_NR_CPUS 16
+// FIXME SMP: leave SMP for a later time
 #define barrier() __asm__ __volatile__("": : :"memory")
 
 ///////////////////////////////////////////////////////////////
@@ -99,13 +118,18 @@
 
 // from include/asm-ia64/smp.h
 #ifdef CONFIG_SMP
-#error "Lots of things to fix to enable CONFIG_SMP!"
-#endif
+#warning "Lots of things to fix to enable CONFIG_SMP!"
+#endif
+// FIXME SMP
 #define        get_cpu()       0
 #define put_cpu()      do {} while(0)
 
 // needed for common/dom0_ops.c until hyperthreading is supported
+#ifdef CONFIG_SMP
+extern int smp_num_siblings;
+#else
 #define smp_num_siblings 1
+#endif
 
 // from linux/include/linux/mm.h
 struct page;
@@ -253,10 +277,6 @@
 
 #define CONFIG_MCKINLEY
 
-//#define CONFIG_SMP 1
-//#define CONFIG_NR_CPUS 2
-//leave SMP for a later time
-#undef CONFIG_SMP
 #undef CONFIG_X86_LOCAL_APIC
 #undef CONFIG_X86_IO_APIC
 #undef CONFIG_X86_L1_CACHE_SHIFT
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/linux-xen/asm/pal.h
--- a/xen/include/asm-ia64/linux-xen/asm/pal.h  Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux-xen/asm/pal.h  Tue Aug 30 18:41:54 2005
@@ -67,6 +67,7 @@
 #define PAL_REGISTER_INFO      39      /* return AR and CR register 
information*/
 #define PAL_SHUTDOWN           40      /* enter processor shutdown state */
 #define PAL_PREFETCH_VISIBILITY        41      /* Make Processor Prefetches 
Visible */
+#define PAL_LOGICAL_TO_PHYSICAL 42     /* returns information on logical to 
physical processor mapping */
 
 #define PAL_COPY_PAL           256     /* relocate PAL procedures and PAL PMI 
*/
 #define PAL_HALT_INFO          257     /* return the low power capabilities of 
processor */
@@ -1559,7 +1560,76 @@
        return iprv.status;
 }
 
+/* data structure for getting information on logical to physical mappings */
+typedef union pal_log_overview_u {
+       struct {
+               u64     num_log         :16,    /* Total number of logical
+                                                * processors on this die
+                                                */
+                       tpc             :8,     /* Threads per core */
+                       reserved3       :8,     /* Reserved */
+                       cpp             :8,     /* Cores per processor */
+                       reserved2       :8,     /* Reserved */
+                       ppid            :8,     /* Physical processor ID */
+                       reserved1       :8;     /* Reserved */
+       } overview_bits;
+       u64 overview_data;
+} pal_log_overview_t;
+
+typedef union pal_proc_n_log_info1_u{
+       struct {
+               u64     tid             :16,    /* Thread id */
+                       reserved2       :16,    /* Reserved */
+                       cid             :16,    /* Core id */
+                       reserved1       :16;    /* Reserved */
+       } ppli1_bits;
+       u64     ppli1_data;
+} pal_proc_n_log_info1_t;
+
+typedef union pal_proc_n_log_info2_u {
+       struct {
+               u64     la              :16,    /* Logical address */
+                       reserved        :48;    /* Reserved */
+       } ppli2_bits;
+       u64     ppli2_data;
+} pal_proc_n_log_info2_t;
+
+typedef struct pal_logical_to_physical_s
+{
+       pal_log_overview_t overview;
+       pal_proc_n_log_info1_t ppli1;
+       pal_proc_n_log_info2_t ppli2;
+} pal_logical_to_physical_t;
+
+#define overview_num_log       overview.overview_bits.num_log
+#define overview_tpc           overview.overview_bits.tpc
+#define overview_cpp           overview.overview_bits.cpp
+#define overview_ppid          overview.overview_bits.ppid
+#define log1_tid               ppli1.ppli1_bits.tid
+#define log1_cid               ppli1.ppli1_bits.cid
+#define log2_la                        ppli2.ppli2_bits.la
+
+/* Get information on logical to physical processor mappings. */
+static inline s64
+ia64_pal_logical_to_phys(u64 proc_number, pal_logical_to_physical_t *mapping)
+{
+       struct ia64_pal_retval iprv;
+
+       PAL_CALL(iprv, PAL_LOGICAL_TO_PHYSICAL, proc_number, 0, 0);
+
+       if (iprv.status == PAL_STATUS_SUCCESS)
+       {
+               if (proc_number == 0)
+                       mapping->overview.overview_data = iprv.v0;
+               mapping->ppli1.ppli1_data = iprv.v1;
+               mapping->ppli2.ppli2_data = iprv.v2;
+       }
+
+       return iprv.status;
+}
+#ifdef XEN
 #include <asm/vmx_pal.h>
+#endif
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_IA64_PAL_H */
diff -r 2b95125015a5 -r f5c4042212b0 
xen/include/asm-ia64/linux-xen/asm/processor.h
--- a/xen/include/asm-ia64/linux-xen/asm/processor.h    Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux-xen/asm/processor.h    Tue Aug 30 18:41:54 2005
@@ -164,6 +164,13 @@
 #ifdef CONFIG_SMP
        __u64 loops_per_jiffy;
        int cpu;
+       __u32 socket_id;        /* physical processor socket id */
+       __u16 core_id;          /* core id */
+       __u16 thread_id;        /* thread id */
+       __u16 num_log;          /* Total number of logical processors on
+                                * this socket that were successfully booted */
+       __u8  cores_per_socket; /* Cores per processor socket */
+       __u8  threads_per_core; /* Threads per core */
 #endif
 
        /* CPUID-derived information: */
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/linux-xen/asm/system.h
--- a/xen/include/asm-ia64/linux-xen/asm/system.h       Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux-xen/asm/system.h       Tue Aug 30 18:41:54 2005
@@ -247,9 +247,9 @@
  */
 # define switch_to(prev,next,last) do {                                        
        \
        if (ia64_psr(ia64_task_regs(prev))->mfh && 
ia64_is_local_fpu_owner(prev)) {                             \
-               ia64_psr(ia64_task_regs(prev))->mfh = 0;                        
\
-               (prev)->thread.flags |= IA64_THREAD_FPH_VALID;                  
\
-               __ia64_save_fpu((prev)->thread.fph);                            
\
+               /* ia64_psr(ia64_task_regs(prev))->mfh = 0; */                  
\
+               /* (prev)->thread.flags |= IA64_THREAD_FPH_VALID; */            
        \
+               /* __ia64_save_fpu((prev)->thread.fph); */                      
        \
        }                                                                       
\
        __switch_to(prev, next, last);                                          
\
 } while (0)
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/linux/asm/sal.h
--- a/xen/include/asm-ia64/linux/asm/sal.h      Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux/asm/sal.h      Tue Aug 30 18:41:54 2005
@@ -91,6 +91,7 @@
 #define SAL_PCI_CONFIG_READ            0x01000010
 #define SAL_PCI_CONFIG_WRITE           0x01000011
 #define SAL_FREQ_BASE                  0x01000012
+#define SAL_PHYSICAL_ID_INFO           0x01000013
 
 #define SAL_UPDATE_PAL                 0x01000020
 
@@ -815,6 +816,17 @@
        return isrv.status;
 }
 
+/* Get physical processor die mapping in the platform. */
+static inline s64
+ia64_sal_physical_id_info(u16 *splid)
+{
+       struct ia64_sal_retval isrv;
+       SAL_CALL(isrv, SAL_PHYSICAL_ID_INFO, 0, 0, 0, 0, 0, 0, 0);
+       if (splid)
+               *splid = isrv.v0;
+       return isrv.status;
+}
+
 extern unsigned long sal_platform_features;
 
 extern int (*salinfo_platform_oemdata)(const u8 *, u8 **, u64 *);
@@ -832,6 +844,44 @@
                                   u64, u64, u64, u64, u64);
 extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
                                      u64, u64, u64, u64, u64);
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * System Abstraction Layer Specification
+ * Section 3.2.5.1: OS_BOOT_RENDEZ to SAL return State.
+ * Note: region regs are stored first in head.S _start. Hence they must
+ * stay up front.
+ */
+struct sal_to_os_boot {
+       u64 rr[8];              /* Region Registers */
+       u64     br[6];          /* br0: return addr into SAL boot rendez 
routine */
+       u64 gr1;                /* SAL:GP */
+       u64 gr12;               /* SAL:SP */
+       u64 gr13;               /* SAL: Task Pointer */
+       u64 fpsr;
+       u64     pfs;
+       u64 rnat;
+       u64 unat;
+       u64 bspstore;
+       u64 dcr;                /* Default Control Register */
+       u64 iva;
+       u64 pta;
+       u64 itv;
+       u64 pmv;
+       u64 cmcv;
+       u64 lrr[2];
+       u64 gr[4];
+       u64 pr;                 /* Predicate registers */
+       u64 lc;                 /* Loop Count */
+       struct ia64_fpreg fp[20];
+};
+
+/*
+ * Global array allocated for NR_CPUS at boot time
+ */
+extern struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
+
+extern void ia64_jump_to_sal(struct sal_to_os_boot *);
+#endif
 
 extern void ia64_sal_handler_init(void *entry_point, void *gpval);
 
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/vhpt.h
--- a/xen/include/asm-ia64/vhpt.h       Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/vhpt.h       Tue Aug 30 18:41:54 2005
@@ -129,7 +129,7 @@
 #define VHPT_CCHAIN_LOOKUP(Name, i_or_d)
 #else
 #ifdef CONFIG_SMP
-#error "VHPT_CCHAIN_LOOKUP needs a semaphore on the VHPT!"
+#warning "FIXME SMP: VHPT_CCHAIN_LOOKUP needs a semaphore on the VHPT!"
 #endif
 
 // VHPT_CCHAIN_LOOKUP is intended to run with psr.i+ic off
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux-xen/sal.c
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/linux-xen/sal.c     Tue Aug 30 18:41:54 2005
@@ -0,0 +1,305 @@
+/*
+ * System Abstraction Layer (SAL) interface routines.
+ *
+ * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ */
+#include <linux/config.h>
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/sal.h>
+#include <asm/pal.h>
+#ifdef XEN
+#include <linux/smp.h>
+#endif
+
+ __cacheline_aligned DEFINE_SPINLOCK(sal_lock);
+unsigned long sal_platform_features;
+
+unsigned short sal_revision;
+unsigned short sal_version;
+
+#define SAL_MAJOR(x) ((x) >> 8)
+#define SAL_MINOR(x) ((x) & 0xff)
+
+static struct {
+       void *addr;     /* function entry point */
+       void *gpval;    /* gp value to use */
+} pdesc;
+
+static long
+default_handler (void)
+{
+       return -1;
+}
+
+ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler;
+ia64_sal_desc_ptc_t *ia64_ptc_domain_info;
+
+const char *
+ia64_sal_strerror (long status)
+{
+       const char *str;
+       switch (status) {
+             case 0: str = "Call completed without error"; break;
+             case 1: str = "Effect a warm boot of the system to complete "
+                             "the update"; break;
+             case -1: str = "Not implemented"; break;
+             case -2: str = "Invalid argument"; break;
+             case -3: str = "Call completed with error"; break;
+             case -4: str = "Virtual address not registered"; break;
+             case -5: str = "No information available"; break;
+             case -6: str = "Insufficient space to add the entry"; break;
+             case -7: str = "Invalid entry_addr value"; break;
+             case -8: str = "Invalid interrupt vector"; break;
+             case -9: str = "Requested memory not available"; break;
+             case -10: str = "Unable to write to the NVM device"; break;
+             case -11: str = "Invalid partition type specified"; break;
+             case -12: str = "Invalid NVM_Object id specified"; break;
+             case -13: str = "NVM_Object already has the maximum number "
+                               "of partitions"; break;
+             case -14: str = "Insufficient space in partition for the "
+                               "requested write sub-function"; break;
+             case -15: str = "Insufficient data buffer space for the "
+                               "requested read record sub-function"; break;
+             case -16: str = "Scratch buffer required for the write/delete "
+                               "sub-function"; break;
+             case -17: str = "Insufficient space in the NVM_Object for the "
+                               "requested create sub-function"; break;
+             case -18: str = "Invalid value specified in the partition_rec "
+                               "argument"; break;
+             case -19: str = "Record oriented I/O not supported for this "
+                               "partition"; break;
+             case -20: str = "Bad format of record to be written or "
+                               "required keyword variable not "
+                               "specified"; break;
+             default: str = "Unknown SAL status code"; break;
+       }
+       return str;
+}
+
+void __init
+ia64_sal_handler_init (void *entry_point, void *gpval)
+{
+       /* fill in the SAL procedure descriptor and point ia64_sal to it: */
+       pdesc.addr = entry_point;
+       pdesc.gpval = gpval;
+       ia64_sal = (ia64_sal_handler) &pdesc;
+}
+
+static void __init
+check_versions (struct ia64_sal_systab *systab)
+{
+       sal_revision = (systab->sal_rev_major << 8) | systab->sal_rev_minor;
+       sal_version = (systab->sal_b_rev_major << 8) | systab->sal_b_rev_minor;
+
+       /* Check for broken firmware */
+       if ((sal_revision == SAL_VERSION_CODE(49, 29))
+           && (sal_version == SAL_VERSION_CODE(49, 29)))
+       {
+               /*
+                * Old firmware for zx2000 prototypes have this weird version 
number,
+                * reset it to something sane.
+                */
+               sal_revision = SAL_VERSION_CODE(2, 8);
+               sal_version = SAL_VERSION_CODE(0, 0);
+       }
+}
+
+static void __init
+sal_desc_entry_point (void *p)
+{
+       struct ia64_sal_desc_entry_point *ep = p;
+       ia64_pal_handler_init(__va(ep->pal_proc));
+       ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
+}
+
+#ifdef CONFIG_SMP
+static void __init
+set_smp_redirect (int flag)
+{
+#ifndef CONFIG_HOTPLUG_CPU
+       if (no_int_routing)
+               smp_int_redirect &= ~flag;
+       else
+               smp_int_redirect |= flag;
+#else
+       /*
+        * For CPU Hotplug we dont want to do any chipset supported
+        * interrupt redirection. The reason is this would require that
+        * All interrupts be stopped and hard bind the irq to a cpu.
+        * Later when the interrupt is fired we need to set the redir hint
+        * on again in the vector. This is combersome for something that the
+        * user mode irq balancer will solve anyways.
+        */
+       no_int_routing=1;
+       smp_int_redirect &= ~flag;
+#endif
+}
+#else
+#define set_smp_redirect(flag) do { } while (0)
+#endif
+
+static void __init
+sal_desc_platform_feature (void *p)
+{
+       struct ia64_sal_desc_platform_feature *pf = p;
+       sal_platform_features = pf->feature_mask;
+
+       printk(KERN_INFO "SAL Platform features:");
+       if (!sal_platform_features) {
+               printk(" None\n");
+               return;
+       }
+
+       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK)
+               printk(" BusLock");
+       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) {
+               printk(" IRQ_Redirection");
+               set_smp_redirect(SMP_IRQ_REDIRECTION);
+       }
+       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) {
+               printk(" IPI_Redirection");
+               set_smp_redirect(SMP_IPI_REDIRECTION);
+       }
+       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)
+               printk(" ITC_Drift");
+       printk("\n");
+}
+
+#ifdef CONFIG_SMP
+static void __init
+sal_desc_ap_wakeup (void *p)
+{
+       struct ia64_sal_desc_ap_wakeup *ap = p;
+
+       switch (ap->mechanism) {
+       case IA64_SAL_AP_EXTERNAL_INT:
+               ap_wakeup_vector = ap->vector;
+               printk(KERN_INFO "SAL: AP wakeup using external interrupt "
+                               "vector 0x%lx\n", ap_wakeup_vector);
+               break;
+       default:
+               printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n");
+               break;
+       }
+}
+
+static void __init
+chk_nointroute_opt(void)
+{
+       char *cp;
+       extern char saved_command_line[];
+
+       for (cp = saved_command_line; *cp; ) {
+               if (memcmp(cp, "nointroute", 10) == 0) {
+                       no_int_routing = 1;
+                       printk ("no_int_routing on\n");
+                       break;
+               } else {
+                       while (*cp != ' ' && *cp)
+                               ++cp;
+                       while (*cp == ' ')
+                               ++cp;
+               }
+       }
+}
+
+#else
+static void __init sal_desc_ap_wakeup(void *p) { }
+#endif
+
+void __init
+ia64_sal_init (struct ia64_sal_systab *systab)
+{
+       char *p;
+       int i;
+
+       if (!systab) {
+               printk(KERN_WARNING "Hmm, no SAL System Table.\n");
+               return;
+       }
+
+       if (strncmp(systab->signature, "SST_", 4) != 0)
+               printk(KERN_ERR "bad signature in system table!");
+
+       check_versions(systab);
+#ifdef CONFIG_SMP
+       chk_nointroute_opt();
+#endif
+
+       /* revisions are coded in BCD, so %x does the job for us */
+       printk(KERN_INFO "SAL %x.%x: %.32s %.32s%sversion %x.%x\n",
+                       SAL_MAJOR(sal_revision), SAL_MINOR(sal_revision),
+                       systab->oem_id, systab->product_id,
+                       systab->product_id[0] ? " " : "",
+                       SAL_MAJOR(sal_version), SAL_MINOR(sal_version));
+
+       p = (char *) (systab + 1);
+       for (i = 0; i < systab->entry_count; i++) {
+               /*
+                * The first byte of each entry type contains the type
+                * descriptor.
+                */
+               switch (*p) {
+               case SAL_DESC_ENTRY_POINT:
+                       sal_desc_entry_point(p);
+                       break;
+               case SAL_DESC_PLATFORM_FEATURE:
+                       sal_desc_platform_feature(p);
+                       break;
+               case SAL_DESC_PTC:
+                       ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p;
+                       break;
+               case SAL_DESC_AP_WAKEUP:
+                       sal_desc_ap_wakeup(p);
+                       break;
+               }
+               p += SAL_DESC_SIZE(*p);
+       }
+}
+
+int
+ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+                u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
+{
+       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+               return -1;
+       SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+       return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall);
+
+int
+ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
+                       u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+                       u64 arg7)
+{
+       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+               return -1;
+       SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+                       arg7);
+       return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_nolock);
+
+int
+ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
+                          u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
+                          u64 arg6, u64 arg7)
+{
+       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
+               return -1;
+       SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
+                          arg7);
+       return 0;
+}
+EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux-xen/smp.c
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/linux-xen/smp.c     Tue Aug 30 18:41:54 2005
@@ -0,0 +1,427 @@
+/*
+ * SMP Support
+ *
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang <davidm@xxxxxxxxxx>
+ *
+ * Lots of stuff stolen from arch/alpha/kernel/smp.c
+ *
+ * 01/05/16 Rohit Seth <rohit.seth@xxxxxxxxx>  IA64-SMP functions. Reorganized
+ * the existing code (on the lines of x86 port).
+ * 00/09/11 David Mosberger <davidm@xxxxxxxxxx> Do loops_per_jiffy
+ * calibration on each CPU.
+ * 00/08/23 Asit Mallick <asit.k.mallick@xxxxxxxxx> fixed logical processor id
+ * 00/03/31 Rohit Seth <rohit.seth@xxxxxxxxx>  Fixes for Bootstrap Processor
+ * & cpu_online_map now gets done here (instead of setup.c)
+ * 99/10/05 davidm     Update to bring it in sync with new command-line 
processing
+ *  scheme.
+ * 10/13/00 Goutham Rao <goutham.rao@xxxxxxxxx> Updated smp_call_function and
+ *             smp_call_function_single to resend IPI on timeouts
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/cache.h>
+#include <linux/delay.h>
+#include <linux/efi.h>
+#include <linux/bitops.h>
+
+#include <asm/atomic.h>
+#include <asm/current.h>
+#include <asm/delay.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/unistd.h>
+#include <asm/mca.h>
+#ifdef XEN
+#include <asm/hw_irq.h>
+#endif
+
+#ifdef XEN
+// FIXME: MOVE ELSEWHERE
+//Huh? This seems to be used on ia64 even if !CONFIG_SMP
+void flush_tlb_mask(cpumask_t mask)
+{
+       dummy();
+}
+//#if CONFIG_SMP || IA64
+#if CONFIG_SMP
+//Huh? This seems to be used on ia64 even if !CONFIG_SMP
+void smp_send_event_check_mask(cpumask_t mask)
+{
+       dummy();
+       //send_IPI_mask(cpu_mask, EVENT_CHECK_VECTOR);
+}
+
+
+//Huh? This seems to be used on ia64 even if !CONFIG_SMP
+int try_flush_tlb_mask(cpumask_t mask)
+{
+       dummy();
+       return 1;
+}
+#endif
+#endif
+
+#ifdef CONFIG_SMP      /* ifdef XEN */
+
+/*
+ * Structure and data for smp_call_function(). This is designed to minimise 
static memory
+ * requirements. It also looks cleaner.
+ */
+static  __cacheline_aligned DEFINE_SPINLOCK(call_lock);
+
+struct call_data_struct {
+       void (*func) (void *info);
+       void *info;
+       long wait;
+       atomic_t started;
+       atomic_t finished;
+};
+
+static volatile struct call_data_struct *call_data;
+
+#define IPI_CALL_FUNC          0
+#define IPI_CPU_STOP           1
+
+/* This needs to be cacheline aligned because it is written to by *other* 
CPUs.  */
+static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
+
+extern void cpu_halt (void);
+
+void
+lock_ipi_calllock(void)
+{
+       spin_lock_irq(&call_lock);
+}
+
+void
+unlock_ipi_calllock(void)
+{
+       spin_unlock_irq(&call_lock);
+}
+
+static void
+stop_this_cpu (void)
+{
+       /*
+        * Remove this CPU:
+        */
+       cpu_clear(smp_processor_id(), cpu_online_map);
+       max_xtp();
+       local_irq_disable();
+#ifndef XEN
+       cpu_halt();
+#endif
+}
+
+void
+cpu_die(void)
+{
+       max_xtp();
+       local_irq_disable();
+#ifndef XEN
+       cpu_halt();
+#endif
+       /* Should never be here */
+       BUG();
+       for (;;);
+}
+
+irqreturn_t
+handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
+{
+       int this_cpu = get_cpu();
+       unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation);
+       unsigned long ops;
+
+       mb();   /* Order interrupt and bit testing. */
+       while ((ops = xchg(pending_ipis, 0)) != 0) {
+               mb();   /* Order bit clearing and data access. */
+               do {
+                       unsigned long which;
+
+                       which = ffz(~ops);
+                       ops &= ~(1 << which);
+
+                       switch (which) {
+                             case IPI_CALL_FUNC:
+                             {
+                                     struct call_data_struct *data;
+                                     void (*func)(void *info);
+                                     void *info;
+                                     int wait;
+
+                                     /* release the 'pointer lock' */
+                                     data = (struct call_data_struct *) 
call_data;
+                                     func = data->func;
+                                     info = data->info;
+                                     wait = data->wait;
+
+                                     mb();
+                                     atomic_inc(&data->started);
+                                     /*
+                                      * At this point the structure may be 
gone unless
+                                      * wait is true.
+                                      */
+                                     (*func)(info);
+
+                                     /* Notify the sending CPU that the task 
is done.  */
+                                     mb();
+                                     if (wait)
+                                             atomic_inc(&data->finished);
+                             }
+                             break;
+
+                             case IPI_CPU_STOP:
+                               stop_this_cpu();
+                               break;
+
+                             default:
+                               printk(KERN_CRIT "Unknown IPI on CPU %d: 
%lu\n", this_cpu, which);
+                               break;
+                       }
+               } while (ops);
+               mb();   /* Order data access and bit testing. */
+       }
+       put_cpu();
+       return IRQ_HANDLED;
+}
+
+/*
+ * Called with preeemption disabled.
+ */
+static inline void
+send_IPI_single (int dest_cpu, int op)
+{
+       set_bit(op, &per_cpu(ipi_operation, dest_cpu));
+       platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
+}
+
+/*
+ * Called with preeemption disabled.
+ */
+static inline void
+send_IPI_allbutself (int op)
+{
+       unsigned int i;
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (cpu_online(i) && i != smp_processor_id())
+                       send_IPI_single(i, op);
+       }
+}
+
+/*
+ * Called with preeemption disabled.
+ */
+static inline void
+send_IPI_all (int op)
+{
+       int i;
+
+       for (i = 0; i < NR_CPUS; i++)
+               if (cpu_online(i))
+                       send_IPI_single(i, op);
+}
+
+/*
+ * Called with preeemption disabled.
+ */
+static inline void
+send_IPI_self (int op)
+{
+       send_IPI_single(smp_processor_id(), op);
+}
+
+/*
+ * Called with preeemption disabled.
+ */
+void
+smp_send_reschedule (int cpu)
+{
+       platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
+}
+
+void
+smp_flush_tlb_all (void)
+{
+       on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1);
+}
+
+void
+smp_flush_tlb_mm (struct mm_struct *mm)
+{
+       preempt_disable();
+       /* this happens for the common case of a single-threaded fork():  */
+       if (likely(mm == current->active_mm && atomic_read(&mm->mm_users) == 1))
+       {
+               local_finish_flush_tlb_mm(mm);
+               preempt_enable();
+               return;
+       }
+
+       preempt_enable();
+       /*
+        * We could optimize this further by using mm->cpu_vm_mask to track 
which CPUs
+        * have been running in the address space.  It's not clear that this is 
worth the
+        * trouble though: to avoid races, we have to raise the IPI on the 
target CPU
+        * anyhow, and once a CPU is interrupted, the cost of 
local_flush_tlb_all() is
+        * rather trivial.
+        */
+       on_each_cpu((void (*)(void *))local_finish_flush_tlb_mm, mm, 1, 1);
+}
+
+/*
+ * Run a function on another CPU
+ *  <func>     The function to run. This must be fast and non-blocking.
+ *  <info>     An arbitrary pointer to pass to the function.
+ *  <nonatomic>        Currently unused.
+ *  <wait>     If true, wait until function has completed on other CPUs.
+ *  [RETURNS]   0 on success, else a negative status code.
+ *
+ * Does not return until the remote CPU is nearly ready to execute <func>
+ * or is or has executed.
+ */
+
+int
+smp_call_function_single (int cpuid, void (*func) (void *info), void *info, 
int nonatomic,
+                         int wait)
+{
+       struct call_data_struct data;
+       int cpus = 1;
+       int me = get_cpu(); /* prevent preemption and reschedule on another 
processor */
+
+       if (cpuid == me) {
+               printk(KERN_INFO "%s: trying to call self\n", __FUNCTION__);
+               put_cpu();
+               return -EBUSY;
+       }
+
+       data.func = func;
+       data.info = info;
+       atomic_set(&data.started, 0);
+       data.wait = wait;
+       if (wait)
+               atomic_set(&data.finished, 0);
+
+#ifdef XEN
+       spin_lock(&call_lock);
+#else
+       spin_lock_bh(&call_lock);
+#endif
+
+       call_data = &data;
+       mb();   /* ensure store to call_data precedes setting of IPI_CALL_FUNC 
*/
+       send_IPI_single(cpuid, IPI_CALL_FUNC);
+
+       /* Wait for response */
+       while (atomic_read(&data.started) != cpus)
+               cpu_relax();
+
+       if (wait)
+               while (atomic_read(&data.finished) != cpus)
+                       cpu_relax();
+       call_data = NULL;
+
+#ifdef XEN
+       spin_unlock(&call_lock);
+#else
+       spin_unlock_bh(&call_lock);
+#endif
+       put_cpu();
+       return 0;
+}
+EXPORT_SYMBOL(smp_call_function_single);
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+/*
+ *  [SUMMARY]  Run a function on all other CPUs.
+ *  <func>     The function to run. This must be fast and non-blocking.
+ *  <info>     An arbitrary pointer to pass to the function.
+ *  <nonatomic>        currently unused.
+ *  <wait>     If true, wait (atomically) until function has completed on 
other CPUs.
+ *  [RETURNS]   0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func> or are 
or have
+ * executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler or from a bottom half handler.
+ */
+int
+smp_call_function (void (*func) (void *info), void *info, int nonatomic, int 
wait)
+{
+       struct call_data_struct data;
+       int cpus = num_online_cpus()-1;
+
+       if (!cpus)
+               return 0;
+
+       /* Can deadlock when called with interrupts disabled */
+#ifdef XEN
+       if (irqs_disabled()) panic("smp_call_function called with interrupts 
disabled\n");
+#else
+       WARN_ON(irqs_disabled());
+#endif
+
+       data.func = func;
+       data.info = info;
+       atomic_set(&data.started, 0);
+       data.wait = wait;
+       if (wait)
+               atomic_set(&data.finished, 0);
+
+       spin_lock(&call_lock);
+
+       call_data = &data;
+       mb();   /* ensure store to call_data precedes setting of IPI_CALL_FUNC 
*/
+       send_IPI_allbutself(IPI_CALL_FUNC);
+
+       /* Wait for response */
+       while (atomic_read(&data.started) != cpus)
+               cpu_relax();
+
+       if (wait)
+               while (atomic_read(&data.finished) != cpus)
+                       cpu_relax();
+       call_data = NULL;
+
+       spin_unlock(&call_lock);
+       return 0;
+}
+EXPORT_SYMBOL(smp_call_function);
+
+/*
+ * this function calls the 'stop' function on all other CPUs in the system.
+ */
+void
+smp_send_stop (void)
+{
+       send_IPI_allbutself(IPI_CPU_STOP);
+}
+
+int __init
+setup_profiling_timer (unsigned int multiplier)
+{
+       return -EINVAL;
+}
+#endif /* CONFIG_SMP ifdef XEN */
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux-xen/smpboot.c
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/arch/ia64/linux-xen/smpboot.c Tue Aug 30 18:41:54 2005
@@ -0,0 +1,903 @@
+/*
+ * SMP boot-related support
+ *
+ * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ * Copyright (C) 2001, 2004-2005 Intel Corp
+ *     Rohit Seth <rohit.seth@xxxxxxxxx>
+ *     Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
+ *     Gordon Jin <gordon.jin@xxxxxxxxx>
+ *     Ashok Raj  <ashok.raj@xxxxxxxxx>
+ *
+ * 01/05/16 Rohit Seth <rohit.seth@xxxxxxxxx>  Moved SMP booting functions 
from smp.c to here.
+ * 01/04/27 David Mosberger <davidm@xxxxxxxxxx>        Added ITC synching code.
+ * 02/07/31 David Mosberger <davidm@xxxxxxxxxx>        Switch over to 
hotplug-CPU boot-sequence.
+ *                                             smp_boot_cpus()/smp_commence() 
is replaced by
+ *                                             
smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
+ * 04/06/21 Ashok Raj          <ashok.raj@xxxxxxxxx> Added CPU Hotplug Support
+ * 04/12/26 Jin Gordon <gordon.jin@xxxxxxxxx>
+ * 04/12/26 Rohit Seth <rohit.seth@xxxxxxxxx>
+ *                                             Add multi-threading and 
multi-core detection
+ * 05/01/30 Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
+ *                                             Setup cpu_sibling_map and 
cpu_core_map
+ */
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/bootmem.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>    /* hg add me */
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/efi.h>
+#include <linux/percpu.h>
+#include <linux/bitops.h>
+
+#include <asm/atomic.h>
+#include <asm/cache.h>
+#include <asm/current.h>
+#include <asm/delay.h>
+#include <asm/ia32.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
+#include <asm/mca.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+#include <asm/unistd.h>
+
+#ifdef XEN
+#include <asm/hw_irq.h>
+int ht_per_core = 1;
+#endif
+
+#ifdef CONFIG_SMP /* ifdef XEN */
+
+#define SMP_DEBUG 0
+
+#if SMP_DEBUG
+#define Dprintk(x...)  printk(x)
+#else
+#define Dprintk(x...)
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Store all idle threads, this can be reused instead of creating
+ * a new thread. Also avoids complicated thread destroy functionality
+ * for idle threads.
+ */
+struct task_struct *idle_thread_array[NR_CPUS];
+
+/*
+ * Global array allocated for NR_CPUS at boot time
+ */
+struct sal_to_os_boot sal_boot_rendez_state[NR_CPUS];
+
+/*
+ * start_ap in head.S uses this to store current booting cpu
+ * info.
+ */
+struct sal_to_os_boot *sal_state_for_booting_cpu = &sal_boot_rendez_state[0];
+
+#define set_brendez_area(x) (sal_state_for_booting_cpu = 
&sal_boot_rendez_state[(x)]);
+
+#define get_idle_for_cpu(x)            (idle_thread_array[(x)])
+#define set_idle_for_cpu(x,p)  (idle_thread_array[(x)] = (p))
+
+#else
+
+#define get_idle_for_cpu(x)            (NULL)
+#define set_idle_for_cpu(x,p)
+#define set_brendez_area(x)
+#endif
+
+
+/*
+ * ITC synchronization related stuff:
+ */
+#define MASTER 0
+#define SLAVE  (SMP_CACHE_BYTES/8)
+
+#define NUM_ROUNDS     64      /* magic value */
+#define NUM_ITERS      5       /* likewise */
+
+static DEFINE_SPINLOCK(itc_sync_lock);
+static volatile unsigned long go[SLAVE + 1];
+
+#define DEBUG_ITC_SYNC 0
+
+extern void __devinit calibrate_delay (void);
+extern void start_ap (void);
+extern unsigned long ia64_iobase;
+
+task_t *task_for_booting_cpu;
+
+/*
+ * State for each CPU
+ */
+DEFINE_PER_CPU(int, cpu_state);
+
+/* Bitmasks of currently online, and possible CPUs */
+cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
+cpumask_t cpu_possible_map;
+EXPORT_SYMBOL(cpu_possible_map);
+
+cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+int smp_num_siblings = 1;
+int smp_num_cpucores = 1;
+
+/* which logical CPU number maps to which CPU (physical APIC ID) */
+volatile int ia64_cpu_to_sapicid[NR_CPUS];
+EXPORT_SYMBOL(ia64_cpu_to_sapicid);
+
+static volatile cpumask_t cpu_callin_map;
+
+struct smp_boot_data smp_boot_data __initdata;
+
+unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */
+
+char __initdata no_int_routing;
+
+unsigned char smp_int_redirect; /* are INT and IPI redirectable by the 
chipset? */
+
+static int __init
+nointroute (char *str)
+{
+       no_int_routing = 1;
+       printk ("no_int_routing on\n");
+       return 1;
+}
+
+__setup("nointroute", nointroute);
+
+void
+sync_master (void *arg)
+{
+       unsigned long flags, i;
+
+       go[MASTER] = 0;
+
+       local_irq_save(flags);
+       {
+               for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
+                       while (!go[MASTER])
+                               cpu_relax();
+                       go[MASTER] = 0;
+                       go[SLAVE] = ia64_get_itc();
+               }
+       }
+       local_irq_restore(flags);
+}
+
+/*
+ * Return the number of cycles by which our itc differs from the itc on the 
master
+ * (time-keeper) CPU.  A positive number indicates our itc is ahead of the 
master,
+ * negative that it is behind.
+ */
+static inline long
+get_delta (long *rt, long *master)
+{
+       unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
+       unsigned long tcenter, t0, t1, tm;
+       long i;
+
+       for (i = 0; i < NUM_ITERS; ++i) {
+               t0 = ia64_get_itc();
+               go[MASTER] = 1;
+               while (!(tm = go[SLAVE]))
+                       cpu_relax();
+               go[SLAVE] = 0;
+               t1 = ia64_get_itc();
+
+               if (t1 - t0 < best_t1 - best_t0)
+                       best_t0 = t0, best_t1 = t1, best_tm = tm;
+       }
+
+       *rt = best_t1 - best_t0;
+       *master = best_tm - best_t0;
+
+       /* average best_t0 and best_t1 without overflow: */
+       tcenter = (best_t0/2 + best_t1/2);
+       if (best_t0 % 2 + best_t1 % 2 == 2)
+               ++tcenter;
+       return tcenter - best_tm;
+}
+
+/*
+ * Synchronize ar.itc of the current (slave) CPU with the ar.itc of the MASTER 
CPU
+ * (normally the time-keeper CPU).  We use a closed loop to eliminate the 
possibility of
+ * unaccounted-for errors (such as getting a machine check in the middle of a 
calibration
+ * step).  The basic idea is for the slave to ask the master what itc value it 
has and to
+ * read its own itc before and after the master responds.  Each iteration 
gives us three
+ * timestamps:
+ *
+ *     slave           master
+ *
+ *     t0 ---\
+ *             ---\
+ *                --->
+ *                     tm
+ *                /---
+ *            /---
+ *     t1 <---
+ *
+ *
+ * The goal is to adjust the slave's ar.itc such that tm falls exactly 
half-way between t0
+ * and t1.  If we achieve this, the clocks are synchronized provided the 
interconnect
+ * between the slave and the master is symmetric.  Even if the interconnect 
were
+ * asymmetric, we would still know that the synchronization error is smaller 
than the
+ * roundtrip latency (t0 - t1).
+ *
+ * When the interconnect is quiet and symmetric, this lets us synchronize the 
itc to
+ * within one or two cycles.  However, we can only *guarantee* that the 
synchronization is
+ * accurate to within a round-trip time, which is typically in the range of 
several
+ * hundred cycles (e.g., ~500 cycles).  In practice, this means that the itc's 
are usually
+ * almost perfectly synchronized, but we shouldn't assume that the accuracy is 
much better
+ * than half a micro second or so.
+ */
+void
+ia64_sync_itc (unsigned int master)
+{
+       long i, delta, adj, adjust_latency = 0, done = 0;
+       unsigned long flags, rt, master_time_stamp, bound;
+#if DEBUG_ITC_SYNC
+       struct {
+               long rt;        /* roundtrip time */
+               long master;    /* master's timestamp */
+               long diff;      /* difference between midpoint and master's 
timestamp */
+               long lat;       /* estimate of itc adjustment latency */
+       } t[NUM_ROUNDS];
+#endif
+
+       /*
+        * Make sure local timer ticks are disabled while we sync.  If
+        * they were enabled, we'd have to worry about nasty issues
+        * like setting the ITC ahead of (or a long time before) the
+        * next scheduled tick.
+        */
+       BUG_ON((ia64_get_itv() & (1 << 16)) == 0);
+
+       go[MASTER] = 1;
+
+       if (smp_call_function_single(master, sync_master, NULL, 1, 0) < 0) {
+               printk(KERN_ERR "sync_itc: failed to get attention of CPU 
%u!\n", master);
+               return;
+       }
+
+       while (go[MASTER])
+               cpu_relax();    /* wait for master to be ready */
+
+       spin_lock_irqsave(&itc_sync_lock, flags);
+       {
+               for (i = 0; i < NUM_ROUNDS; ++i) {
+                       delta = get_delta(&rt, &master_time_stamp);
+                       if (delta == 0) {
+                               done = 1;       /* let's lock on to this... */
+                               bound = rt;
+                       }
+
+                       if (!done) {
+                               if (i > 0) {
+                                       adjust_latency += -delta;
+                                       adj = -delta + adjust_latency/4;
+                               } else
+                                       adj = -delta;
+
+                               ia64_set_itc(ia64_get_itc() + adj);
+                       }
+#if DEBUG_ITC_SYNC
+                       t[i].rt = rt;
+                       t[i].master = master_time_stamp;
+                       t[i].diff = delta;
+                       t[i].lat = adjust_latency/4;
+#endif
+               }
+       }
+       spin_unlock_irqrestore(&itc_sync_lock, flags);
+
+#if DEBUG_ITC_SYNC
+       for (i = 0; i < NUM_ROUNDS; ++i)
+               printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
+                      t[i].rt, t[i].master, t[i].diff, t[i].lat);
+#endif
+
+       printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld 
cycles, "
+              "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt);
+}
+
+/*
+ * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
+ */
+static inline void __devinit
+smp_setup_percpu_timer (void)
+{
+}
+
+static void __devinit
+smp_callin (void)
+{
+       int cpuid, phys_id;
+       extern void ia64_init_itm(void);
+
+#ifdef CONFIG_PERFMON
+       extern void pfm_init_percpu(void);
+#endif
+
+       cpuid = smp_processor_id();
+       phys_id = hard_smp_processor_id();
+
+       if (cpu_online(cpuid)) {
+               printk(KERN_ERR "huh, phys CPU#0x%x, CPU#0x%x already 
present??\n",
+                      phys_id, cpuid);
+               BUG();
+       }
+
+       lock_ipi_calllock();
+       cpu_set(cpuid, cpu_online_map);
+       unlock_ipi_calllock();
+       per_cpu(cpu_state, cpuid) = CPU_ONLINE;
+
+       smp_setup_percpu_timer();
+
+#ifndef XEN
+       ia64_mca_cmc_vector_setup();    /* Setup vector on AP */
+#endif
+
+#ifdef CONFIG_PERFMON
+       pfm_init_percpu();
+#endif
+
+       local_irq_enable();
+
+       if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) {
+               /*
+                * Synchronize the ITC with the BP.  Need to do this after irqs 
are
+                * enabled because ia64_sync_itc() calls 
smp_call_function_single(), which
+                * calls spin_unlock_bh(), which calls spin_unlock_bh(), which 
calls
+                * local_bh_enable(), which bugs out if irqs are not enabled...
+                */
+               Dprintk("Going to syncup ITC with BP.\n");
+               ia64_sync_itc(0);
+       }
+
+       /*
+        * Get our bogomips.
+        */
+       ia64_init_itm();
+#ifndef XEN
+       calibrate_delay();
+#endif
+       local_cpu_data->loops_per_jiffy = loops_per_jiffy;
+
+#ifdef CONFIG_IA32_SUPPORT
+       ia32_gdt_init();
+#endif
+
+       /*
+        * Allow the master to continue.
+        */
+       cpu_set(cpuid, cpu_callin_map);
+       Dprintk("Stack on CPU %d at about %p\n",cpuid, &cpuid);
+}
+
+
+/*
+ * Activate a secondary processor.  head.S calls this.
+ */
+int __devinit
+start_secondary (void *unused)
+{
+       /* Early console may use I/O ports */
+       ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
+       Dprintk("start_secondary: starting CPU 0x%x\n", 
hard_smp_processor_id());
+       efi_map_pal_code();
+       cpu_init();
+       smp_callin();
+
+#ifdef XEN
+       startup_cpu_idle_loop();
+#else
+       cpu_idle();
+#endif
+       return 0;
+}
+
+struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+{
+       return NULL;
+}
+
+#ifndef XEN
+struct create_idle {
+       struct task_struct *idle;
+       struct completion done;
+       int cpu;
+};
+
+void
+do_fork_idle(void *_c_idle)
+{
+       struct create_idle *c_idle = _c_idle;
+
+       c_idle->idle = fork_idle(c_idle->cpu);
+       complete(&c_idle->done);
+}
+#endif
+
+static int __devinit
+do_boot_cpu (int sapicid, int cpu)
+{
+       int timeout;
+#ifndef XEN
+       struct create_idle c_idle = {
+               .cpu    = cpu,
+               .done   = COMPLETION_INITIALIZER(c_idle.done),
+       };
+       DECLARE_WORK(work, do_fork_idle, &c_idle);
+
+       c_idle.idle = get_idle_for_cpu(cpu);
+       if (c_idle.idle) {
+               init_idle(c_idle.idle, cpu);
+               goto do_rest;
+       }
+
+       /*
+        * We can't use kernel_thread since we must avoid to reschedule the 
child.
+        */
+       if (!keventd_up() || current_is_keventd())
+               work.func(work.data);
+       else {
+               schedule_work(&work);
+               wait_for_completion(&c_idle.done);
+       }
+
+       if (IS_ERR(c_idle.idle))
+               panic("failed fork for CPU %d", cpu);
+
+       set_idle_for_cpu(cpu, c_idle.idle);
+
+do_rest:
+       task_for_booting_cpu = c_idle.idle;
+#endif
+
+       Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", 
ap_wakeup_vector, cpu, sapicid);
+
+       set_brendez_area(cpu);
+       platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
+
+       /*
+        * Wait 10s total for the AP to start
+        */
+       Dprintk("Waiting on callin_map ...");
+       for (timeout = 0; timeout < 100000; timeout++) {
+               if (cpu_isset(cpu, cpu_callin_map))
+                       break;  /* It has booted */
+               udelay(100);
+       }
+       Dprintk("\n");
+
+       if (!cpu_isset(cpu, cpu_callin_map)) {
+               printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, 
sapicid);
+               ia64_cpu_to_sapicid[cpu] = -1;
+               cpu_clear(cpu, cpu_online_map);  /* was set in smp_callin() */
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int __init
+decay (char *str)
+{
+       int ticks;
+       get_option (&str, &ticks);
+       return 1;
+}
+
+__setup("decay=", decay);
+
+/*
+ * Initialize the logical CPU number to SAPICID mapping
+ */
+void __init
+smp_build_cpu_map (void)
+{
+       int sapicid, cpu, i;
+       int boot_cpu_id = hard_smp_processor_id();
+
+       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+               ia64_cpu_to_sapicid[cpu] = -1;
+#ifdef CONFIG_HOTPLUG_CPU
+               cpu_set(cpu, cpu_possible_map);
+#endif
+       }
+
+       ia64_cpu_to_sapicid[0] = boot_cpu_id;
+       cpus_clear(cpu_present_map);
+       cpu_set(0, cpu_present_map);
+       cpu_set(0, cpu_possible_map);
+       for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
+               sapicid = smp_boot_data.cpu_phys_id[i];
+               if (sapicid == boot_cpu_id)
+                       continue;
+               cpu_set(cpu, cpu_present_map);
+               cpu_set(cpu, cpu_possible_map);
+               ia64_cpu_to_sapicid[cpu] = sapicid;
+               cpu++;
+       }
+}
+
+/*
+ * Cycle through the APs sending Wakeup IPIs to boot each.
+ */
+void __init
+smp_prepare_cpus (unsigned int max_cpus)
+{
+       int boot_cpu_id = hard_smp_processor_id();
+
+       /*
+        * Initialize the per-CPU profiling counter/multiplier
+        */
+
+       smp_setup_percpu_timer();
+
+       /*
+        * We have the boot CPU online for sure.
+        */
+       cpu_set(0, cpu_online_map);
+       cpu_set(0, cpu_callin_map);
+
+       local_cpu_data->loops_per_jiffy = loops_per_jiffy;
+       ia64_cpu_to_sapicid[0] = boot_cpu_id;
+
+       printk(KERN_INFO "Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
+
+       current_thread_info()->cpu = 0;
+
+       /*
+        * If SMP should be disabled, then really disable it!
+        */
+       if (!max_cpus) {
+               printk(KERN_INFO "SMP mode deactivated.\n");
+               cpus_clear(cpu_online_map);
+               cpus_clear(cpu_present_map);
+               cpus_clear(cpu_possible_map);
+               cpu_set(0, cpu_online_map);
+               cpu_set(0, cpu_present_map);
+               cpu_set(0, cpu_possible_map);
+               return;
+       }
+}
+
+void __devinit smp_prepare_boot_cpu(void)
+{
+       cpu_set(smp_processor_id(), cpu_online_map);
+       cpu_set(smp_processor_id(), cpu_callin_map);
+       per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+}
+
+/*
+ * mt_info[] is a temporary store for all info returned by
+ * PAL_LOGICAL_TO_PHYSICAL, to be copied into cpuinfo_ia64 when the
+ * specific cpu comes.
+ */
+static struct {
+       __u32   socket_id;
+       __u16   core_id;
+       __u16   thread_id;
+       __u16   proc_fixed_addr;
+       __u8    valid;
+} mt_info[NR_CPUS] __devinitdata;
+
+#ifdef CONFIG_HOTPLUG_CPU
+static inline void
+remove_from_mtinfo(int cpu)
+{
+       int i;
+
+       for_each_cpu(i)
+               if (mt_info[i].valid &&  mt_info[i].socket_id ==
+                                               cpu_data(cpu)->socket_id)
+                       mt_info[i].valid = 0;
+}
+
+static inline void
+clear_cpu_sibling_map(int cpu)
+{
+       int i;
+
+       for_each_cpu_mask(i, cpu_sibling_map[cpu])
+               cpu_clear(cpu, cpu_sibling_map[i]);
+       for_each_cpu_mask(i, cpu_core_map[cpu])
+               cpu_clear(cpu, cpu_core_map[i]);
+
+       cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
+}
+
+static void
+remove_siblinginfo(int cpu)
+{
+       int last = 0;
+
+       if (cpu_data(cpu)->threads_per_core == 1 &&
+           cpu_data(cpu)->cores_per_socket == 1) {
+               cpu_clear(cpu, cpu_core_map[cpu]);
+               cpu_clear(cpu, cpu_sibling_map[cpu]);
+               return;
+       }
+
+       last = (cpus_weight(cpu_core_map[cpu]) == 1 ? 1 : 0);
+
+       /* remove it from all sibling map's */
+       clear_cpu_sibling_map(cpu);
+
+       /* if this cpu is the last in the core group, remove all its info 
+        * from mt_info structure
+        */
+       if (last)
+               remove_from_mtinfo(cpu);
+}
+
+extern void fixup_irqs(void);
+/* must be called with cpucontrol mutex held */
+int __cpu_disable(void)
+{
+       int cpu = smp_processor_id();
+
+       /*
+        * dont permit boot processor for now
+        */
+       if (cpu == 0)
+               return -EBUSY;
+
+       remove_siblinginfo(cpu);
+       cpu_clear(cpu, cpu_online_map);
+       fixup_irqs();
+       local_flush_tlb_all();
+       cpu_clear(cpu, cpu_callin_map);
+       return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+       unsigned int i;
+
+       for (i = 0; i < 100; i++) {
+               /* They ack this in play_dead by setting CPU_DEAD */
+               if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+               {
+                       printk ("CPU %d is now offline\n", cpu);
+                       return;
+               }
+               msleep(100);
+       }
+       printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+#else /* !CONFIG_HOTPLUG_CPU */
+int __cpu_disable(void)
+{
+       return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+       /* We said "no" in __cpu_disable */
+       BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+void
+smp_cpus_done (unsigned int dummy)
+{
+       int cpu;
+       unsigned long bogosum = 0;
+
+       /*
+        * Allow the user to impress friends.
+        */
+
+       for (cpu = 0; cpu < NR_CPUS; cpu++)
+               if (cpu_online(cpu))
+                       bogosum += cpu_data(cpu)->loops_per_jiffy;
+
+       printk(KERN_INFO "Total of %d processors activated (%lu.%02lu 
BogoMIPS).\n",
+              (int)num_online_cpus(), bogosum/(500000/HZ), 
(bogosum/(5000/HZ))%100);
+}
+
+static inline void __devinit
+set_cpu_sibling_map(int cpu)
+{
+       int i;
+
+       for_each_online_cpu(i) {
+               if ((cpu_data(cpu)->socket_id == cpu_data(i)->socket_id)) {
+                       cpu_set(i, cpu_core_map[cpu]);
+                       cpu_set(cpu, cpu_core_map[i]);
+                       if (cpu_data(cpu)->core_id == cpu_data(i)->core_id) {
+                               cpu_set(i, cpu_sibling_map[cpu]);
+                               cpu_set(cpu, cpu_sibling_map[i]);
+                       }
+               }
+       }
+}
+
+int __devinit
+__cpu_up (unsigned int cpu)
+{
+       int ret;
+       int sapicid;
+
+       sapicid = ia64_cpu_to_sapicid[cpu];
+       if (sapicid == -1)
+               return -EINVAL;
+
+       /*
+        * Already booted cpu? not valid anymore since we dont
+        * do idle loop tightspin anymore.
+        */
+       if (cpu_isset(cpu, cpu_callin_map))
+               return -EINVAL;
+
+       per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+       /* Processor goes to start_secondary(), sets online flag */
+       ret = do_boot_cpu(sapicid, cpu);
+       if (ret < 0)
+               return ret;
+
+       if (cpu_data(cpu)->threads_per_core == 1 &&
+           cpu_data(cpu)->cores_per_socket == 1) {
+               cpu_set(cpu, cpu_sibling_map[cpu]);
+               cpu_set(cpu, cpu_core_map[cpu]);
+               return 0;
+       }
+
+       set_cpu_sibling_map(cpu);
+
+       return 0;
+}
+
+/*
+ * Assume that CPU's have been discovered by some platform-dependent 
interface.  For
+ * SoftSDV/Lion, that would be ACPI.
+ *
+ * Setup of the IPI irq handler is done in irq.c:init_IRQ_SMP().
+ */
+void __init
+init_smp_config(void)
+{
+       struct fptr {
+               unsigned long fp;
+               unsigned long gp;
+       } *ap_startup;
+       long sal_ret;
+
+       /* Tell SAL where to drop the AP's.  */
+       ap_startup = (struct fptr *) start_ap;
+       sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
+                                      ia64_tpa(ap_startup->fp), 
ia64_tpa(ap_startup->gp), 0, 0, 0, 0);
+       if (sal_ret < 0)
+               printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n",
+                      ia64_sal_strerror(sal_ret));
+}
+
+static inline int __devinit
+check_for_mtinfo_index(void)
+{
+       int i;
+       
+       for_each_cpu(i)
+               if (!mt_info[i].valid)
+                       return i;
+
+       return -1;
+}
+
+/*
+ * Search the mt_info to find out if this socket's cid/tid information is
+ * cached or not. If the socket exists, fill in the core_id and thread_id 
+ * in cpuinfo
+ */
+static int __devinit
+check_for_new_socket(__u16 logical_address, struct cpuinfo_ia64 *c)
+{
+       int i;
+       __u32 sid = c->socket_id;
+
+       for_each_cpu(i) {
+               if (mt_info[i].valid && mt_info[i].proc_fixed_addr == 
logical_address
+                   && mt_info[i].socket_id == sid) {
+                       c->core_id = mt_info[i].core_id;
+                       c->thread_id = mt_info[i].thread_id;
+                       return 1; /* not a new socket */
+               }
+       }
+       return 0;
+}
+
+/*
+ * identify_siblings(cpu) gets called from identify_cpu. This populates the 
+ * information related to logical execution units in per_cpu_data structure.
+ */
+void __devinit
+identify_siblings(struct cpuinfo_ia64 *c)
+{
+       s64 status;
+       u16 pltid;
+       u64 proc_fixed_addr;
+       int count, i;
+       pal_logical_to_physical_t info;
+
+       if (smp_num_cpucores == 1 && smp_num_siblings == 1)
+               return;
+
+       if ((status = ia64_pal_logical_to_phys(0, &info)) != 
PAL_STATUS_SUCCESS) {
+               printk(KERN_ERR "ia64_pal_logical_to_phys failed with %ld\n",
+                      status);
+               return;
+       }
+       if ((status = ia64_sal_physical_id_info(&pltid)) != PAL_STATUS_SUCCESS) 
{
+               printk(KERN_ERR "ia64_sal_pltid failed with %ld\n", status);
+               return;
+       }
+       if ((status = ia64_pal_fixed_addr(&proc_fixed_addr)) != 
PAL_STATUS_SUCCESS) {
+               printk(KERN_ERR "ia64_pal_fixed_addr failed with %ld\n", 
status);
+               return;
+       }
+
+       c->socket_id =  (pltid << 8) | info.overview_ppid;
+       c->cores_per_socket = info.overview_cpp;
+       c->threads_per_core = info.overview_tpc;
+       count = c->num_log = info.overview_num_log;
+
+       /* If the thread and core id information is already cached, then
+        * we will simply update cpu_info and return. Otherwise, we will
+        * do the PAL calls and cache core and thread id's of all the siblings.
+        */
+       if (check_for_new_socket(proc_fixed_addr, c))
+               return;
+
+       for (i = 0; i < count; i++) {
+               int index;
+
+               if (i && (status = ia64_pal_logical_to_phys(i, &info))
+                         != PAL_STATUS_SUCCESS) {
+                       printk(KERN_ERR "ia64_pal_logical_to_phys failed"
+                                       " with %ld\n", status);
+                       return;
+               }
+               if (info.log2_la == proc_fixed_addr) {
+                       c->core_id = info.log1_cid;
+                       c->thread_id = info.log1_tid;
+               }
+
+               index = check_for_mtinfo_index();
+               /* We will not do the mt_info caching optimization in this case.
+                */
+               if (index < 0)
+                       continue;
+
+               mt_info[index].valid = 1;
+               mt_info[index].socket_id = c->socket_id;
+               mt_info[index].core_id = info.log1_cid;
+               mt_info[index].thread_id = info.log1_tid;
+               mt_info[index].proc_fixed_addr = info.log2_la;
+       }
+}
+#endif /* CONFIG_SMP ifdef XEN */
diff -r 2b95125015a5 -r f5c4042212b0 
xen/include/asm-ia64/linux-xen/asm/spinlock.h
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux-xen/asm/spinlock.h     Tue Aug 30 18:41:54 2005
@@ -0,0 +1,241 @@
+#ifndef _ASM_IA64_SPINLOCK_H
+#define _ASM_IA64_SPINLOCK_H
+
+/*
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ *
+ * This file is used for SMP configurations only.
+ */
+
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/intrinsics.h>
+#include <asm/system.h>
+
+typedef struct {
+       volatile unsigned int lock;
+#ifdef CONFIG_PREEMPT
+       unsigned int break_lock;
+#endif
+#ifdef XEN
+       unsigned char recurse_cpu;
+       unsigned char recurse_cnt;
+#endif
+} spinlock_t;
+
+#define SPIN_LOCK_UNLOCKED                     (spinlock_t) { 0 }
+#define spin_lock_init(x)                      ((x)->lock = 0)
+
+#ifdef ASM_SUPPORTED
+/*
+ * Try to get the lock.  If we fail to get the lock, make a non-standard call 
to
+ * ia64_spinlock_contention().  We do not use a normal call because that would 
force all
+ * callers of spin_lock() to be non-leaf routines.  Instead, 
ia64_spinlock_contention() is
+ * carefully coded to touch only those registers that spin_lock() marks 
"clobbered".
+ */
+
+#define IA64_SPINLOCK_CLOBBERS "ar.ccv", "ar.pfs", "p14", "p15", "r27", "r28", 
"r29", "r30", "b6", "memory"
+
+static inline void
+_raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
+{
+       register volatile unsigned int *ptr asm ("r31") = &lock->lock;
+
+#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
+# ifdef CONFIG_ITANIUM
+       /* don't use brl on Itanium... */
+       asm volatile ("{\n\t"
+                     "  mov ar.ccv = r0\n\t"
+                     "  mov r28 = ip\n\t"
+                     "  mov r30 = 1;;\n\t"
+                     "}\n\t"
+                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t"
+                     "movl r29 = ia64_spinlock_contention_pre3_4;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "mov b6 = r29;;\n\t"
+                     "mov r27=%2\n\t"
+                     "(p14) br.cond.spnt.many b6"
+                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
+# else
+       asm volatile ("{\n\t"
+                     "  mov ar.ccv = r0\n\t"
+                     "  mov r28 = ip\n\t"
+                     "  mov r30 = 1;;\n\t"
+                     "}\n\t"
+                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "mov r27=%2\n\t"
+                     "(p14) brl.cond.spnt.many 
ia64_spinlock_contention_pre3_4;;"
+                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
+#else
+# ifdef CONFIG_ITANIUM
+       /* don't use brl on Itanium... */
+       /* mis-declare, so we get the entry-point, not it's function 
descriptor: */
+       asm volatile ("mov r30 = 1\n\t"
+                     "mov r27=%2\n\t"
+                     "mov ar.ccv = r0;;\n\t"
+                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t"
+                     "movl r29 = ia64_spinlock_contention;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "mov b6 = r29;;\n\t"
+                     "(p14) br.call.spnt.many b6 = b6"
+                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
+# else
+       asm volatile ("mov r30 = 1\n\t"
+                     "mov r27=%2\n\t"
+                     "mov ar.ccv = r0;;\n\t"
+                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
+                     "cmp4.ne p14, p0 = r30, r0\n\t"
+                     "(p14) brl.call.spnt.many b6=ia64_spinlock_contention;;"
+                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
+# endif /* CONFIG_MCKINLEY */
+#endif
+}
+#define _raw_spin_lock(lock) _raw_spin_lock_flags(lock, 0)
+#else /* !ASM_SUPPORTED */
+#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
+# define _raw_spin_lock(x)                                                     
        \
+do {                                                                           
        \
+       __u32 *ia64_spinlock_ptr = (__u32 *) (x);                               
        \
+       __u64 ia64_spinlock_val;                                                
        \
+       ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);         
        \
+       if (unlikely(ia64_spinlock_val)) {                                      
        \
+               do {                                                            
        \
+                       while (*ia64_spinlock_ptr)                              
        \
+                               ia64_barrier();                                 
        \
+                       ia64_spinlock_val = 
ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \
+               } while (ia64_spinlock_val);                                    
        \
+       }                                                                       
        \
+} while (0)
+#endif /* !ASM_SUPPORTED */
+
+#define spin_is_locked(x)      ((x)->lock != 0)
+#define _raw_spin_unlock(x)    do { barrier(); ((spinlock_t *) x)->lock = 0; } 
while (0)
+#define _raw_spin_trylock(x)   (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
+#define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
+
+#ifdef XEN
+/*
+ * spin_[un]lock_recursive(): Use these forms when the lock can (safely!) be
+ * reentered recursively on the same CPU. All critical regions that may form
+ * part of a recursively-nested set must be protected by these forms. If there
+ * are any critical regions that cannot form part of such a set, they can use
+ * standard spin_[un]lock().
+ */
+#define _raw_spin_lock_recursive(_lock)            \
+    do {                                           \
+        int cpu = smp_processor_id();              \
+        if ( likely((_lock)->recurse_cpu != cpu) ) \
+        {                                          \
+            spin_lock(_lock);                      \
+            (_lock)->recurse_cpu = cpu;            \
+        }                                          \
+        (_lock)->recurse_cnt++;                    \
+    } while ( 0 )
+
+#define _raw_spin_unlock_recursive(_lock)          \
+    do {                                           \
+        if ( likely(--(_lock)->recurse_cnt == 0) ) \
+        {                                          \
+            (_lock)->recurse_cpu = -1;             \
+            spin_unlock(_lock);                    \
+        }                                          \
+    } while ( 0 )
+#endif
+
+typedef struct {
+       volatile unsigned int read_counter      : 31;
+       volatile unsigned int write_lock        :  1;
+#ifdef CONFIG_PREEMPT
+       unsigned int break_lock;
+#endif
+} rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+
+#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define read_can_lock(rw)      (*(volatile int *)(rw) >= 0)
+#define write_can_lock(rw)     (*(volatile int *)(rw) == 0)
+
+#define _raw_read_lock(rw)                                                     
        \
+do {                                                                           
        \
+       rwlock_t *__read_lock_ptr = (rw);                                       
        \
+                                                                               
        \
+       while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, acq) < 0)) {  
        \
+               ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);                
        \
+               while (*(volatile int *)__read_lock_ptr < 0)                    
        \
+                       cpu_relax();                                            
        \
+       }                                                                       
        \
+} while (0)
+
+#define _raw_read_unlock(rw)                                   \
+do {                                                           \
+       rwlock_t *__read_lock_ptr = (rw);                       \
+       ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);        \
+} while (0)
+
+#ifdef ASM_SUPPORTED
+#define _raw_write_lock(rw)                                                    
\
+do {                                                                           
\
+       __asm__ __volatile__ (                                                  
\
+               "mov ar.ccv = r0\n"                                             
\
+               "dep r29 = -1, r0, 31, 1;;\n"                                   
\
+               "1:\n"                                                          
\
+               "ld4 r2 = [%0];;\n"                                             
\
+               "cmp4.eq p0,p7 = r0,r2\n"                                       
\
+               "(p7) br.cond.spnt.few 1b \n"                                   
\
+               "cmpxchg4.acq r2 = [%0], r29, ar.ccv;;\n"                       
\
+               "cmp4.eq p0,p7 = r0, r2\n"                                      
\
+               "(p7) br.cond.spnt.few 1b;;\n"                                  
\
+               :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory");            
\
+} while(0)
+
+#define _raw_write_trylock(rw)                                                 
\
+({                                                                             
\
+       register long result;                                                   
\
+                                                                               
\
+       __asm__ __volatile__ (                                                  
\
+               "mov ar.ccv = r0\n"                                             
\
+               "dep r29 = -1, r0, 31, 1;;\n"                                   
\
+               "cmpxchg4.acq %0 = [%1], r29, ar.ccv\n"                         
\
+               : "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory");          
\
+       (result == 0);                                                          
\
+})
+
+#else /* !ASM_SUPPORTED */
+
+#define _raw_write_lock(l)                                                     
        \
+({                                                                             
        \
+       __u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1);               
        \
+       __u32 *ia64_write_lock_ptr = (__u32 *) (l);                             
        \
+       do {                                                                    
        \
+               while (*ia64_write_lock_ptr)                                    
        \
+                       ia64_barrier();                                         
        \
+               ia64_val = ia64_cmpxchg4_acq(ia64_write_lock_ptr, ia64_set_val, 
0);     \
+       } while (ia64_val);                                                     
        \
+})
+
+#define _raw_write_trylock(rw)                                         \
+({                                                                     \
+       __u64 ia64_val;                                                 \
+       __u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1);                  \
+       ia64_val = ia64_cmpxchg4_acq((__u32 *)(rw), ia64_set_val, 0);   \
+       (ia64_val == 0);                                                \
+})
+
+#endif /* !ASM_SUPPORTED */
+
+#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
+
+#define _raw_write_unlock(x)                                                   
        \
+({                                                                             
        \
+       smp_mb__before_clear_bit();     /* need barrier before releasing 
lock... */     \
+       clear_bit(31, (x));                                                     
        \
+})
+
+#endif /*  _ASM_IA64_SPINLOCK_H */
diff -r 2b95125015a5 -r f5c4042212b0 
xen/include/asm-ia64/linux-xen/asm/tlbflush.h
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux-xen/asm/tlbflush.h     Tue Aug 30 18:41:54 2005
@@ -0,0 +1,105 @@
+#ifndef _ASM_IA64_TLBFLUSH_H
+#define _ASM_IA64_TLBFLUSH_H
+
+/*
+ * Copyright (C) 2002 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ */
+
+#include <linux/config.h>
+
+#include <linux/mm.h>
+
+#include <asm/intrinsics.h>
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+
+/*
+ * Now for some TLB flushing routines.  This is the kind of stuff that
+ * can be very expensive, so try to avoid them whenever possible.
+ */
+
+/*
+ * Flush everything (kernel mapping may also have changed due to
+ * vmalloc/vfree).
+ */
+extern void local_flush_tlb_all (void);
+
+#ifdef CONFIG_SMP
+  extern void smp_flush_tlb_all (void);
+  extern void smp_flush_tlb_mm (struct mm_struct *mm);
+# define flush_tlb_all()       smp_flush_tlb_all()
+#else
+# define flush_tlb_all()       local_flush_tlb_all()
+#endif
+
+static inline void
+local_finish_flush_tlb_mm (struct mm_struct *mm)
+{
+#ifndef XEN
+       if (mm == current->active_mm)
+               activate_context(mm);
+#endif
+}
+
+/*
+ * Flush a specified user mapping.  This is called, e.g., as a result of 
fork() and
+ * exit().  fork() ends up here because the copy-on-write mechanism needs to 
write-protect
+ * the PTEs of the parent task.
+ */
+static inline void
+flush_tlb_mm (struct mm_struct *mm)
+{
+       if (!mm)
+               return;
+
+#ifndef XEN
+       mm->context = 0;
+#endif
+
+       if (atomic_read(&mm->mm_users) == 0)
+               return;         /* happens as a result of exit_mmap() */
+
+#ifdef CONFIG_SMP
+       smp_flush_tlb_mm(mm);
+#else
+       local_finish_flush_tlb_mm(mm);
+#endif
+}
+
+extern void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, 
unsigned long end);
+
+/*
+ * Page-granular tlb flush.
+ */
+static inline void
+flush_tlb_page (struct vm_area_struct *vma, unsigned long addr)
+{
+#ifdef CONFIG_SMP
+       flush_tlb_range(vma, (addr & PAGE_MASK), (addr & PAGE_MASK) + 
PAGE_SIZE);
+#else
+       if (vma->vm_mm == current->active_mm)
+               ia64_ptcl(addr, (PAGE_SHIFT << 2));
+#ifndef XEN
+       else
+               vma->vm_mm->context = 0;
+#endif
+#endif
+}
+
+/*
+ * Flush the TLB entries mapping the virtually mapped linear page
+ * table corresponding to address range [START-END).
+ */
+static inline void
+flush_tlb_pgtables (struct mm_struct *mm, unsigned long start, unsigned long 
end)
+{
+       /*
+        * Deprecated.  The virtual page table is now flushed via the normal 
gather/flush
+        * interface (see tlb.h).
+        */
+}
+
+#define flush_tlb_kernel_range(start, end)     flush_tlb_all() /* XXX fix me */
+
+#endif /* _ASM_IA64_TLBFLUSH_H */
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/linux/notifier.h
--- /dev/null   Fri Aug 26 13:06:49 2005
+++ b/xen/include/asm-ia64/linux/notifier.h     Tue Aug 30 18:41:54 2005
@@ -0,0 +1,76 @@
+/*
+ *     Routines to manage notifier chains for passing status changes to any
+ *     interested routines. We need this instead of hard coded call lists so
+ *     that modules can poke their nose into the innards. The network devices
+ *     needed them so here they are for the rest of you.
+ *
+ *                             Alan Cox <Alan.Cox@xxxxxxxxx>
+ */
+ 
+#ifndef _LINUX_NOTIFIER_H
+#define _LINUX_NOTIFIER_H
+#include <linux/errno.h>
+
+struct notifier_block
+{
+       int (*notifier_call)(struct notifier_block *self, unsigned long, void 
*);
+       struct notifier_block *next;
+       int priority;
+};
+
+
+#ifdef __KERNEL__
+
+extern int notifier_chain_register(struct notifier_block **list, struct 
notifier_block *n);
+extern int notifier_chain_unregister(struct notifier_block **nl, struct 
notifier_block *n);
+extern int notifier_call_chain(struct notifier_block **n, unsigned long val, 
void *v);
+
+#define NOTIFY_DONE            0x0000          /* Don't care */
+#define NOTIFY_OK              0x0001          /* Suits me */
+#define NOTIFY_STOP_MASK       0x8000          /* Don't call further */
+#define NOTIFY_BAD             (NOTIFY_STOP_MASK|0x0002)       /* Bad/Veto 
action      */
+/*
+ * Clean way to return from the notifier and stop further calls.
+ */
+#define NOTIFY_STOP            (NOTIFY_OK|NOTIFY_STOP_MASK)
+
+/*
+ *     Declared notifiers so far. I can imagine quite a few more chains
+ *     over time (eg laptop power reset chains, reboot chain (to clean 
+ *     device units up), device [un]mount chain, module load/unload chain,
+ *     low memory chain, screenblank chain (for plug in modular 
screenblankers) 
+ *     VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
+ */
+ 
+/* netdevice notifier chain */
+#define NETDEV_UP      0x0001  /* For now you can't veto a device up/down */
+#define NETDEV_DOWN    0x0002
+#define NETDEV_REBOOT  0x0003  /* Tell a protocol stack a network interface
+                                  detected a hardware crash and restarted
+                                  - we can use this eg to kick tcp sessions
+                                  once done */
+#define NETDEV_CHANGE  0x0004  /* Notify device state change */
+#define NETDEV_REGISTER 0x0005
+#define NETDEV_UNREGISTER      0x0006
+#define NETDEV_CHANGEMTU       0x0007
+#define NETDEV_CHANGEADDR      0x0008
+#define NETDEV_GOING_DOWN      0x0009
+#define NETDEV_CHANGENAME      0x000A
+#define NETDEV_FEAT_CHANGE     0x000B
+
+#define SYS_DOWN       0x0001  /* Notify of system down */
+#define SYS_RESTART    SYS_DOWN
+#define SYS_HALT       0x0002  /* Notify of system halt */
+#define SYS_POWER_OFF  0x0003  /* Notify of system power off */
+
+#define NETLINK_URELEASE       0x0001  /* Unicast netlink socket released */
+
+#define CPU_ONLINE             0x0002 /* CPU (unsigned)v is up */
+#define CPU_UP_PREPARE         0x0003 /* CPU (unsigned)v coming up */
+#define CPU_UP_CANCELED                0x0004 /* CPU (unsigned)v NOT coming up 
*/
+#define CPU_DOWN_PREPARE       0x0005 /* CPU (unsigned)v going down */
+#define CPU_DOWN_FAILED                0x0006 /* CPU (unsigned)v NOT going 
down */
+#define CPU_DEAD               0x0007 /* CPU (unsigned)v dead */
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_NOTIFIER_H */
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/linux/sal.c
--- a/xen/arch/ia64/linux/sal.c Fri Aug 26 13:06:49 2005
+++ /dev/null   Tue Aug 30 18:41:54 2005
@@ -1,302 +0,0 @@
-/*
- * System Abstraction Layer (SAL) interface routines.
- *
- * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@xxxxxxxxxx>
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
- */
-#include <linux/config.h>
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-
-#include <asm/page.h>
-#include <asm/sal.h>
-#include <asm/pal.h>
-
- __cacheline_aligned DEFINE_SPINLOCK(sal_lock);
-unsigned long sal_platform_features;
-
-unsigned short sal_revision;
-unsigned short sal_version;
-
-#define SAL_MAJOR(x) ((x) >> 8)
-#define SAL_MINOR(x) ((x) & 0xff)
-
-static struct {
-       void *addr;     /* function entry point */
-       void *gpval;    /* gp value to use */
-} pdesc;
-
-static long
-default_handler (void)
-{
-       return -1;
-}
-
-ia64_sal_handler ia64_sal = (ia64_sal_handler) default_handler;
-ia64_sal_desc_ptc_t *ia64_ptc_domain_info;
-
-const char *
-ia64_sal_strerror (long status)
-{
-       const char *str;
-       switch (status) {
-             case 0: str = "Call completed without error"; break;
-             case 1: str = "Effect a warm boot of the system to complete "
-                             "the update"; break;
-             case -1: str = "Not implemented"; break;
-             case -2: str = "Invalid argument"; break;
-             case -3: str = "Call completed with error"; break;
-             case -4: str = "Virtual address not registered"; break;
-             case -5: str = "No information available"; break;
-             case -6: str = "Insufficient space to add the entry"; break;
-             case -7: str = "Invalid entry_addr value"; break;
-             case -8: str = "Invalid interrupt vector"; break;
-             case -9: str = "Requested memory not available"; break;
-             case -10: str = "Unable to write to the NVM device"; break;
-             case -11: str = "Invalid partition type specified"; break;
-             case -12: str = "Invalid NVM_Object id specified"; break;
-             case -13: str = "NVM_Object already has the maximum number "
-                               "of partitions"; break;
-             case -14: str = "Insufficient space in partition for the "
-                               "requested write sub-function"; break;
-             case -15: str = "Insufficient data buffer space for the "
-                               "requested read record sub-function"; break;
-             case -16: str = "Scratch buffer required for the write/delete "
-                               "sub-function"; break;
-             case -17: str = "Insufficient space in the NVM_Object for the "
-                               "requested create sub-function"; break;
-             case -18: str = "Invalid value specified in the partition_rec "
-                               "argument"; break;
-             case -19: str = "Record oriented I/O not supported for this "
-                               "partition"; break;
-             case -20: str = "Bad format of record to be written or "
-                               "required keyword variable not "
-                               "specified"; break;
-             default: str = "Unknown SAL status code"; break;
-       }
-       return str;
-}
-
-void __init
-ia64_sal_handler_init (void *entry_point, void *gpval)
-{
-       /* fill in the SAL procedure descriptor and point ia64_sal to it: */
-       pdesc.addr = entry_point;
-       pdesc.gpval = gpval;
-       ia64_sal = (ia64_sal_handler) &pdesc;
-}
-
-static void __init
-check_versions (struct ia64_sal_systab *systab)
-{
-       sal_revision = (systab->sal_rev_major << 8) | systab->sal_rev_minor;
-       sal_version = (systab->sal_b_rev_major << 8) | systab->sal_b_rev_minor;
-
-       /* Check for broken firmware */
-       if ((sal_revision == SAL_VERSION_CODE(49, 29))
-           && (sal_version == SAL_VERSION_CODE(49, 29)))
-       {
-               /*
-                * Old firmware for zx2000 prototypes have this weird version 
number,
-                * reset it to something sane.
-                */
-               sal_revision = SAL_VERSION_CODE(2, 8);
-               sal_version = SAL_VERSION_CODE(0, 0);
-       }
-}
-
-static void __init
-sal_desc_entry_point (void *p)
-{
-       struct ia64_sal_desc_entry_point *ep = p;
-       ia64_pal_handler_init(__va(ep->pal_proc));
-       ia64_sal_handler_init(__va(ep->sal_proc), __va(ep->gp));
-}
-
-#ifdef CONFIG_SMP
-static void __init
-set_smp_redirect (int flag)
-{
-#ifndef CONFIG_HOTPLUG_CPU
-       if (no_int_routing)
-               smp_int_redirect &= ~flag;
-       else
-               smp_int_redirect |= flag;
-#else
-       /*
-        * For CPU Hotplug we dont want to do any chipset supported
-        * interrupt redirection. The reason is this would require that
-        * All interrupts be stopped and hard bind the irq to a cpu.
-        * Later when the interrupt is fired we need to set the redir hint
-        * on again in the vector. This is combersome for something that the
-        * user mode irq balancer will solve anyways.
-        */
-       no_int_routing=1;
-       smp_int_redirect &= ~flag;
-#endif
-}
-#else
-#define set_smp_redirect(flag) do { } while (0)
-#endif
-
-static void __init
-sal_desc_platform_feature (void *p)
-{
-       struct ia64_sal_desc_platform_feature *pf = p;
-       sal_platform_features = pf->feature_mask;
-
-       printk(KERN_INFO "SAL Platform features:");
-       if (!sal_platform_features) {
-               printk(" None\n");
-               return;
-       }
-
-       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_BUS_LOCK)
-               printk(" BusLock");
-       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT) {
-               printk(" IRQ_Redirection");
-               set_smp_redirect(SMP_IRQ_REDIRECTION);
-       }
-       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT) {
-               printk(" IPI_Redirection");
-               set_smp_redirect(SMP_IPI_REDIRECTION);
-       }
-       if (sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)
-               printk(" ITC_Drift");
-       printk("\n");
-}
-
-#ifdef CONFIG_SMP
-static void __init
-sal_desc_ap_wakeup (void *p)
-{
-       struct ia64_sal_desc_ap_wakeup *ap = p;
-
-       switch (ap->mechanism) {
-       case IA64_SAL_AP_EXTERNAL_INT:
-               ap_wakeup_vector = ap->vector;
-               printk(KERN_INFO "SAL: AP wakeup using external interrupt "
-                               "vector 0x%lx\n", ap_wakeup_vector);
-               break;
-       default:
-               printk(KERN_ERR "SAL: AP wakeup mechanism unsupported!\n");
-               break;
-       }
-}
-
-static void __init
-chk_nointroute_opt(void)
-{
-       char *cp;
-       extern char saved_command_line[];
-
-       for (cp = saved_command_line; *cp; ) {
-               if (memcmp(cp, "nointroute", 10) == 0) {
-                       no_int_routing = 1;
-                       printk ("no_int_routing on\n");
-                       break;
-               } else {
-                       while (*cp != ' ' && *cp)
-                               ++cp;
-                       while (*cp == ' ')
-                               ++cp;
-               }
-       }
-}
-
-#else
-static void __init sal_desc_ap_wakeup(void *p) { }
-#endif
-
-void __init
-ia64_sal_init (struct ia64_sal_systab *systab)
-{
-       char *p;
-       int i;
-
-       if (!systab) {
-               printk(KERN_WARNING "Hmm, no SAL System Table.\n");
-               return;
-       }
-
-       if (strncmp(systab->signature, "SST_", 4) != 0)
-               printk(KERN_ERR "bad signature in system table!");
-
-       check_versions(systab);
-#ifdef CONFIG_SMP
-       chk_nointroute_opt();
-#endif
-
-       /* revisions are coded in BCD, so %x does the job for us */
-       printk(KERN_INFO "SAL %x.%x: %.32s %.32s%sversion %x.%x\n",
-                       SAL_MAJOR(sal_revision), SAL_MINOR(sal_revision),
-                       systab->oem_id, systab->product_id,
-                       systab->product_id[0] ? " " : "",
-                       SAL_MAJOR(sal_version), SAL_MINOR(sal_version));
-
-       p = (char *) (systab + 1);
-       for (i = 0; i < systab->entry_count; i++) {
-               /*
-                * The first byte of each entry type contains the type
-                * descriptor.
-                */
-               switch (*p) {
-               case SAL_DESC_ENTRY_POINT:
-                       sal_desc_entry_point(p);
-                       break;
-               case SAL_DESC_PLATFORM_FEATURE:
-                       sal_desc_platform_feature(p);
-                       break;
-               case SAL_DESC_PTC:
-                       ia64_ptc_domain_info = (ia64_sal_desc_ptc_t *)p;
-                       break;
-               case SAL_DESC_AP_WAKEUP:
-                       sal_desc_ap_wakeup(p);
-                       break;
-               }
-               p += SAL_DESC_SIZE(*p);
-       }
-}
-
-int
-ia64_sal_oemcall(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
-                u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6, u64 arg7)
-{
-       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
-               return -1;
-       SAL_CALL(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-       return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall);
-
-int
-ia64_sal_oemcall_nolock(struct ia64_sal_retval *isrvp, u64 oemfunc, u64 arg1,
-                       u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
-                       u64 arg7)
-{
-       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
-               return -1;
-       SAL_CALL_NOLOCK(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
-                       arg7);
-       return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall_nolock);
-
-int
-ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
-                          u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5,
-                          u64 arg6, u64 arg7)
-{
-       if (oemfunc < IA64_SAL_OEMFUNC_MIN || oemfunc > IA64_SAL_OEMFUNC_MAX)
-               return -1;
-       SAL_CALL_REENTRANT(*isrvp, oemfunc, arg1, arg2, arg3, arg4, arg5, arg6,
-                          arg7);
-       return 0;
-}
-EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/smp.c
--- a/xen/arch/ia64/smp.c       Fri Aug 26 13:06:49 2005
+++ /dev/null   Tue Aug 30 18:41:54 2005
@@ -1,43 +0,0 @@
-/*
- *     Intel SMP support routines.
- *
- *     (c) 1995 Alan Cox, Building #3 <alan@xxxxxxxxxx>
- *     (c) 1998-99, 2000 Ingo Molnar <mingo@xxxxxxxxxx>
- *
- *     This code is released under the GNU General Public License version 2 or
- *     later.
- */
-
-//#include <xen/irq.h>
-#include <xen/sched.h>
-#include <xen/delay.h>
-#include <xen/spinlock.h>
-#include <asm/smp.h>
-//#include <asm/mc146818rtc.h>
-#include <asm/pgalloc.h>
-//#include <asm/smpboot.h>
-#include <asm/hardirq.h>
-
-
-//Huh? This seems to be used on ia64 even if !CONFIG_SMP
-void flush_tlb_mask(cpumask_t mask)
-{
-       dummy();
-}
-//#if CONFIG_SMP || IA64
-#if CONFIG_SMP
-//Huh? This seems to be used on ia64 even if !CONFIG_SMP
-void smp_send_event_check_mask(cpumask_t mask)
-{
-       dummy();
-       //send_IPI_mask(cpu_mask, EVENT_CHECK_VECTOR);
-}
-
-
-//Huh? This seems to be used on ia64 even if !CONFIG_SMP
-int try_flush_tlb_mask(cpumask_t mask)
-{
-       dummy();
-       return 1;
-}
-#endif
diff -r 2b95125015a5 -r f5c4042212b0 xen/arch/ia64/smpboot.c
--- a/xen/arch/ia64/smpboot.c   Fri Aug 26 13:06:49 2005
+++ /dev/null   Tue Aug 30 18:41:54 2005
@@ -1,2 +0,0 @@
-// expand later
-int ht_per_core = 1;
diff -r 2b95125015a5 -r f5c4042212b0 xen/include/asm-ia64/linux/asm/spinlock.h
--- a/xen/include/asm-ia64/linux/asm/spinlock.h Fri Aug 26 13:06:49 2005
+++ /dev/null   Tue Aug 30 18:41:54 2005
@@ -1,208 +0,0 @@
-#ifndef _ASM_IA64_SPINLOCK_H
-#define _ASM_IA64_SPINLOCK_H
-
-/*
- * Copyright (C) 1998-2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@xxxxxxxxxx>
- * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
- *
- * This file is used for SMP configurations only.
- */
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-
-#include <asm/atomic.h>
-#include <asm/bitops.h>
-#include <asm/intrinsics.h>
-#include <asm/system.h>
-
-typedef struct {
-       volatile unsigned int lock;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} spinlock_t;
-
-#define SPIN_LOCK_UNLOCKED                     (spinlock_t) { 0 }
-#define spin_lock_init(x)                      ((x)->lock = 0)
-
-#ifdef ASM_SUPPORTED
-/*
- * Try to get the lock.  If we fail to get the lock, make a non-standard call 
to
- * ia64_spinlock_contention().  We do not use a normal call because that would 
force all
- * callers of spin_lock() to be non-leaf routines.  Instead, 
ia64_spinlock_contention() is
- * carefully coded to touch only those registers that spin_lock() marks 
"clobbered".
- */
-
-#define IA64_SPINLOCK_CLOBBERS "ar.ccv", "ar.pfs", "p14", "p15", "r27", "r28", 
"r29", "r30", "b6", "memory"
-
-static inline void
-_raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
-{
-       register volatile unsigned int *ptr asm ("r31") = &lock->lock;
-
-#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
-# ifdef CONFIG_ITANIUM
-       /* don't use brl on Itanium... */
-       asm volatile ("{\n\t"
-                     "  mov ar.ccv = r0\n\t"
-                     "  mov r28 = ip\n\t"
-                     "  mov r30 = 1;;\n\t"
-                     "}\n\t"
-                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t"
-                     "movl r29 = ia64_spinlock_contention_pre3_4;;\n\t"
-                     "cmp4.ne p14, p0 = r30, r0\n\t"
-                     "mov b6 = r29;;\n\t"
-                     "mov r27=%2\n\t"
-                     "(p14) br.cond.spnt.many b6"
-                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
-# else
-       asm volatile ("{\n\t"
-                     "  mov ar.ccv = r0\n\t"
-                     "  mov r28 = ip\n\t"
-                     "  mov r30 = 1;;\n\t"
-                     "}\n\t"
-                     "cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
-                     "cmp4.ne p14, p0 = r30, r0\n\t"
-                     "mov r27=%2\n\t"
-                     "(p14) brl.cond.spnt.many 
ia64_spinlock_contention_pre3_4;;"
-                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
-# endif /* CONFIG_MCKINLEY */
-#else
-# ifdef CONFIG_ITANIUM
-       /* don't use brl on Itanium... */
-       /* mis-declare, so we get the entry-point, not it's function 
descriptor: */
-       asm volatile ("mov r30 = 1\n\t"
-                     "mov r27=%2\n\t"
-                     "mov ar.ccv = r0;;\n\t"
-                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t"
-                     "movl r29 = ia64_spinlock_contention;;\n\t"
-                     "cmp4.ne p14, p0 = r30, r0\n\t"
-                     "mov b6 = r29;;\n\t"
-                     "(p14) br.call.spnt.many b6 = b6"
-                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
-# else
-       asm volatile ("mov r30 = 1\n\t"
-                     "mov r27=%2\n\t"
-                     "mov ar.ccv = r0;;\n\t"
-                     "cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
-                     "cmp4.ne p14, p0 = r30, r0\n\t"
-                     "(p14) brl.call.spnt.many b6=ia64_spinlock_contention;;"
-                     : "=r"(ptr) : "r"(ptr), "r" (flags) : 
IA64_SPINLOCK_CLOBBERS);
-# endif /* CONFIG_MCKINLEY */
-#endif
-}
-#define _raw_spin_lock(lock) _raw_spin_lock_flags(lock, 0)
-#else /* !ASM_SUPPORTED */
-#define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock)
-# define _raw_spin_lock(x)                                                     
        \
-do {                                                                           
        \
-       __u32 *ia64_spinlock_ptr = (__u32 *) (x);                               
        \
-       __u64 ia64_spinlock_val;                                                
        \
-       ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0);         
        \
-       if (unlikely(ia64_spinlock_val)) {                                      
        \
-               do {                                                            
        \
-                       while (*ia64_spinlock_ptr)                              
        \
-                               ia64_barrier();                                 
        \
-                       ia64_spinlock_val = 
ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \
-               } while (ia64_spinlock_val);                                    
        \
-       }                                                                       
        \
-} while (0)
-#endif /* !ASM_SUPPORTED */
-
-#define spin_is_locked(x)      ((x)->lock != 0)
-#define _raw_spin_unlock(x)    do { barrier(); ((spinlock_t *) x)->lock = 0; } 
while (0)
-#define _raw_spin_trylock(x)   (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
-#define spin_unlock_wait(x)    do { barrier(); } while ((x)->lock)
-
-typedef struct {
-       volatile unsigned int read_counter      : 31;
-       volatile unsigned int write_lock        :  1;
-#ifdef CONFIG_PREEMPT
-       unsigned int break_lock;
-#endif
-} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
-
-#define rwlock_init(x)         do { *(x) = RW_LOCK_UNLOCKED; } while(0)
-#define read_can_lock(rw)      (*(volatile int *)(rw) >= 0)
-#define write_can_lock(rw)     (*(volatile int *)(rw) == 0)
-
-#define _raw_read_lock(rw)                                                     
        \
-do {                                                                           
        \
-       rwlock_t *__read_lock_ptr = (rw);                                       
        \
-                                                                               
        \
-       while (unlikely(ia64_fetchadd(1, (int *) __read_lock_ptr, acq) < 0)) {  
        \
-               ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);                
        \
-               while (*(volatile int *)__read_lock_ptr < 0)                    
        \
-                       cpu_relax();                                            
        \
-       }                                                                       
        \
-} while (0)
-
-#define _raw_read_unlock(rw)                                   \
-do {                                                           \
-       rwlock_t *__read_lock_ptr = (rw);                       \
-       ia64_fetchadd(-1, (int *) __read_lock_ptr, rel);        \
-} while (0)
-
-#ifdef ASM_SUPPORTED
-#define _raw_write_lock(rw)                                                    
\
-do {                                                                           
\
-       __asm__ __volatile__ (                                                  
\
-               "mov ar.ccv = r0\n"                                             
\
-               "dep r29 = -1, r0, 31, 1;;\n"                                   
\
-               "1:\n"                                                          
\
-               "ld4 r2 = [%0];;\n"                                             
\
-               "cmp4.eq p0,p7 = r0,r2\n"                                       
\
-               "(p7) br.cond.spnt.few 1b \n"                                   
\
-               "cmpxchg4.acq r2 = [%0], r29, ar.ccv;;\n"                       
\
-               "cmp4.eq p0,p7 = r0, r2\n"                                      
\
-               "(p7) br.cond.spnt.few 1b;;\n"                                  
\
-               :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory");            
\
-} while(0)
-
-#define _raw_write_trylock(rw)                                                 
\
-({                                                                             
\
-       register long result;                                                   
\
-                                                                               
\
-       __asm__ __volatile__ (                                                  
\
-               "mov ar.ccv = r0\n"                                             
\
-               "dep r29 = -1, r0, 31, 1;;\n"                                   
\
-               "cmpxchg4.acq %0 = [%1], r29, ar.ccv\n"                         
\
-               : "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory");          
\
-       (result == 0);                                                          
\
-})
-
-#else /* !ASM_SUPPORTED */
-
-#define _raw_write_lock(l)                                                     
        \
-({                                                                             
        \
-       __u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1);               
        \
-       __u32 *ia64_write_lock_ptr = (__u32 *) (l);                             
        \
-       do {                                                                    
        \
-               while (*ia64_write_lock_ptr)                                    
        \
-                       ia64_barrier();                                         
        \
-               ia64_val = ia64_cmpxchg4_acq(ia64_write_lock_ptr, ia64_set_val, 
0);     \
-       } while (ia64_val);                                                     
        \
-})
-
-#define _raw_write_trylock(rw)                                         \
-({                                                                     \
-       __u64 ia64_val;                                                 \
-       __u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1);                  \
-       ia64_val = ia64_cmpxchg4_acq((__u32 *)(rw), ia64_set_val, 0);   \
-       (ia64_val == 0);                                                \
-})
-
-#endif /* !ASM_SUPPORTED */
-
-#define _raw_read_trylock(lock) generic_raw_read_trylock(lock)
-
-#define _raw_write_unlock(x)                                                   
        \
-({                                                                             
        \
-       smp_mb__before_clear_bit();     /* need barrier before releasing 
lock... */     \
-       clear_bit(31, (x));                                                     
        \
-})
-
-#endif /*  _ASM_IA64_SPINLOCK_H */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Enable CONFIG_SMP compile and link, Xen patchbot -unstable <=