ia64/xen-unstable

changeset 12679:a1a04c48da6c

[XEN] Kexec / Kdump: x86_64 specific code

This patch contains the x86_64 implementation of Kexec / Kdump for Xen.

Signed-Off-By: Magnus Damm <magnus@valinux.co.jp>
Signed-Off-By: Simon Horman <horms@verge.net.au>
author Ian Campbell <ian.campbell@xensource.com>
date Thu Nov 30 12:38:51 2006 +0000 (2006-11-30)
parents 5690d18637f5
children aa08fbbf1243
files buildconfigs/linux-defconfig_xen_x86_64 linux-2.6-xen-sparse/arch/x86_64/Kconfig linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch patches/linux-2.6.16.33/series xen/arch/x86/x86_64/entry.S xen/include/asm-x86/x86_64/elf.h xen/include/asm-x86/x86_64/kexec.h
line diff
     1.1 --- a/buildconfigs/linux-defconfig_xen_x86_64	Thu Nov 30 12:38:51 2006 +0000
     1.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64	Thu Nov 30 12:38:51 2006 +0000
     1.3 @@ -139,6 +139,7 @@ CONFIG_SWIOTLB=y
     1.4  CONFIG_PHYSICAL_START=0x100000
     1.5  CONFIG_SECCOMP=y
     1.6  CONFIG_HZ_100=y
     1.7 +CONFIG_KEXEC=y
     1.8  # CONFIG_HZ_250 is not set
     1.9  # CONFIG_HZ_1000 is not set
    1.10  CONFIG_HZ=100
     2.1 --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Thu Nov 30 12:38:51 2006 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Thu Nov 30 12:38:51 2006 +0000
     2.3 @@ -435,7 +435,7 @@ config X86_MCE_AMD
     2.4  
     2.5  config KEXEC
     2.6  	bool "kexec system call (EXPERIMENTAL)"
     2.7 -	depends on EXPERIMENTAL && !X86_64_XEN
     2.8 +	depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST
     2.9  	help
    2.10  	  kexec is a system call that implements the ability to shutdown your
    2.11  	  current kernel, and to start another kernel.  It is like a reboot
     3.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c	Thu Nov 30 12:38:51 2006 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/e820-xen.c	Thu Nov 30 12:38:51 2006 +0000
     3.3 @@ -260,7 +260,11 @@ void __init e820_reserve_resources(struc
     3.4  			request_resource(res, &data_resource);
     3.5  #endif
     3.6  #ifdef CONFIG_KEXEC
     3.7 -			request_resource(res, &crashk_res);
     3.8 +			if (crashk_res.start != crashk_res.end)
     3.9 +				request_resource(res, &crashk_res);
    3.10 +#ifdef CONFIG_XEN
    3.11 +			xen_machine_kexec_register_resources(res);
    3.12 +#endif
    3.13  #endif
    3.14  		}
    3.15  	}
     4.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Thu Nov 30 12:38:51 2006 +0000
     4.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Thu Nov 30 12:38:51 2006 +0000
     4.3 @@ -80,6 +80,10 @@
     4.4  #include <asm/mach-xen/setup_arch_post.h>
     4.5  #include <xen/interface/memory.h>
     4.6  
     4.7 +#ifdef CONFIG_XEN
     4.8 +#include <xen/interface/kexec.h>
     4.9 +#endif
    4.10 +
    4.11  extern unsigned long start_pfn;
    4.12  extern struct edid_info edid_info;
    4.13  
    4.14 @@ -450,6 +454,7 @@ static __init void parse_cmdline_early (
    4.15  		 * after a kernel panic.
    4.16  		 */
    4.17  		else if (!memcmp(from, "crashkernel=", 12)) {
    4.18 +#ifndef CONFIG_XEN
    4.19  			unsigned long size, base;
    4.20  			size = memparse(from+12, &from);
    4.21  			if (*from == '@') {
    4.22 @@ -460,6 +465,10 @@ static __init void parse_cmdline_early (
    4.23  				crashk_res.start = base;
    4.24  				crashk_res.end   = base + size - 1;
    4.25  			}
    4.26 +#else
    4.27 +			printk("Ignoring crashkernel command line, "
    4.28 +			       "parameter will be supplied by xen\n");
    4.29 +#endif
    4.30  		}
    4.31  #endif
    4.32  
    4.33 @@ -812,11 +821,15 @@ void __init setup_arch(char **cmdline_p)
    4.34  #endif
    4.35  #endif	/* !CONFIG_XEN */
    4.36  #ifdef CONFIG_KEXEC
    4.37 +#ifdef CONFIG_XEN
    4.38 +	xen_machine_kexec_setup_resources();
    4.39 +#else
    4.40  	if (crashk_res.start != crashk_res.end) {
    4.41  		reserve_bootmem(crashk_res.start,
    4.42  			crashk_res.end - crashk_res.start + 1);
    4.43  	}
    4.44  #endif
    4.45 +#endif
    4.46  
    4.47  	paging_init();
    4.48  #ifdef CONFIG_X86_LOCAL_APIC
     5.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Thu Nov 30 12:38:51 2006 +0000
     5.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Thu Nov 30 12:38:51 2006 +0000
     5.3 @@ -396,4 +396,11 @@ HYPERVISOR_xenoprof_op(
     5.4  	return _hypercall2(int, xenoprof_op, op, arg);
     5.5  }
     5.6  
     5.7 +static inline int
     5.8 +HYPERVISOR_kexec_op(
     5.9 +	unsigned long op, void *args)
    5.10 +{
    5.11 +	return _hypercall2(int, kexec_op, op, args);
    5.12 +}
    5.13 +
    5.14  #endif /* __HYPERCALL_H__ */
     6.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h	Thu Nov 30 12:38:51 2006 +0000
     6.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h	Thu Nov 30 12:38:51 2006 +0000
     6.3 @@ -90,6 +90,8 @@ extern unsigned long profile_pc(struct p
     6.4  #define profile_pc(regs) instruction_pointer(regs)
     6.5  #endif
     6.6  
     6.7 +#include <linux/compiler.h>
     6.8 +
     6.9  void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
    6.10  
    6.11  struct task_struct;
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch	Thu Nov 30 12:38:51 2006 +0000
     7.3 @@ -0,0 +1,375 @@
     7.4 +From: Magnus Damm <magnus@valinux.co.jp>
     7.5 +Date: Tue, 26 Sep 2006 08:52:38 +0000 (+0200)
     7.6 +Subject: [PATCH] Avoid overwriting the current pgd (V4, x86_64)
     7.7 +X-Git-Tag: v2.6.19-rc1
     7.8 +X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f
     7.9 +
    7.10 +[PATCH] Avoid overwriting the current pgd (V4, x86_64)
    7.11 +
    7.12 +kexec: Avoid overwriting the current pgd (V4, x86_64)
    7.13 +
    7.14 +This patch upgrades the x86_64-specific kexec code to avoid overwriting the
    7.15 +current pgd. Overwriting the current pgd is bad when CONFIG_CRASH_DUMP is used
    7.16 +to start a secondary kernel that dumps the memory of the previous kernel.
    7.17 +
    7.18 +The code introduces a new set of page tables. These tables are used to provide
    7.19 +an executable identity mapping without overwriting the current pgd.
    7.20 +
    7.21 +Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
    7.22 +Signed-off-by: Andi Kleen <ak@suse.de>
    7.23 +---
    7.24 +
    7.25 +--- a/arch/x86_64/kernel/machine_kexec.c
    7.26 ++++ b/arch/x86_64/kernel/machine_kexec.c
    7.27 +@@ -15,6 +15,15 @@
    7.28 + #include <asm/mmu_context.h>
    7.29 + #include <asm/io.h>
    7.30 + 
    7.31 ++#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
    7.32 ++static u64 kexec_pgd[512] PAGE_ALIGNED;
    7.33 ++static u64 kexec_pud0[512] PAGE_ALIGNED;
    7.34 ++static u64 kexec_pmd0[512] PAGE_ALIGNED;
    7.35 ++static u64 kexec_pte0[512] PAGE_ALIGNED;
    7.36 ++static u64 kexec_pud1[512] PAGE_ALIGNED;
    7.37 ++static u64 kexec_pmd1[512] PAGE_ALIGNED;
    7.38 ++static u64 kexec_pte1[512] PAGE_ALIGNED;
    7.39 ++
    7.40 + static void init_level2_page(pmd_t *level2p, unsigned long addr)
    7.41 + {
    7.42 + 	unsigned long end_addr;
    7.43 +@@ -144,32 +153,19 @@ static void load_segments(void)
    7.44 + 		);
    7.45 + }
    7.46 + 
    7.47 +-typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page,
    7.48 +-					unsigned long control_code_buffer,
    7.49 +-					unsigned long start_address,
    7.50 +-					unsigned long pgtable) ATTRIB_NORET;
    7.51 +-
    7.52 +-extern const unsigned char relocate_new_kernel[];
    7.53 +-extern const unsigned long relocate_new_kernel_size;
    7.54 +-
    7.55 + int machine_kexec_prepare(struct kimage *image)
    7.56 + {
    7.57 +-	unsigned long start_pgtable, control_code_buffer;
    7.58 ++	unsigned long start_pgtable;
    7.59 + 	int result;
    7.60 + 
    7.61 + 	/* Calculate the offsets */
    7.62 + 	start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
    7.63 +-	control_code_buffer = start_pgtable + PAGE_SIZE;
    7.64 + 
    7.65 + 	/* Setup the identity mapped 64bit page table */
    7.66 + 	result = init_pgtable(image, start_pgtable);
    7.67 + 	if (result)
    7.68 + 		return result;
    7.69 + 
    7.70 +-	/* Place the code in the reboot code buffer */
    7.71 +-	memcpy(__va(control_code_buffer), relocate_new_kernel,
    7.72 +-						relocate_new_kernel_size);
    7.73 +-
    7.74 + 	return 0;
    7.75 + }
    7.76 + 
    7.77 +@@ -184,28 +180,34 @@ void machine_kexec_cleanup(struct kimage
    7.78 +  */
    7.79 + NORET_TYPE void machine_kexec(struct kimage *image)
    7.80 + {
    7.81 +-	unsigned long page_list;
    7.82 +-	unsigned long control_code_buffer;
    7.83 +-	unsigned long start_pgtable;
    7.84 +-	relocate_new_kernel_t rnk;
    7.85 ++	unsigned long page_list[PAGES_NR];
    7.86 ++	void *control_page;
    7.87 + 
    7.88 + 	/* Interrupts aren't acceptable while we reboot */
    7.89 + 	local_irq_disable();
    7.90 + 
    7.91 +-	/* Calculate the offsets */
    7.92 +-	page_list = image->head;
    7.93 +-	start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
    7.94 +-	control_code_buffer = start_pgtable + PAGE_SIZE;
    7.95 ++	control_page = page_address(image->control_code_page) + PAGE_SIZE;
    7.96 ++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
    7.97 + 
    7.98 +-	/* Set the low half of the page table to my identity mapped
    7.99 +-	 * page table for kexec.  Leave the high half pointing at the
   7.100 +-	 * kernel pages.   Don't bother to flush the global pages
   7.101 +-	 * as that will happen when I fully switch to my identity mapped
   7.102 +-	 * page table anyway.
   7.103 +-	 */
   7.104 +-	memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2);
   7.105 +-	__flush_tlb();
   7.106 ++	page_list[PA_CONTROL_PAGE] = __pa(control_page);
   7.107 ++	page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
   7.108 ++	page_list[PA_PGD] = __pa(kexec_pgd);
   7.109 ++	page_list[VA_PGD] = (unsigned long)kexec_pgd;
   7.110 ++	page_list[PA_PUD_0] = __pa(kexec_pud0);
   7.111 ++	page_list[VA_PUD_0] = (unsigned long)kexec_pud0;
   7.112 ++	page_list[PA_PMD_0] = __pa(kexec_pmd0);
   7.113 ++	page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
   7.114 ++	page_list[PA_PTE_0] = __pa(kexec_pte0);
   7.115 ++	page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
   7.116 ++	page_list[PA_PUD_1] = __pa(kexec_pud1);
   7.117 ++	page_list[VA_PUD_1] = (unsigned long)kexec_pud1;
   7.118 ++	page_list[PA_PMD_1] = __pa(kexec_pmd1);
   7.119 ++	page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
   7.120 ++	page_list[PA_PTE_1] = __pa(kexec_pte1);
   7.121 ++	page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
   7.122 + 
   7.123 ++	page_list[PA_TABLE_PAGE] =
   7.124 ++	  (unsigned long)__pa(page_address(image->control_code_page));
   7.125 + 
   7.126 + 	/* The segment registers are funny things, they have both a
   7.127 + 	 * visible and an invisible part.  Whenever the visible part is
   7.128 +@@ -222,9 +224,10 @@ NORET_TYPE void machine_kexec(struct kim
   7.129 + 	 */
   7.130 + 	set_gdt(phys_to_virt(0),0);
   7.131 + 	set_idt(phys_to_virt(0),0);
   7.132 ++
   7.133 + 	/* now call it */
   7.134 +-	rnk = (relocate_new_kernel_t) control_code_buffer;
   7.135 +-	(*rnk)(page_list, control_code_buffer, image->start, start_pgtable);
   7.136 ++	relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
   7.137 ++			image->start);
   7.138 + }
   7.139 + 
   7.140 + /* crashkernel=size@addr specifies the location to reserve for
   7.141 +--- a/arch/x86_64/kernel/relocate_kernel.S
   7.142 ++++ b/arch/x86_64/kernel/relocate_kernel.S
   7.143 +@@ -7,31 +7,169 @@
   7.144 +  */
   7.145 + 
   7.146 + #include <linux/linkage.h>
   7.147 ++#include <asm/page.h>
   7.148 ++#include <asm/kexec.h>
   7.149 + 
   7.150 +-	/*
   7.151 +-	 * Must be relocatable PIC code callable as a C function, that once
   7.152 +-	 * it starts can not use the previous processes stack.
   7.153 +-	 */
   7.154 +-	.globl relocate_new_kernel
   7.155 ++/*
   7.156 ++ * Must be relocatable PIC code callable as a C function
   7.157 ++ */
   7.158 ++
   7.159 ++#define PTR(x) (x << 3)
   7.160 ++#define PAGE_ALIGNED (1 << PAGE_SHIFT)
   7.161 ++#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
   7.162 ++
   7.163 ++	.text
   7.164 ++	.align PAGE_ALIGNED
   7.165 + 	.code64
   7.166 ++	.globl relocate_kernel
   7.167 ++relocate_kernel:
   7.168 ++	/* %rdi indirection_page
   7.169 ++	 * %rsi page_list
   7.170 ++	 * %rdx start address
   7.171 ++	 */
   7.172 ++
   7.173 ++	/* map the control page at its virtual address */
   7.174 ++
   7.175 ++	movq	$0x0000ff8000000000, %r10        /* mask */
   7.176 ++	mov	$(39 - 3), %cl                   /* bits to shift */
   7.177 ++	movq	PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
   7.178 ++
   7.179 ++	movq	%r11, %r9
   7.180 ++	andq	%r10, %r9
   7.181 ++	shrq	%cl, %r9
   7.182 ++
   7.183 ++	movq	PTR(VA_PGD)(%rsi), %r8
   7.184 ++	addq	%r8, %r9
   7.185 ++	movq	PTR(PA_PUD_0)(%rsi), %r8
   7.186 ++	orq	$PAGE_ATTR, %r8
   7.187 ++	movq	%r8, (%r9)
   7.188 ++
   7.189 ++	shrq	$9, %r10
   7.190 ++	sub	$9, %cl
   7.191 ++
   7.192 ++	movq	%r11, %r9
   7.193 ++	andq	%r10, %r9
   7.194 ++	shrq	%cl, %r9
   7.195 ++
   7.196 ++	movq	PTR(VA_PUD_0)(%rsi), %r8
   7.197 ++	addq	%r8, %r9
   7.198 ++	movq	PTR(PA_PMD_0)(%rsi), %r8
   7.199 ++	orq	$PAGE_ATTR, %r8
   7.200 ++	movq	%r8, (%r9)
   7.201 ++
   7.202 ++	shrq	$9, %r10
   7.203 ++	sub	$9, %cl
   7.204 ++
   7.205 ++	movq	%r11, %r9
   7.206 ++	andq	%r10, %r9
   7.207 ++	shrq	%cl, %r9
   7.208 ++
   7.209 ++	movq	PTR(VA_PMD_0)(%rsi), %r8
   7.210 ++	addq	%r8, %r9
   7.211 ++	movq	PTR(PA_PTE_0)(%rsi), %r8
   7.212 ++	orq	$PAGE_ATTR, %r8
   7.213 ++	movq	%r8, (%r9)
   7.214 ++
   7.215 ++	shrq	$9, %r10
   7.216 ++	sub	$9, %cl
   7.217 ++
   7.218 ++	movq	%r11, %r9
   7.219 ++	andq	%r10, %r9
   7.220 ++	shrq	%cl, %r9
   7.221 ++
   7.222 ++	movq	PTR(VA_PTE_0)(%rsi), %r8
   7.223 ++	addq	%r8, %r9
   7.224 ++	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r8
   7.225 ++	orq	$PAGE_ATTR, %r8
   7.226 ++	movq	%r8, (%r9)
   7.227 ++
   7.228 ++	/* identity map the control page at its physical address */
   7.229 ++
   7.230 ++	movq	$0x0000ff8000000000, %r10        /* mask */
   7.231 ++	mov	$(39 - 3), %cl                   /* bits to shift */
   7.232 ++	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
   7.233 ++
   7.234 ++	movq	%r11, %r9
   7.235 ++	andq	%r10, %r9
   7.236 ++	shrq	%cl, %r9
   7.237 ++
   7.238 ++	movq	PTR(VA_PGD)(%rsi), %r8
   7.239 ++	addq	%r8, %r9
   7.240 ++	movq	PTR(PA_PUD_1)(%rsi), %r8
   7.241 ++	orq	$PAGE_ATTR, %r8
   7.242 ++	movq	%r8, (%r9)
   7.243 ++
   7.244 ++	shrq	$9, %r10
   7.245 ++	sub	$9, %cl
   7.246 ++
   7.247 ++	movq	%r11, %r9
   7.248 ++	andq	%r10, %r9
   7.249 ++	shrq	%cl, %r9
   7.250 ++
   7.251 ++	movq	PTR(VA_PUD_1)(%rsi), %r8
   7.252 ++	addq	%r8, %r9
   7.253 ++	movq	PTR(PA_PMD_1)(%rsi), %r8
   7.254 ++	orq	$PAGE_ATTR, %r8
   7.255 ++	movq	%r8, (%r9)
   7.256 ++
   7.257 ++	shrq	$9, %r10
   7.258 ++	sub	$9, %cl
   7.259 ++
   7.260 ++	movq	%r11, %r9
   7.261 ++	andq	%r10, %r9
   7.262 ++	shrq	%cl, %r9
   7.263 ++
   7.264 ++	movq	PTR(VA_PMD_1)(%rsi), %r8
   7.265 ++	addq	%r8, %r9
   7.266 ++	movq	PTR(PA_PTE_1)(%rsi), %r8
   7.267 ++	orq	$PAGE_ATTR, %r8
   7.268 ++	movq	%r8, (%r9)
   7.269 ++
   7.270 ++	shrq	$9, %r10
   7.271 ++	sub	$9, %cl
   7.272 ++
   7.273 ++	movq	%r11, %r9
   7.274 ++	andq	%r10, %r9
   7.275 ++	shrq	%cl, %r9
   7.276 ++
   7.277 ++	movq	PTR(VA_PTE_1)(%rsi), %r8
   7.278 ++	addq	%r8, %r9
   7.279 ++	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r8
   7.280 ++	orq	$PAGE_ATTR, %r8
   7.281 ++	movq	%r8, (%r9)
   7.282 ++
   7.283 + relocate_new_kernel:
   7.284 +-	/* %rdi page_list
   7.285 +-	 * %rsi reboot_code_buffer
   7.286 ++	/* %rdi indirection_page
   7.287 ++	 * %rsi page_list
   7.288 + 	 * %rdx start address
   7.289 +-	 * %rcx page_table
   7.290 +-	 * %r8  arg5
   7.291 +-	 * %r9  arg6
   7.292 + 	 */
   7.293 + 
   7.294 + 	/* zero out flags, and disable interrupts */
   7.295 + 	pushq $0
   7.296 + 	popfq
   7.297 + 
   7.298 +-	/* set a new stack at the bottom of our page... */
   7.299 +-	lea   4096(%rsi), %rsp
   7.300 ++	/* get physical address of control page now */
   7.301 ++	/* this is impossible after page table switch */
   7.302 ++	movq	PTR(PA_CONTROL_PAGE)(%rsi), %r8
   7.303 ++
   7.304 ++	/* get physical address of page table now too */
   7.305 ++	movq	PTR(PA_TABLE_PAGE)(%rsi), %rcx
   7.306 ++
   7.307 ++	/* switch to new set of page tables */
   7.308 ++	movq	PTR(PA_PGD)(%rsi), %r9
   7.309 ++	movq	%r9, %cr3
   7.310 ++
   7.311 ++	/* setup a new stack at the end of the physical control page */
   7.312 ++	lea	4096(%r8), %rsp
   7.313 ++
   7.314 ++	/* jump to identity mapped page */
   7.315 ++	addq	$(identity_mapped - relocate_kernel), %r8
   7.316 ++	pushq	%r8
   7.317 ++	ret
   7.318 + 
   7.319 +-	/* store the parameters back on the stack */
   7.320 +-	pushq	%rdx /* store the start address */
   7.321 ++identity_mapped:
   7.322 ++	/* store the start address on the stack */
   7.323 ++	pushq   %rdx
   7.324 + 
   7.325 + 	/* Set cr0 to a known state:
   7.326 + 	 * 31 1 == Paging enabled
   7.327 +@@ -136,8 +274,3 @@ relocate_new_kernel:
   7.328 + 	xorq	%r15, %r15
   7.329 + 
   7.330 + 	ret
   7.331 +-relocate_new_kernel_end:
   7.332 +-
   7.333 +-	.globl relocate_new_kernel_size
   7.334 +-relocate_new_kernel_size:
   7.335 +-	.quad relocate_new_kernel_end - relocate_new_kernel
   7.336 +--- a/include/asm-x86_64/kexec.h
   7.337 ++++ b/include/asm-x86_64/kexec.h
   7.338 +@@ -1,6 +1,27 @@
   7.339 + #ifndef _X86_64_KEXEC_H
   7.340 + #define _X86_64_KEXEC_H
   7.341 + 
   7.342 ++#define PA_CONTROL_PAGE  0
   7.343 ++#define VA_CONTROL_PAGE  1
   7.344 ++#define PA_PGD           2
   7.345 ++#define VA_PGD           3
   7.346 ++#define PA_PUD_0         4
   7.347 ++#define VA_PUD_0         5
   7.348 ++#define PA_PMD_0         6
   7.349 ++#define VA_PMD_0         7
   7.350 ++#define PA_PTE_0         8
   7.351 ++#define VA_PTE_0         9
   7.352 ++#define PA_PUD_1         10
   7.353 ++#define VA_PUD_1         11
   7.354 ++#define PA_PMD_1         12
   7.355 ++#define VA_PMD_1         13
   7.356 ++#define PA_PTE_1         14
   7.357 ++#define VA_PTE_1         15
   7.358 ++#define PA_TABLE_PAGE    16
   7.359 ++#define PAGES_NR         17
   7.360 ++
   7.361 ++#ifndef __ASSEMBLY__
   7.362 ++
   7.363 + #include <linux/string.h>
   7.364 + 
   7.365 + #include <asm/page.h>
   7.366 +@@ -64,4 +85,12 @@ static inline void crash_setup_regs(stru
   7.367 + 		newregs->rip = (unsigned long)current_text_addr();
   7.368 + 	}
   7.369 + }
   7.370 ++
   7.371 ++NORET_TYPE void
   7.372 ++relocate_kernel(unsigned long indirection_page,
   7.373 ++		unsigned long page_list,
   7.374 ++		unsigned long start_address) ATTRIB_NORET;
   7.375 ++
   7.376 ++#endif /* __ASSEMBLY__ */
   7.377 ++
   7.378 + #endif /* _X86_64_KEXEC_H */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch	Thu Nov 30 12:38:51 2006 +0000
     8.3 @@ -0,0 +1,161 @@
     8.4 +kexec: Move asm segment handling code to the assembly file (x86_64)
     8.5 +
     8.6 +This patch moves the idt, gdt, and segment handling code from machine_kexec.c
     8.7 +to relocate_kernel.S.  The main reason behind this move is to avoid code 
     8.8 +duplication in the Xen hypervisor. With this patch all code required to kexec
     8.9 +is put on the control page.
    8.10 +
    8.11 +On top of that this patch also counts as a cleanup - I think it is much
    8.12 +nicer to write assembly directly in assembly files than wrap inline assembly
    8.13 +in C functions for no apparent reason.
    8.14 +
    8.15 +Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
    8.16 +---
    8.17 +
    8.18 + Applies to 2.6.19-rc1.
    8.19 +
    8.20 + machine_kexec.c   |   58 -----------------------------------------------------
    8.21 + relocate_kernel.S |   50 +++++++++++++++++++++++++++++++++++++++++----
    8.22 + 2 files changed, 45 insertions(+), 63 deletions(-)
    8.23 +
    8.24 +--- 0002/arch/x86_64/kernel/machine_kexec.c
    8.25 ++++ work/arch/x86_64/kernel/machine_kexec.c	2006-10-05 16:15:49.000000000 +0900
    8.26 +@@ -112,47 +112,6 @@ static int init_pgtable(struct kimage *i
    8.27 +  	return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT);
    8.28 + }
    8.29 + 
    8.30 +-static void set_idt(void *newidt, u16 limit)
    8.31 +-{
    8.32 +-	struct desc_ptr curidt;
    8.33 +-
    8.34 +-	/* x86-64 supports unaliged loads & stores */
    8.35 +-	curidt.size    = limit;
    8.36 +-	curidt.address = (unsigned long)newidt;
    8.37 +-
    8.38 +-	__asm__ __volatile__ (
    8.39 +-		"lidtq %0\n"
    8.40 +-		: : "m" (curidt)
    8.41 +-		);
    8.42 +-};
    8.43 +-
    8.44 +-
    8.45 +-static void set_gdt(void *newgdt, u16 limit)
    8.46 +-{
    8.47 +-	struct desc_ptr curgdt;
    8.48 +-
    8.49 +-	/* x86-64 supports unaligned loads & stores */
    8.50 +-	curgdt.size    = limit;
    8.51 +-	curgdt.address = (unsigned long)newgdt;
    8.52 +-
    8.53 +-	__asm__ __volatile__ (
    8.54 +-		"lgdtq %0\n"
    8.55 +-		: : "m" (curgdt)
    8.56 +-		);
    8.57 +-};
    8.58 +-
    8.59 +-static void load_segments(void)
    8.60 +-{
    8.61 +-	__asm__ __volatile__ (
    8.62 +-		"\tmovl %0,%%ds\n"
    8.63 +-		"\tmovl %0,%%es\n"
    8.64 +-		"\tmovl %0,%%ss\n"
    8.65 +-		"\tmovl %0,%%fs\n"
    8.66 +-		"\tmovl %0,%%gs\n"
    8.67 +-		: : "a" (__KERNEL_DS) : "memory"
    8.68 +-		);
    8.69 +-}
    8.70 +-
    8.71 + int machine_kexec_prepare(struct kimage *image)
    8.72 + {
    8.73 + 	unsigned long start_pgtable;
    8.74 +@@ -209,23 +168,6 @@ NORET_TYPE void machine_kexec(struct kim
    8.75 + 	page_list[PA_TABLE_PAGE] =
    8.76 + 	  (unsigned long)__pa(page_address(image->control_code_page));
    8.77 + 
    8.78 +-	/* The segment registers are funny things, they have both a
    8.79 +-	 * visible and an invisible part.  Whenever the visible part is
    8.80 +-	 * set to a specific selector, the invisible part is loaded
    8.81 +-	 * with from a table in memory.  At no other time is the
    8.82 +-	 * descriptor table in memory accessed.
    8.83 +-	 *
    8.84 +-	 * I take advantage of this here by force loading the
    8.85 +-	 * segments, before I zap the gdt with an invalid value.
    8.86 +-	 */
    8.87 +-	load_segments();
    8.88 +-	/* The gdt & idt are now invalid.
    8.89 +-	 * If you want to load them you must set up your own idt & gdt.
    8.90 +-	 */
    8.91 +-	set_gdt(phys_to_virt(0),0);
    8.92 +-	set_idt(phys_to_virt(0),0);
    8.93 +-
    8.94 +-	/* now call it */
    8.95 + 	relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
    8.96 + 			image->start);
    8.97 + }
    8.98 +--- 0002/arch/x86_64/kernel/relocate_kernel.S
    8.99 ++++ work/arch/x86_64/kernel/relocate_kernel.S	2006-10-05 16:18:07.000000000 +0900
   8.100 +@@ -159,13 +159,39 @@ relocate_new_kernel:
   8.101 + 	movq	PTR(PA_PGD)(%rsi), %r9
   8.102 + 	movq	%r9, %cr3
   8.103 + 
   8.104 ++	/* setup idt */
   8.105 ++	movq    %r8, %rax
   8.106 ++	addq    $(idt_80 - relocate_kernel), %rax
   8.107 ++	lidtq   (%rax)
   8.108 ++
   8.109 ++	/* setup gdt */
   8.110 ++	movq    %r8, %rax
   8.111 ++	addq    $(gdt - relocate_kernel), %rax
   8.112 ++	movq    %r8, %r9
   8.113 ++	addq    $((gdt_80 - relocate_kernel) + 2), %r9
   8.114 ++	movq    %rax, (%r9)
   8.115 ++
   8.116 ++	movq    %r8, %rax
   8.117 ++	addq    $(gdt_80 - relocate_kernel), %rax
   8.118 ++	lgdtq   (%rax)
   8.119 ++
   8.120 ++	/* setup data segment registers */
   8.121 ++	xorl	%eax, %eax
   8.122 ++	movl    %eax, %ds
   8.123 ++	movl    %eax, %es
   8.124 ++	movl    %eax, %fs
   8.125 ++	movl    %eax, %gs
   8.126 ++	movl    %eax, %ss
   8.127 ++	
   8.128 + 	/* setup a new stack at the end of the physical control page */
   8.129 + 	lea	4096(%r8), %rsp
   8.130 + 
   8.131 +-	/* jump to identity mapped page */
   8.132 +-	addq	$(identity_mapped - relocate_kernel), %r8
   8.133 +-	pushq	%r8
   8.134 +-	ret
   8.135 ++	/* load new code segment and jump to identity mapped page */
   8.136 ++	movq	%r8, %rax
   8.137 ++	addq    $(identity_mapped - relocate_kernel), %rax
   8.138 ++	pushq	$(gdt_cs - gdt)
   8.139 ++	pushq	%rax
   8.140 ++	lretq
   8.141 + 
   8.142 + identity_mapped:
   8.143 + 	/* store the start address on the stack */
   8.144 +@@ -272,5 +298,19 @@ identity_mapped:
   8.145 + 	xorq	%r13, %r13
   8.146 + 	xorq	%r14, %r14
   8.147 + 	xorq	%r15, %r15
   8.148 +-
   8.149 + 	ret
   8.150 ++
   8.151 ++	.align  16
   8.152 ++gdt:
   8.153 ++	.quad	0x0000000000000000	/* NULL descriptor */
   8.154 ++gdt_cs:
   8.155 ++	.quad   0x00af9a000000ffff
   8.156 ++gdt_end:
   8.157 ++
   8.158 ++gdt_80:
   8.159 ++	.word	gdt_end - gdt - 1	/* limit */
   8.160 ++	.quad	0			/* base - filled in by code above */
   8.161 ++
   8.162 ++idt_80:
   8.163 ++	.word	0			/* limit */
   8.164 ++	.quad	0			/* base */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-x86_64.patch	Thu Nov 30 12:38:51 2006 +0000
     9.3 @@ -0,0 +1,219 @@
     9.4 +--- 0001/arch/x86_64/kernel/crash.c
     9.5 ++++ work/arch/x86_64/kernel/crash.c
     9.6 +@@ -92,6 +92,7 @@ static void crash_save_self(struct pt_re
     9.7 + 	crash_save_this_cpu(regs, cpu);
     9.8 + }
     9.9 + 
    9.10 ++#ifndef CONFIG_XEN
    9.11 + #ifdef CONFIG_SMP
    9.12 + static atomic_t waiting_for_crash_ipi;
    9.13 + 
    9.14 +@@ -156,6 +157,7 @@ static void nmi_shootdown_cpus(void)
    9.15 + 	/* There are no cpus to shootdown */
    9.16 + }
    9.17 + #endif
    9.18 ++#endif /* CONFIG_XEN */
    9.19 + 
    9.20 + void machine_crash_shutdown(struct pt_regs *regs)
    9.21 + {
    9.22 +@@ -173,6 +175,8 @@ void machine_crash_shutdown(struct pt_re
    9.23 + 
    9.24 + 	/* Make a note of crashing cpu. Will be used in NMI callback.*/
    9.25 + 	crashing_cpu = smp_processor_id();
    9.26 ++
    9.27 ++#ifndef CONFIG_XEN
    9.28 + 	nmi_shootdown_cpus();
    9.29 + 
    9.30 + 	if(cpu_has_apic)
    9.31 +@@ -181,6 +185,6 @@ void machine_crash_shutdown(struct pt_re
    9.32 + #if defined(CONFIG_X86_IO_APIC)
    9.33 + 	disable_IO_APIC();
    9.34 + #endif
    9.35 +-
    9.36 ++#endif /* CONFIG_XEN */
    9.37 + 	crash_save_self(regs);
    9.38 + }
    9.39 +--- 0010/arch/x86_64/kernel/machine_kexec.c
    9.40 ++++ work/arch/x86_64/kernel/machine_kexec.c
    9.41 +@@ -24,6 +24,104 @@ static u64 kexec_pud1[512] PAGE_ALIGNED;
    9.42 + static u64 kexec_pmd1[512] PAGE_ALIGNED;
    9.43 + static u64 kexec_pte1[512] PAGE_ALIGNED;
    9.44 + 
    9.45 ++#ifdef CONFIG_XEN
    9.46 ++
    9.47 ++/* In the case of Xen, override hypervisor functions to be able to create
    9.48 ++ * a regular identity mapping page table...
    9.49 ++ */
    9.50 ++
    9.51 ++#include <xen/interface/kexec.h>
    9.52 ++#include <xen/interface/memory.h>
    9.53 ++
    9.54 ++#define x__pmd(x) ((pmd_t) { (x) } )
    9.55 ++#define x__pud(x) ((pud_t) { (x) } )
    9.56 ++#define x__pgd(x) ((pgd_t) { (x) } )
    9.57 ++
    9.58 ++#define x_pmd_val(x)   ((x).pmd)
    9.59 ++#define x_pud_val(x)   ((x).pud)
    9.60 ++#define x_pgd_val(x)   ((x).pgd)
    9.61 ++
    9.62 ++static inline void x_set_pmd(pmd_t *dst, pmd_t val)
    9.63 ++{
    9.64 ++	x_pmd_val(*dst) = x_pmd_val(val);
    9.65 ++}
    9.66 ++
    9.67 ++static inline void x_set_pud(pud_t *dst, pud_t val)
    9.68 ++{
    9.69 ++	x_pud_val(*dst) = phys_to_machine(x_pud_val(val));
    9.70 ++}
    9.71 ++
    9.72 ++static inline void x_pud_clear (pud_t *pud)
    9.73 ++{
    9.74 ++	x_pud_val(*pud) = 0;
    9.75 ++}
    9.76 ++
    9.77 ++static inline void x_set_pgd(pgd_t *dst, pgd_t val)
    9.78 ++{
    9.79 ++	x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val));
    9.80 ++}
    9.81 ++
    9.82 ++static inline void x_pgd_clear (pgd_t * pgd)
    9.83 ++{
    9.84 ++	x_pgd_val(*pgd) = 0;
    9.85 ++}
    9.86 ++
    9.87 ++#define X__PAGE_KERNEL_LARGE_EXEC \
    9.88 ++         _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE
    9.89 ++#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY
    9.90 ++
    9.91 ++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
    9.92 ++
    9.93 ++#if PAGES_NR > KEXEC_XEN_NO_PAGES
    9.94 ++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
    9.95 ++#endif
    9.96 ++
    9.97 ++#if PA_CONTROL_PAGE != 0
    9.98 ++#error PA_CONTROL_PAGE is non zero - Xen support will break
    9.99 ++#endif
   9.100 ++
   9.101 ++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
   9.102 ++{
   9.103 ++	void *control_page;
   9.104 ++	void *table_page;
   9.105 ++
   9.106 ++	memset(xki->page_list, 0, sizeof(xki->page_list));
   9.107 ++
   9.108 ++	control_page = page_address(image->control_code_page) + PAGE_SIZE;
   9.109 ++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
   9.110 ++
   9.111 ++	table_page = page_address(image->control_code_page);
   9.112 ++
   9.113 ++	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
   9.114 ++	xki->page_list[PA_TABLE_PAGE] = __ma(table_page);
   9.115 ++
   9.116 ++	xki->page_list[PA_PGD] = __ma(kexec_pgd);
   9.117 ++	xki->page_list[PA_PUD_0] = __ma(kexec_pud0);
   9.118 ++	xki->page_list[PA_PUD_1] = __ma(kexec_pud1);
   9.119 ++	xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
   9.120 ++	xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
   9.121 ++	xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
   9.122 ++	xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
   9.123 ++}
   9.124 ++
   9.125 ++#else /* CONFIG_XEN */
   9.126 ++
   9.127 ++#define x__pmd(x) __pmd(x)
   9.128 ++#define x__pud(x) __pud(x)
   9.129 ++#define x__pgd(x) __pgd(x)
   9.130 ++
   9.131 ++#define x_set_pmd(x, y) set_pmd(x, y)
   9.132 ++#define x_set_pud(x, y) set_pud(x, y)
   9.133 ++#define x_set_pgd(x, y) set_pgd(x, y)
   9.134 ++
   9.135 ++#define x_pud_clear(x) pud_clear(x)
   9.136 ++#define x_pgd_clear(x) pgd_clear(x)
   9.137 ++
   9.138 ++#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC
   9.139 ++#define X_KERNPG_TABLE _KERNPG_TABLE
   9.140 ++
   9.141 ++#endif /* CONFIG_XEN */
   9.142 ++
   9.143 + static void init_level2_page(pmd_t *level2p, unsigned long addr)
   9.144 + {
   9.145 + 	unsigned long end_addr;
   9.146 +@@ -31,7 +129,7 @@ static void init_level2_page(pmd_t *leve
   9.147 + 	addr &= PAGE_MASK;
   9.148 + 	end_addr = addr + PUD_SIZE;
   9.149 + 	while (addr < end_addr) {
   9.150 +-		set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
   9.151 ++		x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
   9.152 + 		addr += PMD_SIZE;
   9.153 + 	}
   9.154 + }
   9.155 +@@ -56,12 +154,12 @@ static int init_level3_page(struct kimag
   9.156 + 		}
   9.157 + 		level2p = (pmd_t *)page_address(page);
   9.158 + 		init_level2_page(level2p, addr);
   9.159 +-		set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE));
   9.160 ++		x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE));
   9.161 + 		addr += PUD_SIZE;
   9.162 + 	}
   9.163 + 	/* clear the unused entries */
   9.164 + 	while (addr < end_addr) {
   9.165 +-		pud_clear(level3p++);
   9.166 ++		x_pud_clear(level3p++);
   9.167 + 		addr += PUD_SIZE;
   9.168 + 	}
   9.169 + out:
   9.170 +@@ -92,12 +190,12 @@ static int init_level4_page(struct kimag
   9.171 + 		if (result) {
   9.172 + 			goto out;
   9.173 + 		}
   9.174 +-		set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE));
   9.175 ++		x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE));
   9.176 + 		addr += PGDIR_SIZE;
   9.177 + 	}
   9.178 + 	/* clear the unused entries */
   9.179 + 	while (addr < end_addr) {
   9.180 +-		pgd_clear(level4p++);
   9.181 ++		x_pgd_clear(level4p++);
   9.182 + 		addr += PGDIR_SIZE;
   9.183 + 	}
   9.184 + out:
   9.185 +@@ -108,8 +206,14 @@ out:
   9.186 + static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
   9.187 + {
   9.188 + 	pgd_t *level4p;
   9.189 ++	unsigned long x_end_pfn = end_pfn;
   9.190 ++
   9.191 ++#ifdef CONFIG_XEN
   9.192 ++	x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
   9.193 ++#endif
   9.194 ++
   9.195 + 	level4p = (pgd_t *)__va(start_pgtable);
   9.196 +- 	return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT);
   9.197 ++ 	return init_level4_page(image, level4p, 0, x_end_pfn << PAGE_SHIFT);
   9.198 + }
   9.199 + 
   9.200 + int machine_kexec_prepare(struct kimage *image)
   9.201 +--- 0009/include/asm-x86_64/kexec.h
   9.202 ++++ work/include/asm-x86_64/kexec.h
   9.203 +@@ -91,6 +91,19 @@ relocate_kernel(unsigned long indirectio
   9.204 + 		unsigned long page_list,
   9.205 + 		unsigned long start_address) ATTRIB_NORET;
   9.206 + 
   9.207 ++/* Under Xen we need to work with machine addresses. These macros give the
   9.208 ++ * machine address of a certain page to the generic kexec code instead of 
   9.209 ++ * the pseudo physical address which would be given by the default macros.
   9.210 ++ */
   9.211 ++
   9.212 ++#ifdef CONFIG_XEN
   9.213 ++#define KEXEC_ARCH_HAS_PAGE_MACROS
   9.214 ++#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
   9.215 ++#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
   9.216 ++#define kexec_virt_to_phys(addr) virt_to_machine(addr)
   9.217 ++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
   9.218 ++#endif
   9.219 ++
   9.220 + #endif /* __ASSEMBLY__ */
   9.221 + 
   9.222 + #endif /* _X86_64_KEXEC_H */
    10.1 --- a/patches/linux-2.6.16.33/series	Thu Nov 30 12:38:51 2006 +0000
    10.2 +++ b/patches/linux-2.6.16.33/series	Thu Nov 30 12:38:51 2006 +0000
    10.3 @@ -4,6 +4,9 @@ git-2a8a3d5b65e86ec1dfef7d268c64a909eab9
    10.4  git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch
    10.5  linux-2.6.19-rc1-kexec-move_segment_code-i386.patch
    10.6  linux-2.6.19-rc1-kexec-xen-i386.patch
    10.7 +git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch
    10.8 +linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch
    10.9 +linux-2.6.19-rc1-kexec-xen-x86_64.patch
   10.10  blktap-aio-16_03_06.patch
   10.11  device_bind.patch
   10.12  fix-hz-suspend.patch
    11.1 --- a/xen/arch/x86/x86_64/entry.S	Thu Nov 30 12:38:51 2006 +0000
    11.2 +++ b/xen/arch/x86/x86_64/entry.S	Thu Nov 30 12:38:51 2006 +0000
    11.3 @@ -559,6 +559,7 @@ ENTRY(hypercall_table)
    11.4          .quad do_hvm_op
    11.5          .quad do_sysctl             /* 35 */
    11.6          .quad do_domctl
    11.7 +        .quad do_kexec_op
    11.8          .rept NR_hypercalls-((.-hypercall_table)/8)
    11.9          .quad do_ni_hypercall
   11.10          .endr
   11.11 @@ -601,6 +602,7 @@ ENTRY(hypercall_args_table)
   11.12          .byte 2 /* do_hvm_op            */
   11.13          .byte 1 /* do_sysctl            */  /* 35 */
   11.14          .byte 1 /* do_domctl            */
   11.15 +        .byte 2 /* do_kexec             */
   11.16          .rept NR_hypercalls-(.-hypercall_args_table)
   11.17          .byte 0 /* do_ni_hypercall      */
   11.18          .endr
    12.1 --- a/xen/include/asm-x86/x86_64/elf.h	Thu Nov 30 12:38:51 2006 +0000
    12.2 +++ b/xen/include/asm-x86/x86_64/elf.h	Thu Nov 30 12:38:51 2006 +0000
    12.3 @@ -1,16 +1,82 @@
    12.4  #ifndef __X86_64_ELF_H__
    12.5  #define __X86_64_ELF_H__
    12.6  
    12.7 -#include <xen/lib.h>       /* for printk() used in stub */
    12.8 +#include <asm/processor.h>
    12.9  
   12.10  typedef struct {
   12.11 -    unsigned long dummy;
   12.12 +    unsigned long r15;
   12.13 +    unsigned long r14;
   12.14 +    unsigned long r13;
   12.15 +    unsigned long r12;
   12.16 +    unsigned long rbp;
   12.17 +    unsigned long rbx;
   12.18 +    unsigned long r11;
   12.19 +    unsigned long r10;
   12.20 +    unsigned long r9;
   12.21 +    unsigned long r8;
   12.22 +    unsigned long rax;
   12.23 +    unsigned long rcx;
   12.24 +    unsigned long rdx;
   12.25 +    unsigned long rsi;
   12.26 +    unsigned long rdi;
   12.27 +    unsigned long orig_rax;
   12.28 +    unsigned long rip;
   12.29 +    unsigned long cs;
   12.30 +    unsigned long eflags;
   12.31 +    unsigned long rsp;
   12.32 +    unsigned long ss;
   12.33 +    unsigned long thread_fs;
   12.34 +    unsigned long thread_gs;
   12.35 +    unsigned long ds;
   12.36 +    unsigned long es;
   12.37 +    unsigned long fs;
   12.38 +    unsigned long gs;
   12.39  } ELF_Gregset;
   12.40  
   12.41  extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
   12.42                                        crash_xen_core_t *xen_core_regs)
   12.43  {
   12.44 -    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   12.45 +    unsigned long tmp;
   12.46 +
   12.47 +    asm volatile("movq %%r15,%0" : "=m"(core_regs->r15));
   12.48 +    asm volatile("movq %%r14,%0" : "=m"(core_regs->r14));
   12.49 +    asm volatile("movq %%r13,%0" : "=m"(core_regs->r13));
   12.50 +    asm volatile("movq %%r12,%0" : "=m"(core_regs->r12));
   12.51 +    asm volatile("movq %%rbp,%0" : "=m"(core_regs->rbp));
   12.52 +    asm volatile("movq %%rbx,%0" : "=m"(core_regs->rbx));
   12.53 +    asm volatile("movq %%r11,%0" : "=m"(core_regs->r11));
   12.54 +    asm volatile("movq %%r10,%0" : "=m"(core_regs->r10));
   12.55 +    asm volatile("movq %%r9,%0" : "=m"(core_regs->r9));
   12.56 +    asm volatile("movq %%r8,%0" : "=m"(core_regs->r8));
   12.57 +    asm volatile("movq %%rax,%0" : "=m"(core_regs->rax));
   12.58 +    asm volatile("movq %%rcx,%0" : "=m"(core_regs->rcx));
   12.59 +    asm volatile("movq %%rdx,%0" : "=m"(core_regs->rdx));
   12.60 +    asm volatile("movq %%rsi,%0" : "=m"(core_regs->rsi));
   12.61 +    asm volatile("movq %%rdi,%0" : "=m"(core_regs->rdi));
   12.62 +    /* orig_rax not filled in for now */
   12.63 +    core_regs->rip = (unsigned long)current_text_addr();
   12.64 +    asm volatile("movl %%cs, %%eax;" :"=a"(core_regs->cs));
   12.65 +    asm volatile("pushfq; popq %0" :"=m"(core_regs->eflags));
   12.66 +    asm volatile("movq %%rsp,%0" : "=m"(core_regs->rsp));
   12.67 +    asm volatile("movl %%ss, %%eax;" :"=a"(core_regs->ss));
   12.68 +    /* thread_fs not filled in for now */
   12.69 +    /* thread_gs not filled in for now */
   12.70 +    asm volatile("movl %%ds, %%eax;" :"=a"(core_regs->ds));
   12.71 +    asm volatile("movl %%es, %%eax;" :"=a"(core_regs->es));
   12.72 +    asm volatile("movl %%fs, %%eax;" :"=a"(core_regs->fs));
   12.73 +    asm volatile("movl %%gs, %%eax;" :"=a"(core_regs->gs));
   12.74 +
   12.75 +    asm volatile("mov %%cr0, %0" : "=r" (tmp) : );
   12.76 +    xen_core_regs->cr0 = tmp;
   12.77 +
   12.78 +    asm volatile("mov %%cr2, %0" : "=r" (tmp) : );
   12.79 +    xen_core_regs->cr2 = tmp;
   12.80 +
   12.81 +    asm volatile("mov %%cr3, %0" : "=r" (tmp) : );
   12.82 +    xen_core_regs->cr3 = tmp;
   12.83 +
   12.84 +    asm volatile("mov %%cr4, %0" : "=r" (tmp) : );
   12.85 +    xen_core_regs->cr4 = tmp;
   12.86  }
   12.87  
   12.88  #endif /* __X86_64_ELF_H__ */
    13.1 --- a/xen/include/asm-x86/x86_64/kexec.h	Thu Nov 30 12:38:51 2006 +0000
    13.2 +++ b/xen/include/asm-x86/x86_64/kexec.h	Thu Nov 30 12:38:51 2006 +0000
    13.3 @@ -1,14 +1,29 @@
    13.4 +/******************************************************************************
    13.5 + * kexec.h
    13.6 + * 
    13.7 + * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1
    13.8 + *
    13.9 + */
   13.10 +
   13.11  #ifndef __X86_64_KEXEC_H__
   13.12  #define __X86_64_KEXEC_H__
   13.13 -
   13.14 -#include <xen/lib.h>       /* for printk() used in stub */
   13.15 +  
   13.16  #include <xen/types.h>
   13.17 -#include <public/xen.h>
   13.18  #include <xen/kexec.h>
   13.19 +#include <asm/fixmap.h>
   13.20 +
   13.21 +typedef void (*relocate_new_kernel_t)(
   13.22 +                unsigned long indirection_page,
   13.23 +                unsigned long page_list,
   13.24 +                unsigned long start_address);
   13.25  
   13.26  static inline void machine_kexec(xen_kexec_image_t *image)
   13.27  {
   13.28 -    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   13.29 +    relocate_new_kernel_t rnk;
   13.30 +
   13.31 +    rnk = (relocate_new_kernel_t) image->page_list[1];
   13.32 +    (*rnk)(image->indirection_page, (unsigned long)image->page_list, 
   13.33 +           image->start_address);
   13.34  }
   13.35  
   13.36  #endif /* __X86_64_KEXEC_H__ */