--- x/xen/arch/ia64/asm-offsets.c
+++ x/xen/arch/ia64/asm-offsets.c
@@ -203,6 +203,8 @@ void foo(void)
 
 	BLANK();
 	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET, offsetof (struct cpuinfo_ia64, nsec_per_cyc));
+	DEFINE(IA64_CPUINFO_PTCE_BASE_OFFSET, offsetof (struct cpuinfo_ia64, ptce_base));
+	DEFINE(IA64_CPUINFO_PTCE_COUNT_OFFSET, offsetof (struct cpuinfo_ia64, ptce_count));
 	DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
 
 
--- x/xen/arch/ia64/linux-xen/efi.c
+++ x/xen/arch/ia64/linux-xen/efi.c
@@ -300,8 +300,13 @@ efi_memmap_walk_uc (efi_freemem_callback
  * Abstraction Layer chapter 11 in ADAG
  */
 
+#ifdef XEN
+static void *
+__efi_get_pal_addr (void)
+#else
 void *
 efi_get_pal_addr (void)
+#endif
 {
 	void *efi_map_start, *efi_map_end, *p;
 	efi_memory_desc_t *md;
@@ -369,6 +374,14 @@ efi_get_pal_addr (void)
 
 #ifdef XEN
 void *pal_vaddr = 0;
+
+void *
+efi_get_pal_addr(void)
+{
+	if (pal_vaddr)
+		return pal_vaddr;
+	return pal_vaddr = __efi_get_pal_addr();
+}
 #endif
 
 void
@@ -376,9 +389,7 @@ efi_map_pal_code (void)
 {
 #ifdef XEN
 	u64 psr;
-	if (!pal_vaddr) {
-		pal_vaddr = efi_get_pal_addr ();
-	}
+	efi_get_pal_addr();
 #else
 	void *pal_vaddr = efi_get_pal_addr ();
 	u64 psr;
@@ -952,3 +963,49 @@ efi_memmap_init(unsigned long *s, unsign
 	*s = (u64)kern_memmap;
 	*e = (u64)++k;
 }
+
+#ifdef XEN
+/* find a block of memory aligned to 64M exclude reserved regions
+ * rsvd_regions are sorted
+ */
+unsigned long
+kdump_find_rsvd_region(unsigned long size, struct rsvd_region *r, int n)
+{
+	int i;
+	u64 start, end;
+	u64 alignment = 1UL << _PAGE_SIZE_64M;
+	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 (!efi_wb(md))
+			continue;
+		start = ALIGN(md->phys_addr, alignment);
+		end = efi_md_end(md);
+		for (i = 0; i < n; i++) {
+			if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
+				if (__pa(r[i].start) > start + size)
+					return start;
+				start = ALIGN(__pa(r[i].end), alignment);
+				if (i < n - 1
+				    && __pa(r[i + 1].start) < start + size)
+					continue;
+				else
+					break;
+			}
+		}
+		if (end > start + size)
+			return start;
+	}
+
+	printk(KERN_WARNING
+	       "Cannot reserve 0x%lx byte of memory for crashdump\n", size);
+	return ~0UL;
+}
+#endif
--- x/xen/arch/ia64/linux-xen/setup.c
+++ x/xen/arch/ia64/linux-xen/setup.c
@@ -64,6 +64,9 @@
 #ifdef XEN
 #include <asm/vmx.h>
 #include <asm/io.h>
+#include <asm/kexec.h>
+#include <public/kexec.h>
+#include <xen/kexec.h>
 #endif
 
 #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
@@ -252,6 +255,39 @@ reserve_memory (void)
 	efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
 	n++;
 
+#ifdef XEN
+	/* crashkernel=size@offset specifies the size to reserve for a crash
+	 * kernel. If offset is 0, then it is determined automatically.
+	 * By reserving this memory we guarantee that linux never set's it
+	 * up as a DMA target. Useful for holding code to do something
+	 * appropriate after a kernel panic.
+	 */
+	if (kexec_crash_area.size > 0) {
+		if (!kexec_crash_area.start) {
+			sort_regions(rsvd_region, n);
+			kexec_crash_area.start = 
+				kdump_find_rsvd_region(kexec_crash_area.size,
+						       rsvd_region, n);
+		}
+		if (kexec_crash_area.start != ~0UL) {
+			printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+			       kexec_crash_area.size >> 20,
+			       kexec_crash_area.size >> 10,
+			       kexec_crash_area.start);
+			rsvd_region[n].start =
+				(unsigned long)__va(kexec_crash_area.start);
+			rsvd_region[n].end =
+				(unsigned long)__va(kexec_crash_area.start +
+				   		    kexec_crash_area.size);
+			n++;
+		}
+		else {
+			kexec_crash_area.size = 0;
+			kexec_crash_area.start = 0;
+		}
+	}
+#endif
+
 	/* end of memory marker */
 	rsvd_region[n].start = ~0UL;
 	rsvd_region[n].end   = ~0UL;
--- x/xen/arch/ia64/vmx/vmx_vcpu.c
+++ x/xen/arch/ia64/vmx/vmx_vcpu.c
@@ -66,6 +66,7 @@
 #include <asm/hw_irq.h>
 #include <asm/vmx_pal_vsa.h>
 #include <asm/kregs.h>
+#include <linux/efi.h>
 //unsigned long last_guest_rsm = 0x0;
 
 #ifdef	VTI_DEBUG
@@ -211,7 +212,6 @@ vmx_vcpu_get_plat(VCPU *vcpu)
 IA64FAULT vmx_vcpu_set_rr(VCPU *vcpu, u64 reg, u64 val)
 {
     ia64_rr oldrr,newrr;
-    extern void * pal_vaddr;
     u64 rrval;
 
     vcpu_get_rr(vcpu, reg, &oldrr.rrval);
--- x/xen/arch/ia64/xen/Makefile
+++ x/xen/arch/ia64/xen/Makefile
@@ -1,5 +1,6 @@
 subdir-y += oprofile
 
+obj-y += relocate_kernel.o
 obj-y += machine_kexec.o
 obj-y += crash.o
 obj-y += acpi.o
--- x/xen/arch/ia64/xen/crash.c
+++ x/xen/arch/ia64/xen/crash.c
@@ -1,10 +1,33 @@
-#include <xen/lib.h>       /* for printk() used in stub */
-#include <xen/types.h>
-#include <public/kexec.h>
+/******************************************************************************
+ * crash.c
+ *
+ * Based heavily on arch/ia64/kernel/crash.c from Linux 2.6.20-rc1
+ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@verge.net.au>
+ * - Magnus Damm <magnus@valinux.co.jp>
+ */
+
+#include <xen/types.h>         /* Should be included by xen/kexec.h ? */
+#include <linux/thread_info.h> /* Should be included by linux/preempt.h ? */
+
+#include <xen/kexec.h>
+#include <linux/hardirq.h>
+#include <linux/smp.h>
+#include <asm/processor.h>
 
 void machine_crash_shutdown(void)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+    //printk("machine_crash_shutdown: %d\n", smp_processor_id());
+    if (in_interrupt())
+        ia64_eoi();
+    kexec_crash_save_info();
+    printk(__FILE__ ": %s: save the eqivalent of x86's "
+           "dom0->shared_info->arch.pfn_to_mfn_frame_list_list?\n",
+           __FUNCTION__);
+#ifdef CONFIG_SMP
+    smp_send_stop();
+#endif
 }
 
 /*
--- x/xen/arch/ia64/xen/hypercall.c
+++ x/xen/arch/ia64/xen/hypercall.c
@@ -74,7 +74,7 @@ const hypercall_t ia64_hypercall_table[N
 	(hypercall_t)do_hvm_op,			/*  */
 	(hypercall_t)do_sysctl,			/*  */                  /* 35 */
 	(hypercall_t)do_domctl,			/*  */
-	(hypercall_t)do_ni_hypercall,		/*  */
+	(hypercall_t)do_kexec_op,		/*  */
 	(hypercall_t)do_ni_hypercall,		/*  */
 	(hypercall_t)do_ni_hypercall,		/*  */
 	(hypercall_t)do_ni_hypercall,		/*  */                 /* 40 */
--- x/xen/arch/ia64/xen/machine_kexec.c
+++ x/xen/arch/ia64/xen/machine_kexec.c
@@ -1,26 +1,127 @@
-#include <xen/lib.h>       /* for printk() used in stubs */
+/******************************************************************************
+ * machine_kexec.c
+ *
+ * Based on arch/ia64/kernel/machine_kexec.c from Linux 2.6.20-rc1
+ *
+ * Xen port written by:
+ * - Simon 'Horms' Horman <horms@verge.net.au>
+ * - Magnus Damm <magnus@valinux.co.jp>
+ */
+
+#include <asm/smp.h>
+#include <xen/lib.h>
 #include <xen/types.h>
+#include <xen/smp.h>
 #include <public/kexec.h>
+#include <linux/efi.h>
+#include <asm/delay.h>
+#include <asm/meminit.h>
+#include <asm/hw_irq.h>
+#include <asm/kexec.h>
+
+typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
+                                        unsigned long indirection_page,
+					unsigned long start_address,
+					unsigned long boot_param,
+					unsigned long pal_addr,
+					unsigned long cpu_data_pa) ATTRIB_NORET;
+	  
+#define kexec_flush_icache_page(page) 					\
+do {									\
+	unsigned long page_addr = (unsigned long)page_address(page);	\
+	flush_icache_range(page_addr, page_addr + PAGE_SIZE);		\
+} while(0)
 
 int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
-    return -1;
+    unsigned long code_addr = (unsigned long)__va(image->reboot_code_buffer);
+    const unsigned long *func;
+
+    func = (unsigned long *)&relocate_new_kernel;
+
+    /* XXX: code_addr may not be big enough ! */
+    memcpy((void *)code_addr, (const void *)*func, relocate_new_kernel_size);
+    flush_icache_range(code_addr, code_addr + relocate_new_kernel_size);
+    return 0;
 }
 
 void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+}
+
+/*
+ * boot_param is used inside purgatory and purgatory runs
+ * in physical mode, so translate the addresses that purgatory
+ * accesses from virtual to physical.
+ */
+static unsigned long machine_kexec_prepare_boot_param (void)
+{
+	efi_system_table_t *systab;
+
+	systab = (efi_system_table_t *)__va(ia64_boot_param->efi_systab);
+
+	if ((unsigned long)systab->runtime > PAGE_OFFSET) {
+		systab->runtime->set_virtual_address_map =
+				__pa(systab->runtime->set_virtual_address_map);
+		systab->runtime = (efi_runtime_services_t *)
+				__pa(systab->runtime);
+	}
+
+	return __pa(ia64_boot_param);
+}
+
+static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
+{
+    xen_kexec_image_t *image = arg;
+    relocate_new_kernel_t rnk;
+    unsigned long code_addr = (unsigned long)__va(image->reboot_code_buffer);
+    unsigned long cpu_data_pa = (unsigned long)
+				__pa(cpu_data(smp_processor_id()));
+    unsigned long vector;
+    int ii;
+
+    /* Interrupts aren't acceptable while we reboot */
+    local_irq_disable();
+
+    /* Mask CMC and Performance Monitor interrupts */
+    ia64_setreg(_IA64_REG_CR_PMV, 1 << 16);
+    ia64_setreg(_IA64_REG_CR_CMCV, 1 << 16);
+
+    /* Mask ITV and Local Redirect Registers */
+    ia64_set_itv(1 << 16);
+    ia64_set_lrr0(1 << 16);
+    ia64_set_lrr1(1 << 16);
+
+    /* terminate possible nested in-service interrupts */
+    for (ii = 0; ii < 16; ii++)
+        ia64_eoi();
+
+    /* unmask TPR and clear any pending interrupts */
+    ia64_setreg(_IA64_REG_CR_TPR, 0);
+    ia64_srlz_d();
+    vector = ia64_get_ivr();
+    while (vector != IA64_SPURIOUS_INT_VECTOR) {
+        ia64_eoi();
+        vector = ia64_get_ivr();
+    }
+    platform_kernel_launch_event();
+    rnk = (relocate_new_kernel_t)&code_addr;
+    (*rnk)(image->indirection_page, image->start_address,
+    	   machine_kexec_prepare_boot_param(),
+           GRANULEROUNDDOWN((unsigned long) pal_vaddr), cpu_data_pa);
+    BUG();
 }
 
 void machine_kexec(xen_kexec_image_t *image)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+	unw_init_running(ia64_machine_kexec, image);
+	for(;;);
+	ia64_machine_kexec(NULL, image);
 }
 
 void machine_reboot_kexec(xen_kexec_image_t *image)
 {
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
+    machine_kexec(image);
 }
 
 /*
--- /dev/null
+++ x/xen/arch/ia64/xen/relocate_kernel.S
@@ -0,0 +1,353 @@
+/*
+ * arch/ia64/kernel/relocate_kernel.S
+ *
+ * Relocate kexec'able kernel and start it
+ *
+ * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2005 Khalid Aziz  <khalid.aziz@hp.com>
+ * Copyright (C) 2005 Intel Corp,  Zou Nan hai <nanhai.zou@intel.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+#include <asm/asmmacro.h>
+#include <asm/kregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/mca_asm.h>
+
+       /* Must be relocatable PIC code callable as a C function
+        */
+GLOBAL_ENTRY(relocate_new_kernel)
+	.prologue
+#if XEN
+	alloc r31=ar.pfs,5,0,0,0
+#else
+	alloc r31=ar.pfs,4,0,0,0
+#endif
+        .body
+.reloc_entry:
+{
+	rsm psr.i| psr.ic
+	mov r2=ip
+}
+	;;
+{
+        flushrs                         // must be first insn in group
+        srlz.i
+}
+	;;
+#if XEN
+	dep r2=0,r2,60,4		//to physical address
+#else
+	dep r2=0,r2,61,3		//to physical address
+#endif
+	;;
+	//first switch to physical mode
+	add r3=1f-.reloc_entry, r2
+	movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
+	mov ar.rsc=0	          	// put RSE in enforced lazy mode
+	;;
+	add sp=(memory_stack_end - 16 - .reloc_entry),r2
+	add r8=(register_stack - .reloc_entry),r2
+	;;
+	mov r18=ar.rnat
+	mov ar.bspstore=r8
+	;;
+        mov cr.ipsr=r16
+        mov cr.iip=r3
+        mov cr.ifs=r0
+	srlz.i
+	;;
+	mov ar.rnat=r18
+	rfi
+	;;
+1:
+	//physical mode code begin
+	mov b6=in1
+#if XEN
+	dep r28=0,in2,60,4	//to physical address
+#else
+	dep r28=0,in2,61,3	//to physical address
+#endif
+
+	// purge all TC entries
+#define O(member)       IA64_CPUINFO_##member##_OFFSET
+#if XEN
+	mov r2=in4			// load phys addr of cpu_info into r2
+#else
+        GET_THIS_PADDR(r2, cpu_info)    // load phys addr of cpu_info into r2
+#endif
+        ;;
+        addl r17=O(PTCE_STRIDE),r2
+        addl r2=O(PTCE_BASE),r2
+        ;;
+        ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));;    	// r18=ptce_base
+        ld4 r19=[r2],4                                  // r19=ptce_count[0]
+        ld4 r21=[r17],4                                 // r21=ptce_stride[0]
+        ;;
+        ld4 r20=[r2]                                    // r20=ptce_count[1]
+        ld4 r22=[r17]                                   // r22=ptce_stride[1]
+        ;;
+        adds r20=-1,r20
+        ;;
+#undef O
+2:
+        cmp.ltu p6,p7=r24,r19
+(p7)    br.cond.dpnt.few 4f
+        mov ar.lc=r20
+3:
+        ptc.e r18
+        ;;
+        add r18=r22,r18
+        br.cloop.sptk.few 3b
+        ;;
+        add r18=r21,r18
+        add r24=1,r24
+        ;;
+        br.sptk.few 2b
+4:
+        srlz.i
+        ;;
+#if XEN
+	srlz.d
+	;;
+#endif
+	//purge TR entry for kernel text and data
+        movl r16=KERNEL_START
+        mov r18=KERNEL_TR_PAGE_SHIFT<<2
+        ;;
+        ptr.i r16, r18
+        ptr.d r16, r18
+        ;;
+        srlz.i
+        ;;
+
+	// purge TR entry for percpu data
+        movl r16=PERCPU_ADDR
+        mov r18=PERCPU_PAGE_SHIFT<<2
+        ;;
+        ptr.d r16,r18
+        ;;
+        srlz.d
+	;;
+
+        // purge TR entry for pal code
+        mov r16=in3
+        mov r18=IA64_GRANULE_SHIFT<<2
+        ;;
+        ptr.i r16,r18
+        ;;
+        srlz.i
+	;;
+
+        // purge TR entry for stack
+        mov r16=IA64_KR(CURRENT_STACK)
+        ;;
+        shl r16=r16,IA64_GRANULE_SHIFT
+        movl r19=PAGE_OFFSET
+        ;;
+        add r16=r19,r16
+        mov r18=IA64_GRANULE_SHIFT<<2
+        ;;
+        ptr.d r16,r18
+        ;;
+        srlz.i
+	;;
+
+	//copy segments
+	movl r16=PAGE_MASK
+        mov  r30=in0                    // in0 is page_list
+        br.sptk.few .dest_page
+	;;
+.loop:
+	ld8  r30=[in0], 8;;
+.dest_page:
+	tbit.z p0, p6=r30, 0;;    	// 0x1 dest page
+(p6)	and r17=r30, r16
+(p6)	br.cond.sptk.few .loop;;
+
+	tbit.z p0, p6=r30, 1;;		// 0x2 indirect page
+(p6)	and in0=r30, r16
+(p6)	br.cond.sptk.few .loop;;
+
+	tbit.z p0, p6=r30, 2;;		// 0x4 end flag
+(p6)	br.cond.sptk.few .end_loop;;
+
+	tbit.z p6, p0=r30, 3;;		// 0x8 source page
+(p6)	br.cond.sptk.few .loop
+
+	and r18=r30, r16
+
+	// simple copy page, may optimize later
+	movl r14=PAGE_SIZE/8 - 1;;
+	mov ar.lc=r14;;
+1:
+	ld8 r14=[r18], 8;;
+	st8 [r17]=r14;;
+	fc.i r17
+	add r17=8, r17
+	br.ctop.sptk.few 1b
+	br.sptk.few .loop
+	;;
+
+.end_loop:
+	sync.i			// for fc.i
+	;;
+	srlz.i
+	;;
+	srlz.d
+	;;
+	br.call.sptk.many b0=b6;;
+
+.align  32
+memory_stack:
+	.fill           8192, 1, 0
+memory_stack_end:
+register_stack:
+	.fill           8192, 1, 0
+register_stack_end:
+relocate_new_kernel_end:
+END(relocate_new_kernel)
+
+.global relocate_new_kernel_size
+relocate_new_kernel_size:
+	data8	relocate_new_kernel_end - relocate_new_kernel
+
+GLOBAL_ENTRY(ia64_dump_cpu_regs)
+        .prologue
+        alloc loc0=ar.pfs,1,2,0,0
+        .body
+        mov     ar.rsc=0                // put RSE in enforced lazy mode
+        add     loc1=4*8, in0           // save r4 and r5 first
+        ;;
+{
+        flushrs                         // flush dirty regs to backing store
+        srlz.i
+}
+        st8 [loc1]=r4, 8
+        ;;
+        st8 [loc1]=r5, 8
+        ;;
+        add loc1=32*8, in0
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r0, 8			// r0
+        st8 [loc1]=r4, 8		// rnat
+        mov r5=pr
+        ;;
+        st8 [in0]=r1, 8			// r1
+        st8 [loc1]=r5, 8		// pr
+        mov r4=b0
+        ;;
+        st8 [in0]=r2, 8			// r2
+        st8 [loc1]=r4, 8		// b0
+        mov r5=b1;
+        ;;
+        st8 [in0]=r3, 24		// r3
+        st8 [loc1]=r5, 8		// b1
+        mov r4=b2
+        ;;
+        st8 [in0]=r6, 8			// r6
+        st8 [loc1]=r4, 8		// b2
+	mov r5=b3
+        ;;
+        st8 [in0]=r7, 8			// r7
+        st8 [loc1]=r5, 8		// b3
+        mov r4=b4
+        ;;
+        st8 [in0]=r8, 8			// r8
+        st8 [loc1]=r4, 8		// b4
+        mov r5=b5
+        ;;
+        st8 [in0]=r9, 8			// r9
+        st8 [loc1]=r5, 8		// b5
+        mov r4=b6
+        ;;
+        st8 [in0]=r10, 8		// r10
+        st8 [loc1]=r5, 8		// b6
+        mov r5=b7
+        ;;
+        st8 [in0]=r11, 8		// r11
+        st8 [loc1]=r5, 8		// b7
+        mov r4=b0
+        ;;
+        st8 [in0]=r12, 8		// r12
+        st8 [loc1]=r4, 8		// ip
+        mov r5=loc0
+	;;
+        st8 [in0]=r13, 8		// r13
+        extr.u r5=r5, 0, 38		// ar.pfs.pfm
+	mov r4=r0			// user mask
+        ;;
+        st8 [in0]=r14, 8		// r14
+        st8 [loc1]=r5, 8		// cfm
+        ;;
+        st8 [in0]=r15, 8		// r15
+        st8 [loc1]=r4, 8        	// user mask
+	mov r5=ar.rsc
+        ;;
+        st8 [in0]=r16, 8		// r16
+        st8 [loc1]=r5, 8        	// ar.rsc
+        mov r4=ar.bsp
+        ;;
+        st8 [in0]=r17, 8		// r17
+        st8 [loc1]=r4, 8        	// ar.bsp
+        mov r5=ar.bspstore
+        ;;
+        st8 [in0]=r18, 8		// r18
+        st8 [loc1]=r5, 8        	// ar.bspstore
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r19, 8		// r19
+        st8 [loc1]=r4, 8        	// ar.rnat
+        mov r5=ar.ccv
+        ;;
+        st8 [in0]=r20, 8		// r20
+	st8 [loc1]=r5, 8        	// ar.ccv
+        mov r4=ar.unat
+        ;;
+        st8 [in0]=r21, 8		// r21
+        st8 [loc1]=r4, 8        	// ar.unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r22, 8		// r22
+        st8 [loc1]=r5, 8        	// ar.fpsr
+        mov r4 = ar.unat
+        ;;
+        st8 [in0]=r23, 8		// r23
+        st8 [loc1]=r4, 8        	// unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r24, 8		// r24
+        st8 [loc1]=r5, 8        	// fpsr
+        mov r4 = ar.pfs
+        ;;
+        st8 [in0]=r25, 8		// r25
+        st8 [loc1]=r4, 8        	// ar.pfs
+        mov r5 = ar.lc
+        ;;
+        st8 [in0]=r26, 8		// r26
+        st8 [loc1]=r5, 8        	// ar.lc
+        mov r4 = ar.ec
+        ;;
+        st8 [in0]=r27, 8		// r27
+        st8 [loc1]=r4, 8        	// ar.ec
+        mov r5 = ar.csd
+        ;;
+        st8 [in0]=r28, 8		// r28
+        st8 [loc1]=r5, 8        	// ar.csd
+        mov r4 = ar.ssd
+        ;;
+        st8 [in0]=r29, 8		// r29
+        st8 [loc1]=r4, 8        	// ar.ssd
+        ;;
+        st8 [in0]=r30, 8		// r30
+        ;;
+	st8 [in0]=r31, 8		// r31
+        mov ar.pfs=loc0
+        ;;
+        br.ret.sptk.many rp
+END(ia64_dump_cpu_regs)
+
+
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -486,6 +486,10 @@ void __init __start_xen(multiboot_info_t
 #endif
     }
 
+    if (!kexec_crash_area.size || !kexec_crash_area.start) {
+        kexec_crash_area.start = 0;
+        kexec_crash_area.size = 0;
+    }
     if ( kexec_crash_area.size > 0 )
     {
         unsigned long kdump_start, kdump_size, k;
--- x/xen/common/kexec.c
+++ x/xen/common/kexec.c
@@ -53,17 +53,9 @@ static void __init parse_crashkernel(con
 {
     unsigned long start, size;
 
-    size = parse_size_and_unit(str, &str);
+    kexec_crash_area.size = parse_size_and_unit(str, &str);
     if ( *str == '@' )
-        start = parse_size_and_unit(str+1, NULL);
-    else
-        start = 0;
-
-    if ( start && size )
-    {
-        kexec_crash_area.start = start;
-        kexec_crash_area.size = size;
-    }
+        kexec_crash_area.start = parse_size_and_unit(str+1, NULL);
 }
 custom_param("crashkernel", parse_crashkernel);
 
--- x/xen/include/asm-ia64/elf.h
+++ x/xen/include/asm-ia64/elf.h
@@ -4,7 +4,20 @@
 #include <xen/lib.h>       /* for printk() used in stub */
 
 typedef struct {
-    unsigned long dummy;
+    unsigned long r1;
+    unsigned long r2;
+    unsigned long r13;
+    unsigned long cr_iip;
+    unsigned long ar_rsc;
+    unsigned long r30;
+    unsigned long ar_bspstore;
+    unsigned long ar_rnat;
+    unsigned long ar_ccv;
+    unsigned long ar_unat;
+    unsigned long ar_pfs;
+    unsigned long r31;
+    unsigned long ar_csd;
+    unsigned long ar_ssd;
 } ELF_Gregset;
 
 typedef struct {
--- x/xen/include/asm-ia64/kexec.h
+++ x/xen/include/asm-ia64/kexec.h
@@ -1,15 +1,16 @@
 #ifndef __IA64_KEXEC_H__
 #define __IA64_KEXEC_H__
 
-#include <xen/lib.h>       /* for printk() used in stub */
 #include <xen/types.h>
-#include <public/xen.h>
 #include <xen/kexec.h>
 
-static inline void machine_kexec(xen_kexec_image_t *image)
-{
-    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
-}
+extern const unsigned int relocate_new_kernel_size;
+extern void relocate_new_kernel(unsigned long, unsigned long,
+                                struct ia64_boot_param *, unsigned long);
+void crash_save_xen_notes(void);
+void machine_kexec(xen_kexec_image_t *image);
+unsigned long kdump_find_rsvd_region(unsigned long size,
+				     struct rsvd_region *rsvd_regions, int n);
 
 #endif /* __IA64_KEXEC_H__ */
 
--- x/xen/include/asm-ia64/linux-xen/asm/machvec.h
+++ x/xen/include/asm-ia64/linux-xen/asm/machvec.h
@@ -34,6 +34,7 @@ typedef int ia64_mv_pci_legacy_read_t (s
 				       u8 size);
 typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
 					u8 size);
+typedef void ia64_mv_kernel_launch_event_t(void);
 
 /* DMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
@@ -302,6 +303,7 @@ struct ia64_machine_vector {
 	ia64_mv_readw_relaxed_t *readw_relaxed;
 	ia64_mv_readl_relaxed_t *readl_relaxed;
 	ia64_mv_readq_relaxed_t *readq_relaxed;
+	ia64_mv_kernel_launch_event_t *kernel_launch_event;
 } __attribute__((__aligned__(16))); /* align attrib? see above comment */
 
 #define MACHVEC_INIT(name)			\
@@ -398,6 +400,9 @@ extern ia64_mv_dma_supported		swiotlb_dm
 #ifndef platform_tlb_migrate_finish
 # define platform_tlb_migrate_finish	machvec_noop_mm
 #endif
+#ifndef platform_kernel_launch_event
+# define platform_kernel_launch_event	machvec_noop
+#endif
 #ifndef platform_dma_init
 # define platform_dma_init		swiotlb_init
 #endif
--- x/xen/include/asm-ia64/linux-xen/linux/efi.h
+++ x/xen/include/asm-ia64/linux-xen/linux/efi.h
@@ -22,6 +22,10 @@
 #include <asm/page.h>
 #include <asm/system.h>
 
+#ifdef XEN
+extern void * pal_vaddr;
+#endif
+
 #define EFI_SUCCESS		0
 #define EFI_LOAD_ERROR          ( 1 | (1UL << (BITS_PER_LONG-1)))
 #define EFI_INVALID_PARAMETER	( 2 | (1UL << (BITS_PER_LONG-1)))
--- x/xen/include/public/kexec.h
+++ x/xen/include/public/kexec.h
@@ -79,6 +79,9 @@ typedef struct xen_kexec_image {
 #if defined(__i386__) || defined(__x86_64__)
     unsigned long page_list[KEXEC_XEN_NO_PAGES];
 #endif
+#if defined(__ia64__)
+    unsigned long reboot_code_buffer;
+#endif
     unsigned long indirection_page;
     unsigned long start_address;
 } xen_kexec_image_t;
