ia64/xen-unstable

changeset 12678:5690d18637f5

[XEN] Kexec / Kdump: x86_32 specific code

This patch contains the x86_32 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 2b43fb3afb3e
children a1a04c48da6c
files buildconfigs/linux-defconfig_xen_x86_32 linux-2.6-xen-sparse/arch/i386/Kconfig linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch patches/linux-2.6.16.33/series xen/arch/x86/x86_32/entry.S xen/include/asm-x86/x86_32/elf.h xen/include/asm-x86/x86_32/kexec.h
line diff
     1.1 --- a/buildconfigs/linux-defconfig_xen_x86_32	Thu Nov 30 12:38:51 2006 +0000
     1.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32	Thu Nov 30 12:38:51 2006 +0000
     1.3 @@ -184,6 +184,7 @@ CONFIG_MTRR=y
     1.4  CONFIG_REGPARM=y
     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
    1.11 @@ -2776,6 +2777,7 @@ CONFIG_NTFS_FS=m
    1.12  #
    1.13  CONFIG_PROC_FS=y
    1.14  CONFIG_PROC_KCORE=y
    1.15 +# CONFIG_PROC_VMCORE is not set
    1.16  CONFIG_SYSFS=y
    1.17  CONFIG_TMPFS=y
    1.18  # CONFIG_HUGETLB_PAGE is not set
     2.1 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Thu Nov 30 12:38:51 2006 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Thu Nov 30 12:38:51 2006 +0000
     2.3 @@ -726,7 +726,7 @@ source kernel/Kconfig.hz
     2.4  
     2.5  config KEXEC
     2.6  	bool "kexec system call (EXPERIMENTAL)"
     2.7 -	depends on EXPERIMENTAL && !X86_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/i386/kernel/setup-xen.c	Thu Nov 30 12:38:51 2006 +0000
     3.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Thu Nov 30 12:38:51 2006 +0000
     3.3 @@ -69,6 +69,10 @@
     3.4  #include "setup_arch_pre.h"
     3.5  #include <bios_ebda.h>
     3.6  
     3.7 +#ifdef CONFIG_XEN
     3.8 +#include <xen/interface/kexec.h>
     3.9 +#endif
    3.10 +
    3.11  /* Forward Declaration. */
    3.12  void __init find_max_pfn(void);
    3.13  
    3.14 @@ -943,6 +947,7 @@ static void __init parse_cmdline_early (
    3.15  		 * after a kernel panic.
    3.16  		 */
    3.17  		else if (!memcmp(from, "crashkernel=", 12)) {
    3.18 +#ifndef CONFIG_XEN
    3.19  			unsigned long size, base;
    3.20  			size = memparse(from+12, &from);
    3.21  			if (*from == '@') {
    3.22 @@ -953,6 +958,10 @@ static void __init parse_cmdline_early (
    3.23  				crashk_res.start = base;
    3.24  				crashk_res.end   = base + size - 1;
    3.25  			}
    3.26 +#else
    3.27 +			printk("Ignoring crashkernel command line, "
    3.28 +			       "parameter will be supplied by xen\n");
    3.29 +#endif
    3.30  		}
    3.31  #endif
    3.32  #ifdef CONFIG_PROC_VMCORE
    3.33 @@ -1322,10 +1331,14 @@ void __init setup_bootmem_allocator(void
    3.34  	}
    3.35  #endif
    3.36  #ifdef CONFIG_KEXEC
    3.37 +#ifdef CONFIG_XEN
    3.38 +	xen_machine_kexec_setup_resources();
    3.39 +#else
    3.40  	if (crashk_res.start != crashk_res.end)
    3.41  		reserve_bootmem(crashk_res.start,
    3.42  			crashk_res.end - crashk_res.start + 1);
    3.43  #endif
    3.44 +#endif
    3.45  
    3.46  	if (!xen_feature(XENFEAT_auto_translated_physmap))
    3.47  		phys_to_machine_mapping =
    3.48 @@ -1389,7 +1402,11 @@ legacy_init_iomem_resources(struct e820e
    3.49  			request_resource(res, data_resource);
    3.50  #endif
    3.51  #ifdef CONFIG_KEXEC
    3.52 -			request_resource(res, &crashk_res);
    3.53 +			if (crashk_res.start != crashk_res.end)
    3.54 +			     request_resource(res, &crashk_res);
    3.55 +#ifdef CONFIG_XEN
    3.56 +			xen_machine_kexec_register_resources(res);
    3.57 +#endif
    3.58  #endif
    3.59  		}
    3.60  	}
     4.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Thu Nov 30 12:38:51 2006 +0000
     4.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Thu Nov 30 12:38:51 2006 +0000
     4.3 @@ -395,5 +395,13 @@ HYPERVISOR_xenoprof_op(
     4.4  	return _hypercall2(int, xenoprof_op, op, arg);
     4.5  }
     4.6  
     4.7 +static inline int
     4.8 +HYPERVISOR_kexec_op(
     4.9 +	unsigned long op, void *args)
    4.10 +{
    4.11 +	return _hypercall2(int, kexec_op, op, args);
    4.12 +}
    4.13 +
    4.14 +
    4.15  
    4.16  #endif /* __HYPERCALL_H__ */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch	Thu Nov 30 12:38:51 2006 +0000
     5.3 @@ -0,0 +1,401 @@
     5.4 +From: Magnus Damm <magnus@valinux.co.jp>
     5.5 +Date: Tue, 26 Sep 2006 08:52:38 +0000 (+0200)
     5.6 +Subject: [PATCH] i386: Avoid overwriting the current pgd (V4, i386)
     5.7 +X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3566561bfadffcb5dbc85d576be80c0dbf2cccc9
     5.8 +
     5.9 +[PATCH] i386: Avoid overwriting the current pgd (V4, i386)
    5.10 +
    5.11 +kexec: Avoid overwriting the current pgd (V4, i386)
    5.12 +
    5.13 +This patch upgrades the i386-specific kexec code to avoid overwriting the
    5.14 +current pgd. Overwriting the current pgd is bad when CONFIG_CRASH_DUMP is used
    5.15 +to start a secondary kernel that dumps the memory of the previous kernel.
    5.16 +
    5.17 +The code introduces a new set of page tables. These tables are used to provide
    5.18 +an executable identity mapping without overwriting the current pgd.
    5.19 +
    5.20 +Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
    5.21 +Signed-off-by: Andi Kleen <ak@suse.de>
    5.22 +---
    5.23 +
    5.24 +--- a/arch/i386/kernel/machine_kexec.c
    5.25 ++++ b/arch/i386/kernel/machine_kexec.c
    5.26 +@@ -21,70 +21,13 @@
    5.27 + #include <asm/system.h>
    5.28 + 
    5.29 + #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
    5.30 +-
    5.31 +-#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
    5.32 +-#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
    5.33 +-#define L2_ATTR (_PAGE_PRESENT)
    5.34 +-
    5.35 +-#define LEVEL0_SIZE (1UL << 12UL)
    5.36 +-
    5.37 +-#ifndef CONFIG_X86_PAE
    5.38 +-#define LEVEL1_SIZE (1UL << 22UL)
    5.39 +-static u32 pgtable_level1[1024] PAGE_ALIGNED;
    5.40 +-
    5.41 +-static void identity_map_page(unsigned long address)
    5.42 +-{
    5.43 +-	unsigned long level1_index, level2_index;
    5.44 +-	u32 *pgtable_level2;
    5.45 +-
    5.46 +-	/* Find the current page table */
    5.47 +-	pgtable_level2 = __va(read_cr3());
    5.48 +-
    5.49 +-	/* Find the indexes of the physical address to identity map */
    5.50 +-	level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
    5.51 +-	level2_index = address / LEVEL1_SIZE;
    5.52 +-
    5.53 +-	/* Identity map the page table entry */
    5.54 +-	pgtable_level1[level1_index] = address | L0_ATTR;
    5.55 +-	pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
    5.56 +-
    5.57 +-	/* Flush the tlb so the new mapping takes effect.
    5.58 +-	 * Global tlb entries are not flushed but that is not an issue.
    5.59 +-	 */
    5.60 +-	load_cr3(pgtable_level2);
    5.61 +-}
    5.62 +-
    5.63 +-#else
    5.64 +-#define LEVEL1_SIZE (1UL << 21UL)
    5.65 +-#define LEVEL2_SIZE (1UL << 30UL)
    5.66 +-static u64 pgtable_level1[512] PAGE_ALIGNED;
    5.67 +-static u64 pgtable_level2[512] PAGE_ALIGNED;
    5.68 +-
    5.69 +-static void identity_map_page(unsigned long address)
    5.70 +-{
    5.71 +-	unsigned long level1_index, level2_index, level3_index;
    5.72 +-	u64 *pgtable_level3;
    5.73 +-
    5.74 +-	/* Find the current page table */
    5.75 +-	pgtable_level3 = __va(read_cr3());
    5.76 +-
    5.77 +-	/* Find the indexes of the physical address to identity map */
    5.78 +-	level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
    5.79 +-	level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
    5.80 +-	level3_index = address / LEVEL2_SIZE;
    5.81 +-
    5.82 +-	/* Identity map the page table entry */
    5.83 +-	pgtable_level1[level1_index] = address | L0_ATTR;
    5.84 +-	pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
    5.85 +-	set_64bit(&pgtable_level3[level3_index],
    5.86 +-					       __pa(pgtable_level2) | L2_ATTR);
    5.87 +-
    5.88 +-	/* Flush the tlb so the new mapping takes effect.
    5.89 +-	 * Global tlb entries are not flushed but that is not an issue.
    5.90 +-	 */
    5.91 +-	load_cr3(pgtable_level3);
    5.92 +-}
    5.93 ++static u32 kexec_pgd[1024] PAGE_ALIGNED;
    5.94 ++#ifdef CONFIG_X86_PAE
    5.95 ++static u32 kexec_pmd0[1024] PAGE_ALIGNED;
    5.96 ++static u32 kexec_pmd1[1024] PAGE_ALIGNED;
    5.97 + #endif
    5.98 ++static u32 kexec_pte0[1024] PAGE_ALIGNED;
    5.99 ++static u32 kexec_pte1[1024] PAGE_ALIGNED;
   5.100 + 
   5.101 + static void set_idt(void *newidt, __u16 limit)
   5.102 + {
   5.103 +@@ -128,16 +71,6 @@ static void load_segments(void)
   5.104 + #undef __STR
   5.105 + }
   5.106 + 
   5.107 +-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
   5.108 +-					unsigned long indirection_page,
   5.109 +-					unsigned long reboot_code_buffer,
   5.110 +-					unsigned long start_address,
   5.111 +-					unsigned int has_pae) ATTRIB_NORET;
   5.112 +-
   5.113 +-extern const unsigned char relocate_new_kernel[];
   5.114 +-extern void relocate_new_kernel_end(void);
   5.115 +-extern const unsigned int relocate_new_kernel_size;
   5.116 +-
   5.117 + /*
   5.118 +  * A architecture hook called to validate the
   5.119 +  * proposed image and prepare the control pages
   5.120 +@@ -170,25 +103,29 @@ void machine_kexec_cleanup(struct kimage
   5.121 +  */
   5.122 + NORET_TYPE void machine_kexec(struct kimage *image)
   5.123 + {
   5.124 +-	unsigned long page_list;
   5.125 +-	unsigned long reboot_code_buffer;
   5.126 +-
   5.127 +-	relocate_new_kernel_t rnk;
   5.128 ++	unsigned long page_list[PAGES_NR];
   5.129 ++	void *control_page;
   5.130 + 
   5.131 + 	/* Interrupts aren't acceptable while we reboot */
   5.132 + 	local_irq_disable();
   5.133 + 
   5.134 +-	/* Compute some offsets */
   5.135 +-	reboot_code_buffer = page_to_pfn(image->control_code_page)
   5.136 +-								<< PAGE_SHIFT;
   5.137 +-	page_list = image->head;
   5.138 +-
   5.139 +-	/* Set up an identity mapping for the reboot_code_buffer */
   5.140 +-	identity_map_page(reboot_code_buffer);
   5.141 +-
   5.142 +-	/* copy it out */
   5.143 +-	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
   5.144 +-						relocate_new_kernel_size);
   5.145 ++	control_page = page_address(image->control_code_page);
   5.146 ++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
   5.147 ++
   5.148 ++	page_list[PA_CONTROL_PAGE] = __pa(control_page);
   5.149 ++	page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
   5.150 ++	page_list[PA_PGD] = __pa(kexec_pgd);
   5.151 ++	page_list[VA_PGD] = (unsigned long)kexec_pgd;
   5.152 ++#ifdef CONFIG_X86_PAE
   5.153 ++	page_list[PA_PMD_0] = __pa(kexec_pmd0);
   5.154 ++	page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
   5.155 ++	page_list[PA_PMD_1] = __pa(kexec_pmd1);
   5.156 ++	page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
   5.157 ++#endif
   5.158 ++	page_list[PA_PTE_0] = __pa(kexec_pte0);
   5.159 ++	page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
   5.160 ++	page_list[PA_PTE_1] = __pa(kexec_pte1);
   5.161 ++	page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
   5.162 + 
   5.163 + 	/* The segment registers are funny things, they have both a
   5.164 + 	 * visible and an invisible part.  Whenever the visible part is
   5.165 +@@ -207,8 +144,8 @@ NORET_TYPE void machine_kexec(struct kim
   5.166 + 	set_idt(phys_to_virt(0),0);
   5.167 + 
   5.168 + 	/* now call it */
   5.169 +-	rnk = (relocate_new_kernel_t) reboot_code_buffer;
   5.170 +-	(*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
   5.171 ++	relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
   5.172 ++			image->start, cpu_has_pae);
   5.173 + }
   5.174 + 
   5.175 + /* crashkernel=size@addr specifies the location to reserve for
   5.176 +--- a/arch/i386/kernel/relocate_kernel.S
   5.177 ++++ b/arch/i386/kernel/relocate_kernel.S
   5.178 +@@ -7,16 +7,138 @@
   5.179 +  */
   5.180 + 
   5.181 + #include <linux/linkage.h>
   5.182 ++#include <asm/page.h>
   5.183 ++#include <asm/kexec.h>
   5.184 ++
   5.185 ++/*
   5.186 ++ * Must be relocatable PIC code callable as a C function
   5.187 ++ */
   5.188 ++
   5.189 ++#define PTR(x) (x << 2)
   5.190 ++#define PAGE_ALIGNED (1 << PAGE_SHIFT)
   5.191 ++#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
   5.192 ++#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
   5.193 ++
   5.194 ++	.text
   5.195 ++	.align PAGE_ALIGNED
   5.196 ++	.globl relocate_kernel
   5.197 ++relocate_kernel:
   5.198 ++	movl	8(%esp), %ebp /* list of pages */
   5.199 ++
   5.200 ++#ifdef CONFIG_X86_PAE
   5.201 ++	/* map the control page at its virtual address */
   5.202 ++
   5.203 ++	movl	PTR(VA_PGD)(%ebp), %edi
   5.204 ++	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
   5.205 ++	andl	$0xc0000000, %eax
   5.206 ++	shrl	$27, %eax
   5.207 ++	addl	%edi, %eax
   5.208 ++
   5.209 ++	movl	PTR(PA_PMD_0)(%ebp), %edx
   5.210 ++	orl	$PAE_PGD_ATTR, %edx
   5.211 ++	movl	%edx, (%eax)
   5.212 ++
   5.213 ++	movl	PTR(VA_PMD_0)(%ebp), %edi
   5.214 ++	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
   5.215 ++	andl	$0x3fe00000, %eax
   5.216 ++	shrl	$18, %eax
   5.217 ++	addl	%edi, %eax
   5.218 ++
   5.219 ++	movl	PTR(PA_PTE_0)(%ebp), %edx
   5.220 ++	orl	$PAGE_ATTR, %edx
   5.221 ++	movl	%edx, (%eax)
   5.222 ++
   5.223 ++	movl	PTR(VA_PTE_0)(%ebp), %edi
   5.224 ++	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
   5.225 ++	andl	$0x001ff000, %eax
   5.226 ++	shrl	$9, %eax
   5.227 ++	addl	%edi, %eax
   5.228 ++
   5.229 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
   5.230 ++	orl	$PAGE_ATTR, %edx
   5.231 ++	movl	%edx, (%eax)
   5.232 ++
   5.233 ++	/* identity map the control page at its physical address */
   5.234 ++
   5.235 ++	movl	PTR(VA_PGD)(%ebp), %edi
   5.236 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
   5.237 ++	andl	$0xc0000000, %eax
   5.238 ++	shrl	$27, %eax
   5.239 ++	addl	%edi, %eax
   5.240 ++
   5.241 ++	movl	PTR(PA_PMD_1)(%ebp), %edx
   5.242 ++	orl	$PAE_PGD_ATTR, %edx
   5.243 ++	movl	%edx, (%eax)
   5.244 ++
   5.245 ++	movl	PTR(VA_PMD_1)(%ebp), %edi
   5.246 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
   5.247 ++	andl	$0x3fe00000, %eax
   5.248 ++	shrl	$18, %eax
   5.249 ++	addl	%edi, %eax
   5.250 ++
   5.251 ++	movl	PTR(PA_PTE_1)(%ebp), %edx
   5.252 ++	orl	$PAGE_ATTR, %edx
   5.253 ++	movl	%edx, (%eax)
   5.254 ++
   5.255 ++	movl	PTR(VA_PTE_1)(%ebp), %edi
   5.256 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
   5.257 ++	andl	$0x001ff000, %eax
   5.258 ++	shrl	$9, %eax
   5.259 ++	addl	%edi, %eax
   5.260 ++
   5.261 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
   5.262 ++	orl	$PAGE_ATTR, %edx
   5.263 ++	movl	%edx, (%eax)
   5.264 ++#else
   5.265 ++	/* map the control page at its virtual address */
   5.266 ++
   5.267 ++	movl	PTR(VA_PGD)(%ebp), %edi
   5.268 ++	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
   5.269 ++	andl	$0xffc00000, %eax
   5.270 ++	shrl	$20, %eax
   5.271 ++	addl	%edi, %eax
   5.272 ++
   5.273 ++	movl	PTR(PA_PTE_0)(%ebp), %edx
   5.274 ++	orl	$PAGE_ATTR, %edx
   5.275 ++	movl	%edx, (%eax)
   5.276 ++
   5.277 ++	movl	PTR(VA_PTE_0)(%ebp), %edi
   5.278 ++	movl	PTR(VA_CONTROL_PAGE)(%ebp), %eax
   5.279 ++	andl	$0x003ff000, %eax
   5.280 ++	shrl	$10, %eax
   5.281 ++	addl	%edi, %eax
   5.282 ++
   5.283 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
   5.284 ++	orl	$PAGE_ATTR, %edx
   5.285 ++	movl	%edx, (%eax)
   5.286 ++
   5.287 ++	/* identity map the control page at its physical address */
   5.288 ++
   5.289 ++	movl	PTR(VA_PGD)(%ebp), %edi
   5.290 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
   5.291 ++	andl	$0xffc00000, %eax
   5.292 ++	shrl	$20, %eax
   5.293 ++	addl	%edi, %eax
   5.294 ++
   5.295 ++	movl	PTR(PA_PTE_1)(%ebp), %edx
   5.296 ++	orl	$PAGE_ATTR, %edx
   5.297 ++	movl	%edx, (%eax)
   5.298 ++
   5.299 ++	movl	PTR(VA_PTE_1)(%ebp), %edi
   5.300 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %eax
   5.301 ++	andl	$0x003ff000, %eax
   5.302 ++	shrl	$10, %eax
   5.303 ++	addl	%edi, %eax
   5.304 ++
   5.305 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edx
   5.306 ++	orl	$PAGE_ATTR, %edx
   5.307 ++	movl	%edx, (%eax)
   5.308 ++#endif
   5.309 + 
   5.310 +-	/*
   5.311 +-	 * Must be relocatable PIC code callable as a C function, that once
   5.312 +-	 * it starts can not use the previous processes stack.
   5.313 +-	 */
   5.314 +-	.globl relocate_new_kernel
   5.315 + relocate_new_kernel:
   5.316 + 	/* read the arguments and say goodbye to the stack */
   5.317 + 	movl  4(%esp), %ebx /* page_list */
   5.318 +-	movl  8(%esp), %ebp /* reboot_code_buffer */
   5.319 ++	movl  8(%esp), %ebp /* list of pages */
   5.320 + 	movl  12(%esp), %edx /* start address */
   5.321 + 	movl  16(%esp), %ecx /* cpu_has_pae */
   5.322 + 
   5.323 +@@ -24,11 +146,26 @@ relocate_new_kernel:
   5.324 + 	pushl $0
   5.325 + 	popfl
   5.326 + 
   5.327 +-	/* set a new stack at the bottom of our page... */
   5.328 +-	lea   4096(%ebp), %esp
   5.329 ++	/* get physical address of control page now */
   5.330 ++	/* this is impossible after page table switch */
   5.331 ++	movl	PTR(PA_CONTROL_PAGE)(%ebp), %edi
   5.332 ++
   5.333 ++	/* switch to new set of page tables */
   5.334 ++	movl	PTR(PA_PGD)(%ebp), %eax
   5.335 ++	movl	%eax, %cr3
   5.336 ++
   5.337 ++	/* setup a new stack at the end of the physical control page */
   5.338 ++	lea	4096(%edi), %esp
   5.339 + 
   5.340 +-	/* store the parameters back on the stack */
   5.341 +-	pushl   %edx /* store the start address */
   5.342 ++	/* jump to identity mapped page */
   5.343 ++	movl    %edi, %eax
   5.344 ++	addl    $(identity_mapped - relocate_kernel), %eax
   5.345 ++	pushl   %eax
   5.346 ++	ret
   5.347 ++
   5.348 ++identity_mapped:
   5.349 ++	/* store the start address on the stack */
   5.350 ++	pushl   %edx
   5.351 + 
   5.352 + 	/* Set cr0 to a known state:
   5.353 + 	 * 31 0 == Paging disabled
   5.354 +@@ -113,8 +250,3 @@ relocate_new_kernel:
   5.355 + 	xorl    %edi, %edi
   5.356 + 	xorl    %ebp, %ebp
   5.357 + 	ret
   5.358 +-relocate_new_kernel_end:
   5.359 +-
   5.360 +-	.globl relocate_new_kernel_size
   5.361 +-relocate_new_kernel_size:
   5.362 +-	.long relocate_new_kernel_end - relocate_new_kernel
   5.363 +--- a/include/asm-i386/kexec.h
   5.364 ++++ b/include/asm-i386/kexec.h
   5.365 +@@ -1,6 +1,26 @@
   5.366 + #ifndef _I386_KEXEC_H
   5.367 + #define _I386_KEXEC_H
   5.368 + 
   5.369 ++#define PA_CONTROL_PAGE  0
   5.370 ++#define VA_CONTROL_PAGE  1
   5.371 ++#define PA_PGD           2
   5.372 ++#define VA_PGD           3
   5.373 ++#define PA_PTE_0         4
   5.374 ++#define VA_PTE_0         5
   5.375 ++#define PA_PTE_1         6
   5.376 ++#define VA_PTE_1         7
   5.377 ++#ifdef CONFIG_X86_PAE
   5.378 ++#define PA_PMD_0         8
   5.379 ++#define VA_PMD_0         9
   5.380 ++#define PA_PMD_1         10
   5.381 ++#define VA_PMD_1         11
   5.382 ++#define PAGES_NR         12
   5.383 ++#else
   5.384 ++#define PAGES_NR         8
   5.385 ++#endif
   5.386 ++
   5.387 ++#ifndef __ASSEMBLY__
   5.388 ++
   5.389 + #include <asm/fixmap.h>
   5.390 + #include <asm/ptrace.h>
   5.391 + #include <asm/string.h>
   5.392 +@@ -72,5 +92,12 @@ static inline void crash_setup_regs(stru
   5.393 +                newregs->eip = (unsigned long)current_text_addr();
   5.394 +        }
   5.395 + }
   5.396 ++asmlinkage NORET_TYPE void
   5.397 ++relocate_kernel(unsigned long indirection_page,
   5.398 ++		unsigned long control_page,
   5.399 ++		unsigned long start_address,
   5.400 ++		unsigned int has_pae) ATTRIB_NORET;
   5.401 ++
   5.402 ++#endif /* __ASSEMBLY__ */
   5.403 + 
   5.404 + #endif /* _I386_KEXEC_H */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch	Thu Nov 30 12:38:51 2006 +0000
     6.3 @@ -0,0 +1,169 @@
     6.4 +kexec: Move asm segment handling code to the assembly file (i386)
     6.5 +
     6.6 +This patch moves the idt, gdt, and segment handling code from machine_kexec.c
     6.7 +to relocate_kernel.S. The main reason behind this move is to avoid code 
     6.8 +duplication in the Xen hypervisor. With this patch all code required to kexec
     6.9 +is put on the control page.
    6.10 +
    6.11 +On top of that this patch also counts as a cleanup - I think it is much
    6.12 +nicer to write assembly directly in assembly files than wrap inline assembly
    6.13 +in C functions for no apparent reason.
    6.14 +
    6.15 +Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
    6.16 +---
    6.17 +
    6.18 + Applies to 2.6.19-rc1.
    6.19 +
    6.20 + machine_kexec.c   |   59 -----------------------------------------------------
    6.21 + relocate_kernel.S |   58 +++++++++++++++++++++++++++++++++++++++++++++++-----
    6.22 + 2 files changed, 53 insertions(+), 64 deletions(-)
    6.23 +
    6.24 +--- 0002/arch/i386/kernel/machine_kexec.c
    6.25 ++++ work/arch/i386/kernel/machine_kexec.c	2006-10-05 15:49:08.000000000 +0900
    6.26 +@@ -29,48 +29,6 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED
    6.27 + static u32 kexec_pte0[1024] PAGE_ALIGNED;
    6.28 + static u32 kexec_pte1[1024] PAGE_ALIGNED;
    6.29 + 
    6.30 +-static void set_idt(void *newidt, __u16 limit)
    6.31 +-{
    6.32 +-	struct Xgt_desc_struct curidt;
    6.33 +-
    6.34 +-	/* ia32 supports unaliged loads & stores */
    6.35 +-	curidt.size    = limit;
    6.36 +-	curidt.address = (unsigned long)newidt;
    6.37 +-
    6.38 +-	load_idt(&curidt);
    6.39 +-};
    6.40 +-
    6.41 +-
    6.42 +-static void set_gdt(void *newgdt, __u16 limit)
    6.43 +-{
    6.44 +-	struct Xgt_desc_struct curgdt;
    6.45 +-
    6.46 +-	/* ia32 supports unaligned loads & stores */
    6.47 +-	curgdt.size    = limit;
    6.48 +-	curgdt.address = (unsigned long)newgdt;
    6.49 +-
    6.50 +-	load_gdt(&curgdt);
    6.51 +-};
    6.52 +-
    6.53 +-static void load_segments(void)
    6.54 +-{
    6.55 +-#define __STR(X) #X
    6.56 +-#define STR(X) __STR(X)
    6.57 +-
    6.58 +-	__asm__ __volatile__ (
    6.59 +-		"\tljmp $"STR(__KERNEL_CS)",$1f\n"
    6.60 +-		"\t1:\n"
    6.61 +-		"\tmovl $"STR(__KERNEL_DS)",%%eax\n"
    6.62 +-		"\tmovl %%eax,%%ds\n"
    6.63 +-		"\tmovl %%eax,%%es\n"
    6.64 +-		"\tmovl %%eax,%%fs\n"
    6.65 +-		"\tmovl %%eax,%%gs\n"
    6.66 +-		"\tmovl %%eax,%%ss\n"
    6.67 +-		::: "eax", "memory");
    6.68 +-#undef STR
    6.69 +-#undef __STR
    6.70 +-}
    6.71 +-
    6.72 + /*
    6.73 +  * A architecture hook called to validate the
    6.74 +  * proposed image and prepare the control pages
    6.75 +@@ -127,23 +85,6 @@ NORET_TYPE void machine_kexec(struct kim
    6.76 + 	page_list[PA_PTE_1] = __pa(kexec_pte1);
    6.77 + 	page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
    6.78 + 
    6.79 +-	/* The segment registers are funny things, they have both a
    6.80 +-	 * visible and an invisible part.  Whenever the visible part is
    6.81 +-	 * set to a specific selector, the invisible part is loaded
    6.82 +-	 * with from a table in memory.  At no other time is the
    6.83 +-	 * descriptor table in memory accessed.
    6.84 +-	 *
    6.85 +-	 * I take advantage of this here by force loading the
    6.86 +-	 * segments, before I zap the gdt with an invalid value.
    6.87 +-	 */
    6.88 +-	load_segments();
    6.89 +-	/* The gdt & idt are now invalid.
    6.90 +-	 * If you want to load them you must set up your own idt & gdt.
    6.91 +-	 */
    6.92 +-	set_gdt(phys_to_virt(0),0);
    6.93 +-	set_idt(phys_to_virt(0),0);
    6.94 +-
    6.95 +-	/* now call it */
    6.96 + 	relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
    6.97 + 			image->start, cpu_has_pae);
    6.98 + }
    6.99 +--- 0002/arch/i386/kernel/relocate_kernel.S
   6.100 ++++ work/arch/i386/kernel/relocate_kernel.S	2006-10-05 16:03:21.000000000 +0900
   6.101 +@@ -154,14 +154,45 @@ relocate_new_kernel:
   6.102 + 	movl	PTR(PA_PGD)(%ebp), %eax
   6.103 + 	movl	%eax, %cr3
   6.104 + 
   6.105 ++	/* setup idt */
   6.106 ++	movl	%edi, %eax
   6.107 ++	addl	$(idt_48 - relocate_kernel), %eax
   6.108 ++	lidtl	(%eax)
   6.109 ++
   6.110 ++	/* setup gdt */
   6.111 ++	movl	%edi, %eax
   6.112 ++	addl	$(gdt - relocate_kernel), %eax
   6.113 ++	movl	%edi, %esi
   6.114 ++	addl	$((gdt_48 - relocate_kernel) + 2), %esi
   6.115 ++	movl	%eax, (%esi)
   6.116 ++	
   6.117 ++	movl	%edi, %eax
   6.118 ++	addl	$(gdt_48 - relocate_kernel), %eax
   6.119 ++	lgdtl	(%eax)
   6.120 ++
   6.121 ++	/* setup data segment registers */
   6.122 ++	mov	$(gdt_ds - gdt), %eax
   6.123 ++	mov	%eax, %ds
   6.124 ++	mov	%eax, %es
   6.125 ++	mov	%eax, %fs
   6.126 ++	mov	%eax, %gs
   6.127 ++	mov	%eax, %ss
   6.128 ++	
   6.129 + 	/* setup a new stack at the end of the physical control page */
   6.130 + 	lea	4096(%edi), %esp
   6.131 + 
   6.132 +-	/* jump to identity mapped page */
   6.133 +-	movl    %edi, %eax
   6.134 +-	addl    $(identity_mapped - relocate_kernel), %eax
   6.135 +-	pushl   %eax
   6.136 +-	ret
   6.137 ++	/* load new code segment and jump to identity mapped page */
   6.138 ++	movl	%edi, %esi
   6.139 ++	xorl	%eax, %eax
   6.140 ++	pushl	%eax
   6.141 ++	pushl	%esi
   6.142 ++	pushl	%eax
   6.143 ++	movl	$(gdt_cs - gdt), %eax
   6.144 ++	pushl	%eax	
   6.145 ++	movl	%edi, %eax
   6.146 ++	addl	$(identity_mapped - relocate_kernel),%eax
   6.147 ++	pushl	%eax
   6.148 ++	iretl
   6.149 + 
   6.150 + identity_mapped:
   6.151 + 	/* store the start address on the stack */
   6.152 +@@ -250,3 +281,20 @@ identity_mapped:
   6.153 + 	xorl    %edi, %edi
   6.154 + 	xorl    %ebp, %ebp
   6.155 + 	ret
   6.156 ++
   6.157 ++	.align	16
   6.158 ++gdt:
   6.159 ++	.quad	0x0000000000000000	/* NULL descriptor */
   6.160 ++gdt_cs:	
   6.161 ++	.quad	0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
   6.162 ++gdt_ds:
   6.163 ++	.quad	0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */
   6.164 ++gdt_end:
   6.165 ++	
   6.166 ++gdt_48:
   6.167 ++	.word	gdt_end - gdt - 1	/* limit */
   6.168 ++	.long	0			/* base - filled in by code above */
   6.169 ++
   6.170 ++idt_48:
   6.171 ++	.word	0			/* limit */
   6.172 ++	.long	0			/* base */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-xen-i386.patch	Thu Nov 30 12:38:51 2006 +0000
     7.3 @@ -0,0 +1,108 @@
     7.4 +--- 0001/arch/i386/kernel/crash.c
     7.5 ++++ work/arch/i386/kernel/crash.c
     7.6 +@@ -90,6 +90,7 @@ static void crash_save_self(struct pt_re
     7.7 + 	crash_save_this_cpu(regs, cpu);
     7.8 + }
     7.9 + 
    7.10 ++#ifndef CONFIG_XEN
    7.11 + #ifdef CONFIG_SMP
    7.12 + static atomic_t waiting_for_crash_ipi;
    7.13 + 
    7.14 +@@ -158,6 +159,7 @@ static void nmi_shootdown_cpus(void)
    7.15 + 	/* There are no cpus to shootdown */
    7.16 + }
    7.17 + #endif
    7.18 ++#endif /* CONFIG_XEN */
    7.19 + 
    7.20 + void machine_crash_shutdown(struct pt_regs *regs)
    7.21 + {
    7.22 +@@ -174,10 +176,12 @@ void machine_crash_shutdown(struct pt_re
    7.23 + 
    7.24 + 	/* Make a note of crashing cpu. Will be used in NMI callback.*/
    7.25 + 	crashing_cpu = smp_processor_id();
    7.26 ++#ifndef CONFIG_XEN
    7.27 + 	nmi_shootdown_cpus();
    7.28 + 	lapic_shutdown();
    7.29 + #if defined(CONFIG_X86_IO_APIC)
    7.30 + 	disable_IO_APIC();
    7.31 + #endif
    7.32 ++#endif /* CONFIG_XEN */
    7.33 + 	crash_save_self(regs);
    7.34 + }
    7.35 +--- 0007/arch/i386/kernel/machine_kexec.c
    7.36 ++++ work/arch/i386/kernel/machine_kexec.c
    7.37 +@@ -19,6 +19,10 @@
    7.38 + #include <asm/desc.h>
    7.39 + #include <asm/system.h>
    7.40 + 
    7.41 ++#ifdef CONFIG_XEN
    7.42 ++#include <xen/interface/kexec.h>
    7.43 ++#endif
    7.44 ++
    7.45 + #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
    7.46 + static u32 kexec_pgd[1024] PAGE_ALIGNED;
    7.47 + #ifdef CONFIG_X86_PAE
    7.48 +@@ -28,6 +32,40 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED
    7.49 + static u32 kexec_pte0[1024] PAGE_ALIGNED;
    7.50 + static u32 kexec_pte1[1024] PAGE_ALIGNED;
    7.51 + 
    7.52 ++#ifdef CONFIG_XEN
    7.53 ++
    7.54 ++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
    7.55 ++
    7.56 ++#if PAGES_NR > KEXEC_XEN_NO_PAGES
    7.57 ++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
    7.58 ++#endif
    7.59 ++
    7.60 ++#if PA_CONTROL_PAGE != 0
    7.61 ++#error PA_CONTROL_PAGE is non zero - Xen support will break
    7.62 ++#endif
    7.63 ++
    7.64 ++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
    7.65 ++{
    7.66 ++	void *control_page;
    7.67 ++
    7.68 ++	memset(xki->page_list, 0, sizeof(xki->page_list));
    7.69 ++
    7.70 ++	control_page = page_address(image->control_code_page);
    7.71 ++	memcpy(control_page, relocate_kernel, PAGE_SIZE);
    7.72 ++
    7.73 ++	xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
    7.74 ++	xki->page_list[PA_PGD] = __ma(kexec_pgd);
    7.75 ++#ifdef CONFIG_X86_PAE
    7.76 ++	xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
    7.77 ++	xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
    7.78 ++#endif
    7.79 ++	xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
    7.80 ++	xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
    7.81 ++
    7.82 ++}
    7.83 ++
    7.84 ++#endif /* CONFIG_XEN */
    7.85 ++
    7.86 + /*
    7.87 +  * A architecture hook called to validate the
    7.88 +  * proposed image and prepare the control pages
    7.89 +--- 0006/include/asm-i386/kexec.h
    7.90 ++++ work/include/asm-i386/kexec.h
    7.91 +@@ -98,6 +98,20 @@ relocate_kernel(unsigned long indirectio
    7.92 + 		unsigned long start_address,
    7.93 + 		unsigned int has_pae) ATTRIB_NORET;
    7.94 + 
    7.95 ++
    7.96 ++/* Under Xen we need to work with machine addresses. These macros give the
    7.97 ++ * machine address of a certain page to the generic kexec code instead of 
    7.98 ++ * the pseudo physical address which would be given by the default macros.
    7.99 ++ */
   7.100 ++
   7.101 ++#ifdef CONFIG_XEN
   7.102 ++#define KEXEC_ARCH_HAS_PAGE_MACROS
   7.103 ++#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
   7.104 ++#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
   7.105 ++#define kexec_virt_to_phys(addr) virt_to_machine(addr)
   7.106 ++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
   7.107 ++#endif
   7.108 ++
   7.109 + #endif /* __ASSEMBLY__ */
   7.110 + 
   7.111 + #endif /* _I386_KEXEC_H */
     8.1 --- a/patches/linux-2.6.16.33/series	Thu Nov 30 12:38:51 2006 +0000
     8.2 +++ b/patches/linux-2.6.16.33/series	Thu Nov 30 12:38:51 2006 +0000
     8.3 @@ -1,6 +1,9 @@
     8.4  kexec-generic.patch
     8.5  git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch
     8.6  git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch
     8.7 +git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch
     8.8 +linux-2.6.19-rc1-kexec-move_segment_code-i386.patch
     8.9 +linux-2.6.19-rc1-kexec-xen-i386.patch
    8.10  blktap-aio-16_03_06.patch
    8.11  device_bind.patch
    8.12  fix-hz-suspend.patch
     9.1 --- a/xen/arch/x86/x86_32/entry.S	Thu Nov 30 12:38:51 2006 +0000
     9.2 +++ b/xen/arch/x86/x86_32/entry.S	Thu Nov 30 12:38:51 2006 +0000
     9.3 @@ -659,6 +659,7 @@ ENTRY(hypercall_table)
     9.4          .long do_hvm_op
     9.5          .long do_sysctl             /* 35 */
     9.6          .long do_domctl
     9.7 +        .long do_kexec_op
     9.8          .rept NR_hypercalls-((.-hypercall_table)/4)
     9.9          .long do_ni_hypercall
    9.10          .endr
    9.11 @@ -701,6 +702,7 @@ ENTRY(hypercall_args_table)
    9.12          .byte 2 /* do_hvm_op            */
    9.13          .byte 1 /* do_sysctl            */  /* 35 */
    9.14          .byte 1 /* do_domctl            */
    9.15 +        .byte 2 /* do_kexec_op          */
    9.16          .rept NR_hypercalls-(.-hypercall_args_table)
    9.17          .byte 0 /* do_ni_hypercall      */
    9.18          .endr
    10.1 --- a/xen/include/asm-x86/x86_32/elf.h	Thu Nov 30 12:38:51 2006 +0000
    10.2 +++ b/xen/include/asm-x86/x86_32/elf.h	Thu Nov 30 12:38:51 2006 +0000
    10.3 @@ -1,16 +1,62 @@
    10.4  #ifndef __X86_32_ELF_H__
    10.5  #define __X86_32_ELF_H__
    10.6  
    10.7 -#include <xen/lib.h>       /* for printk() used in stub */
    10.8 +#include <asm/processor.h>
    10.9  
   10.10  typedef struct {
   10.11 -    unsigned long dummy;
   10.12 +    unsigned long ebx;
   10.13 +    unsigned long ecx;
   10.14 +    unsigned long edx;
   10.15 +    unsigned long esi;
   10.16 +    unsigned long edi;
   10.17 +    unsigned long ebp;
   10.18 +    unsigned long eax;
   10.19 +    unsigned long ds;
   10.20 +    unsigned long es;
   10.21 +    unsigned long fs;
   10.22 +    unsigned long gs;
   10.23 +    unsigned long orig_eax;
   10.24 +    unsigned long eip;
   10.25 +    unsigned long cs;
   10.26 +    unsigned long eflags;
   10.27 +    unsigned long esp;
   10.28 +    unsigned long ss;
   10.29  } ELF_Gregset;
   10.30  
   10.31  extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
   10.32                                        crash_xen_core_t *xen_core_regs)
   10.33  {
   10.34 -    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   10.35 +    unsigned long tmp;
   10.36 +
   10.37 +    asm volatile("movl %%ebx,%0" : "=m"(core_regs->ebx));
   10.38 +    asm volatile("movl %%ecx,%0" : "=m"(core_regs->ecx));
   10.39 +    asm volatile("movl %%edx,%0" : "=m"(core_regs->edx));
   10.40 +    asm volatile("movl %%esi,%0" : "=m"(core_regs->esi));
   10.41 +    asm volatile("movl %%edi,%0" : "=m"(core_regs->edi));
   10.42 +    asm volatile("movl %%ebp,%0" : "=m"(core_regs->ebp));
   10.43 +    asm volatile("movl %%eax,%0" : "=m"(core_regs->eax));
   10.44 +    asm volatile("movw %%ds, %%ax;" :"=a"(core_regs->ds));
   10.45 +    asm volatile("movw %%es, %%ax;" :"=a"(core_regs->es));
   10.46 +    asm volatile("movw %%fs, %%ax;" :"=a"(core_regs->fs));
   10.47 +    asm volatile("movw %%gs, %%ax;" :"=a"(core_regs->gs));
   10.48 +    /* orig_eax not filled in for now */
   10.49 +    core_regs->eip = (unsigned long)current_text_addr();
   10.50 +    asm volatile("movw %%cs, %%ax;" :"=a"(core_regs->cs));
   10.51 +    asm volatile("pushfl; popl %0" :"=m"(core_regs->eflags));
   10.52 +    asm volatile("movl %%esp,%0" : "=m"(core_regs->esp));
   10.53 +    asm volatile("movw %%ss, %%ax;" :"=a"(core_regs->ss));
   10.54 +
   10.55 +    asm volatile("mov %%cr0, %0" : "=r" (tmp) : );
   10.56 +    xen_core_regs->cr0 = tmp;
   10.57 +
   10.58 +    asm volatile("mov %%cr2, %0" : "=r" (tmp) : );
   10.59 +    xen_core_regs->cr2 = tmp;
   10.60 +
   10.61 +    asm volatile("mov %%cr3, %0" : "=r" (tmp) : );
   10.62 +    xen_core_regs->cr3 = tmp;
   10.63 +
   10.64 +    asm volatile("mov %%cr4, %0" : "=r" (tmp) : );
   10.65 +    xen_core_regs->cr4 = tmp;
   10.66  }
   10.67  
   10.68  #endif /* __X86_32_ELF_H__ */
    11.1 --- a/xen/include/asm-x86/x86_32/kexec.h	Thu Nov 30 12:38:51 2006 +0000
    11.2 +++ b/xen/include/asm-x86/x86_32/kexec.h	Thu Nov 30 12:38:51 2006 +0000
    11.3 @@ -1,17 +1,33 @@
    11.4 -#ifndef __X86_32_KEXEC_H__
    11.5 -#define __X86_32_KEXEC_H__
    11.6 +/******************************************************************************
    11.7 + * kexec.h
    11.8 + * 
    11.9 + * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1
   11.10 + *
   11.11 + */
   11.12 +  
   11.13 +#ifndef __X86_KEXEC_X86_32_H__
   11.14 +#define __X86_KEXEC_X86_32_H__
   11.15  
   11.16 -#include <xen/lib.h>       /* for printk() used in stub */
   11.17  #include <xen/types.h>
   11.18 -#include <public/xen.h>
   11.19  #include <xen/kexec.h>
   11.20 +#include <asm/fixmap.h>
   11.21 +
   11.22 +typedef asmlinkage void (*relocate_new_kernel_t)(
   11.23 +               unsigned long indirection_page,
   11.24 +               unsigned long page_list,
   11.25 +               unsigned long start_address,
   11.26 +               unsigned int has_pae);
   11.27  
   11.28  static inline void machine_kexec(xen_kexec_image_t *image)
   11.29  {
   11.30 -    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   11.31 +    relocate_new_kernel_t rnk;
   11.32 +
   11.33 +    rnk = (relocate_new_kernel_t) image->page_list[1];
   11.34 +    (*rnk)(image->indirection_page, (unsigned long)image->page_list, 
   11.35 +           image->start_address, (unsigned long)cpu_has_pae);
   11.36  }
   11.37  
   11.38 -#endif /* __X86_32_KEXEC_H__ */
   11.39 +#endif /* __X86_KEXEC_X86_32_H__ */
   11.40  
   11.41  /*
   11.42   * Local variables: