Xen 
 
Home About Xen.org Xen Xen Summit Wiki Mailing List Bug Tracker Xen Downloads
 
   
 

xen-changelog

[Xen-changelog] Merge after removing dependency on linux-2.6.11 source t

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Merge after removing dependency on linux-2.6.11 source tree
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 26 Aug 2005 09:10:14 +0000
Delivery-date: Fri, 26 Aug 2005 09:09:36 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User djm@xxxxxxxxxxxxxxx
# Node ID 1ee9236cc2245b0f9d6e6454d4f67175e7cf30e9
# Parent  be8fe9b3987c422a77fa0f0275ed25fd64294dec
# Parent  0380b4cc3c1a1cec3271bb7266d119c1ea5252f3
Merge after removing dependency on linux-2.6.11 source tree

diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/Makefile
--- a/xen/arch/ia64/Makefile    Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/Makefile    Mon Aug  8 19:21:23 2005
@@ -1,4 +1,6 @@
 include $(BASEDIR)/Rules.mk
+
+VPATH = linux linux-xen
 
 # libs-y       += arch/ia64/lib/lib.a
 
@@ -75,7 +77,7 @@
                -o xen.lds.s xen.lds.S
 
 ia64lib.o:
-       $(MAKE) -C lib && cp lib/ia64lib.o .
+       $(MAKE) -C linux/lib && cp linux/lib/ia64lib.o .
 
 clean:
        rm -f *.o *~ core  xen.lds.s 
$(BASEDIR)/include/asm-ia64/.offsets.h.stamp asm-offsets.s
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/Rules.mk
--- a/xen/arch/ia64/Rules.mk    Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/Rules.mk    Mon Aug  8 19:21:23 2005
@@ -6,14 +6,21 @@
 CROSS_COMPILE ?= /usr/local/sp_env/v2.2.5/i686/bin/ia64-unknown-linux-
 endif
 AFLAGS  += -D__ASSEMBLY__
-CPPFLAGS  += -I$(BASEDIR)/include -I$(BASEDIR)/include/asm-ia64
+CPPFLAGS  += -I$(BASEDIR)/include -I$(BASEDIR)/include/asm-ia64        \
+             -I$(BASEDIR)/include/asm-ia64/linux                       \
+            -I$(BASEDIR)/include/asm-ia64/linux-xen                    \
+             -I$(BASEDIR)/arch/ia64/linux -I$(BASEDIR)/arch/ia64/linux-xen
+
 CFLAGS  := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing
 #CFLAGS  += -O3                # -O3 over-inlines making debugging tough!
 CFLAGS  += -O2         # but no optimization causes compile errors!
 #CFLAGS  += -iwithprefix include -Wall -DMONITOR_BASE=$(MONITOR_BASE)
 CFLAGS  += -iwithprefix include -Wall
 CFLAGS  += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__
-CFLAGS  += -I$(BASEDIR)/include/asm-ia64
+CFLAGS  += -I$(BASEDIR)/include/asm-ia64 -I$(BASEDIR)/include/asm-ia64/linux \
+           -I$(BASEDIR)/include/asm-ia64/linux                                 
\
+           -I$(BASEDIR)/include/asm-ia64/linux-xen                     \
+           -I$(BASEDIR)/arch/ia64/linux -I$(BASEDIR)/arch/ia64/linux-xen
 CFLAGS  += -Wno-pointer-arith -Wredundant-decls
 CFLAGS  += -DIA64 -DXEN -DLINUX_2_6
 CFLAGS += -ffixed-r13 -mfixed-range=f12-f15,f32-f127
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/tools/mkbuildtree
--- a/xen/arch/ia64/tools/mkbuildtree   Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/tools/mkbuildtree   Mon Aug  8 19:21:23 2005
@@ -3,15 +3,10 @@
 # run in xen-X.X/xen directory after unpacking linux in same directory
 
 XEN=$PWD
-LINUX=$XEN/../../linux-2.6.11
-LINUXPATCH=$XEN/arch/ia64/patch/linux-2.6.11
-XENPATCH=$XEN/arch/ia64/patch/xen-2.0.1
 
 cp_patch ()
 {
-       #diff -u $LINUX/$1 $XEN/$2 > $LINUXPATCH/$3
-       cp $LINUX/$1 $XEN/$2
-       patch <$LINUXPATCH/$3 $XEN/$2
+       true;
 }
 
 xen_patch ()
@@ -22,34 +17,13 @@
 
 softlink ()
 {
-       ln -s $LINUX/$1 $XEN/$2
+       true;
 }
 
 null ()
 {
-       touch $XEN/$1
+       true;
 }
-
-
-# ensure linux directory is set up
-if [ ! -d $LINUX ]; then
-       echo "ERROR: $LINUX directory doesn't exist"
-       exit
-fi
-
-# setup
-
-#mkdir arch/ia64
-#mkdir arch/ia64/lib
-#mkdir include/asm-ia64
-mkdir include/asm-generic
-mkdir include/asm-ia64/linux
-mkdir include/asm-ia64/linux/byteorder
-mkdir include/asm-ia64/sn
-# use "gcc -Iinclude/asm-ia64" to find these linux includes
-#ln -s $XEN/include/xen $XEN/include/linux
-#ln -s $XEN/include/asm-ia64/linux $XEN/include/asm-ia64/xen 
-ln -s ../slab.h include/asm-ia64/linux/slab.h
 
 # prepare for building asm-offsets (circular dependency)
 #echo '#define IA64_TASK_SIZE 0' > include/asm-ia64/asm-offsets.h
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/linux-xen/efi.c
--- /dev/null   Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/linux-xen/efi.c     Mon Aug  8 19:21:23 2005
@@ -0,0 +1,866 @@
+/*
+ * Extensible Firmware Interface
+ *
+ * Based on Extensible Firmware Interface Specification version 0.9 April 30, 
1999
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ * Copyright (C) 1999-2003 Hewlett-Packard Co.
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ *     Stephane Eranian <eranian@xxxxxxxxxx>
+ *
+ * All EFI Runtime Services are not implemented yet as EFI only
+ * supports physical mode addressing on SoftSDV. This is to be fixed
+ * in a future version.  --drummond 1999-07-20
+ *
+ * Implemented EFI runtime services and virtual mode calls.  --davidm
+ *
+ * Goutham Rao: <goutham.rao@xxxxxxxxx>
+ *     Skip non-WB memory and ignore empty memory ranges.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/efi.h>
+
+#include <asm/io.h>
+#include <asm/kregs.h>
+#include <asm/meminit.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/mca.h>
+
+#define EFI_DEBUG      0
+
+extern efi_status_t efi_call_phys (void *, ...);
+
+struct efi efi;
+EXPORT_SYMBOL(efi);
+static efi_runtime_services_t *runtime;
+static unsigned long mem_limit = ~0UL, max_addr = ~0UL;
+
+#define efi_call_virt(f, args...)      (*(f))(args)
+
+#define STUB_GET_TIME(prefix, adjust_arg)                                      
                  \
+static efi_status_t                                                            
                  \
+prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)                         
                  \
+{                                                                              
                  \
+       struct ia64_fpreg fr[6];                                                
                  \
+       efi_time_cap_t *atc = NULL;                                             
                  \
+       efi_status_t ret;                                                       
                  \
+                                                                               
                  \
+       if (tc)                                                                 
                  \
+               atc = adjust_arg(tc);                                           
                  \
+       ia64_save_scratch_fpregs(fr);                                           
                  \
+       ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), 
adjust_arg(tm), atc); \
+       ia64_load_scratch_fpregs(fr);                                           
                  \
+       return ret;                                                             
                  \
+}
+
+#define STUB_SET_TIME(prefix, adjust_arg)                                      
                \
+static efi_status_t                                                            
                \
+prefix##_set_time (efi_time_t *tm)                                             
                \
+{                                                                              
                \
+       struct ia64_fpreg fr[6];                                                
                \
+       efi_status_t ret;                                                       
                \
+                                                                               
                \
+       ia64_save_scratch_fpregs(fr);                                           
                \
+       ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), 
adjust_arg(tm));    \
+       ia64_load_scratch_fpregs(fr);                                           
                \
+       return ret;                                                             
                \
+}
+
+#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg)                               
                \
+static efi_status_t                                                            
                \
+prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t 
*tm)            \
+{                                                                              
                \
+       struct ia64_fpreg fr[6];                                                
                \
+       efi_status_t ret;                                                       
                \
+                                                                               
                \
+       ia64_save_scratch_fpregs(fr);                                           
                \
+       ret = efi_call_##prefix((efi_get_wakeup_time_t *) 
__va(runtime->get_wakeup_time),       \
+                               adjust_arg(enabled), adjust_arg(pending), 
adjust_arg(tm));      \
+       ia64_load_scratch_fpregs(fr);                                           
                \
+       return ret;                                                             
                \
+}
+
+#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg)                               
                \
+static efi_status_t                                                            
                \
+prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)                  
                \
+{                                                                              
                \
+       struct ia64_fpreg fr[6];                                                
                \
+       efi_time_t *atm = NULL;                                                 
                \
+       efi_status_t ret;                                                       
                \
+                                                                               
                \
+       if (tm)                                                                 
                \
+               atm = adjust_arg(tm);                                           
                \
+       ia64_save_scratch_fpregs(fr);                                           
                \
+       ret = efi_call_##prefix((efi_set_wakeup_time_t *) 
__va(runtime->set_wakeup_time),       \
+                               enabled, atm);                                  
                \
+       ia64_load_scratch_fpregs(fr);                                           
                \
+       return ret;                                                             
                \
+}
+
+#define STUB_GET_VARIABLE(prefix, adjust_arg)                                  
        \
+static efi_status_t                                                            
        \
+prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,      
        \
+                      unsigned long *data_size, void *data)                    
        \
+{                                                                              
        \
+       struct ia64_fpreg fr[6];                                                
        \
+       u32 *aattr = NULL;                                                      
                \
+       efi_status_t ret;                                                       
        \
+                                                                               
        \
+       if (attr)                                                               
        \
+               aattr = adjust_arg(attr);                                       
        \
+       ia64_save_scratch_fpregs(fr);                                           
        \
+       ret = efi_call_##prefix((efi_get_variable_t *) 
__va(runtime->get_variable),     \
+                               adjust_arg(name), adjust_arg(vendor), aattr,    
        \
+                               adjust_arg(data_size), adjust_arg(data));       
        \
+       ia64_load_scratch_fpregs(fr);                                           
        \
+       return ret;                                                             
        \
+}
+
+#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg)                             
                \
+static efi_status_t                                                            
                \
+prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, 
efi_guid_t *vendor)  \
+{                                                                              
                \
+       struct ia64_fpreg fr[6];                                                
                \
+       efi_status_t ret;                                                       
                \
+                                                                               
                \
+       ia64_save_scratch_fpregs(fr);                                           
                \
+       ret = efi_call_##prefix((efi_get_next_variable_t *) 
__va(runtime->get_next_variable),   \
+                               adjust_arg(name_size), adjust_arg(name), 
adjust_arg(vendor));   \
+       ia64_load_scratch_fpregs(fr);                                           
                \
+       return ret;                                                             
                \
+}
+
+#define STUB_SET_VARIABLE(prefix, adjust_arg)                                  
        \
+static efi_status_t                                                            
        \
+prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long 
attr,     \
+                      unsigned long data_size, void *data)                     
        \
+{                                                                              
        \
+       struct ia64_fpreg fr[6];                                                
        \
+       efi_status_t ret;                                                       
        \
+                                                                               
        \
+       ia64_save_scratch_fpregs(fr);                                           
        \
+       ret = efi_call_##prefix((efi_set_variable_t *) 
__va(runtime->set_variable),     \
+                               adjust_arg(name), adjust_arg(vendor), attr, 
data_size,  \
+                               adjust_arg(data));                              
        \
+       ia64_load_scratch_fpregs(fr);                                           
        \
+       return ret;                                                             
        \
+}
+
+#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg)                      
                \
+static efi_status_t                                                            
                \
+prefix##_get_next_high_mono_count (u32 *count)                                 
                \
+{                                                                              
                \
+       struct ia64_fpreg fr[6];                                                
                \
+       efi_status_t ret;                                                       
                \
+                                                                               
                \
+       ia64_save_scratch_fpregs(fr);                                           
                \
+       ret = efi_call_##prefix((efi_get_next_high_mono_count_t *)              
                \
+                               __va(runtime->get_next_high_mono_count), 
adjust_arg(count));    \
+       ia64_load_scratch_fpregs(fr);                                           
                \
+       return ret;                                                             
                \
+}
+
+#define STUB_RESET_SYSTEM(prefix, adjust_arg)                                  
\
+static void                                                                    
\
+prefix##_reset_system (int reset_type, efi_status_t status,                    
\
+                      unsigned long data_size, efi_char16_t *data)             
\
+{                                                                              
\
+       struct ia64_fpreg fr[6];                                                
\
+       efi_char16_t *adata = NULL;                                             
\
+                                                                               
\
+       if (data)                                                               
\
+               adata = adjust_arg(data);                                       
\
+                                                                               
\
+       ia64_save_scratch_fpregs(fr);                                           
\
+       efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system),   
\
+                         reset_type, status, data_size, adata);                
\
+       /* should not return, but just in case... */                            
\
+       ia64_load_scratch_fpregs(fr);                                           
\
+}
+
+#define phys_ptr(arg)  ((__typeof__(arg)) ia64_tpa(arg))
+
+STUB_GET_TIME(phys, phys_ptr)
+STUB_SET_TIME(phys, phys_ptr)
+STUB_GET_WAKEUP_TIME(phys, phys_ptr)
+STUB_SET_WAKEUP_TIME(phys, phys_ptr)
+STUB_GET_VARIABLE(phys, phys_ptr)
+STUB_GET_NEXT_VARIABLE(phys, phys_ptr)
+STUB_SET_VARIABLE(phys, phys_ptr)
+STUB_GET_NEXT_HIGH_MONO_COUNT(phys, phys_ptr)
+STUB_RESET_SYSTEM(phys, phys_ptr)
+
+#define id(arg)        arg
+
+STUB_GET_TIME(virt, id)
+STUB_SET_TIME(virt, id)
+STUB_GET_WAKEUP_TIME(virt, id)
+STUB_SET_WAKEUP_TIME(virt, id)
+STUB_GET_VARIABLE(virt, id)
+STUB_GET_NEXT_VARIABLE(virt, id)
+STUB_SET_VARIABLE(virt, id)
+STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id)
+STUB_RESET_SYSTEM(virt, id)
+
+void
+efi_gettimeofday (struct timespec *ts)
+{
+       efi_time_t tm;
+
+       memset(ts, 0, sizeof(ts));
+       if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS)
+               return;
+
+       ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, 
tm.second);
+       ts->tv_nsec = tm.nanosecond;
+}
+
+static int
+is_available_memory (efi_memory_desc_t *md)
+{
+       if (!(md->attribute & EFI_MEMORY_WB))
+               return 0;
+
+       switch (md->type) {
+             case EFI_LOADER_CODE:
+             case EFI_LOADER_DATA:
+             case EFI_BOOT_SERVICES_CODE:
+             case EFI_BOOT_SERVICES_DATA:
+             case EFI_CONVENTIONAL_MEMORY:
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor 
covers
+ * memory that is normally available to the kernel, issue a warning that some 
memory
+ * is being ignored.
+ */
+static void
+trim_bottom (efi_memory_desc_t *md, u64 start_addr)
+{
+       u64 num_skipped_pages;
+
+       if (md->phys_addr >= start_addr || !md->num_pages)
+               return;
+
+       num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
+       if (num_skipped_pages > md->num_pages)
+               num_skipped_pages = md->num_pages;
+
+       if (is_available_memory(md))
+               printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx 
due to granule hole "
+                      "at 0x%lx\n", __FUNCTION__,
+                      (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
+                      md->phys_addr, start_addr - IA64_GRANULE_SIZE);
+       /*
+        * NOTE: Don't set md->phys_addr to START_ADDR because that could cause 
the memory
+        * descriptor list to become unsorted.  In such a case, md->num_pages 
will be
+        * zero, so the Right Thing will happen.
+        */
+       md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
+       md->num_pages -= num_skipped_pages;
+}
+
+static void
+trim_top (efi_memory_desc_t *md, u64 end_addr)
+{
+       u64 num_dropped_pages, md_end_addr;
+
+       md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+       if (md_end_addr <= end_addr || !md->num_pages)
+               return;
+
+       num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
+       if (num_dropped_pages > md->num_pages)
+               num_dropped_pages = md->num_pages;
+
+       if (is_available_memory(md))
+               printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx 
due to granule hole "
+                      "at 0x%lx\n", __FUNCTION__,
+                      (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
+                      md->phys_addr, end_addr);
+       md->num_pages -= num_dropped_pages;
+}
+
+/*
+ * Walks the EFI memory map and calls CALLBACK once for each EFI memory 
descriptor that
+ * has memory that is available for OS use.
+ */
+void
+efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
+{
+       int prev_valid = 0;
+       struct range {
+               u64 start;
+               u64 end;
+       } prev, curr;
+       void *efi_map_start, *efi_map_end, *p, *q;
+       efi_memory_desc_t *md, *check_md;
+       u64 efi_desc_size, start, end, granule_addr, last_granule_addr, 
first_non_wb_addr = 0;
+       unsigned long total_mem = 0;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               /* skip over non-WB memory descriptors; that's all we're 
interested in... */
+               if (!(md->attribute & EFI_MEMORY_WB))
+                       continue;
+
+#ifdef XEN
+// this works around a problem in the ski bootloader
+{
+               extern long running_on_sim;
+               if (running_on_sim && md->type != EFI_CONVENTIONAL_MEMORY)
+                       continue;
+}
+// this is a temporary hack to avoid CONFIG_VIRTUAL_MEM_MAP
+               if (md->phys_addr >= 0x100000000) continue;
+#endif
+               /*
+                * granule_addr is the base of md's first granule.
+                * [granule_addr - first_non_wb_addr) is guaranteed to
+                * be contiguous WB memory.
+                */
+               granule_addr = GRANULEROUNDDOWN(md->phys_addr);
+               first_non_wb_addr = max(first_non_wb_addr, granule_addr);
+
+               if (first_non_wb_addr < md->phys_addr) {
+                       trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
+                       granule_addr = GRANULEROUNDDOWN(md->phys_addr);
+                       first_non_wb_addr = max(first_non_wb_addr, 
granule_addr);
+               }
+
+               for (q = p; q < efi_map_end; q += efi_desc_size) {
+                       check_md = q;
+
+                       if ((check_md->attribute & EFI_MEMORY_WB) &&
+                           (check_md->phys_addr == first_non_wb_addr))
+                               first_non_wb_addr += check_md->num_pages << 
EFI_PAGE_SHIFT;
+                       else
+                               break;          /* non-WB or hole */
+               }
+
+               last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
+               if (last_granule_addr < md->phys_addr + (md->num_pages << 
EFI_PAGE_SHIFT))
+                       trim_top(md, last_granule_addr);
+
+               if (is_available_memory(md)) {
+                       if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) 
>= max_addr) {
+                               if (md->phys_addr >= max_addr)
+                                       continue;
+                               md->num_pages = (max_addr - md->phys_addr) >> 
EFI_PAGE_SHIFT;
+                               first_non_wb_addr = max_addr;
+                       }
+
+                       if (total_mem >= mem_limit)
+                               continue;
+
+                       if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > 
mem_limit) {
+                               unsigned long limit_addr = md->phys_addr;
+
+                               limit_addr += mem_limit - total_mem;
+                               limit_addr = GRANULEROUNDDOWN(limit_addr);
+
+                               if (md->phys_addr > limit_addr)
+                                       continue;
+
+                               md->num_pages = (limit_addr - md->phys_addr) >>
+                                               EFI_PAGE_SHIFT;
+                               first_non_wb_addr = max_addr = md->phys_addr +
+                                             (md->num_pages << EFI_PAGE_SHIFT);
+                       }
+                       total_mem += (md->num_pages << EFI_PAGE_SHIFT);
+
+                       if (md->num_pages == 0)
+                               continue;
+
+                       curr.start = PAGE_OFFSET + md->phys_addr;
+                       curr.end   = curr.start + (md->num_pages << 
EFI_PAGE_SHIFT);
+
+                       if (!prev_valid) {
+                               prev = curr;
+                               prev_valid = 1;
+                       } else {
+                               if (curr.start < prev.start)
+                                       printk(KERN_ERR "Oops: EFI memory table 
not ordered!\n");
+
+                               if (prev.end == curr.start) {
+                                       /* merge two consecutive memory ranges 
*/
+                                       prev.end = curr.end;
+                               } else {
+                                       start = PAGE_ALIGN(prev.start);
+                                       end = prev.end & PAGE_MASK;
+                                       if ((end > start) && (*callback)(start, 
end, arg) < 0)
+                                               return;
+                                       prev = curr;
+                               }
+                       }
+               }
+       }
+       if (prev_valid) {
+               start = PAGE_ALIGN(prev.start);
+               end = prev.end & PAGE_MASK;
+               if (end > start)
+                       (*callback)(start, end, arg);
+       }
+}
+
+/*
+ * Look for the PAL_CODE region reported by EFI and maps it using an
+ * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
+ * Abstraction Layer chapter 11 in ADAG
+ */
+
+void *
+efi_get_pal_addr (void)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+       int pal_code_count = 0;
+       u64 vaddr, mask;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (md->type != EFI_PAL_CODE)
+                       continue;
+
+               if (++pal_code_count > 1) {
+                       printk(KERN_ERR "Too many EFI Pal Code memory ranges, 
dropped @ %lx\n",
+                              md->phys_addr);
+                       continue;
+               }
+               /*
+                * The only ITLB entry in region 7 that is used is the one 
installed by
+                * __start().  That entry covers a 64MB range.
+                */
+               mask  = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
+               vaddr = PAGE_OFFSET + md->phys_addr;
+
+               /*
+                * We must check that the PAL mapping won't overlap with the 
kernel
+                * mapping.
+                *
+                * PAL code is guaranteed to be aligned on a power of 2 between 
4k and
+                * 256KB and that only one ITR is needed to map it. This 
implies that the
+                * PAL code is always aligned on its size, i.e., the closest 
matching page
+                * size supported by the TLB. Therefore PAL code is guaranteed 
never to
+                * cross a 64MB unless it is bigger than 64MB (very unlikely!). 
 So for
+                * now the following test is enough to determine whether or not 
we need a
+                * dedicated ITR for the PAL code.
+                */
+               if ((vaddr & mask) == (KERNEL_START & mask)) {
+                       printk(KERN_INFO "%s: no need to install ITR for PAL 
code\n",
+                              __FUNCTION__);
+                       continue;
+               }
+
+               if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE)
+                       panic("Woah!  PAL code size bigger than a granule!");
+
+#if EFI_DEBUG
+               mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
+
+               printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into 
[0x%lx-0x%lx)\n",
+                       smp_processor_id(), md->phys_addr,
+                       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
+                       vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
+#endif
+               return __va(md->phys_addr);
+       }
+       printk(KERN_WARNING "%s: no PAL-code memory-descriptor found",
+              __FUNCTION__);
+       return NULL;
+}
+
+void
+efi_map_pal_code (void)
+{
+       void *pal_vaddr = efi_get_pal_addr ();
+       u64 psr;
+
+       if (!pal_vaddr)
+               return;
+
+       /*
+        * Cannot write to CRx with PSR.ic=1
+        */
+       psr = ia64_clear_ic();
+       ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) 
pal_vaddr),
+                pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)),
+                IA64_GRANULE_SHIFT);
+       ia64_set_psr(psr);              /* restore psr */
+       ia64_srlz_i();
+}
+
+void __init
+efi_init (void)
+{
+       void *efi_map_start, *efi_map_end;
+       efi_config_table_t *config_tables;
+       efi_char16_t *c16;
+       u64 efi_desc_size;
+       char *cp, *end, vendor[100] = "unknown";
+       extern char saved_command_line[];
+       int i;
+
+       /* it's too early to be able to use the standard kernel command line 
support... */
+       for (cp = saved_command_line; *cp; ) {
+               if (memcmp(cp, "mem=", 4) == 0) {
+                       cp += 4;
+                       mem_limit = memparse(cp, &end);
+                       if (end != cp)
+                               break;
+                       cp = end;
+               } else if (memcmp(cp, "max_addr=", 9) == 0) {
+                       cp += 9;
+                       max_addr = GRANULEROUNDDOWN(memparse(cp, &end));
+                       if (end != cp)
+                               break;
+                       cp = end;
+               } else {
+                       while (*cp != ' ' && *cp)
+                               ++cp;
+                       while (*cp == ' ')
+                               ++cp;
+               }
+       }
+       if (max_addr != ~0UL)
+               printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 
20);
+
+       efi.systab = __va(ia64_boot_param->efi_systab);
+
+       /*
+        * Verify the EFI Table
+        */
+       if (efi.systab == NULL)
+               panic("Woah! Can't find EFI system table.\n");
+       if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+               panic("Woah! EFI system table signature incorrect\n");
+       if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
+               printk(KERN_WARNING "Warning: EFI system table major version 
mismatch: "
+                      "got %d.%02d, expected %d.%02d\n",
+                      efi.systab->hdr.revision >> 16, efi.systab->hdr.revision 
& 0xffff,
+                      EFI_SYSTEM_TABLE_REVISION >> 16, 
EFI_SYSTEM_TABLE_REVISION & 0xffff);
+
+       config_tables = __va(efi.systab->tables);
+
+       /* Show what we know for posterity */
+       c16 = __va(efi.systab->fw_vendor);
+       if (c16) {
+               for (i = 0;i < (int) sizeof(vendor) && *c16; ++i)
+                       vendor[i] = *c16++;
+               vendor[i] = '\0';
+       }
+
+       printk(KERN_INFO "EFI v%u.%.02u by %s:",
+              efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 
0xffff, vendor);
+
+       for (i = 0; i < (int) efi.systab->nr_tables; i++) {
+               if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
+                       efi.mps = __va(config_tables[i].table);
+                       printk(" MPS=0x%lx", config_tables[i].table);
+               } else if (efi_guidcmp(config_tables[i].guid, 
ACPI_20_TABLE_GUID) == 0) {
+                       efi.acpi20 = __va(config_tables[i].table);
+                       printk(" ACPI 2.0=0x%lx", config_tables[i].table);
+               } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) 
== 0) {
+                       efi.acpi = __va(config_tables[i].table);
+                       printk(" ACPI=0x%lx", config_tables[i].table);
+               } else if (efi_guidcmp(config_tables[i].guid, 
SMBIOS_TABLE_GUID) == 0) {
+                       efi.smbios = __va(config_tables[i].table);
+                       printk(" SMBIOS=0x%lx", config_tables[i].table);
+               } else if (efi_guidcmp(config_tables[i].guid, 
SAL_SYSTEM_TABLE_GUID) == 0) {
+                       efi.sal_systab = __va(config_tables[i].table);
+                       printk(" SALsystab=0x%lx", config_tables[i].table);
+               } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) 
== 0) {
+                       efi.hcdp = __va(config_tables[i].table);
+                       printk(" HCDP=0x%lx", config_tables[i].table);
+               }
+       }
+       printk("\n");
+
+       runtime = __va(efi.systab->runtime);
+       efi.get_time = phys_get_time;
+       efi.set_time = phys_set_time;
+       efi.get_wakeup_time = phys_get_wakeup_time;
+       efi.set_wakeup_time = phys_set_wakeup_time;
+       efi.get_variable = phys_get_variable;
+       efi.get_next_variable = phys_get_next_variable;
+       efi.set_variable = phys_set_variable;
+       efi.get_next_high_mono_count = phys_get_next_high_mono_count;
+       efi.reset_system = phys_reset_system;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+#if EFI_DEBUG
+       /* print EFI memory map: */
+       {
+               efi_memory_desc_t *md;
+               void *p;
+
+               for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += 
efi_desc_size) {
+                       md = p;
+                       printk("mem%02u: type=%u, attr=0x%lx, 
range=[0x%016lx-0x%016lx) (%luMB)\n",
+                              i, md->type, md->attribute, md->phys_addr,
+                              md->phys_addr + (md->num_pages << 
EFI_PAGE_SHIFT),
+                              md->num_pages >> (20 - EFI_PAGE_SHIFT));
+               }
+       }
+#endif
+
+       efi_map_pal_code();
+       efi_enter_virtual_mode();
+}
+
+void
+efi_enter_virtual_mode (void)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       efi_status_t status;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (md->attribute & EFI_MEMORY_RUNTIME) {
+                       /*
+                        * Some descriptors have multiple bits set, so the 
order of
+                        * the tests is relevant.
+                        */
+                       if (md->attribute & EFI_MEMORY_WB) {
+                               md->virt_addr = (u64) __va(md->phys_addr);
+                       } else if (md->attribute & EFI_MEMORY_UC) {
+                               md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+                       } else if (md->attribute & EFI_MEMORY_WC) {
+#if 0
+                               md->virt_addr = ia64_remap(md->phys_addr, 
(_PAGE_A | _PAGE_P
+                                                                          | 
_PAGE_D
+                                                                          | 
_PAGE_MA_WC
+                                                                          | 
_PAGE_PL_0
+                                                                          | 
_PAGE_AR_RW));
+#else
+                               printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
+                               md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+#endif
+                       } else if (md->attribute & EFI_MEMORY_WT) {
+#if 0
+                               md->virt_addr = ia64_remap(md->phys_addr, 
(_PAGE_A | _PAGE_P
+                                                                          | 
_PAGE_D | _PAGE_MA_WT
+                                                                          | 
_PAGE_PL_0
+                                                                          | 
_PAGE_AR_RW));
+#else
+                               printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
+                               md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+#endif
+                       }
+               }
+       }
+
+       status = efi_call_phys(__va(runtime->set_virtual_address_map),
+                              ia64_boot_param->efi_memmap_size,
+                              efi_desc_size, 
ia64_boot_param->efi_memdesc_version,
+                              ia64_boot_param->efi_memmap);
+       if (status != EFI_SUCCESS) {
+               printk(KERN_WARNING "warning: unable to switch EFI into virtual 
mode "
+                      "(status=%lu)\n", status);
+               return;
+       }
+
+       /*
+        * Now that EFI is in virtual mode, we call the EFI functions more 
efficiently:
+        */
+       efi.get_time = virt_get_time;
+       efi.set_time = virt_set_time;
+       efi.get_wakeup_time = virt_get_wakeup_time;
+       efi.set_wakeup_time = virt_set_wakeup_time;
+       efi.get_variable = virt_get_variable;
+       efi.get_next_variable = virt_get_next_variable;
+       efi.set_variable = virt_set_variable;
+       efi.get_next_high_mono_count = virt_get_next_high_mono_count;
+       efi.reset_system = virt_reset_system;
+}
+
+/*
+ * Walk the EFI memory map looking for the I/O port range.  There can only be 
one entry of
+ * this type, other I/O port ranges should be described via ACPI.
+ */
+u64
+efi_get_iobase (void)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
+                       if (md->attribute & EFI_MEMORY_UC)
+                               return md->phys_addr;
+               }
+       }
+       return 0;
+}
+
+#ifdef XEN
+// variation of efi_get_iobase which returns entire memory descriptor
+efi_memory_desc_t *
+efi_get_io_md (void)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+               if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
+                       if (md->attribute & EFI_MEMORY_UC)
+                               return md;
+               }
+       }
+       return 0;
+}
+#endif
+
+u32
+efi_mem_type (unsigned long phys_addr)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (phys_addr - md->phys_addr < (md->num_pages << 
EFI_PAGE_SHIFT))
+                        return md->type;
+       }
+       return 0;
+}
+
+u64
+efi_mem_attributes (unsigned long phys_addr)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (phys_addr - md->phys_addr < (md->num_pages << 
EFI_PAGE_SHIFT))
+                       return md->attribute;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(efi_mem_attributes);
+
+int
+valid_phys_addr_range (unsigned long phys_addr, unsigned long *size)
+{
+       void *efi_map_start, *efi_map_end, *p;
+       efi_memory_desc_t *md;
+       u64 efi_desc_size;
+
+       efi_map_start = __va(ia64_boot_param->efi_memmap);
+       efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+       efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+       for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+               md = p;
+
+               if (phys_addr - md->phys_addr < (md->num_pages << 
EFI_PAGE_SHIFT)) {
+                       if (!(md->attribute & EFI_MEMORY_WB))
+                               return 0;
+
+                       if (*size > md->phys_addr + (md->num_pages << 
EFI_PAGE_SHIFT) - phys_addr)
+                               *size = md->phys_addr + (md->num_pages << 
EFI_PAGE_SHIFT) - phys_addr;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+int __init
+efi_uart_console_only(void)
+{
+       efi_status_t status;
+       char *s, name[] = "ConOut";
+       efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID;
+       efi_char16_t *utf16, name_utf16[32];
+       unsigned char data[1024];
+       unsigned long size = sizeof(data);
+       struct efi_generic_dev_path *hdr, *end_addr;
+       int uart = 0;
+
+       /* Convert to UTF-16 */
+       utf16 = name_utf16;
+       s = name;
+       while (*s)
+               *utf16++ = *s++ & 0x7f;
+       *utf16 = 0;
+
+       status = efi.get_variable(name_utf16, &guid, NULL, &size, data);
+       if (status != EFI_SUCCESS) {
+               printk(KERN_ERR "No EFI %s variable?\n", name);
+               return 0;
+       }
+
+       hdr = (struct efi_generic_dev_path *) data;
+       end_addr = (struct efi_generic_dev_path *) ((u8 *) data + size);
+       while (hdr < end_addr) {
+               if (hdr->type == EFI_DEV_MSG &&
+                   hdr->sub_type == EFI_DEV_MSG_UART)
+                       uart = 1;
+               else if (hdr->type == EFI_DEV_END_PATH ||
+                         hdr->type == EFI_DEV_END_PATH2) {
+                       if (!uart)
+                               return 0;
+                       if (hdr->sub_type == EFI_DEV_END_ENTIRE)
+                               return 1;
+                       uart = 0;
+               }
+               hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + 
hdr->length);
+       }
+       printk(KERN_ERR "Malformed %s value\n", name);
+       return 0;
+}
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/linux-xen/entry.S
--- /dev/null   Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/linux-xen/entry.S   Mon Aug  8 19:21:23 2005
@@ -0,0 +1,1653 @@
+/*
+ * ia64/kernel/entry.S
+ *
+ * Kernel entry points.
+ *
+ * Copyright (C) 1998-2003, 2005 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ * Copyright (C) 1999, 2002-2003
+ *     Asit Mallick <Asit.K.Mallick@xxxxxxxxx>
+ *     Don Dugger <Don.Dugger@xxxxxxxxx>
+ *     Suresh Siddha <suresh.b.siddha@xxxxxxxxx>
+ *     Fenghua Yu <fenghua.yu@xxxxxxxxx>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ */
+/*
+ * ia64_switch_to now places correct virtual mapping in in TR2 for
+ * kernel stack. This allows us to handle interrupts without changing
+ * to physical mode.
+ *
+ * Jonathan Nicklin    <nicklin@xxxxxxxxxxxxxxxxxxxxxxxx>
+ * Patrick O'Rourke    <orourke@xxxxxxxxxxxxxxxxxxxxxxxx>
+ * 11/07/2000
+ */
+/*
+ * Global (preserved) predicate usage on syscall entry/exit path:
+ *
+ *     pKStk:          See entry.h.
+ *     pUStk:          See entry.h.
+ *     pSys:           See entry.h.
+ *     pNonSys:        !pSys
+ */
+
+#include <linux/config.h>
+
+#include <asm/asmmacro.h>
+#include <asm/cache.h>
+#include <asm/errno.h>
+#include <asm/kregs.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/percpu.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+
+#include "minstate.h"
+
+#ifndef XEN
+       /*
+        * execve() is special because in case of success, we need to
+        * setup a null register window frame.
+        */
+ENTRY(ia64_execve)
+       /*
+        * Allocate 8 input registers since ptrace() may clobber them
+        */
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc loc1=ar.pfs,8,2,4,0
+       mov loc0=rp
+       .body
+       mov out0=in0                    // filename
+       ;;                              // stop bit between alloc and call
+       mov out1=in1                    // argv
+       mov out2=in2                    // envp
+       add out3=16,sp                  // regs
+       br.call.sptk.many rp=sys_execve
+.ret0:
+#ifdef CONFIG_IA32_SUPPORT
+       /*
+        * Check if we're returning to ia32 mode. If so, we need to restore 
ia32 registers
+        * from pt_regs.
+        */
+       adds r16=PT(CR_IPSR)+16,sp
+       ;;
+       ld8 r16=[r16]
+#endif
+       cmp4.ge p6,p7=r8,r0
+       mov ar.pfs=loc1                 // restore ar.pfs
+       sxt4 r8=r8                      // return 64-bit result
+       ;;
+       stf.spill [sp]=f0
+(p6)   cmp.ne pKStk,pUStk=r0,r0        // a successful execve() lands us in 
user-mode...
+       mov rp=loc0
+(p6)   mov ar.pfs=r0                   // clear ar.pfs on success
+(p7)   br.ret.sptk.many rp
+
+       /*
+        * In theory, we'd have to zap this state only to prevent leaking of
+        * security sensitive state (e.g., if current->mm->dumpable is zero).  
However,
+        * this executes in less than 20 cycles even on Itanium, so it's not 
worth
+        * optimizing for...).
+        */
+       mov ar.unat=0;          mov ar.lc=0
+       mov r4=0;               mov f2=f0;              mov b1=r0
+       mov r5=0;               mov f3=f0;              mov b2=r0
+       mov r6=0;               mov f4=f0;              mov b3=r0
+       mov r7=0;               mov f5=f0;              mov b4=r0
+       ldf.fill f12=[sp];      mov f13=f0;             mov b5=r0
+       ldf.fill f14=[sp];      ldf.fill f15=[sp];      mov f16=f0
+       ldf.fill f17=[sp];      ldf.fill f18=[sp];      mov f19=f0
+       ldf.fill f20=[sp];      ldf.fill f21=[sp];      mov f22=f0
+       ldf.fill f23=[sp];      ldf.fill f24=[sp];      mov f25=f0
+       ldf.fill f26=[sp];      ldf.fill f27=[sp];      mov f28=f0
+       ldf.fill f29=[sp];      ldf.fill f30=[sp];      mov f31=f0
+#ifdef CONFIG_IA32_SUPPORT
+       tbit.nz p6,p0=r16, IA64_PSR_IS_BIT
+       movl loc0=ia64_ret_from_ia32_execve
+       ;;
+(p6)   mov rp=loc0
+#endif
+       br.ret.sptk.many rp
+END(ia64_execve)
+
+/*
+ * sys_clone2(u64 flags, u64 ustack_base, u64 ustack_size, u64 parent_tidptr, 
u64 child_tidptr,
+ *           u64 tls)
+ */
+GLOBAL_ENTRY(sys_clone2)
+       /*
+        * Allocate 8 input registers since ptrace() may clobber them
+        */
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc r16=ar.pfs,8,2,6,0
+       DO_SAVE_SWITCH_STACK
+       adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
+       mov loc0=rp
+       mov loc1=r16                            // save ar.pfs across do_fork
+       .body
+       mov out1=in1
+       mov out3=in2
+       tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
+       mov out4=in3    // parent_tidptr: valid only w/CLONE_PARENT_SETTID
+       ;;
+(p6)   st8 [r2]=in5                            // store TLS in r16 for 
copy_thread()
+       mov out5=in4    // child_tidptr:  valid only w/CLONE_CHILD_SETTID or 
CLONE_CHILD_CLEARTID
+       adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
+       mov out0=in0                            // out0 = clone_flags
+       br.call.sptk.many rp=do_fork
+.ret1: .restore sp
+       adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
+       mov ar.pfs=loc1
+       mov rp=loc0
+       br.ret.sptk.many rp
+END(sys_clone2)
+
+/*
+ * sys_clone(u64 flags, u64 ustack_base, u64 parent_tidptr, u64 child_tidptr, 
u64 tls)
+ *     Deprecated.  Use sys_clone2() instead.
+ */
+GLOBAL_ENTRY(sys_clone)
+       /*
+        * Allocate 8 input registers since ptrace() may clobber them
+        */
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc r16=ar.pfs,8,2,6,0
+       DO_SAVE_SWITCH_STACK
+       adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp
+       mov loc0=rp
+       mov loc1=r16                            // save ar.pfs across do_fork
+       .body
+       mov out1=in1
+       mov out3=16                             // stacksize (compensates for 
16-byte scratch area)
+       tbit.nz p6,p0=in0,CLONE_SETTLS_BIT
+       mov out4=in2    // parent_tidptr: valid only w/CLONE_PARENT_SETTID
+       ;;
+(p6)   st8 [r2]=in4                            // store TLS in r13 (tp)
+       mov out5=in3    // child_tidptr:  valid only w/CLONE_CHILD_SETTID or 
CLONE_CHILD_CLEARTID
+       adds out2=IA64_SWITCH_STACK_SIZE+16,sp  // out2 = &regs
+       mov out0=in0                            // out0 = clone_flags
+       br.call.sptk.many rp=do_fork
+.ret2: .restore sp
+       adds sp=IA64_SWITCH_STACK_SIZE,sp       // pop the switch stack
+       mov ar.pfs=loc1
+       mov rp=loc0
+       br.ret.sptk.many rp
+END(sys_clone)
+#endif /* !XEN */
+
+/*
+ * prev_task <- ia64_switch_to(struct task_struct *next)
+ *     With Ingo's new scheduler, interrupts are disabled when this routine 
gets
+ *     called.  The code starting at .map relies on this.  The rest of the code
+ *     doesn't care about the interrupt masking status.
+ */
+GLOBAL_ENTRY(ia64_switch_to)
+       .prologue
+       alloc r16=ar.pfs,1,0,0,0
+       DO_SAVE_SWITCH_STACK
+       .body
+
+       adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13
+       movl r25=init_task
+       mov r27=IA64_KR(CURRENT_STACK)
+       adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0
+#ifdef XEN
+       dep r20=0,in0,60,4              // physical address of "next"
+#else
+       dep r20=0,in0,61,3              // physical address of "next"
+#endif
+       ;;
+       st8 [r22]=sp                    // save kernel stack pointer of old task
+       shr.u r26=r20,IA64_GRANULE_SHIFT
+       cmp.eq p7,p6=r25,in0
+       ;;
+       /*
+        * If we've already mapped this task's page, we can skip doing it again.
+        */
+(p6)   cmp.eq p7,p6=r26,r27
+(p6)   br.cond.dpnt .map
+       ;;
+.done:
+(p6)   ssm psr.ic                      // if we had to map, reenable the 
psr.ic bit FIRST!!!
+       ;;
+(p6)   srlz.d
+       ld8 sp=[r21]                    // load kernel stack pointer of new task
+       mov IA64_KR(CURRENT)=in0        // update "current" application register
+       mov r8=r13                      // return pointer to previously running 
task
+       mov r13=in0                     // set "current" pointer
+       ;;
+       DO_LOAD_SWITCH_STACK
+
+#ifdef CONFIG_SMP
+       sync.i                          // ensure "fc"s done by this CPU are 
visible on other CPUs
+#endif
+       br.ret.sptk.many rp             // boogie on out in new context
+
+.map:
+#ifdef XEN
+       // avoid overlapping with kernel TR
+       movl r25=KERNEL_START
+       dep  r23=0,in0,0,KERNEL_TR_PAGE_SHIFT
+       ;;
+       cmp.eq p7,p0=r25,r23
+       ;;
+(p7)   mov IA64_KR(CURRENT_STACK)=r26  // remember last page we mapped...
+(p7)   br.cond.sptk .done
+#endif
+       rsm psr.ic                      // interrupts (psr.i) are already 
disabled here
+       movl r25=PAGE_KERNEL
+       ;;
+       srlz.d
+       or r23=r25,r20                  // construct PA | page properties
+       mov r25=IA64_GRANULE_SHIFT<<2
+       ;;
+       mov cr.itir=r25
+       mov cr.ifa=in0                  // VA of next task...
+       ;;
+       mov r25=IA64_TR_CURRENT_STACK
+       mov IA64_KR(CURRENT_STACK)=r26  // remember last page we mapped...
+       ;;
+       itr.d dtr[r25]=r23              // wire in new mapping...
+       br.cond.sptk .done
+END(ia64_switch_to)
+
+/*
+ * Note that interrupts are enabled during save_switch_stack and 
load_switch_stack.  This
+ * means that we may get an interrupt with "sp" pointing to the new kernel 
stack while
+ * ar.bspstore is still pointing to the old kernel backing store area.  Since 
ar.rsc,
+ * ar.rnat, ar.bsp, and ar.bspstore are all preserved by interrupts, this is 
not a
+ * problem.  Also, we don't need to specify unwind information for preserved 
registers
+ * that are not modified in save_switch_stack as the right unwind information 
is already
+ * specified at the call-site of save_switch_stack.
+ */
+
+/*
+ * save_switch_stack:
+ *     - r16 holds ar.pfs
+ *     - b7 holds address to return to
+ *     - rp (b0) holds return address to save
+ */
+GLOBAL_ENTRY(save_switch_stack)
+       .prologue
+       .altrp b7
+       flushrs                 // flush dirty regs to backing store (must be 
first in insn group)
+       .save @priunat,r17
+       mov r17=ar.unat         // preserve caller's
+       .body
+#ifdef CONFIG_ITANIUM
+       adds r2=16+128,sp
+       adds r3=16+64,sp
+       adds r14=SW(R4)+16,sp
+       ;;
+       st8.spill [r14]=r4,16           // spill r4
+       lfetch.fault.excl.nt1 [r3],128
+       ;;
+       lfetch.fault.excl.nt1 [r2],128
+       lfetch.fault.excl.nt1 [r3],128
+       ;;
+       lfetch.fault.excl [r2]
+       lfetch.fault.excl [r3]
+       adds r15=SW(R5)+16,sp
+#else
+       add r2=16+3*128,sp
+       add r3=16,sp
+       add r14=SW(R4)+16,sp
+       ;;
+       st8.spill [r14]=r4,SW(R6)-SW(R4)        // spill r4 and prefetch offset 
0x1c0
+       lfetch.fault.excl.nt1 [r3],128  //              prefetch offset 0x010
+       ;;
+       lfetch.fault.excl.nt1 [r3],128  //              prefetch offset 0x090
+       lfetch.fault.excl.nt1 [r2],128  //              prefetch offset 0x190
+       ;;
+       lfetch.fault.excl.nt1 [r3]      //              prefetch offset 0x110
+       lfetch.fault.excl.nt1 [r2]      //              prefetch offset 0x210
+       adds r15=SW(R5)+16,sp
+#endif
+       ;;
+       st8.spill [r15]=r5,SW(R7)-SW(R5)        // spill r5
+       mov.m ar.rsc=0                  // put RSE in mode: enforced lazy, 
little endian, pl 0
+       add r2=SW(F2)+16,sp             // r2 = &sw->f2
+       ;;
+       st8.spill [r14]=r6,SW(B0)-SW(R6)        // spill r6
+       mov.m r18=ar.fpsr               // preserve fpsr
+       add r3=SW(F3)+16,sp             // r3 = &sw->f3
+       ;;
+       stf.spill [r2]=f2,32
+       mov.m r19=ar.rnat
+       mov r21=b0
+
+       stf.spill [r3]=f3,32
+       st8.spill [r15]=r7,SW(B2)-SW(R7)        // spill r7
+       mov r22=b1
+       ;;
+       // since we're done with the spills, read and save ar.unat:
+       mov.m r29=ar.unat
+       mov.m r20=ar.bspstore
+       mov r23=b2
+       stf.spill [r2]=f4,32
+       stf.spill [r3]=f5,32
+       mov r24=b3
+       ;;
+       st8 [r14]=r21,SW(B1)-SW(B0)             // save b0
+       st8 [r15]=r23,SW(B3)-SW(B2)             // save b2
+       mov r25=b4
+       mov r26=b5
+       ;;
+       st8 [r14]=r22,SW(B4)-SW(B1)             // save b1
+       st8 [r15]=r24,SW(AR_PFS)-SW(B3)         // save b3
+       mov r21=ar.lc           // I-unit
+       stf.spill [r2]=f12,32
+       stf.spill [r3]=f13,32
+       ;;
+       st8 [r14]=r25,SW(B5)-SW(B4)             // save b4
+       st8 [r15]=r16,SW(AR_LC)-SW(AR_PFS)      // save ar.pfs
+       stf.spill [r2]=f14,32
+       stf.spill [r3]=f15,32
+       ;;
+       st8 [r14]=r26                           // save b5
+       st8 [r15]=r21                           // save ar.lc
+       stf.spill [r2]=f16,32
+       stf.spill [r3]=f17,32
+       ;;
+       stf.spill [r2]=f18,32
+       stf.spill [r3]=f19,32
+       ;;
+       stf.spill [r2]=f20,32
+       stf.spill [r3]=f21,32
+       ;;
+       stf.spill [r2]=f22,32
+       stf.spill [r3]=f23,32
+       ;;
+       stf.spill [r2]=f24,32
+       stf.spill [r3]=f25,32
+       ;;
+       stf.spill [r2]=f26,32
+       stf.spill [r3]=f27,32
+       ;;
+       stf.spill [r2]=f28,32
+       stf.spill [r3]=f29,32
+       ;;
+       stf.spill [r2]=f30,SW(AR_UNAT)-SW(F30)
+       stf.spill [r3]=f31,SW(PR)-SW(F31)
+       add r14=SW(CALLER_UNAT)+16,sp
+       ;;
+       st8 [r2]=r29,SW(AR_RNAT)-SW(AR_UNAT)    // save ar.unat
+       st8 [r14]=r17,SW(AR_FPSR)-SW(CALLER_UNAT) // save caller_unat
+       mov r21=pr
+       ;;
+       st8 [r2]=r19,SW(AR_BSPSTORE)-SW(AR_RNAT) // save ar.rnat
+       st8 [r3]=r21                            // save predicate registers
+       ;;
+       st8 [r2]=r20                            // save ar.bspstore
+       st8 [r14]=r18                           // save fpsr
+       mov ar.rsc=3            // put RSE back into eager mode, pl 0
+       br.cond.sptk.many b7
+END(save_switch_stack)
+
+/*
+ * load_switch_stack:
+ *     - "invala" MUST be done at call site (normally in DO_LOAD_SWITCH_STACK)
+ *     - b7 holds address to return to
+ *     - must not touch r8-r11
+ */
+#ifdef XEN
+GLOBAL_ENTRY(load_switch_stack)
+#else
+ENTRY(load_switch_stack)
+#endif
+       .prologue
+       .altrp b7
+
+       .body
+       lfetch.fault.nt1 [sp]
+       adds r2=SW(AR_BSPSTORE)+16,sp
+       adds r3=SW(AR_UNAT)+16,sp
+       mov ar.rsc=0                                            // put RSE into 
enforced lazy mode
+       adds r14=SW(CALLER_UNAT)+16,sp
+       adds r15=SW(AR_FPSR)+16,sp
+       ;;
+       ld8 r27=[r2],(SW(B0)-SW(AR_BSPSTORE))   // bspstore
+       ld8 r29=[r3],(SW(B1)-SW(AR_UNAT))       // unat
+       ;;
+       ld8 r21=[r2],16         // restore b0
+       ld8 r22=[r3],16         // restore b1
+       ;;
+       ld8 r23=[r2],16         // restore b2
+       ld8 r24=[r3],16         // restore b3
+       ;;
+       ld8 r25=[r2],16         // restore b4
+       ld8 r26=[r3],16         // restore b5
+       ;;
+       ld8 r16=[r2],(SW(PR)-SW(AR_PFS))        // ar.pfs
+       ld8 r17=[r3],(SW(AR_RNAT)-SW(AR_LC))    // ar.lc
+       ;;
+       ld8 r28=[r2]            // restore pr
+       ld8 r30=[r3]            // restore rnat
+       ;;
+       ld8 r18=[r14],16        // restore caller's unat
+       ld8 r19=[r15],24        // restore fpsr
+       ;;
+       ldf.fill f2=[r14],32
+       ldf.fill f3=[r15],32
+       ;;
+       ldf.fill f4=[r14],32
+       ldf.fill f5=[r15],32
+       ;;
+       ldf.fill f12=[r14],32
+       ldf.fill f13=[r15],32
+       ;;
+       ldf.fill f14=[r14],32
+       ldf.fill f15=[r15],32
+       ;;
+       ldf.fill f16=[r14],32
+       ldf.fill f17=[r15],32
+       ;;
+       ldf.fill f18=[r14],32
+       ldf.fill f19=[r15],32
+       mov b0=r21
+       ;;
+       ldf.fill f20=[r14],32
+       ldf.fill f21=[r15],32
+       mov b1=r22
+       ;;
+       ldf.fill f22=[r14],32
+       ldf.fill f23=[r15],32
+       mov b2=r23
+       ;;
+       mov ar.bspstore=r27
+       mov ar.unat=r29         // establish unat holding the NaT bits for r4-r7
+       mov b3=r24
+       ;;
+       ldf.fill f24=[r14],32
+       ldf.fill f25=[r15],32
+       mov b4=r25
+       ;;
+       ldf.fill f26=[r14],32
+       ldf.fill f27=[r15],32
+       mov b5=r26
+       ;;
+       ldf.fill f28=[r14],32
+       ldf.fill f29=[r15],32
+       mov ar.pfs=r16
+       ;;
+       ldf.fill f30=[r14],32
+       ldf.fill f31=[r15],24
+       mov ar.lc=r17
+       ;;
+       ld8.fill r4=[r14],16
+       ld8.fill r5=[r15],16
+       mov pr=r28,-1
+       ;;
+       ld8.fill r6=[r14],16
+       ld8.fill r7=[r15],16
+
+       mov ar.unat=r18                         // restore caller's unat
+       mov ar.rnat=r30                         // must restore after bspstore 
but before rsc!
+       mov ar.fpsr=r19                         // restore fpsr
+       mov ar.rsc=3                            // put RSE back into eager 
mode, pl 0
+       br.cond.sptk.many b7
+END(load_switch_stack)
+
+#ifndef XEN
+GLOBAL_ENTRY(__ia64_syscall)
+       .regstk 6,0,0,0
+       mov r15=in5                             // put syscall number in place
+       break __BREAK_SYSCALL
+       movl r2=errno
+       cmp.eq p6,p7=-1,r10
+       ;;
+(p6)   st4 [r2]=r8
+(p6)   mov r8=-1
+       br.ret.sptk.many rp
+END(__ia64_syscall)
+
+GLOBAL_ENTRY(execve)
+       mov r15=__NR_execve                     // put syscall number in place
+       break __BREAK_SYSCALL
+       br.ret.sptk.many rp
+END(execve)
+
+GLOBAL_ENTRY(clone)
+       mov r15=__NR_clone                      // put syscall number in place
+       break __BREAK_SYSCALL
+       br.ret.sptk.many rp
+END(clone)
+
+       /*
+        * Invoke a system call, but do some tracing before and after the call.
+        * We MUST preserve the current register frame throughout this routine
+        * because some system calls (such as ia64_execve) directly
+        * manipulate ar.pfs.
+        */
+GLOBAL_ENTRY(ia64_trace_syscall)
+       PT_REGS_UNWIND_INFO(0)
+       /*
+        * We need to preserve the scratch registers f6-f11 in case the system
+        * call is sigreturn.
+        */
+       adds r16=PT(F6)+16,sp
+       adds r17=PT(F7)+16,sp
+       ;;
+       stf.spill [r16]=f6,32
+       stf.spill [r17]=f7,32
+       ;;
+       stf.spill [r16]=f8,32
+       stf.spill [r17]=f9,32
+       ;;
+       stf.spill [r16]=f10
+       stf.spill [r17]=f11
+       br.call.sptk.many rp=syscall_trace_enter // give parent a chance to 
catch syscall args
+       adds r16=PT(F6)+16,sp
+       adds r17=PT(F7)+16,sp
+       ;;
+       ldf.fill f6=[r16],32
+       ldf.fill f7=[r17],32
+       ;;
+       ldf.fill f8=[r16],32
+       ldf.fill f9=[r17],32
+       ;;
+       ldf.fill f10=[r16]
+       ldf.fill f11=[r17]
+       // the syscall number may have changed, so re-load it and re-calculate 
the
+       // syscall entry-point:
+       adds r15=PT(R15)+16,sp                  // r15 = &pt_regs.r15 (syscall 
#)
+       ;;
+       ld8 r15=[r15]
+       mov r3=NR_syscalls - 1
+       ;;
+       adds r15=-1024,r15
+       movl r16=sys_call_table
+       ;;
+       shladd r20=r15,3,r16                    // r20 = sys_call_table + 
8*(syscall-1024)
+       cmp.leu p6,p7=r15,r3
+       ;;
+(p6)   ld8 r20=[r20]                           // load address of syscall 
entry point
+(p7)   movl r20=sys_ni_syscall
+       ;;
+       mov b6=r20
+       br.call.sptk.many rp=b6                 // do the syscall
+.strace_check_retval:
+       cmp.lt p6,p0=r8,r0                      // syscall failed?
+       adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
+       adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
+       mov r10=0
+(p6)   br.cond.sptk strace_error               // syscall failed ->
+       ;;                                      // avoid RAW on r10
+.strace_save_retval:
+.mem.offset 0,0; st8.spill [r2]=r8             // store return value in slot 
for r8
+.mem.offset 8,0; st8.spill [r3]=r10            // clear error indication in 
slot for r10
+       br.call.sptk.many rp=syscall_trace_leave // give parent a chance to 
catch return value
+.ret3: br.cond.sptk .work_pending_syscall_end
+
+strace_error:
+       ld8 r3=[r2]                             // load pt_regs.r8
+       sub r9=0,r8                             // negate return value to get 
errno value
+       ;;
+       cmp.ne p6,p0=r3,r0                      // is pt_regs.r8!=0?
+       adds r3=16,r2                           // r3=&pt_regs.r10
+       ;;
+(p6)   mov r10=-1
+(p6)   mov r8=r9
+       br.cond.sptk .strace_save_retval
+END(ia64_trace_syscall)
+
+       /*
+        * When traced and returning from sigreturn, we invoke syscall_trace 
but then
+        * go straight to ia64_leave_kernel rather than ia64_leave_syscall.
+        */
+GLOBAL_ENTRY(ia64_strace_leave_kernel)
+       PT_REGS_UNWIND_INFO(0)
+{      /*
+        * Some versions of gas generate bad unwind info if the first 
instruction of a
+        * procedure doesn't go into the first slot of a bundle.  This is a 
workaround.
+        */
+       nop.m 0
+       nop.i 0
+       br.call.sptk.many rp=syscall_trace_leave // give parent a chance to 
catch return value
+}
+.ret4: br.cond.sptk ia64_leave_kernel
+END(ia64_strace_leave_kernel)
+#endif
+
+GLOBAL_ENTRY(ia64_ret_from_clone)
+       PT_REGS_UNWIND_INFO(0)
+{      /*
+        * Some versions of gas generate bad unwind info if the first 
instruction of a
+        * procedure doesn't go into the first slot of a bundle.  This is a 
workaround.
+        */
+       nop.m 0
+       nop.i 0
+       /*
+        * We need to call schedule_tail() to complete the scheduling process.
+        * Called by ia64_switch_to() after do_fork()->copy_thread().  r8 
contains the
+        * address of the previously executing task.
+        */
+       br.call.sptk.many rp=ia64_invoke_schedule_tail
+}
+#ifdef XEN
+       // new domains are cloned but not exec'ed so switch to user mode here
+       cmp.ne pKStk,pUStk=r0,r0
+#ifdef CONFIG_VTI
+       br.cond.spnt ia64_leave_hypervisor
+#else // CONFIG_VTI
+       br.cond.spnt ia64_leave_kernel
+#endif // CONFIG_VTI
+#else
+.ret8:
+       adds r2=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+       ld4 r2=[r2]
+       ;;
+       mov r8=0
+       and r2=_TIF_SYSCALL_TRACEAUDIT,r2
+       ;;
+       cmp.ne p6,p0=r2,r0
+(p6)   br.cond.spnt .strace_check_retval
+#endif
+       ;;                                      // added stop bits to prevent 
r8 dependency
+END(ia64_ret_from_clone)
+       // fall through
+GLOBAL_ENTRY(ia64_ret_from_syscall)
+       PT_REGS_UNWIND_INFO(0)
+       cmp.ge p6,p7=r8,r0                      // syscall executed 
successfully?
+       adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
+       mov r10=r0                              // clear error indication in r10
+(p7)   br.cond.spnt handle_syscall_error       // handle potential syscall 
failure
+END(ia64_ret_from_syscall)
+       // fall through
+/*
+ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
+ *     need to switch to bank 0 and doesn't restore the scratch registers.
+ *     To avoid leaking kernel bits, the scratch registers are set to
+ *     the following known-to-be-safe values:
+ *
+ *               r1: restored (global pointer)
+ *               r2: cleared
+ *               r3: 1 (when returning to user-level)
+ *           r8-r11: restored (syscall return value(s))
+ *              r12: restored (user-level stack pointer)
+ *              r13: restored (user-level thread pointer)
+ *              r14: cleared
+ *              r15: restored (syscall #)
+ *          r16-r17: cleared
+ *              r18: user-level b6
+ *              r19: cleared
+ *              r20: user-level ar.fpsr
+ *              r21: user-level b0
+ *              r22: cleared
+ *              r23: user-level ar.bspstore
+ *              r24: user-level ar.rnat
+ *              r25: user-level ar.unat
+ *              r26: user-level ar.pfs
+ *              r27: user-level ar.rsc
+ *              r28: user-level ip
+ *              r29: user-level psr
+ *              r30: user-level cfm
+ *              r31: user-level pr
+ *           f6-f11: cleared
+ *               pr: restored (user-level pr)
+ *               b0: restored (user-level rp)
+ *               b6: restored
+ *               b7: cleared
+ *          ar.unat: restored (user-level ar.unat)
+ *           ar.pfs: restored (user-level ar.pfs)
+ *           ar.rsc: restored (user-level ar.rsc)
+ *          ar.rnat: restored (user-level ar.rnat)
+ *      ar.bspstore: restored (user-level ar.bspstore)
+ *          ar.fpsr: restored (user-level ar.fpsr)
+ *           ar.ccv: cleared
+ *           ar.csd: cleared
+ *           ar.ssd: cleared
+ */
+ENTRY(ia64_leave_syscall)
+       PT_REGS_UNWIND_INFO(0)
+       /*
+        * work.need_resched etc. mustn't get changed by this CPU before it 
returns to
+        * user- or fsys-mode, hence we disable interrupts early on.
+        *
+        * p6 controls whether current_thread_info()->flags needs to be check 
for
+        * extra work.  We always check for extra work when returning to 
user-level.
+        * With CONFIG_PREEMPT, we also check for extra work when the 
preempt_count
+        * is 0.  After extra work processing has been completed, execution
+        * resumes at .work_processed_syscall with p6 set to 1 if the 
extra-work-check
+        * needs to be redone.
+        */
+#ifdef CONFIG_PREEMPT
+       rsm psr.i                               // disable interrupts
+       cmp.eq pLvSys,p0=r0,r0                  // pLvSys=1: leave from syscall
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+       .pred.rel.mutex pUStk,pKStk
+(pKStk) ld4 r21=[r20]                  // r21 <- preempt_count
+(pUStk)        mov r21=0                       // r21 <- 0
+       ;;
+       cmp.eq p6,p0=r21,r0             // p6 <- pUStk || (preempt_count == 0)
+#else /* !CONFIG_PREEMPT */
+(pUStk)        rsm psr.i
+       cmp.eq pLvSys,p0=r0,r0          // pLvSys=1: leave from syscall
+(pUStk)        cmp.eq.unc p6,p0=r0,r0          // p6 <- pUStk
+#endif
+.work_processed_syscall:
+       adds r2=PT(LOADRS)+16,r12
+       adds r3=PT(AR_BSPSTORE)+16,r12
+#ifdef XEN
+       ;;
+#else
+       adds r18=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+(p6)   ld4 r31=[r18]                           // load 
current_thread_info()->flags
+#endif
+       ld8 r19=[r2],PT(B6)-PT(LOADRS)          // load ar.rsc value for 
"loadrs"
+       mov b7=r0               // clear b7
+       ;;
+       ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE)    // load ar.bspstore (may be 
garbage)
+       ld8 r18=[r2],PT(R9)-PT(B6)              // load b6
+#ifndef XEN
+(p6)   and r15=TIF_WORK_MASK,r31               // any work other than 
TIF_SYSCALL_TRACE?
+#endif
+       ;;
+       mov r16=ar.bsp                          // M2  get existing backing 
store pointer
+#ifndef XEN
+(p6)   cmp4.ne.unc p6,p0=r15, r0               // any special work pending?
+(p6)   br.cond.spnt .work_pending_syscall
+#endif
+       ;;
+       // start restoring the state saved on the kernel stack (struct pt_regs):
+       ld8 r9=[r2],PT(CR_IPSR)-PT(R9)
+       ld8 r11=[r3],PT(CR_IIP)-PT(R11)
+       mov f6=f0               // clear f6
+       ;;
+       invala                  // M0|1 invalidate ALAT
+       rsm psr.i | psr.ic      // M2 initiate turning off of interrupt and 
interruption collection
+       mov f9=f0               // clear f9
+
+       ld8 r29=[r2],16         // load cr.ipsr
+       ld8 r28=[r3],16                 // load cr.iip
+       mov f8=f0               // clear f8
+       ;;
+       ld8 r30=[r2],16         // M0|1 load cr.ifs
+       mov.m ar.ssd=r0         // M2 clear ar.ssd
+       cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore 
cr.ifs
+       ;;
+       ld8 r25=[r3],16         // M0|1 load ar.unat
+       mov.m ar.csd=r0         // M2 clear ar.csd
+       mov r22=r0              // clear r22
+       ;;
+       ld8 r26=[r2],PT(B0)-PT(AR_PFS)  // M0|1 load ar.pfs
+(pKStk)        mov r22=psr             // M2 read PSR now that interrupts are 
disabled
+       mov f10=f0              // clear f10
+       ;;
+       ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // load b0
+       ld8 r27=[r3],PT(PR)-PT(AR_RSC)  // load ar.rsc
+       mov f11=f0              // clear f11
+       ;;
+       ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT)    // load ar.rnat (may be garbage)
+       ld8 r31=[r3],PT(R1)-PT(PR)              // load predicates
+(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13
+       ;;
+       ld8 r20=[r2],PT(R12)-PT(AR_FPSR)        // load ar.fpsr
+       ld8.fill r1=[r3],16     // load r1
+(pUStk) mov r17=1
+       ;;
+       srlz.d                  // M0  ensure interruption collection is off
+       ld8.fill r13=[r3],16
+       mov f7=f0               // clear f7
+       ;;
+       ld8.fill r12=[r2]       // restore r12 (sp)
+       ld8.fill r15=[r3]       // restore r15
+#ifdef XEN
+       movl r3=THIS_CPU(ia64_phys_stacked_size_p8)
+#else
+       addl r3=THIS_CPU(ia64_phys_stacked_size_p8),r0
+#endif
+       ;;
+(pUStk)        ld4 r3=[r3]             // r3 = cpu_data->phys_stacked_size_p8
+(pUStk) st1 [r14]=r17
+       mov b6=r18              // I0  restore b6
+       ;;
+       mov r14=r0              // clear r14
+       shr.u r18=r19,16        // I0|1 get byte size of existing "dirty" 
partition
+(pKStk) br.cond.dpnt.many skip_rbs_switch
+
+       mov.m ar.ccv=r0         // clear ar.ccv
+(pNonSys) br.cond.dpnt.many dont_preserve_current_frame
+       br.cond.sptk.many rbs_switch
+END(ia64_leave_syscall)
+
+#ifdef CONFIG_IA32_SUPPORT
+GLOBAL_ENTRY(ia64_ret_from_ia32_execve)
+       PT_REGS_UNWIND_INFO(0)
+       adds r2=PT(R8)+16,sp                    // r2 = &pt_regs.r8
+       adds r3=PT(R10)+16,sp                   // r3 = &pt_regs.r10
+       ;;
+       .mem.offset 0,0
+       st8.spill [r2]=r8       // store return value in slot for r8 and set 
unat bit
+       .mem.offset 8,0
+       st8.spill [r3]=r0       // clear error indication in slot for r10 and 
set unat bit
+END(ia64_ret_from_ia32_execve_syscall)
+       // fall through
+#endif /* CONFIG_IA32_SUPPORT */
+GLOBAL_ENTRY(ia64_leave_kernel)
+       PT_REGS_UNWIND_INFO(0)
+       /*
+        * work.need_resched etc. mustn't get changed by this CPU before it 
returns to
+        * user- or fsys-mode, hence we disable interrupts early on.
+        *
+        * p6 controls whether current_thread_info()->flags needs to be check 
for
+        * extra work.  We always check for extra work when returning to 
user-level.
+        * With CONFIG_PREEMPT, we also check for extra work when the 
preempt_count
+        * is 0.  After extra work processing has been completed, execution
+        * resumes at .work_processed_syscall with p6 set to 1 if the 
extra-work-check
+        * needs to be redone.
+        */
+#ifdef CONFIG_PREEMPT
+       rsm psr.i                               // disable interrupts
+       cmp.eq p0,pLvSys=r0,r0                  // pLvSys=0: leave from kernel
+(pKStk)        adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+       .pred.rel.mutex pUStk,pKStk
+(pKStk)        ld4 r21=[r20]                   // r21 <- preempt_count
+(pUStk)        mov r21=0                       // r21 <- 0
+       ;;
+       cmp.eq p6,p0=r21,r0             // p6 <- pUStk || (preempt_count == 0)
+#else
+(pUStk)        rsm psr.i
+       cmp.eq p0,pLvSys=r0,r0          // pLvSys=0: leave from kernel
+(pUStk)        cmp.eq.unc p6,p0=r0,r0          // p6 <- pUStk
+#endif
+.work_processed_kernel:
+#ifdef XEN
+       alloc loc0=ar.pfs,0,1,1,0
+       adds out0=16,r12
+       ;;
+(p6)   br.call.sptk.many b0=deliver_pending_interrupt
+       mov ar.pfs=loc0
+       mov r31=r0
+#else
+       adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+       ;;
+(p6)   ld4 r31=[r17]                           // load 
current_thread_info()->flags
+#endif
+       adds r21=PT(PR)+16,r12
+       ;;
+
+       lfetch [r21],PT(CR_IPSR)-PT(PR)
+       adds r2=PT(B6)+16,r12
+       adds r3=PT(R16)+16,r12
+       ;;
+       lfetch [r21]
+       ld8 r28=[r2],8          // load b6
+       adds r29=PT(R24)+16,r12
+
+       ld8.fill r16=[r3]
+       adds r30=PT(AR_CCV)+16,r12
+(p6)   and r19=TIF_WORK_MASK,r31               // any work other than 
TIF_SYSCALL_TRACE?
+       ;;
+       adds r3=PT(AR_CSD)-PT(R16),r3
+       ld8.fill r24=[r29]
+       ld8 r15=[r30]           // load ar.ccv
+(p6)   cmp4.ne.unc p6,p0=r19, r0               // any special work pending?
+       ;;
+       ld8 r29=[r2],16         // load b7
+       ld8 r30=[r3],16         // load ar.csd
+#ifndef XEN
+(p6)   br.cond.spnt .work_pending
+#endif
+       ;;
+       ld8 r31=[r2],16         // load ar.ssd
+       ld8.fill r8=[r3],16
+       ;;
+       ld8.fill r9=[r2],16
+       ld8.fill r10=[r3],PT(R17)-PT(R10)
+       ;;
+       ld8.fill r11=[r2],PT(R18)-PT(R11)
+       ld8.fill r17=[r3],16
+       ;;
+       ld8.fill r18=[r2],16
+       ld8.fill r19=[r3],16
+       ;;
+       ld8.fill r20=[r2],16
+       ld8.fill r21=[r3],16
+       mov ar.csd=r30
+       mov ar.ssd=r31
+       ;;
+       rsm psr.i | psr.ic      // initiate turning off of interrupt and 
interruption collection
+       invala                  // invalidate ALAT
+       ;;
+       ld8.fill r22=[r2],24
+       ld8.fill r23=[r3],24
+       mov b6=r28
+       ;;
+       ld8.fill r25=[r2],16
+       ld8.fill r26=[r3],16
+       mov b7=r29
+       ;;
+       ld8.fill r27=[r2],16
+       ld8.fill r28=[r3],16
+       ;;
+       ld8.fill r29=[r2],16
+       ld8.fill r30=[r3],24
+       ;;
+       ld8.fill r31=[r2],PT(F9)-PT(R31)
+       adds r3=PT(F10)-PT(F6),r3
+       ;;
+       ldf.fill f9=[r2],PT(F6)-PT(F9)
+       ldf.fill f10=[r3],PT(F8)-PT(F10)
+       ;;
+       ldf.fill f6=[r2],PT(F7)-PT(F6)
+       ;;
+       ldf.fill f7=[r2],PT(F11)-PT(F7)
+       ldf.fill f8=[r3],32
+       ;;
+       srlz.i                  // ensure interruption collection is off
+       mov ar.ccv=r15
+       ;;
+       ldf.fill f11=[r2]
+       bsw.0                   // switch back to bank 0 (no stop bit required 
beforehand...)
+       ;;
+(pUStk)        mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency)
+       adds r16=PT(CR_IPSR)+16,r12
+       adds r17=PT(CR_IIP)+16,r12
+
+(pKStk)        mov r22=psr             // M2 read PSR now that interrupts are 
disabled
+       nop.i 0
+       nop.i 0
+       ;;
+       ld8 r29=[r16],16        // load cr.ipsr
+       ld8 r28=[r17],16        // load cr.iip
+       ;;
+       ld8 r30=[r16],16        // load cr.ifs
+       ld8 r25=[r17],16        // load ar.unat
+       ;;
+       ld8 r26=[r16],16        // load ar.pfs
+       ld8 r27=[r17],16        // load ar.rsc
+       cmp.eq p9,p0=r0,r0      // set p9 to indicate that we should restore 
cr.ifs
+       ;;
+       ld8 r24=[r16],16        // load ar.rnat (may be garbage)
+       ld8 r23=[r17],16        // load ar.bspstore (may be garbage)
+       ;;
+       ld8 r31=[r16],16        // load predicates
+       ld8 r21=[r17],16        // load b0
+       ;;
+       ld8 r19=[r16],16        // load ar.rsc value for "loadrs"
+       ld8.fill r1=[r17],16    // load r1
+       ;;
+       ld8.fill r12=[r16],16
+       ld8.fill r13=[r17],16
+(pUStk)        adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18
+       ;;
+       ld8 r20=[r16],16        // ar.fpsr
+       ld8.fill r15=[r17],16
+       ;;
+       ld8.fill r14=[r16],16
+       ld8.fill r2=[r17]
+(pUStk)        mov r17=1
+       ;;
+       ld8.fill r3=[r16]
+(pUStk)        st1 [r18]=r17           // restore current->thread.on_ustack
+       shr.u r18=r19,16        // get byte size of existing "dirty" partition
+       ;;
+       mov r16=ar.bsp          // get existing backing store pointer
+#ifdef XEN
+       movl r17=THIS_CPU(ia64_phys_stacked_size_p8)
+#else
+       addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0
+#endif
+       ;;
+       ld4 r17=[r17]           // r17 = cpu_data->phys_stacked_size_p8
+(pKStk)        br.cond.dpnt skip_rbs_switch
+
+       /*
+        * Restore user backing store.
+        *
+        * NOTE: alloc, loadrs, and cover can't be predicated.
+        */
+(pNonSys) br.cond.dpnt dont_preserve_current_frame
+
+rbs_switch:
+       cover                           // add current frame into dirty 
partition and set cr.ifs
+       ;;
+       mov r19=ar.bsp                  // get new backing store pointer
+       sub r16=r16,r18                 // krbs = old bsp - size of dirty 
partition
+       cmp.ne p9,p0=r0,r0              // clear p9 to skip restore of cr.ifs
+       ;;
+       sub r19=r19,r16                 // calculate total byte size of dirty 
partition
+       add r18=64,r18                  // don't force in0-in7 into memory...
+       ;;
+       shl r19=r19,16                  // shift size of dirty partition into 
loadrs position
+       ;;
+dont_preserve_current_frame:
+       /*
+        * To prevent leaking bits between the kernel and user-space,
+        * we must clear the stacked registers in the "invalid" partition here.
+        * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium,
+        * 5 registers/cycle on McKinley).
+        */
+#      define pRecurse p6
+#      define pReturn  p7
+#ifdef CONFIG_ITANIUM
+#      define Nregs    10
+#else
+#      define Nregs    14
+#endif
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       shr.u loc1=r18,9                // RNaTslots <= floor(dirtySize / 
(64*8))
+       sub r17=r17,r18                 // r17 = (physStackedSize + 8) - 
dirtySize
+       ;;
+       mov ar.rsc=r19                  // load ar.rsc to be used for "loadrs"
+       shladd in0=loc1,3,r17
+       mov in1=0
+       ;;
+       TEXT_ALIGN(32)
+rse_clear_invalid:
+#ifdef CONFIG_ITANIUM
+       // cycle 0
+ { .mii
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to 
clear, (re)curse
+       add out0=-Nregs*8,in0
+}{ .mfb
+       add out1=1,in1                  // increment recursion count
+       nop.f 0
+       nop.b 0                         // can't do br.call here because of 
alloc (WAW on CFM)
+       ;;
+}{ .mfi        // cycle 1
+       mov loc1=0
+       nop.f 0
+       mov loc2=0
+}{ .mib
+       mov loc3=0
+       mov loc4=0
+(pRecurse) br.call.sptk.many b0=rse_clear_invalid
+
+}{ .mfi        // cycle 2
+       mov loc5=0
+       nop.f 0
+       cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to 
do a br.ret
+}{ .mib
+       mov loc6=0
+       mov loc7=0
+(pReturn) br.ret.sptk.many b0
+}
+#else /* !CONFIG_ITANIUM */
+       alloc loc0=ar.pfs,2,Nregs-2,2,0
+       cmp.lt pRecurse,p0=Nregs*8,in0  // if more than Nregs regs left to 
clear, (re)curse
+       add out0=-Nregs*8,in0
+       add out1=1,in1                  // increment recursion count
+       mov loc1=0
+       mov loc2=0
+       ;;
+       mov loc3=0
+       mov loc4=0
+       mov loc5=0
+       mov loc6=0
+       mov loc7=0
+(pRecurse) br.call.sptk.few b0=rse_clear_invalid
+       ;;
+       mov loc8=0
+       mov loc9=0
+       cmp.ne pReturn,p0=r0,in1        // if recursion count != 0, we need to 
do a br.ret
+       mov loc10=0
+       mov loc11=0
+(pReturn) br.ret.sptk.many b0
+#endif /* !CONFIG_ITANIUM */
+#      undef pRecurse
+#      undef pReturn
+       ;;
+       alloc r17=ar.pfs,0,0,0,0        // drop current register frame
+       ;;
+       loadrs
+       ;;
+skip_rbs_switch:
+       mov ar.unat=r25         // M2
+(pKStk)        extr.u r22=r22,21,1     // I0 extract current value of psr.pp 
from r22
+(pLvSys)mov r19=r0             // A  clear r19 for leave_syscall, no-op 
otherwise
+       ;;
+(pUStk)        mov ar.bspstore=r23     // M2
+(pKStk)        dep r29=r22,r29,21,1    // I0 update ipsr.pp with psr.pp
+(pLvSys)mov r16=r0             // A  clear r16 for leave_syscall, no-op 
otherwise
+       ;;
+       mov cr.ipsr=r29         // M2
+       mov ar.pfs=r26          // I0
+(pLvSys)mov r17=r0             // A  clear r17 for leave_syscall, no-op 
otherwise
+
+(p9)   mov cr.ifs=r30          // M2
+       mov b0=r21              // I0
+(pLvSys)mov r18=r0             // A  clear r18 for leave_syscall, no-op 
otherwise
+
+       mov ar.fpsr=r20         // M2
+       mov cr.iip=r28          // M2
+       nop 0
+       ;;
+(pUStk)        mov ar.rnat=r24         // M2 must happen with RSE in lazy mode
+       nop 0
+(pLvSys)mov r2=r0
+
+       mov ar.rsc=r27          // M2
+       mov pr=r31,-1           // I0
+       rfi                     // B
+
+#ifndef XEN
+       /*
+        * On entry:
+        *      r20 = &current->thread_info->pre_count (if CONFIG_PREEMPT)
+        *      r31 = current->thread_info->flags
+        * On exit:
+        *      p6 = TRUE if work-pending-check needs to be redone
+        */
+.work_pending_syscall:
+       add r2=-8,r2
+       add r3=-8,r3
+       ;;
+       st8 [r2]=r8
+       st8 [r3]=r10
+.work_pending:
+       tbit.nz p6,p0=r31,TIF_SIGDELAYED                // signal delayed from  
MCA/INIT/NMI/PMI context?
+(p6)   br.cond.sptk.few .sigdelayed
+       ;;
+       tbit.z p6,p0=r31,TIF_NEED_RESCHED               // 
current_thread_info()->need_resched==0?
+(p6)   br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+       ;;
+(pKStk) st4 [r20]=r21
+       ssm psr.i               // enable interrupts
+#endif
+       br.call.spnt.many rp=schedule
+.ret9: cmp.eq p6,p0=r0,r0                              // p6 <- 1
+       rsm psr.i               // disable interrupts
+       ;;
+#ifdef CONFIG_PREEMPT
+(pKStk)        adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+       ;;
+(pKStk)        st4 [r20]=r0            // preempt_count() <- 0
+#endif
+(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+       br.cond.sptk.many .work_processed_kernel        // re-check
+
+.notify:
+(pUStk)        br.call.spnt.many rp=notify_resume_user
+.ret10:        cmp.ne p6,p0=r0,r0                              // p6 <- 0
+(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+       br.cond.sptk.many .work_processed_kernel        // don't re-check
+
+// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context 
where
+// it could not be delivered.  Deliver it now.  The signal might be for us and
+// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed
+// signal.
+
+.sigdelayed:
+       br.call.sptk.many rp=do_sigdelayed
+       cmp.eq p6,p0=r0,r0                              // p6 <- 1, always 
re-check
+(pLvSys)br.cond.sptk.few  .work_pending_syscall_end
+       br.cond.sptk.many .work_processed_kernel        // re-check
+
+.work_pending_syscall_end:
+       adds r2=PT(R8)+16,r12
+       adds r3=PT(R10)+16,r12
+       ;;
+       ld8 r8=[r2]
+       ld8 r10=[r3]
+       br.cond.sptk.many .work_processed_syscall       // re-check
+#endif
+
+END(ia64_leave_kernel)
+
+ENTRY(handle_syscall_error)
+       /*
+        * Some system calls (e.g., ptrace, mmap) can return arbitrary values 
which could
+        * lead us to mistake a negative return value as a failed syscall.  
Those syscall
+        * must deposit a non-zero value in pt_regs.r8 to indicate an error.  If
+        * pt_regs.r8 is zero, we assume that the call completed successfully.
+        */
+       PT_REGS_UNWIND_INFO(0)
+       ld8 r3=[r2]             // load pt_regs.r8
+       ;;
+       cmp.eq p6,p7=r3,r0      // is pt_regs.r8==0?
+       ;;
+(p7)   mov r10=-1
+(p7)   sub r8=0,r8             // negate return value to get errno
+       br.cond.sptk ia64_leave_syscall
+END(handle_syscall_error)
+
+       /*
+        * Invoke schedule_tail(task) while preserving in0-in7, which may be 
needed
+        * in case a system call gets restarted.
+        */
+GLOBAL_ENTRY(ia64_invoke_schedule_tail)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc loc1=ar.pfs,8,2,1,0
+       mov loc0=rp
+       mov out0=r8                             // Address of previous task
+       ;;
+       br.call.sptk.many rp=schedule_tail
+.ret11:        mov ar.pfs=loc1
+       mov rp=loc0
+       br.ret.sptk.many rp
+END(ia64_invoke_schedule_tail)
+
+#ifndef XEN
+       /*
+        * Setup stack and call do_notify_resume_user().  Note that pSys and 
pNonSys need to
+        * be set up by the caller.  We declare 8 input registers so the system 
call
+        * args get preserved, in case we need to restart a system call.
+        */
+ENTRY(notify_resume_user)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of 
syscall restart!
+       mov r9=ar.unat
+       mov loc0=rp                             // save return address
+       mov out0=0                              // there is no "oldset"
+       adds out1=8,sp                          // out1=&sigscratch->ar_pfs
+(pSys) mov out2=1                              // out2==1 => we're in a syscall
+       ;;
+(pNonSys) mov out2=0                           // out2==0 => not a syscall
+       .fframe 16
+       .spillpsp ar.unat, 16                   // (note that offset is 
relative to psp+0x10!)
+       st8 [sp]=r9,-16                         // allocate space for ar.unat 
and save it
+       st8 [out1]=loc1,-8                      // save ar.pfs, out1=&sigscratch
+       .body
+       br.call.sptk.many rp=do_notify_resume_user
+.ret15:        .restore sp
+       adds sp=16,sp                           // pop scratch stack space
+       ;;
+       ld8 r9=[sp]                             // load new unat from 
sigscratch->scratch_unat
+       mov rp=loc0
+       ;;
+       mov ar.unat=r9
+       mov ar.pfs=loc1
+       br.ret.sptk.many rp
+END(notify_resume_user)
+
+GLOBAL_ENTRY(sys_rt_sigsuspend)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
+       alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of 
syscall restart!
+       mov r9=ar.unat
+       mov loc0=rp                             // save return address
+       mov out0=in0                            // mask
+       mov out1=in1                            // sigsetsize
+       adds out2=8,sp                          // out2=&sigscratch->ar_pfs
+       ;;
+       .fframe 16
+       .spillpsp ar.unat, 16                   // (note that offset is 
relative to psp+0x10!)
+       st8 [sp]=r9,-16                         // allocate space for ar.unat 
and save it
+       st8 [out2]=loc1,-8                      // save ar.pfs, out2=&sigscratch
+       .body
+       br.call.sptk.many rp=ia64_rt_sigsuspend
+.ret17:        .restore sp
+       adds sp=16,sp                           // pop scratch stack space
+       ;;
+       ld8 r9=[sp]                             // load new unat from 
sw->caller_unat
+       mov rp=loc0
+       ;;
+       mov ar.unat=r9
+       mov ar.pfs=loc1
+       br.ret.sptk.many rp
+END(sys_rt_sigsuspend)
+
+ENTRY(sys_rt_sigreturn)
+       PT_REGS_UNWIND_INFO(0)
+       /*
+        * Allocate 8 input registers since ptrace() may clobber them
+        */
+       alloc r2=ar.pfs,8,0,1,0
+       .prologue
+       PT_REGS_SAVES(16)
+       adds sp=-16,sp
+       .body
+       cmp.eq pNonSys,pSys=r0,r0               // sigreturn isn't a normal 
syscall...
+       ;;
+       /*
+        * leave_kernel() restores f6-f11 from pt_regs, but since the 
streamlined
+        * syscall-entry path does not save them we save them here instead.  
Note: we
+        * don't need to save any other registers that are not saved by the 
stream-lined
+        * syscall path, because restore_sigcontext() restores them.
+        */
+       adds r16=PT(F6)+32,sp
+       adds r17=PT(F7)+32,sp
+       ;;
+       stf.spill [r16]=f6,32
+       stf.spill [r17]=f7,32
+       ;;
+       stf.spill [r16]=f8,32
+       stf.spill [r17]=f9,32
+       ;;
+       stf.spill [r16]=f10
+       stf.spill [r17]=f11
+       adds out0=16,sp                         // out0 = &sigscratch
+       br.call.sptk.many rp=ia64_rt_sigreturn
+.ret19:        .restore sp 0
+       adds sp=16,sp
+       ;;
+       ld8 r9=[sp]                             // load new ar.unat
+       mov.sptk b7=r8,ia64_leave_kernel
+       ;;
+       mov ar.unat=r9
+       br.many b7
+END(sys_rt_sigreturn)
+#endif
+
+GLOBAL_ENTRY(ia64_prepare_handle_unaligned)
+       .prologue
+       /*
+        * r16 = fake ar.pfs, we simply need to make sure privilege is still 0
+        */
+       mov r16=r0
+       DO_SAVE_SWITCH_STACK
+       br.call.sptk.many rp=ia64_handle_unaligned      // stack frame setup in 
ivt
+.ret21:        .body
+       DO_LOAD_SWITCH_STACK
+       br.cond.sptk.many rp                            // goes to 
ia64_leave_kernel
+END(ia64_prepare_handle_unaligned)
+
+#ifndef XEN
+       //
+       // unw_init_running(void (*callback)(info, arg), void *arg)
+       //
+#      define EXTRA_FRAME_SIZE ((UNW_FRAME_INFO_SIZE+15)&~15)
+
+GLOBAL_ENTRY(unw_init_running)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       alloc loc1=ar.pfs,2,3,3,0
+       ;;
+       ld8 loc2=[in0],8
+       mov loc0=rp
+       mov r16=loc1
+       DO_SAVE_SWITCH_STACK
+       .body
+
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       .fframe IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE
+       SWITCH_STACK_SAVES(EXTRA_FRAME_SIZE)
+       adds sp=-EXTRA_FRAME_SIZE,sp
+       .body
+       ;;
+       adds out0=16,sp                         // &info
+       mov out1=r13                            // current
+       adds out2=16+EXTRA_FRAME_SIZE,sp        // &switch_stack
+       br.call.sptk.many rp=unw_init_frame_info
+1:     adds out0=16,sp                         // &info
+       mov b6=loc2
+       mov loc2=gp                             // save gp across indirect 
function call
+       ;;
+       ld8 gp=[in0]
+       mov out1=in1                            // arg
+       br.call.sptk.many rp=b6                 // invoke the callback function
+1:     mov gp=loc2                             // restore gp
+
+       // For now, we don't allow changing registers from within
+       // unw_init_running; if we ever want to allow that, we'd
+       // have to do a load_switch_stack here:
+       .restore sp
+       adds sp=IA64_SWITCH_STACK_SIZE+EXTRA_FRAME_SIZE,sp
+
+       mov ar.pfs=loc1
+       mov rp=loc0
+       br.ret.sptk.many rp
+END(unw_init_running)
+
+       .rodata
+       .align 8
+       .globl sys_call_table
+sys_call_table:
+       data8 sys_ni_syscall            //  This must be sys_ni_syscall!  See 
ivt.S.
+       data8 sys_exit                          // 1025
+       data8 sys_read
+       data8 sys_write
+       data8 sys_open
+       data8 sys_close
+       data8 sys_creat                         // 1030
+       data8 sys_link
+       data8 sys_unlink
+       data8 ia64_execve
+       data8 sys_chdir
+       data8 sys_fchdir                        // 1035
+       data8 sys_utimes
+       data8 sys_mknod
+       data8 sys_chmod
+       data8 sys_chown
+       data8 sys_lseek                         // 1040
+       data8 sys_getpid
+       data8 sys_getppid
+       data8 sys_mount
+       data8 sys_umount
+       data8 sys_setuid                        // 1045
+       data8 sys_getuid
+       data8 sys_geteuid
+       data8 sys_ptrace
+       data8 sys_access
+       data8 sys_sync                          // 1050
+       data8 sys_fsync
+       data8 sys_fdatasync
+       data8 sys_kill
+       data8 sys_rename
+       data8 sys_mkdir                         // 1055
+       data8 sys_rmdir
+       data8 sys_dup
+       data8 sys_pipe
+       data8 sys_times
+       data8 ia64_brk                          // 1060
+       data8 sys_setgid
+       data8 sys_getgid
+       data8 sys_getegid
+       data8 sys_acct
+       data8 sys_ioctl                         // 1065
+       data8 sys_fcntl
+       data8 sys_umask
+       data8 sys_chroot
+       data8 sys_ustat
+       data8 sys_dup2                          // 1070
+       data8 sys_setreuid
+       data8 sys_setregid
+       data8 sys_getresuid
+       data8 sys_setresuid
+       data8 sys_getresgid                     // 1075
+       data8 sys_setresgid
+       data8 sys_getgroups
+       data8 sys_setgroups
+       data8 sys_getpgid
+       data8 sys_setpgid                       // 1080
+       data8 sys_setsid
+       data8 sys_getsid
+       data8 sys_sethostname
+       data8 sys_setrlimit
+       data8 sys_getrlimit                     // 1085
+       data8 sys_getrusage
+       data8 sys_gettimeofday
+       data8 sys_settimeofday
+       data8 sys_select
+       data8 sys_poll                          // 1090
+       data8 sys_symlink
+       data8 sys_readlink
+       data8 sys_uselib
+       data8 sys_swapon
+       data8 sys_swapoff                       // 1095
+       data8 sys_reboot
+       data8 sys_truncate
+       data8 sys_ftruncate
+       data8 sys_fchmod
+       data8 sys_fchown                        // 1100
+       data8 ia64_getpriority
+       data8 sys_setpriority
+       data8 sys_statfs
+       data8 sys_fstatfs
+       data8 sys_gettid                        // 1105
+       data8 sys_semget
+       data8 sys_semop
+       data8 sys_semctl
+       data8 sys_msgget
+       data8 sys_msgsnd                        // 1110
+       data8 sys_msgrcv
+       data8 sys_msgctl
+       data8 sys_shmget
+       data8 ia64_shmat
+       data8 sys_shmdt                         // 1115
+       data8 sys_shmctl
+       data8 sys_syslog
+       data8 sys_setitimer
+       data8 sys_getitimer
+       data8 sys_ni_syscall                    // 1120         /* was: 
ia64_oldstat */
+       data8 sys_ni_syscall                                    /* was: 
ia64_oldlstat */
+       data8 sys_ni_syscall                                    /* was: 
ia64_oldfstat */
+       data8 sys_vhangup
+       data8 sys_lchown
+       data8 sys_remap_file_pages              // 1125
+       data8 sys_wait4
+       data8 sys_sysinfo
+       data8 sys_clone
+       data8 sys_setdomainname
+       data8 sys_newuname                      // 1130
+       data8 sys_adjtimex
+       data8 sys_ni_syscall                                    /* was: 
ia64_create_module */
+       data8 sys_init_module
+       data8 sys_delete_module
+       data8 sys_ni_syscall                    // 1135         /* was: 
sys_get_kernel_syms */
+       data8 sys_ni_syscall                                    /* was: 
sys_query_module */
+       data8 sys_quotactl
+       data8 sys_bdflush
+       data8 sys_sysfs
+       data8 sys_personality                   // 1140
+       data8 sys_ni_syscall            // sys_afs_syscall
+       data8 sys_setfsuid
+       data8 sys_setfsgid
+       data8 sys_getdents
+       data8 sys_flock                         // 1145
+       data8 sys_readv
+       data8 sys_writev
+       data8 sys_pread64
+       data8 sys_pwrite64
+       data8 sys_sysctl                        // 1150
+       data8 sys_mmap
+       data8 sys_munmap
+       data8 sys_mlock
+       data8 sys_mlockall
+       data8 sys_mprotect                      // 1155
+       data8 ia64_mremap
+       data8 sys_msync
+       data8 sys_munlock
+       data8 sys_munlockall
+       data8 sys_sched_getparam                // 1160
+       data8 sys_sched_setparam
+       data8 sys_sched_getscheduler
+       data8 sys_sched_setscheduler
+       data8 sys_sched_yield
+       data8 sys_sched_get_priority_max        // 1165
+       data8 sys_sched_get_priority_min
+       data8 sys_sched_rr_get_interval
+       data8 sys_nanosleep
+       data8 sys_nfsservctl
+       data8 sys_prctl                         // 1170
+       data8 sys_getpagesize
+       data8 sys_mmap2
+       data8 sys_pciconfig_read
+       data8 sys_pciconfig_write
+       data8 sys_perfmonctl                    // 1175
+       data8 sys_sigaltstack
+       data8 sys_rt_sigaction
+       data8 sys_rt_sigpending
+       data8 sys_rt_sigprocmask
+       data8 sys_rt_sigqueueinfo               // 1180
+       data8 sys_rt_sigreturn
+       data8 sys_rt_sigsuspend
+       data8 sys_rt_sigtimedwait
+       data8 sys_getcwd
+       data8 sys_capget                        // 1185
+       data8 sys_capset
+       data8 sys_sendfile64
+       data8 sys_ni_syscall            // sys_getpmsg (STREAMS)
+       data8 sys_ni_syscall            // sys_putpmsg (STREAMS)
+       data8 sys_socket                        // 1190
+       data8 sys_bind
+       data8 sys_connect
+       data8 sys_listen
+       data8 sys_accept
+       data8 sys_getsockname                   // 1195
+       data8 sys_getpeername
+       data8 sys_socketpair
+       data8 sys_send
+       data8 sys_sendto
+       data8 sys_recv                          // 1200
+       data8 sys_recvfrom
+       data8 sys_shutdown
+       data8 sys_setsockopt
+       data8 sys_getsockopt
+       data8 sys_sendmsg                       // 1205
+       data8 sys_recvmsg
+       data8 sys_pivot_root
+       data8 sys_mincore
+       data8 sys_madvise
+       data8 sys_newstat                       // 1210
+       data8 sys_newlstat
+       data8 sys_newfstat
+       data8 sys_clone2
+       data8 sys_getdents64
+       data8 sys_getunwind                     // 1215
+       data8 sys_readahead
+       data8 sys_setxattr
+       data8 sys_lsetxattr
+       data8 sys_fsetxattr
+       data8 sys_getxattr                      // 1220
+       data8 sys_lgetxattr
+       data8 sys_fgetxattr
+       data8 sys_listxattr
+       data8 sys_llistxattr
+       data8 sys_flistxattr                    // 1225
+       data8 sys_removexattr
+       data8 sys_lremovexattr
+       data8 sys_fremovexattr
+       data8 sys_tkill
+       data8 sys_futex                         // 1230
+       data8 sys_sched_setaffinity
+       data8 sys_sched_getaffinity
+       data8 sys_set_tid_address
+       data8 sys_fadvise64_64
+       data8 sys_tgkill                        // 1235
+       data8 sys_exit_group
+       data8 sys_lookup_dcookie
+       data8 sys_io_setup
+       data8 sys_io_destroy
+       data8 sys_io_getevents                  // 1240
+       data8 sys_io_submit
+       data8 sys_io_cancel
+       data8 sys_epoll_create
+       data8 sys_epoll_ctl
+       data8 sys_epoll_wait                    // 1245
+       data8 sys_restart_syscall
+       data8 sys_semtimedop
+       data8 sys_timer_create
+       data8 sys_timer_settime
+       data8 sys_timer_gettime                 // 1250
+       data8 sys_timer_getoverrun
+       data8 sys_timer_delete
+       data8 sys_clock_settime
+       data8 sys_clock_gettime
+       data8 sys_clock_getres                  // 1255
+       data8 sys_clock_nanosleep
+       data8 sys_fstatfs64
+       data8 sys_statfs64
+       data8 sys_mbind
+       data8 sys_get_mempolicy                 // 1260
+       data8 sys_set_mempolicy
+       data8 sys_mq_open
+       data8 sys_mq_unlink
+       data8 sys_mq_timedsend
+       data8 sys_mq_timedreceive               // 1265
+       data8 sys_mq_notify
+       data8 sys_mq_getsetattr
+       data8 sys_ni_syscall                    // reserved for kexec_load
+       data8 sys_ni_syscall                    // reserved for vserver
+       data8 sys_waitid                        // 1270
+       data8 sys_add_key
+       data8 sys_request_key
+       data8 sys_keyctl
+       data8 sys_ni_syscall
+       data8 sys_ni_syscall                    // 1275
+       data8 sys_ni_syscall
+       data8 sys_ni_syscall
+       data8 sys_ni_syscall
+       data8 sys_ni_syscall
+
+       .org sys_call_table + 8*NR_syscalls     // guard against failures to 
increase NR_syscalls
+#endif
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/linux-xen/entry.h
--- /dev/null   Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/linux-xen/entry.h   Mon Aug  8 19:21:23 2005
@@ -0,0 +1,97 @@
+#include <linux/config.h>
+
+/*
+ * Preserved registers that are shared between code in ivt.S and
+ * entry.S.  Be careful not to step on these!
+ */
+#define PRED_LEAVE_SYSCALL     1 /* TRUE iff leave from syscall */
+#define PRED_KERNEL_STACK      2 /* returning to kernel-stacks? */
+#define PRED_USER_STACK                3 /* returning to user-stacks? */
+#ifdef CONFIG_VTI
+#define PRED_EMUL              2 /* Need to save r4-r7 for inst emulation */
+#define PRED_NON_EMUL          3 /* No need to save r4-r7 for normal path */
+#define PRED_BN0               6 /* Guest is in bank 0 */
+#define PRED_BN1               7 /* Guest is in bank 1 */
+#endif // CONFIG_VTI
+#define PRED_SYSCALL           4 /* inside a system call? */
+#define PRED_NON_SYSCALL       5 /* complement of PRED_SYSCALL */
+
+#ifdef __ASSEMBLY__
+# define PASTE2(x,y)   x##y
+# define PASTE(x,y)    PASTE2(x,y)
+
+# define pLvSys                PASTE(p,PRED_LEAVE_SYSCALL)
+# define pKStk         PASTE(p,PRED_KERNEL_STACK)
+# define pUStk         PASTE(p,PRED_USER_STACK)
+#ifdef CONFIG_VTI
+# define pEml          PASTE(p,PRED_EMUL)
+# define pNonEml       PASTE(p,PRED_NON_EMUL)
+# define pBN0          PASTE(p,PRED_BN0)
+# define pBN1          PASTE(p,PRED_BN1)
+#endif // CONFIG_VTI
+# define pSys          PASTE(p,PRED_SYSCALL)
+# define pNonSys       PASTE(p,PRED_NON_SYSCALL)
+#endif
+
+#define PT(f)          (IA64_PT_REGS_##f##_OFFSET)
+#define SW(f)          (IA64_SWITCH_STACK_##f##_OFFSET)
+#ifdef CONFIG_VTI
+#define VPD(f)      (VPD_##f##_START_OFFSET)
+#endif // CONFIG_VTI
+
+#define PT_REGS_SAVES(off)                     \
+       .unwabi 3, 'i';                         \
+       .fframe IA64_PT_REGS_SIZE+16+(off);     \
+       .spillsp rp, PT(CR_IIP)+16+(off);       \
+       .spillsp ar.pfs, PT(CR_IFS)+16+(off);   \
+       .spillsp ar.unat, PT(AR_UNAT)+16+(off); \
+       .spillsp ar.fpsr, PT(AR_FPSR)+16+(off); \
+       .spillsp pr, PT(PR)+16+(off);
+
+#define PT_REGS_UNWIND_INFO(off)               \
+       .prologue;                              \
+       PT_REGS_SAVES(off);                     \
+       .body
+
+#define SWITCH_STACK_SAVES(off)                                                
        \
+       .savesp ar.unat,SW(CALLER_UNAT)+16+(off);                               
\
+       .savesp ar.fpsr,SW(AR_FPSR)+16+(off);                                   
\
+       .spillsp f2,SW(F2)+16+(off); .spillsp f3,SW(F3)+16+(off);               
\
+       .spillsp f4,SW(F4)+16+(off); .spillsp f5,SW(F5)+16+(off);               
\
+       .spillsp f16,SW(F16)+16+(off); .spillsp f17,SW(F17)+16+(off);           
\
+       .spillsp f18,SW(F18)+16+(off); .spillsp f19,SW(F19)+16+(off);           
\
+       .spillsp f20,SW(F20)+16+(off); .spillsp f21,SW(F21)+16+(off);           
\
+       .spillsp f22,SW(F22)+16+(off); .spillsp f23,SW(F23)+16+(off);           
\
+       .spillsp f24,SW(F24)+16+(off); .spillsp f25,SW(F25)+16+(off);           
\
+       .spillsp f26,SW(F26)+16+(off); .spillsp f27,SW(F27)+16+(off);           
\
+       .spillsp f28,SW(F28)+16+(off); .spillsp f29,SW(F29)+16+(off);           
\
+       .spillsp f30,SW(F30)+16+(off); .spillsp f31,SW(F31)+16+(off);           
\
+       .spillsp r4,SW(R4)+16+(off); .spillsp r5,SW(R5)+16+(off);               
\
+       .spillsp r6,SW(R6)+16+(off); .spillsp r7,SW(R7)+16+(off);               
\
+       .spillsp b0,SW(B0)+16+(off); .spillsp b1,SW(B1)+16+(off);               
\
+       .spillsp b2,SW(B2)+16+(off); .spillsp b3,SW(B3)+16+(off);               
\
+       .spillsp b4,SW(B4)+16+(off); .spillsp b5,SW(B5)+16+(off);               
\
+       .spillsp ar.pfs,SW(AR_PFS)+16+(off); .spillsp ar.lc,SW(AR_LC)+16+(off); 
\
+       .spillsp @priunat,SW(AR_UNAT)+16+(off);                                 
\
+       .spillsp ar.rnat,SW(AR_RNAT)+16+(off);                                  
\
+       .spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off);                          
\
+       .spillsp pr,SW(PR)+16+(off))
+
+#define DO_SAVE_SWITCH_STACK                   \
+       movl r28=1f;                            \
+       ;;                                      \
+       .fframe IA64_SWITCH_STACK_SIZE;         \
+       adds sp=-IA64_SWITCH_STACK_SIZE,sp;     \
+       mov.ret.sptk b7=r28,1f;                 \
+       SWITCH_STACK_SAVES(0);                  \
+       br.cond.sptk.many save_switch_stack;    \
+1:
+
+#define DO_LOAD_SWITCH_STACK                   \
+       movl r28=1f;                            \
+       ;;                                      \
+       invala;                                 \
+       mov.ret.sptk b7=r28,1f;                 \
+       br.cond.sptk.many load_switch_stack;    \
+1:     .restore sp;                            \
+       adds sp=IA64_SWITCH_STACK_SIZE,sp
diff -r be8fe9b3987c -r 1ee9236cc224 xen/arch/ia64/linux-xen/head.S
--- /dev/null   Tue Aug  2 22:38:45 2005
+++ b/xen/arch/ia64/linux-xen/head.S    Mon Aug  8 19:21:23 2005
@@ -0,0 +1,1026 @@
+/*
+ * Here is where the ball gets rolling as far as the kernel is concerned.
+ * When control is transferred to _start, the bootload has already
+ * loaded us to the correct address.  All that's left to do here is
+ * to set up the kernel's global pointer and jump to the kernel
+ * entry point.
+ *
+ * Copyright (C) 1998-2001, 2003, 2005 Hewlett-Packard Co
+ *     David Mosberger-Tang <davidm@xxxxxxxxxx>
+ *     Stephane Eranian <eranian@xxxxxxxxxx>
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@xxxxxxxxxxx>
+ * Copyright (C) 1999 Intel Corp.
+ * Copyright (C) 1999 Asit Mallick <Asit.K.Mallick@xxxxxxxxx>
+ * Copyright (C) 1999 Don Dugger <Don.Dugger@xxxxxxxxx>
+ * Copyright (C) 2002 Fenghua Yu <fenghua.yu@xxxxxxxxx>
+ *   -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
+ */
+
+#include <linux/config.h>
+
+#include <asm/asmmacro.h>
+#include <asm/fpu.h>
+#include <asm/kregs.h>
+#include <asm/mmu_context.h>
+#include <asm/offsets.h>
+#include <asm/pal.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+       .section __special_page_section,"ax"
+
+       .global empty_zero_page
+empty_zero_page:
+       .skip PAGE_SIZE
+
+       .global swapper_pg_dir
+swapper_pg_dir:
+       .skip PAGE_SIZE
+
+       .rodata
+halt_msg:
+       stringz "Halting kernel\n"
+
+       .text
+
+       .global start_ap
+
+       /*
+        * Start the kernel.  When the bootloader passes control to _start(), 
r28
+        * points to the address of the boot parameter area.  Execution reaches
+        * here in physical mode.
+        */
+GLOBAL_ENTRY(_start)
+start_ap:
+       .prologue
+       .save rp, r0            // terminate unwind chain with a NULL rp
+       .body
+
+       rsm psr.i | psr.ic
+       ;;
+       srlz.i
+       ;;
+       /*
+        * Initialize kernel region registers:
+        *      rr[0]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[1]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[2]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[3]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[4]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[5]: VHPT enabled, page size = PAGE_SHIFT
+        *      rr[6]: VHPT disabled, page size = IA64_GRANULE_SHIFT
+        *      rr[7]: VHPT disabled, page size = IA64_GRANULE_SHIFT
+        * We initialize all of them to prevent inadvertently assuming
+        * something about the state of address translation early in boot.
+        */
+       movl r6=((ia64_rid(IA64_REGION_ID_KERNEL, (0<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r7=(0<<61)
+       movl r8=((ia64_rid(IA64_REGION_ID_KERNEL, (1<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r9=(1<<61)
+       movl r10=((ia64_rid(IA64_REGION_ID_KERNEL, (2<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r11=(2<<61)
+       movl r12=((ia64_rid(IA64_REGION_ID_KERNEL, (3<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r13=(3<<61)
+       movl r14=((ia64_rid(IA64_REGION_ID_KERNEL, (4<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r15=(4<<61)
+       movl r16=((ia64_rid(IA64_REGION_ID_KERNEL, (5<<61)) << 8) | (PAGE_SHIFT 
<< 2) | 1)
+       movl r17=(5<<61)
+       movl r18=((ia64_rid(IA64_REGION_ID_KERNEL, (6<<61)) << 8) | 
(IA64_GRANULE_SHIFT << 2))
+       movl r19=(6<<61)
+       movl r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | 
(IA64_GRANULE_SHIFT << 2))
+       movl r21=(7<<61)
+       ;;
+       mov rr[r7]=r6
+       mov rr[r9]=r8
+       mov rr[r11]=r10
+       mov rr[r13]=r12
+       mov rr[r15]=r14
+       mov rr[r17]=r16
+       mov rr[r19]=r18
+       mov rr[r21]=r20
+       ;;
+       /*
+        * Now pin mappings into the TLB for kernel text and data
+        */
+       mov r18=KERNEL_TR_PAGE_SHIFT<<2
+       movl r17=KERNEL_START
+       ;;
+       mov cr.itir=r18
+       mov cr.ifa=r17
+       mov r16=IA64_TR_KERNEL
+       mov r3=ip
+       movl r18=PAGE_KERNEL
+       ;;
+       dep r2=0,r3,0,KERNEL_TR_PAGE_SHIFT
+       ;;
+       or r18=r2,r18
+       ;;
+       srlz.i
+       ;;
+       itr.i itr[r16]=r18
+       ;;
+       itr.d dtr[r16]=r18
+       ;;
+       srlz.i
+
+       /*
+        * Switch into virtual mode:
+        */
+#ifdef CONFIG_VTI
+       movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH \
+                 |IA64_PSR_DI)
+#else // CONFIG_VTI
+       movl 
r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \
+                 |IA64_PSR_DI)
+#endif // CONFIG_VTI
+       ;;
+       mov cr.ipsr=r16
+       movl r17=1f
+       ;;
+       mov cr.iip=r17
+       mov cr.ifs=r0
+       ;;
+       rfi
+       ;;
+1:     // now we are in virtual mode
+
+       // set IVT entry point---can't access I/O ports without it
+#ifdef CONFIG_VTI
+    movl r3=vmx_ia64_ivt
+#else // CONFIG_VTI
+       movl r3=ia64_ivt
+#endif // CONFIG_VTI
+       ;;
+       mov cr.iva=r3
+       movl r2=FPSR_DEFAULT
+       ;;
+       srlz.i
+       movl gp=__gp
+
+       mov ar.fpsr=r2
+       ;;
+
+#define isAP   p2      // are we an Application Processor?
+#define isBP   p3      // are we the Bootstrap Processor?
+
+#ifdef CONFIG_SMP
+       /*
+        * Find the init_task for the currently booting CPU.  At poweron, and in
+        * UP mode, task_for_booting_cpu is NULL.
+        */
+       movl r3=task_for_booting_cpu
+       ;;
+       ld8 r3=[r3]
+       movl r2=init_task
+       ;;
+       cmp.eq isBP,isAP=r3,r0
+       ;;
+(isAP) mov r2=r3
+#else
+       movl r2=init_task
+       cmp.eq isBP,isAP=r0,r0
+#endif
+       ;;
+       tpa r3=r2               // r3 == phys addr of task struct
+       mov r16=-1
+(isBP) br.cond.dpnt .load_current // BP stack is on region 5 --- no need to 
map it
+
+       // load mapping for stack (virtaddr in r2, physaddr in r3)
+       rsm psr.ic
+       movl r17=PAGE_KERNEL
+       ;;
+       srlz.d
+       dep r18=0,r3,0,12
+       ;;
+       or r18=r17,r18
+#ifdef XEN
+       dep r2=-1,r3,60,4       // IMVA of task
+#else
+       dep r2=-1,r3,61,3       // IMVA of task
+#endif
+       ;;
+       mov r17=rr[r2]
+       shr.u r16=r3,IA64_GRANULE_SHIFT
+       ;;
+       dep r17=0,r17,8,24
+       ;;
+       mov cr.itir=r17
+       mov cr.ifa=r2
+
+       mov r19=IA64_TR_CURRENT_STACK
+       ;;
+       itr.d dtr[r19]=r18
+       ;;
+       ssm psr.ic
+       srlz.d
+       ;;
+
+.load_current:
+       // load the "current" pointer (r13) and ar.k6 with the current task
+#ifdef CONFIG_VTI
+       mov r21=r2              // virtual address
+       ;;
+       bsw.1
+       ;;
+#else // CONFIG_VTI
+       mov IA64_KR(CURRENT)=r2         // virtual address
+       mov IA64_KR(CURRENT_STACK)=r16
+#endif // CONFIG_VTI
+       mov r13=r2
+       /*
+        * Reserve space at the top of the stack for "struct pt_regs".  Kernel 
threads
+        * don't store interesting values in that structure, but the space 
still needs
+        * to be there because time-critical stuff such as the context 
switching can
+        * be implemented more efficiently (for example, __switch_to()
+        * always sets the psr.dfh bit of the task it is switching to).
+        */
+       addl r12=IA64_STK_OFFSET-IA64_PT_REGS_SIZE-16,r2
+       addl r2=IA64_RBS_OFFSET,r2      // initialize the RSE
+       mov ar.rsc=0            // place RSE in enforced lazy mode
+       ;;
+       loadrs                  // clear the dirty partition
+       ;;
+       mov ar.bspstore=r2      // establish the new RSE stack
+       ;;
+       mov ar.rsc=0x3          // place RSE in eager mode
+
+#ifdef XEN
+(isBP) dep r28=-1,r28,60,4     // make address virtual
+#else
+(isBP) dep r28=-1,r28,61,3     // make address virtual
+#endif
+(isBP) movl r2=ia64_boot_param
+       ;;
+(isBP) st8 [r2]=r28            // save the address of the boot param area 
passed by the bootloader
+
+#ifdef CONFIG_SMP
+(isAP) br.call.sptk.many rp=start_secondary
+.ret0:
+(isAP) br.cond.sptk self
+#endif
+
+       // This is executed by the bootstrap processor (bsp) only:
+
+#ifdef CONFIG_IA64_FW_EMU
+       // initialize PAL & SAL emulator:
+       br.call.sptk.many rp=sys_fw_init
+.ret1:
+#endif
+       br.call.sptk.many rp=start_kernel
+.ret2: addl r3=@ltoff(halt_msg),gp
+       ;;
+       alloc r2=ar.pfs,8,0,2,0
+       ;;
+       ld8 out0=[r3]
+       br.call.sptk.many b0=console_print
+
+self:  hint @pause
+       ;;
+       br.sptk.many self               // endless loop
+       ;;
+END(_start)
+
+GLOBAL_ENTRY(ia64_save_debug_regs)
+       alloc r16=ar.pfs,1,0,0,0
+       mov r20=ar.lc                   // preserve ar.lc
+       mov ar.lc=IA64_NUM_DBG_REGS-1
+       mov r18=0
+       add r19=IA64_NUM_DBG_REGS*8,in0
+       ;;
+1:     mov r16=dbr[r18]
+#ifdef CONFIG_ITANIUM
+       ;;
+       srlz.d
+#endif
+       mov r17=ibr[r18]
+       add r18=1,r18
+       ;;
+       st8.nta [in0]=r16,8
+       st8.nta [r19]=r17,8
+       br.cloop.sptk.many 1b
+       ;;
+       mov ar.lc=r20                   // restore ar.lc
+       br.ret.sptk.many rp
+END(ia64_save_debug_regs)
+
+GLOBAL_ENTRY(ia64_load_debug_regs)
+       alloc r16=ar.pfs,1,0,0,0
+       lfetch.nta [in0]
+       mov r20=ar.lc                   // preserve ar.lc
+       add r19=IA64_NUM_DBG_REGS*8,in0
+       mov ar.lc=IA64_NUM_DBG_REGS-1
+       mov r18=-1
+       ;;
+1:     ld8.nta r16=[in0],8
+       ld8.nta r17=[r19],8
+       add r18=1,r18
+       ;;
+       mov dbr[r18]=r16
+#ifdef CONFIG_ITANIUM
+       ;;
+       srlz.d                          // Errata 132 (NoFix status)
+#endif
+       mov ibr[r18]=r17
+       br.cloop.sptk.many 1b
+       ;;
+       mov ar.lc=r20                   // restore ar.lc
+       br.ret.sptk.many rp
+END(ia64_load_debug_regs)
+
+GLOBAL_ENTRY(__ia64_save_fpu)
+       alloc r2=ar.pfs,1,4,0,0
+