ia64/xen-unstable

changeset 12676:c988f781817d

[XEN] Kexec / Kdump: Generic code

This patch implements the generic portion of the Kexec / Kdump port to 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:50 2006 +0000 (2006-11-30)
parents d1b0a5adaeab
children 2b43fb3afb3e
files linux-2.6-xen-sparse/drivers/xen/core/Makefile linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c patches/linux-2.6.16.33/kexec-generic.patch patches/linux-2.6.16.33/series xen/arch/ia64/xen/Makefile xen/arch/ia64/xen/crash.c xen/arch/ia64/xen/machine_kexec.c xen/arch/powerpc/Makefile xen/arch/powerpc/crash.c xen/arch/powerpc/machine_kexec.c xen/arch/x86/Makefile xen/arch/x86/crash.c xen/arch/x86/machine_kexec.c xen/common/Makefile xen/common/kexec.c xen/common/page_alloc.c xen/drivers/char/console.c xen/include/asm-ia64/elf.h xen/include/asm-ia64/kexec.h xen/include/asm-powerpc/elf.h xen/include/asm-powerpc/kexec.h xen/include/asm-x86/elf.h xen/include/asm-x86/kexec.h xen/include/public/elfnote.h xen/include/public/kexec.h xen/include/xen/elf.h xen/include/xen/elfcore.h xen/include/xen/hypercall.h xen/include/xen/kexec.h xen/include/xen/mm.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/Makefile	Wed Nov 29 23:40:40 2006 +0000
     1.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/Makefile	Thu Nov 30 12:38:50 2006 +0000
     1.3 @@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SYSFS)		+= xen_sysfs.o
     1.4  obj-$(CONFIG_XEN_SKBUFF)	+= skbuff.o
     1.5  obj-$(CONFIG_XEN_REBOOT)	+= reboot.o machine_reboot.o
     1.6  obj-$(CONFIG_XEN_SMPBOOT)	+= smpboot.o
     1.7 +obj-$(CONFIG_KEXEC)		+= machine_kexec.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c	Thu Nov 30 12:38:50 2006 +0000
     2.3 @@ -0,0 +1,170 @@
     2.4 +/*
     2.5 + * drivers/xen/core/machine_kexec.c 
     2.6 + * handle transition of Linux booting another kernel
     2.7 + */
     2.8 +
     2.9 +#include <linux/kexec.h>
    2.10 +#include <xen/interface/kexec.h>
    2.11 +#include <linux/mm.h>
    2.12 +#include <linux/bootmem.h>
    2.13 +#include <asm/hypercall.h>
    2.14 +
    2.15 +extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
    2.16 +					 struct kimage *image);
    2.17 +
    2.18 +int xen_max_nr_phys_cpus;
    2.19 +struct resource xen_hypervisor_res;
    2.20 +struct resource *xen_phys_cpus;
    2.21 +
    2.22 +void xen_machine_kexec_setup_resources(void)
    2.23 +{
    2.24 +	xen_kexec_range_t range;
    2.25 +	struct resource *res;
    2.26 +	int k = 0;
    2.27 +
    2.28 +	/* determine maximum number of physical cpus */
    2.29 +
    2.30 +	while (1) {
    2.31 +		memset(&range, 0, sizeof(range));
    2.32 +		range.range = KEXEC_RANGE_MA_CPU;
    2.33 +		range.nr = k;
    2.34 +
    2.35 +		if (HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range))
    2.36 +			break;
    2.37 +
    2.38 +		k++;
    2.39 +	}
    2.40 +
    2.41 +	xen_max_nr_phys_cpus = k;
    2.42 +
    2.43 +	/* allocate xen_phys_cpus */
    2.44 +
    2.45 +	xen_phys_cpus = alloc_bootmem_low(k * sizeof(struct resource));
    2.46 +	BUG_ON(!xen_phys_cpus);
    2.47 +
    2.48 +	/* fill in xen_phys_cpus with per-cpu crash note information */
    2.49 +
    2.50 +	for (k = 0; k < xen_max_nr_phys_cpus; k++) {
    2.51 +		memset(&range, 0, sizeof(range));
    2.52 +		range.range = KEXEC_RANGE_MA_CPU;
    2.53 +		range.nr = k;
    2.54 +
    2.55 +		BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
    2.56 +
    2.57 +		res = xen_phys_cpus + k;
    2.58 +
    2.59 +		memset(res, 0, sizeof(*res));
    2.60 +		res->name = "Crash note";
    2.61 +		res->start = range.start;
    2.62 +		res->end = range.start + range.size - 1;
    2.63 +		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
    2.64 +	}
    2.65 +
    2.66 +	/* fill in xen_hypervisor_res with hypervisor machine address range */
    2.67 +
    2.68 +	memset(&range, 0, sizeof(range));
    2.69 +	range.range = KEXEC_RANGE_MA_XEN;
    2.70 +
    2.71 +	BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
    2.72 +
    2.73 +	xen_hypervisor_res.name = "Hypervisor code and data";
    2.74 +	xen_hypervisor_res.start = range.start;
    2.75 +	xen_hypervisor_res.end = range.start + range.size - 1;
    2.76 +	xen_hypervisor_res.flags = IORESOURCE_BUSY | IORESOURCE_MEM;
    2.77 +
    2.78 +	/* fill in crashk_res if range is reserved by hypervisor */
    2.79 +
    2.80 +	memset(&range, 0, sizeof(range));
    2.81 +	range.range = KEXEC_RANGE_MA_CRASH;
    2.82 +
    2.83 +	BUG_ON(HYPERVISOR_kexec_op(KEXEC_CMD_kexec_get_range, &range));
    2.84 +
    2.85 +	if (range.size) {
    2.86 +		crashk_res.start = range.start;
    2.87 +		crashk_res.end = range.start + range.size - 1;
    2.88 +	}
    2.89 +}
    2.90 +
    2.91 +void xen_machine_kexec_register_resources(struct resource *res)
    2.92 +{
    2.93 +	int k;
    2.94 +
    2.95 +	request_resource(res, &xen_hypervisor_res);
    2.96 +
    2.97 +	for (k = 0; k < xen_max_nr_phys_cpus; k++)
    2.98 +		request_resource(res, xen_phys_cpus + k);
    2.99 +
   2.100 +}
   2.101 +
   2.102 +static void setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
   2.103 +{
   2.104 +	machine_kexec_setup_load_arg(xki, image);
   2.105 +
   2.106 +	xki->indirection_page = image->head;
   2.107 +	xki->start_address = image->start;
   2.108 +}
   2.109 +
   2.110 +/*
   2.111 + * Load the image into xen so xen can kdump itself
   2.112 + * This might have been done in prepare, but prepare
   2.113 + * is currently called too early. It might make sense
   2.114 + * to move prepare, but for now, just add an extra hook.
   2.115 + */
   2.116 +int xen_machine_kexec_load(struct kimage *image)
   2.117 +{
   2.118 +	xen_kexec_load_t xkl;
   2.119 +
   2.120 +	memset(&xkl, 0, sizeof(xkl));
   2.121 +	xkl.type = image->type;
   2.122 +	setup_load_arg(&xkl.image, image);
   2.123 +	return HYPERVISOR_kexec_op(KEXEC_CMD_kexec_load, &xkl);
   2.124 +}
   2.125 +
   2.126 +/*
   2.127 + * Unload the image that was stored by machine_kexec_load()
   2.128 + * This might have been done in machine_kexec_cleanup() but it
   2.129 + * is called too late, and its possible xen could try and kdump
   2.130 + * using resources that have been freed.
   2.131 + */
   2.132 +void xen_machine_kexec_unload(struct kimage *image)
   2.133 +{
   2.134 +	xen_kexec_load_t xkl;
   2.135 +
   2.136 +	memset(&xkl, 0, sizeof(xkl));
   2.137 +	xkl.type = image->type;
   2.138 +	HYPERVISOR_kexec_op(KEXEC_CMD_kexec_unload, &xkl);
   2.139 +}
   2.140 +
   2.141 +/*
   2.142 + * Do not allocate memory (or fail in any way) in machine_kexec().
   2.143 + * We are past the point of no return, committed to rebooting now.
   2.144 + *
   2.145 + * This has the hypervisor move to the prefered reboot CPU, 
   2.146 + * stop all CPUs and kexec. That is it combines machine_shutdown()
   2.147 + * and machine_kexec() in Linux kexec terms.
   2.148 + */
   2.149 +NORET_TYPE void xen_machine_kexec(struct kimage *image)
   2.150 +{
   2.151 +	xen_kexec_exec_t xke;
   2.152 +
   2.153 +	memset(&xke, 0, sizeof(xke));
   2.154 +	xke.type = image->type;
   2.155 +	HYPERVISOR_kexec_op(KEXEC_CMD_kexec, &xke);
   2.156 +	panic("KEXEC_CMD_kexec hypercall should not return\n");
   2.157 +}
   2.158 +
   2.159 +void machine_shutdown(void)
   2.160 +{
   2.161 +	/* do nothing */
   2.162 +}
   2.163 +
   2.164 +
   2.165 +/*
   2.166 + * Local variables:
   2.167 + *  c-file-style: "linux"
   2.168 + *  indent-tabs-mode: t
   2.169 + *  c-indent-level: 8
   2.170 + *  c-basic-offset: 8
   2.171 + *  tab-width: 8
   2.172 + * End:
   2.173 + */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/patches/linux-2.6.16.33/kexec-generic.patch	Thu Nov 30 12:38:50 2006 +0000
     3.3 @@ -0,0 +1,228 @@
     3.4 +--- 0001/include/linux/kexec.h
     3.5 ++++ work/include/linux/kexec.h
     3.6 +@@ -31,6 +31,13 @@
     3.7 + #error KEXEC_ARCH not defined
     3.8 + #endif
     3.9 + 
    3.10 ++#ifndef KEXEC_ARCH_HAS_PAGE_MACROS
    3.11 ++#define kexec_page_to_pfn(page)  page_to_pfn(page)
    3.12 ++#define kexec_pfn_to_page(pfn)   pfn_to_page(pfn)
    3.13 ++#define kexec_virt_to_phys(addr) virt_to_phys(addr)
    3.14 ++#define kexec_phys_to_virt(addr) phys_to_virt(addr)
    3.15 ++#endif
    3.16 ++
    3.17 + /*
    3.18 +  * This structure is used to hold the arguments that are used when loading
    3.19 +  * kernel binaries.
    3.20 +@@ -91,6 +98,13 @@ struct kimage {
    3.21 + extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
    3.22 + extern int machine_kexec_prepare(struct kimage *image);
    3.23 + extern void machine_kexec_cleanup(struct kimage *image);
    3.24 ++#ifdef CONFIG_XEN
    3.25 ++extern int xen_machine_kexec_load(struct kimage *image);
    3.26 ++extern void xen_machine_kexec_unload(struct kimage *image);
    3.27 ++extern NORET_TYPE void xen_machine_kexec(struct kimage *image) ATTRIB_NORET;
    3.28 ++extern void xen_machine_kexec_setup_resources(void);
    3.29 ++extern void xen_machine_kexec_register_resources(struct resource *res);
    3.30 ++#endif
    3.31 + extern asmlinkage long sys_kexec_load(unsigned long entry,
    3.32 + 					unsigned long nr_segments,
    3.33 + 					struct kexec_segment __user *segments,
    3.34 +--- 0001/kernel/kexec.c
    3.35 ++++ work/kernel/kexec.c
    3.36 +@@ -403,7 +403,7 @@ static struct page *kimage_alloc_normal_
    3.37 + 		pages = kimage_alloc_pages(GFP_KERNEL, order);
    3.38 + 		if (!pages)
    3.39 + 			break;
    3.40 +-		pfn   = page_to_pfn(pages);
    3.41 ++		pfn   = kexec_page_to_pfn(pages);
    3.42 + 		epfn  = pfn + count;
    3.43 + 		addr  = pfn << PAGE_SHIFT;
    3.44 + 		eaddr = epfn << PAGE_SHIFT;
    3.45 +@@ -437,6 +437,7 @@ static struct page *kimage_alloc_normal_
    3.46 + 	return pages;
    3.47 + }
    3.48 + 
    3.49 ++#ifndef CONFIG_XEN
    3.50 + static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
    3.51 + 						      unsigned int order)
    3.52 + {
    3.53 +@@ -490,7 +491,7 @@ static struct page *kimage_alloc_crash_c
    3.54 + 		}
    3.55 + 		/* If I don't overlap any segments I have found my hole! */
    3.56 + 		if (i == image->nr_segments) {
    3.57 +-			pages = pfn_to_page(hole_start >> PAGE_SHIFT);
    3.58 ++			pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
    3.59 + 			break;
    3.60 + 		}
    3.61 + 	}
    3.62 +@@ -517,6 +518,13 @@ struct page *kimage_alloc_control_pages(
    3.63 + 
    3.64 + 	return pages;
    3.65 + }
    3.66 ++#else /* !CONFIG_XEN */
    3.67 ++struct page *kimage_alloc_control_pages(struct kimage *image,
    3.68 ++					 unsigned int order)
    3.69 ++{
    3.70 ++	return kimage_alloc_normal_control_pages(image, order);
    3.71 ++}
    3.72 ++#endif
    3.73 + 
    3.74 + static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
    3.75 + {
    3.76 +@@ -532,7 +540,7 @@ static int kimage_add_entry(struct kimag
    3.77 + 			return -ENOMEM;
    3.78 + 
    3.79 + 		ind_page = page_address(page);
    3.80 +-		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
    3.81 ++		*image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
    3.82 + 		image->entry = ind_page;
    3.83 + 		image->last_entry = ind_page +
    3.84 + 				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
    3.85 +@@ -593,13 +601,13 @@ static int kimage_terminate(struct kimag
    3.86 + #define for_each_kimage_entry(image, ptr, entry) \
    3.87 + 	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
    3.88 + 		ptr = (entry & IND_INDIRECTION)? \
    3.89 +-			phys_to_virt((entry & PAGE_MASK)): ptr +1)
    3.90 ++			kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
    3.91 + 
    3.92 + static void kimage_free_entry(kimage_entry_t entry)
    3.93 + {
    3.94 + 	struct page *page;
    3.95 + 
    3.96 +-	page = pfn_to_page(entry >> PAGE_SHIFT);
    3.97 ++	page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
    3.98 + 	kimage_free_pages(page);
    3.99 + }
   3.100 + 
   3.101 +@@ -611,6 +619,10 @@ static void kimage_free(struct kimage *i
   3.102 + 	if (!image)
   3.103 + 		return;
   3.104 + 
   3.105 ++#ifdef CONFIG_XEN
   3.106 ++	xen_machine_kexec_unload(image);
   3.107 ++#endif
   3.108 ++
   3.109 + 	kimage_free_extra_pages(image);
   3.110 + 	for_each_kimage_entry(image, ptr, entry) {
   3.111 + 		if (entry & IND_INDIRECTION) {
   3.112 +@@ -686,7 +698,7 @@ static struct page *kimage_alloc_page(st
   3.113 + 	 * have a match.
   3.114 + 	 */
   3.115 + 	list_for_each_entry(page, &image->dest_pages, lru) {
   3.116 +-		addr = page_to_pfn(page) << PAGE_SHIFT;
   3.117 ++		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
   3.118 + 		if (addr == destination) {
   3.119 + 			list_del(&page->lru);
   3.120 + 			return page;
   3.121 +@@ -701,12 +713,12 @@ static struct page *kimage_alloc_page(st
   3.122 + 		if (!page)
   3.123 + 			return NULL;
   3.124 + 		/* If the page cannot be used file it away */
   3.125 +-		if (page_to_pfn(page) >
   3.126 ++		if (kexec_page_to_pfn(page) >
   3.127 + 				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
   3.128 + 			list_add(&page->lru, &image->unuseable_pages);
   3.129 + 			continue;
   3.130 + 		}
   3.131 +-		addr = page_to_pfn(page) << PAGE_SHIFT;
   3.132 ++		addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
   3.133 + 
   3.134 + 		/* If it is the destination page we want use it */
   3.135 + 		if (addr == destination)
   3.136 +@@ -729,7 +741,7 @@ static struct page *kimage_alloc_page(st
   3.137 + 			struct page *old_page;
   3.138 + 
   3.139 + 			old_addr = *old & PAGE_MASK;
   3.140 +-			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
   3.141 ++			old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
   3.142 + 			copy_highpage(page, old_page);
   3.143 + 			*old = addr | (*old & ~PAGE_MASK);
   3.144 + 
   3.145 +@@ -779,7 +791,7 @@ static int kimage_load_normal_segment(st
   3.146 + 			result  = -ENOMEM;
   3.147 + 			goto out;
   3.148 + 		}
   3.149 +-		result = kimage_add_page(image, page_to_pfn(page)
   3.150 ++		result = kimage_add_page(image, kexec_page_to_pfn(page)
   3.151 + 								<< PAGE_SHIFT);
   3.152 + 		if (result < 0)
   3.153 + 			goto out;
   3.154 +@@ -811,6 +823,7 @@ out:
   3.155 + 	return result;
   3.156 + }
   3.157 + 
   3.158 ++#ifndef CONFIG_XEN
   3.159 + static int kimage_load_crash_segment(struct kimage *image,
   3.160 + 					struct kexec_segment *segment)
   3.161 + {
   3.162 +@@ -833,7 +846,7 @@ static int kimage_load_crash_segment(str
   3.163 + 		char *ptr;
   3.164 + 		size_t uchunk, mchunk;
   3.165 + 
   3.166 +-		page = pfn_to_page(maddr >> PAGE_SHIFT);
   3.167 ++		page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
   3.168 + 		if (page == 0) {
   3.169 + 			result  = -ENOMEM;
   3.170 + 			goto out;
   3.171 +@@ -881,6 +894,13 @@ static int kimage_load_segment(struct ki
   3.172 + 
   3.173 + 	return result;
   3.174 + }
   3.175 ++#else /* CONFIG_XEN */
   3.176 ++static int kimage_load_segment(struct kimage *image,
   3.177 ++				struct kexec_segment *segment)
   3.178 ++{
   3.179 ++	return kimage_load_normal_segment(image, segment);
   3.180 ++}
   3.181 ++#endif
   3.182 + 
   3.183 + /*
   3.184 +  * Exec Kernel system call: for obvious reasons only root may call it.
   3.185 +@@ -991,6 +1011,11 @@ asmlinkage long sys_kexec_load(unsigned 
   3.186 + 		if (result)
   3.187 + 			goto out;
   3.188 + 	}
   3.189 ++#ifdef CONFIG_XEN
   3.190 ++	result = xen_machine_kexec_load(image);
   3.191 ++	if (result)
   3.192 ++		goto out;
   3.193 ++#endif
   3.194 + 	/* Install the new kernel, and  Uninstall the old */
   3.195 + 	image = xchg(dest_image, image);
   3.196 + 
   3.197 +@@ -1045,7 +1070,6 @@ void crash_kexec(struct pt_regs *regs)
   3.198 + 	struct kimage *image;
   3.199 + 	int locked;
   3.200 + 
   3.201 +-
   3.202 + 	/* Take the kexec_lock here to prevent sys_kexec_load
   3.203 + 	 * running on one cpu from replacing the crash kernel
   3.204 + 	 * we are using after a panic on a different cpu.
   3.205 +@@ -1061,7 +1085,11 @@ void crash_kexec(struct pt_regs *regs)
   3.206 + 			struct pt_regs fixed_regs;
   3.207 + 			crash_setup_regs(&fixed_regs, regs);
   3.208 + 			machine_crash_shutdown(&fixed_regs);
   3.209 ++#ifdef CONFIG_XEN
   3.210 ++			xen_machine_kexec(image);
   3.211 ++#else
   3.212 + 			machine_kexec(image);
   3.213 ++#endif
   3.214 + 		}
   3.215 + 		xchg(&kexec_lock, 0);
   3.216 + 	}
   3.217 +--- 0002/kernel/sys.c
   3.218 ++++ work/kernel/sys.c
   3.219 +@@ -435,8 +435,12 @@ void kernel_kexec(void)
   3.220 + 	kernel_restart_prepare(NULL);
   3.221 + 	printk(KERN_EMERG "Starting new kernel\n");
   3.222 + 	machine_shutdown();
   3.223 ++#ifdef CONFIG_XEN
   3.224 ++	xen_machine_kexec(image);
   3.225 ++#else
   3.226 + 	machine_kexec(image);
   3.227 + #endif
   3.228 ++#endif
   3.229 + }
   3.230 + EXPORT_SYMBOL_GPL(kernel_kexec);
   3.231 + 
     4.1 --- a/patches/linux-2.6.16.33/series	Wed Nov 29 23:40:40 2006 +0000
     4.2 +++ b/patches/linux-2.6.16.33/series	Thu Nov 30 12:38:50 2006 +0000
     4.3 @@ -1,3 +1,4 @@
     4.4 +kexec-generic.patch
     4.5  blktap-aio-16_03_06.patch
     4.6  device_bind.patch
     4.7  fix-hz-suspend.patch
     5.1 --- a/xen/arch/ia64/xen/Makefile	Wed Nov 29 23:40:40 2006 +0000
     5.2 +++ b/xen/arch/ia64/xen/Makefile	Thu Nov 30 12:38:50 2006 +0000
     5.3 @@ -1,3 +1,5 @@
     5.4 +obj-y += machine_kexec.o
     5.5 +obj-y += crash.o
     5.6  obj-y += acpi.o
     5.7  obj-y += dom0_ops.o
     5.8  obj-y += domain.o
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/ia64/xen/crash.c	Thu Nov 30 12:38:50 2006 +0000
     6.3 @@ -0,0 +1,19 @@
     6.4 +#include <xen/lib.h>       /* for printk() used in stub */
     6.5 +#include <xen/types.h>
     6.6 +#include <public/kexec.h>
     6.7 +
     6.8 +void machine_crash_shutdown(void)
     6.9 +{
    6.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    6.11 +}
    6.12 +
    6.13 +/*
    6.14 + * Local variables:
    6.15 + * mode: C
    6.16 + * c-set-style: "BSD"
    6.17 + * c-basic-offset: 4
    6.18 + * tab-width: 4
    6.19 + * indent-tabs-mode: nil
    6.20 + * End:
    6.21 + */
    6.22 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/arch/ia64/xen/machine_kexec.c	Thu Nov 30 12:38:50 2006 +0000
     7.3 @@ -0,0 +1,34 @@
     7.4 +#include <xen/lib.h>       /* for printk() used in stubs */
     7.5 +#include <xen/types.h>
     7.6 +#include <public/kexec.h>
     7.7 +
     7.8 +int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
     7.9 +{
    7.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    7.11 +    return -1;
    7.12 +}
    7.13 +
    7.14 +void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
    7.15 +{
    7.16 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    7.17 +}
    7.18 +
    7.19 +void machine_kexec(xen_kexec_image_t *image)
    7.20 +{
    7.21 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    7.22 +}
    7.23 +
    7.24 +void machine_shutdown(xen_kexec_image_t *image)
    7.25 +{
    7.26 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    7.27 +}
    7.28 +
    7.29 +/*
    7.30 + * Local variables:
    7.31 + * mode: C
    7.32 + * c-set-style: "BSD"
    7.33 + * c-basic-offset: 4
    7.34 + * tab-width: 4
    7.35 + * indent-tabs-mode: nil
    7.36 + * End:
    7.37 + */
     8.1 --- a/xen/arch/powerpc/Makefile	Wed Nov 29 23:40:40 2006 +0000
     8.2 +++ b/xen/arch/powerpc/Makefile	Thu Nov 30 12:38:50 2006 +0000
     8.3 @@ -40,6 +40,8 @@ obj-y += smp-tbsync.o
     8.4  obj-y += sysctl.o
     8.5  obj-y += time.o
     8.6  obj-y += usercopy.o
     8.7 +obj-y += machine_kexec.o
     8.8 +obj-y += crash.o
     8.9  
    8.10  obj-$(debug) += 0opt.o
    8.11  obj-$(crash_debug) += gdbstub.o
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/arch/powerpc/crash.c	Thu Nov 30 12:38:50 2006 +0000
     9.3 @@ -0,0 +1,19 @@
     9.4 +#include <xen/lib.h>       /* for printk() used in stub */
     9.5 +#include <xen/types.h>
     9.6 +#include <public/kexec.h>
     9.7 +
     9.8 +void machine_crash_shutdown(void)
     9.9 +{
    9.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
    9.11 +}
    9.12 +
    9.13 +/*
    9.14 + * Local variables:
    9.15 + * mode: C
    9.16 + * c-set-style: "BSD"
    9.17 + * c-basic-offset: 4
    9.18 + * tab-width: 4
    9.19 + * indent-tabs-mode: nil
    9.20 + * End:
    9.21 + */
    9.22 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/arch/powerpc/machine_kexec.c	Thu Nov 30 12:38:50 2006 +0000
    10.3 @@ -0,0 +1,34 @@
    10.4 +#include <xen/lib.h>       /* for printk() used in stubs */
    10.5 +#include <xen/types.h>
    10.6 +#include <public/kexec.h>
    10.7 +
    10.8 +int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
    10.9 +{
   10.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   10.11 +    return -1;
   10.12 +}
   10.13 +
   10.14 +void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
   10.15 +{
   10.16 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   10.17 +}
   10.18 +
   10.19 +void machine_kexec(xen_kexec_image_t *image)
   10.20 +{
   10.21 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   10.22 +}
   10.23 +
   10.24 +void machine_shutdown(xen_kexec_image_t *image)
   10.25 +{
   10.26 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   10.27 +}
   10.28 +
   10.29 +/*
   10.30 + * Local variables:
   10.31 + * mode: C
   10.32 + * c-set-style: "BSD"
   10.33 + * c-basic-offset: 4
   10.34 + * tab-width: 4
   10.35 + * indent-tabs-mode: nil
   10.36 + * End:
   10.37 + */
    11.1 --- a/xen/arch/x86/Makefile	Wed Nov 29 23:40:40 2006 +0000
    11.2 +++ b/xen/arch/x86/Makefile	Thu Nov 30 12:38:50 2006 +0000
    11.3 @@ -43,6 +43,8 @@ obj-y += trampoline.o
    11.4  obj-y += traps.o
    11.5  obj-y += usercopy.o
    11.6  obj-y += x86_emulate.o
    11.7 +obj-y += machine_kexec.o
    11.8 +obj-y += crash.o
    11.9  
   11.10  obj-$(crash_debug) += gdbstub.o
   11.11  
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xen/arch/x86/crash.c	Thu Nov 30 12:38:50 2006 +0000
    12.3 @@ -0,0 +1,19 @@
    12.4 +#include <xen/lib.h>       /* for printk() used in stub */
    12.5 +#include <xen/types.h>
    12.6 +#include <public/kexec.h>
    12.7 +
    12.8 +void machine_crash_shutdown(void)
    12.9 +{
   12.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   12.11 +}
   12.12 +
   12.13 +/*
   12.14 + * Local variables:
   12.15 + * mode: C
   12.16 + * c-set-style: "BSD"
   12.17 + * c-basic-offset: 4
   12.18 + * tab-width: 4
   12.19 + * indent-tabs-mode: nil
   12.20 + * End:
   12.21 + */
   12.22 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen/arch/x86/machine_kexec.c	Thu Nov 30 12:38:50 2006 +0000
    13.3 @@ -0,0 +1,34 @@
    13.4 +#include <xen/lib.h>       /* for printk() used in stubs */
    13.5 +#include <xen/types.h>
    13.6 +#include <public/kexec.h>
    13.7 +
    13.8 +int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
    13.9 +{
   13.10 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   13.11 +    return -1;
   13.12 +}
   13.13 +
   13.14 +void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image)
   13.15 +{
   13.16 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   13.17 +}
   13.18 +
   13.19 +void machine_kexec(xen_kexec_image_t *image)
   13.20 +{
   13.21 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   13.22 +}
   13.23 +
   13.24 +void machine_shutdown(xen_kexec_image_t *image)
   13.25 +{
   13.26 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   13.27 +}
   13.28 +
   13.29 +/*
   13.30 + * Local variables:
   13.31 + * mode: C
   13.32 + * c-set-style: "BSD"
   13.33 + * c-basic-offset: 4
   13.34 + * tab-width: 4
   13.35 + * indent-tabs-mode: nil
   13.36 + * End:
   13.37 + */
    14.1 --- a/xen/common/Makefile	Wed Nov 29 23:40:40 2006 +0000
    14.2 +++ b/xen/common/Makefile	Thu Nov 30 12:38:50 2006 +0000
    14.3 @@ -7,6 +7,7 @@ obj-y += event_channel.o
    14.4  obj-y += grant_table.o
    14.5  obj-y += kernel.o
    14.6  obj-y += keyhandler.o
    14.7 +obj-y += kexec.o
    14.8  obj-y += lib.o
    14.9  obj-y += memory.o
   14.10  obj-y += multicall.o
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/common/kexec.c	Thu Nov 30 12:38:50 2006 +0000
    15.3 @@ -0,0 +1,370 @@
    15.4 +/******************************************************************************
    15.5 + * kexec.c - Achitecture independent kexec code for Xen
    15.6 + * 
    15.7 + * Xen port written by:
    15.8 + * - Simon 'Horms' Horman <horms@verge.net.au>
    15.9 + * - Magnus Damm <magnus@valinux.co.jp>
   15.10 + */
   15.11 +
   15.12 +#include <asm/kexec.h>
   15.13 +#include <xen/lib.h>
   15.14 +#include <xen/ctype.h>
   15.15 +#include <xen/errno.h>
   15.16 +#include <xen/guest_access.h>
   15.17 +#include <xen/sched.h>
   15.18 +#include <xen/types.h>
   15.19 +#include <xen/kexec.h>
   15.20 +#include <xen/keyhandler.h>
   15.21 +#include <public/kexec.h>
   15.22 +#include <xen/cpumask.h>
   15.23 +#include <asm/atomic.h>
   15.24 +#include <xen/spinlock.h>
   15.25 +#include <xen/version.h>
   15.26 +#include <public/elfnote.h>
   15.27 +
   15.28 +static char opt_crashkernel[32] = "";
   15.29 +string_param("crashkernel", opt_crashkernel);
   15.30 +
   15.31 +DEFINE_PER_CPU (crash_note_t, crash_notes);
   15.32 +cpumask_t crash_saved_cpus;
   15.33 +int crashing_cpu;
   15.34 +
   15.35 +xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
   15.36 +
   15.37 +#define KEXEC_FLAG_DEFAULT_POS   (KEXEC_IMAGE_NR + 0)
   15.38 +#define KEXEC_FLAG_CRASH_POS     (KEXEC_IMAGE_NR + 1)
   15.39 +#define KEXEC_FLAG_IN_PROGRESS   (KEXEC_IMAGE_NR + 2)
   15.40 +
   15.41 +unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... */
   15.42 +
   15.43 +spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
   15.44 +
   15.45 +static void one_cpu_only(void)
   15.46 +{
   15.47 +   /* Only allow the first cpu to continue - force other cpus to spin */
   15.48 +    if (test_and_set_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
   15.49 +    {
   15.50 +        while (1);
   15.51 +    }
   15.52 +}
   15.53 +
   15.54 +/* Save the registers in the per-cpu crash note buffer */
   15.55 +
   15.56 +void machine_crash_save_cpu(void)
   15.57 +{
   15.58 +    int cpu = smp_processor_id();
   15.59 +    crash_note_t *cntp;
   15.60 +
   15.61 +    if (!cpu_test_and_set(cpu, crash_saved_cpus))
   15.62 +    {
   15.63 +        cntp = &per_cpu(crash_notes, cpu);
   15.64 +        elf_core_save_regs(&cntp->core.desc.desc.pr_reg,
   15.65 +                           &cntp->xen_regs.desc.desc);
   15.66 +
   15.67 +        /* setup crash "CORE" note */
   15.68 +        setup_crash_note(cntp, core, CORE_STR, CORE_STR_LEN, NT_PRSTATUS);
   15.69 +
   15.70 +        /* setup crash note "Xen", XEN_ELFNOTE_CRASH_REGS */
   15.71 +        setup_crash_note(cntp, xen_regs, XEN_STR, XEN_STR_LEN, 
   15.72 +                         XEN_ELFNOTE_CRASH_REGS);
   15.73 +    }
   15.74 +}
   15.75 +
   15.76 +/* Setup the single Xen specific info crash note */
   15.77 +
   15.78 +crash_xen_info_t *machine_crash_save_info(void)
   15.79 +{
   15.80 +    int cpu = smp_processor_id();
   15.81 +    crash_note_t *cntp;
   15.82 +    crash_xen_info_t *info;
   15.83 +
   15.84 +    BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
   15.85 +
   15.86 +    cntp = &per_cpu(crash_notes, cpu);
   15.87 +
   15.88 +    /* setup crash note "Xen", XEN_ELFNOTE_CRASH_INFO */
   15.89 +    setup_crash_note(cntp, xen_info, XEN_STR, XEN_STR_LEN, 
   15.90 +                     XEN_ELFNOTE_CRASH_INFO);
   15.91 +
   15.92 +    info = &cntp->xen_info.desc.desc;
   15.93 +
   15.94 +    info->xen_major_version = xen_major_version();
   15.95 +    info->xen_minor_version = xen_minor_version();
   15.96 +    info->xen_extra_version = __pa(xen_extra_version());
   15.97 +    info->xen_changeset = __pa(xen_changeset());
   15.98 +    info->xen_compiler = __pa(xen_compiler());
   15.99 +    info->xen_compile_date = __pa(xen_compile_date());
  15.100 +    info->xen_compile_time = __pa(xen_compile_time());
  15.101 +    info->tainted = tainted;
  15.102 +
  15.103 +    return info;
  15.104 +}
  15.105 +
  15.106 +void machine_crash_kexec(void)
  15.107 +{
  15.108 +    int pos;
  15.109 +    xen_kexec_image_t *image;
  15.110 +
  15.111 +    one_cpu_only();
  15.112 + 
  15.113 +    machine_crash_save_cpu();
  15.114 +    crashing_cpu = smp_processor_id();
  15.115 +
  15.116 +    machine_crash_shutdown();
  15.117 +
  15.118 +    pos = (test_bit(KEXEC_FLAG_CRASH_POS, &kexec_flags) != 0);
  15.119 +
  15.120 +    if (test_bit(KEXEC_IMAGE_CRASH_BASE + pos, &kexec_flags))
  15.121 +    {
  15.122 +        image = &kexec_image[KEXEC_IMAGE_CRASH_BASE + pos];
  15.123 +        machine_kexec(image); /* Does not return */
  15.124 +    }
  15.125 +
  15.126 +    while (1); /* No image available - just spin */
  15.127 +}
  15.128 +
  15.129 +static void do_crashdump_trigger(unsigned char key)
  15.130 +{
  15.131 +	printk("triggering crashdump\n");
  15.132 +	machine_crash_kexec();
  15.133 +}
  15.134 +
  15.135 +static __init int register_crashdump_trigger(void)
  15.136 +{
  15.137 +	register_keyhandler('c', do_crashdump_trigger, "trigger a crashdump");
  15.138 +	return 0;
  15.139 +}
  15.140 +__initcall(register_crashdump_trigger);
  15.141 +
  15.142 +void machine_kexec_reserved(xen_kexec_reserve_t *reservation)
  15.143 +{
  15.144 +    unsigned long val[2];
  15.145 +    char *str = opt_crashkernel;
  15.146 +    int k = 0; 
  15.147 +
  15.148 +    memset(reservation, 0, sizeof(*reservation));
  15.149 +
  15.150 +    while (k < ARRAY_SIZE(val)) {
  15.151 +        if (*str == '\0') {
  15.152 +            break;
  15.153 +        }
  15.154 +        val[k] = simple_strtoul(str, &str, 0);
  15.155 +        switch (toupper(*str)) {
  15.156 +        case 'G': val[k] <<= 10;
  15.157 +        case 'M': val[k] <<= 10;
  15.158 +        case 'K': val[k] <<= 10;
  15.159 +            str++;
  15.160 +        }
  15.161 +        if (*str == '@') {
  15.162 +            str++;
  15.163 +        }
  15.164 +        k++;
  15.165 +    }
  15.166 +
  15.167 +    if (k == ARRAY_SIZE(val)) {
  15.168 +        reservation->size = val[0];
  15.169 +        reservation->start = val[1];
  15.170 +    }
  15.171 +}
  15.172 +
  15.173 +static int kexec_get_reserve(xen_kexec_range_t *range)
  15.174 +{
  15.175 +    xen_kexec_reserve_t reservation;
  15.176 +    
  15.177 +    machine_kexec_reserved(&reservation);
  15.178 +
  15.179 +    range->start = reservation.start;
  15.180 +    range->size = reservation.size;
  15.181 +    return 0;
  15.182 +}
  15.183 +
  15.184 +extern unsigned long _text, _end;
  15.185 +
  15.186 +static int kexec_get_xen(xen_kexec_range_t *range, int get_ma)
  15.187 +{
  15.188 +    if (get_ma)
  15.189 +        range->start = virt_to_maddr(&_text);
  15.190 +    else
  15.191 +        range->start = (unsigned long) &_text;
  15.192 +
  15.193 +    range->size = &_end - &_text;
  15.194 +    return 0;
  15.195 +}
  15.196 +
  15.197 +static int kexec_get_cpu(xen_kexec_range_t *range)
  15.198 +{
  15.199 +    if (range->nr < 0 || range->nr >= num_present_cpus())
  15.200 +        return -EINVAL;
  15.201 +
  15.202 +    range->start = __pa((unsigned long)&per_cpu(crash_notes, range->nr));
  15.203 +    range->size = sizeof(crash_note_t);
  15.204 +    return 0;
  15.205 +}
  15.206 +
  15.207 +static int kexec_get_range(XEN_GUEST_HANDLE(void) uarg)
  15.208 +{
  15.209 +    xen_kexec_range_t range;
  15.210 +    int ret = -EINVAL;
  15.211 +    
  15.212 +    if (unlikely(copy_from_guest(&range, uarg, 1)))
  15.213 +        return -EFAULT;
  15.214 +
  15.215 +    switch (range.range)
  15.216 +    {
  15.217 +    case KEXEC_RANGE_MA_CRASH:
  15.218 +        ret = kexec_get_reserve(&range);
  15.219 +        break;
  15.220 +    case KEXEC_RANGE_MA_XEN:
  15.221 +        ret = kexec_get_xen(&range, 1);
  15.222 +        break;
  15.223 +    case KEXEC_RANGE_VA_XEN:
  15.224 +        ret = kexec_get_xen(&range, 0);
  15.225 +        break;
  15.226 +    case KEXEC_RANGE_MA_CPU:
  15.227 +        ret = kexec_get_cpu(&range);
  15.228 +        break;
  15.229 +    }
  15.230 +
  15.231 +    if (ret == 0 && unlikely(copy_to_guest(uarg, &range, 1)))
  15.232 +        return -EFAULT;
  15.233 +    
  15.234 +    return ret;
  15.235 +}
  15.236 +
  15.237 +static int kexec_load_get_bits(int type, int *base, int *bit)
  15.238 +{
  15.239 +    switch (type)
  15.240 +    {
  15.241 +    case KEXEC_TYPE_DEFAULT:
  15.242 +        *base = KEXEC_IMAGE_DEFAULT_BASE;
  15.243 +        *bit = KEXEC_FLAG_DEFAULT_POS;
  15.244 +        break;
  15.245 +    case KEXEC_TYPE_CRASH:
  15.246 +        *base = KEXEC_IMAGE_CRASH_BASE;
  15.247 +        *bit = KEXEC_FLAG_CRASH_POS;
  15.248 +        break;
  15.249 +    default:
  15.250 +        return -1;
  15.251 +    }
  15.252 +    return 0;
  15.253 +}
  15.254 +
  15.255 +static int kexec_load_unload(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
  15.256 +{
  15.257 +    xen_kexec_load_t load;
  15.258 +    xen_kexec_image_t *image;
  15.259 +    int base, bit, pos;
  15.260 +    int ret = 0;
  15.261 +
  15.262 +    if (unlikely(copy_from_guest(&load, uarg, 1)))
  15.263 +        return -EFAULT;
  15.264 +
  15.265 +    if (kexec_load_get_bits(load.type, &base, &bit))
  15.266 +        return -EINVAL;
  15.267 +
  15.268 +    pos = (test_bit(bit, &kexec_flags) != 0);
  15.269 +
  15.270 +    /* Load the user data into an unused image */
  15.271 +    if (op == KEXEC_CMD_kexec_load)
  15.272 +    {
  15.273 +        image = &kexec_image[base + !pos];
  15.274 +
  15.275 +        BUG_ON(test_bit((base + !pos), &kexec_flags)); /* must be free */
  15.276 +
  15.277 +        memcpy(image, &load.image, sizeof(*image));
  15.278 +            
  15.279 +        if (!(ret = machine_kexec_load(load.type, base + !pos, image)))
  15.280 +        {
  15.281 +            /* Set image present bit */
  15.282 +            set_bit((base + !pos), &kexec_flags);
  15.283 +
  15.284 +            /* Make new image the active one */
  15.285 +            change_bit(bit, &kexec_flags);
  15.286 +        }
  15.287 +    }
  15.288 +
  15.289 +    /* Unload the old image if present and load successful */
  15.290 +    if (ret == 0 && !test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
  15.291 +    {
  15.292 +        if (test_and_clear_bit((base + pos), &kexec_flags))
  15.293 +        {
  15.294 +            image = &kexec_image[base + pos];
  15.295 +            machine_kexec_unload(load.type, base + pos, image);
  15.296 +        }
  15.297 +    }
  15.298 +
  15.299 +    return ret;
  15.300 +}
  15.301 +
  15.302 +static int kexec_exec(XEN_GUEST_HANDLE(void) uarg)
  15.303 +{
  15.304 +    xen_kexec_exec_t exec;
  15.305 +    xen_kexec_image_t *image;
  15.306 +    int base, bit, pos;
  15.307 +
  15.308 +    if (unlikely(copy_from_guest(&exec, uarg, 1)))
  15.309 +        return -EFAULT;
  15.310 +
  15.311 +    if (kexec_load_get_bits(exec.type, &base, &bit))
  15.312 +        return -EINVAL;
  15.313 +
  15.314 +    pos = (test_bit(bit, &kexec_flags) != 0);
  15.315 +
  15.316 +    /* Only allow kexec/kdump into loaded images */
  15.317 +    if (!test_bit(base + pos, &kexec_flags))
  15.318 +        return -ENOENT;
  15.319 +
  15.320 +    switch (exec.type)
  15.321 +    {
  15.322 +    case KEXEC_TYPE_DEFAULT:
  15.323 +        image = &kexec_image[base + pos];
  15.324 +        one_cpu_only();
  15.325 +        machine_shutdown(image); /* Does not return */
  15.326 +        break;
  15.327 +    case KEXEC_TYPE_CRASH:
  15.328 +        machine_crash_kexec(); /* Does not return */
  15.329 +        break;
  15.330 +    }
  15.331 +
  15.332 +    return -EINVAL; /* never reached */
  15.333 +}
  15.334 +
  15.335 +long do_kexec_op(unsigned long op, XEN_GUEST_HANDLE(void) uarg)
  15.336 +{
  15.337 +    unsigned long flags;
  15.338 +    int ret = -EINVAL;
  15.339 +
  15.340 +    if ( !IS_PRIV(current->domain) )  
  15.341 +        return -EPERM;
  15.342 +
  15.343 +    switch (op)
  15.344 +    {
  15.345 +    case KEXEC_CMD_kexec_get_range:
  15.346 +        ret = kexec_get_range(uarg);
  15.347 +        break;
  15.348 +    case KEXEC_CMD_kexec_load:
  15.349 +    case KEXEC_CMD_kexec_unload:
  15.350 +        spin_lock_irqsave(&kexec_lock, flags);
  15.351 +        if (!test_bit(KEXEC_FLAG_IN_PROGRESS, &kexec_flags))
  15.352 +        {
  15.353 +            ret = kexec_load_unload(op, uarg);
  15.354 +        }
  15.355 +        spin_unlock_irqrestore(&kexec_lock, flags);
  15.356 +        break;
  15.357 +    case KEXEC_CMD_kexec:
  15.358 +        ret = kexec_exec(uarg);
  15.359 +        break;
  15.360 +    }
  15.361 +
  15.362 +    return ret;
  15.363 +}
  15.364 +
  15.365 +/*
  15.366 + * Local variables:
  15.367 + * mode: C
  15.368 + * c-set-style: "BSD"
  15.369 + * c-basic-offset: 4
  15.370 + * tab-width: 4
  15.371 + * indent-tabs-mode: nil
  15.372 + * End:
  15.373 + */
    16.1 --- a/xen/common/page_alloc.c	Wed Nov 29 23:40:40 2006 +0000
    16.2 +++ b/xen/common/page_alloc.c	Thu Nov 30 12:38:50 2006 +0000
    16.3 @@ -237,24 +237,35 @@ void init_boot_pages(paddr_t ps, paddr_t
    16.4      }
    16.5  }
    16.6  
    16.7 +unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
    16.8 +{
    16.9 +    unsigned long i;
   16.10 +
   16.11 +    for ( i = 0; i < nr_pfns; i++ )
   16.12 +        if ( allocated_in_map(pfn_at + i) )
   16.13 +             break;
   16.14 +
   16.15 +    if ( i == nr_pfns )
   16.16 +    {
   16.17 +        map_alloc(pfn_at, nr_pfns);
   16.18 +        return pfn_at;
   16.19 +    }
   16.20 +
   16.21 +    return 0;
   16.22 +}
   16.23 +
   16.24  unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
   16.25  {
   16.26 -    unsigned long pg, i;
   16.27 +    unsigned long pg, i = 0;
   16.28  
   16.29      for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
   16.30      {
   16.31 -        for ( i = 0; i < nr_pfns; i++ )
   16.32 -            if ( allocated_in_map(pg + i) )
   16.33 -                 break;
   16.34 -
   16.35 -        if ( i == nr_pfns )
   16.36 -        {
   16.37 -            map_alloc(pg, nr_pfns);
   16.38 -            return pg;
   16.39 -        }
   16.40 +        i = alloc_boot_pages_at(nr_pfns, pg);
   16.41 +        if (i != 0)
   16.42 +            break;
   16.43      }
   16.44  
   16.45 -    return 0;
   16.46 +    return i;
   16.47  }
   16.48  
   16.49  
    17.1 --- a/xen/drivers/char/console.c	Wed Nov 29 23:40:40 2006 +0000
    17.2 +++ b/xen/drivers/char/console.c	Thu Nov 30 12:38:50 2006 +0000
    17.3 @@ -27,6 +27,7 @@
    17.4  #include <xen/guest_access.h>
    17.5  #include <xen/shutdown.h>
    17.6  #include <xen/vga.h>
    17.7 +#include <xen/kexec.h>
    17.8  #include <asm/current.h>
    17.9  #include <asm/debugger.h>
   17.10  #include <asm/io.h>
   17.11 @@ -865,6 +866,8 @@ void panic(const char *fmt, ...)
   17.12  
   17.13      debugger_trap_immediate();
   17.14  
   17.15 +    machine_crash_kexec();
   17.16 +
   17.17      if ( opt_noreboot )
   17.18      {
   17.19          machine_halt();
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xen/include/asm-ia64/elf.h	Thu Nov 30 12:38:50 2006 +0000
    18.3 @@ -0,0 +1,30 @@
    18.4 +#ifndef __IA64_ELF_H__
    18.5 +#define __IA64_ELF_H__
    18.6 +
    18.7 +#include <xen/lib.h>       /* for printk() used in stub */
    18.8 +
    18.9 +typedef struct {
   18.10 +    unsigned long dummy;
   18.11 +} ELF_Gregset;
   18.12 +
   18.13 +typedef struct {
   18.14 +    unsigned long dummy;
   18.15 +} crash_xen_core_t;
   18.16 +
   18.17 +extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
   18.18 +                                      crash_xen_core_t *xen_core_regs)
   18.19 +{
   18.20 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   18.21 +}
   18.22 +
   18.23 +#endif /* __IA64_ELF_H__ */
   18.24 +
   18.25 +/*
   18.26 + * Local variables:
   18.27 + * mode: C
   18.28 + * c-set-style: "BSD"
   18.29 + * c-basic-offset: 4
   18.30 + * tab-width: 4
   18.31 + * indent-tabs-mode: nil
   18.32 + * End:
   18.33 + */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/xen/include/asm-ia64/kexec.h	Thu Nov 30 12:38:50 2006 +0000
    19.3 @@ -0,0 +1,25 @@
    19.4 +#ifndef __IA64_KEXEC_H__
    19.5 +#define __IA64_KEXEC_H__
    19.6 +
    19.7 +#include <xen/lib.h>       /* for printk() used in stub */
    19.8 +#include <xen/types.h>
    19.9 +#include <public/xen.h>
   19.10 +#include <xen/kexec.h>
   19.11 +
   19.12 +static inline void machine_kexec(xen_kexec_image_t *image)
   19.13 +{
   19.14 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   19.15 +}
   19.16 +
   19.17 +#endif /* __IA64_KEXEC_H__ */
   19.18 +
   19.19 +/*
   19.20 + * Local variables:
   19.21 + * mode: C
   19.22 + * c-set-style: "BSD"
   19.23 + * c-basic-offset: 4
   19.24 + * tab-width: 4
   19.25 + * indent-tabs-mode: nil
   19.26 + * End:
   19.27 + */
   19.28 +
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/xen/include/asm-powerpc/elf.h	Thu Nov 30 12:38:50 2006 +0000
    20.3 @@ -0,0 +1,30 @@
    20.4 +#ifndef _ASM_ELF_H__
    20.5 +#define _ASM_ELF_H__
    20.6 +
    20.7 +#include <xen/lib.h>       /* for printk() used in stub */
    20.8 +
    20.9 +typedef struct {
   20.10 +    unsigned long dummy;
   20.11 +} ELF_Gregset;
   20.12 +
   20.13 +typedef struct {
   20.14 +    unsigned long dummy;
   20.15 +} crash_xen_core_t;
   20.16 +
   20.17 +extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
   20.18 +                                      crash_xen_core_t *xen_core_regs)
   20.19 +{
   20.20 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   20.21 +}
   20.22 +
   20.23 +#endif /* _ASM_ELF_H__ */
   20.24 +
   20.25 +/*
   20.26 + * Local variables:
   20.27 + * mode: C
   20.28 + * c-set-style: "BSD"
   20.29 + * c-basic-offset: 4
   20.30 + * tab-width: 4
   20.31 + * indent-tabs-mode: nil
   20.32 + * End:
   20.33 + */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/xen/include/asm-powerpc/kexec.h	Thu Nov 30 12:38:50 2006 +0000
    21.3 @@ -0,0 +1,25 @@
    21.4 +#ifndef _ASM_KEXEC_H__
    21.5 +#define _ASM_KEXEC_H__
    21.6 +
    21.7 +#include <xen/lib.h>       /* for printk() used in stub */
    21.8 +#include <xen/types.h>
    21.9 +#include <public/xen.h>
   21.10 +#include <xen/kexec.h>
   21.11 +
   21.12 +static inline void machine_kexec(xen_kexec_image_t *image)
   21.13 +{
   21.14 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   21.15 +}
   21.16 +
   21.17 +#endif /* _ASM_KEXEC_H__ */
   21.18 +
   21.19 +/*
   21.20 + * Local variables:
   21.21 + * mode: C
   21.22 + * c-set-style: "BSD"
   21.23 + * c-basic-offset: 4
   21.24 + * tab-width: 4
   21.25 + * indent-tabs-mode: nil
   21.26 + * End:
   21.27 + */
   21.28 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/xen/include/asm-x86/elf.h	Thu Nov 30 12:38:50 2006 +0000
    22.3 @@ -0,0 +1,30 @@
    22.4 +#ifndef __X86_ELF_H__
    22.5 +#define __X86_ELF_H__
    22.6 +
    22.7 +#include <xen/lib.h>       /* for printk() used in stub */
    22.8 +
    22.9 +typedef struct {
   22.10 +    unsigned long dummy;
   22.11 +} ELF_Gregset;
   22.12 +
   22.13 +typedef struct {
   22.14 +    unsigned long dummy;
   22.15 +} crash_xen_core_t;
   22.16 +
   22.17 +extern inline void elf_core_save_regs(ELF_Gregset *core_regs, 
   22.18 +                                      crash_xen_core_t *xen_core_regs)
   22.19 +{
   22.20 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   22.21 +}
   22.22 +
   22.23 +#endif /* __X86_ELF_H__ */
   22.24 +
   22.25 +/*
   22.26 + * Local variables:
   22.27 + * mode: C
   22.28 + * c-set-style: "BSD"
   22.29 + * c-basic-offset: 4
   22.30 + * tab-width: 4
   22.31 + * indent-tabs-mode: nil
   22.32 + * End:
   22.33 + */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/xen/include/asm-x86/kexec.h	Thu Nov 30 12:38:50 2006 +0000
    23.3 @@ -0,0 +1,24 @@
    23.4 +#ifndef __X86_KEXEC_H__
    23.5 +#define __X86_KEXEC_H__
    23.6 +
    23.7 +#include <xen/lib.h>       /* for printk() used in stub */
    23.8 +#include <xen/types.h>
    23.9 +#include <public/xen.h>
   23.10 +#include <xen/kexec.h>
   23.11 +
   23.12 +static inline void machine_kexec(xen_kexec_image_t *image)
   23.13 +{
   23.14 +    printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__);
   23.15 +}
   23.16 +
   23.17 +#endif /* __X86_KEXEC_H__ */
   23.18 +
   23.19 +/*
   23.20 + * Local variables:
   23.21 + * mode: C
   23.22 + * c-set-style: "BSD"
   23.23 + * c-basic-offset: 4
   23.24 + * tab-width: 4
   23.25 + * indent-tabs-mode: nil
   23.26 + * End:
   23.27 + */
    24.1 --- a/xen/include/public/elfnote.h	Wed Nov 29 23:40:40 2006 +0000
    24.2 +++ b/xen/include/public/elfnote.h	Thu Nov 30 12:38:50 2006 +0000
    24.3 @@ -147,6 +147,25 @@
    24.4   */
    24.5  #define XEN_ELFNOTE_HV_START_LOW  12
    24.6  
    24.7 +/*
    24.8 + * System information exported through crash notes.
    24.9 + *
   24.10 + * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_INFO 
   24.11 + * note in case of a system crash. This note will contain various
   24.12 + * information about the system, see xen/include/xen/elfcore.h.
   24.13 + */
   24.14 +#define XEN_ELFNOTE_CRASH_INFO 0x1000001
   24.15 +
   24.16 +/*
   24.17 + * System registers exported through crash notes.
   24.18 + *
   24.19 + * The kexec / kdump code will create one XEN_ELFNOTE_CRASH_REGS 
   24.20 + * note per cpu in case of a system crash. This note is architecture
   24.21 + * specific and will contain registers not saved in the "CORE" note.
   24.22 + * See xen/include/xen/elfcore.h for more information.
   24.23 + */
   24.24 +#define XEN_ELFNOTE_CRASH_REGS 0x1000002
   24.25 +
   24.26  #endif /* __XEN_PUBLIC_ELFNOTE_H__ */
   24.27  
   24.28  /*
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/xen/include/public/kexec.h	Thu Nov 30 12:38:50 2006 +0000
    25.3 @@ -0,0 +1,131 @@
    25.4 +/******************************************************************************
    25.5 + * kexec.h - Public portion
    25.6 + * 
    25.7 + * Xen port written by:
    25.8 + * - Simon 'Horms' Horman <horms@verge.net.au>
    25.9 + * - Magnus Damm <magnus@valinux.co.jp>
   25.10 + */
   25.11 +
   25.12 +#ifndef _XEN_PUBLIC_KEXEC_H
   25.13 +#define _XEN_PUBLIC_KEXEC_H
   25.14 +
   25.15 +
   25.16 +/* This file describes the Kexec / Kdump hypercall interface for Xen.
   25.17 + *
   25.18 + * Kexec under vanilla Linux allows a user to reboot the physical machine 
   25.19 + * into a new user-specified kernel. The Xen port extends this idea
   25.20 + * to allow rebooting of the machine from dom0. When kexec for dom0
   25.21 + * is used to reboot,  both the hypervisor and the domains get replaced
   25.22 + * with some other kernel. It is possible to kexec between vanilla
   25.23 + * Linux and Xen and back again. Xen to Xen works well too.
   25.24 + *
   25.25 + * The hypercall interface for kexec can be divided into three main
   25.26 + * types of hypercall operations:
   25.27 + *
   25.28 + * 1) Range information:
   25.29 + *    This is used by the dom0 kernel to ask the hypervisor about various 
   25.30 + *    address information. This information is needed to allow kexec-tools 
   25.31 + *    to fill in the ELF headers for /proc/vmcore properly.
   25.32 + *
   25.33 + * 2) Load and unload of images:
   25.34 + *    There are no big surprises here, the kexec binary from kexec-tools
   25.35 + *    runs in userspace in dom0. The tool loads/unloads data into the
   25.36 + *    dom0 kernel such as new kernel, initramfs and hypervisor. When
   25.37 + *    loaded the dom0 kernel performs a load hypercall operation, and
   25.38 + *    before releasing all page references the dom0 kernel calls unload.
   25.39 + *
   25.40 + * 3) Kexec operation:
   25.41 + *    This is used to start a previously loaded kernel.
   25.42 + */
   25.43 +
   25.44 +#include "xen.h"
   25.45 +
   25.46 +/*
   25.47 + * Prototype for this hypercall is:
   25.48 + *  int kexec_op(int cmd, void *args)
   25.49 + * @cmd  == KEXEC_CMD_... 
   25.50 + *          KEXEC operation to perform
   25.51 + * @args == Operation-specific extra arguments (NULL if none).
   25.52 + */
   25.53 +
   25.54 +/*
   25.55 + * Kexec supports two types of operation:
   25.56 + * - kexec into a regular kernel, very similar to a standard reboot
   25.57 + *   - KEXEC_TYPE_DEFAULT is used to specify this type
   25.58 + * - kexec into a special "crash kernel", aka kexec-on-panic
   25.59 + *   - KEXEC_TYPE_CRASH is used to specify this type
   25.60 + *   - parts of our system may be broken at kexec-on-panic time
   25.61 + *     - the code should be kept as simple and self-contained as possible
   25.62 + */
   25.63 +
   25.64 +#define KEXEC_TYPE_DEFAULT 0
   25.65 +#define KEXEC_TYPE_CRASH   1
   25.66 +
   25.67 +
   25.68 +/* The kexec implementation for Xen allows the user to load two
   25.69 + * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH.
   25.70 + * All data needed for a kexec reboot is kept in one xen_kexec_image_t
   25.71 + * per "instance". The data mainly consists of machine address lists to pages
   25.72 + * together with destination addresses. The data in xen_kexec_image_t
   25.73 + * is passed to the "code page" which is one page of code that performs
   25.74 + * the final relocations before jumping to the new kernel.
   25.75 + */
   25.76 + 
   25.77 +typedef struct xen_kexec_image {
   25.78 +    unsigned long indirection_page;
   25.79 +    unsigned long start_address;
   25.80 +} xen_kexec_image_t;
   25.81 +
   25.82 +/*
   25.83 + * Perform kexec having previously loaded a kexec or kdump kernel
   25.84 + * as appropriate.
   25.85 + * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
   25.86 + */
   25.87 +#define KEXEC_CMD_kexec                 0
   25.88 +typedef struct xen_kexec_exec {
   25.89 +    int type;
   25.90 +} xen_kexec_exec_t;
   25.91 +
   25.92 +/*
   25.93 + * Load/Unload kernel image for kexec or kdump.
   25.94 + * type  == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in]
   25.95 + * image == relocation information for kexec (ignored for unload) [in]
   25.96 + */
   25.97 +#define KEXEC_CMD_kexec_load            1
   25.98 +#define KEXEC_CMD_kexec_unload          2
   25.99 +typedef struct xen_kexec_load {
  25.100 +    int type;
  25.101 +    xen_kexec_image_t image;
  25.102 +} xen_kexec_load_t;
  25.103 +
  25.104 +#define KEXEC_RANGE_MA_CRASH 0   /* machine address and size of crash area */
  25.105 +#define KEXEC_RANGE_MA_XEN   1   /* machine address and size of Xen itself */
  25.106 +#define KEXEC_RANGE_VA_XEN   2   /* virtual adrress and size of Xen itself */
  25.107 +#define KEXEC_RANGE_MA_CPU   3   /* machine address and size of a CPU note */
  25.108 +
  25.109 +/*
  25.110 + * Find the address and size of certain memory areas
  25.111 + * range == KEXEC_RANGE_... [in]
  25.112 + * nr    == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in]
  25.113 + * size  == number of bytes reserved in window [out]
  25.114 + * start == address of the first byte in the window [out]
  25.115 + */
  25.116 +#define KEXEC_CMD_kexec_get_range       3
  25.117 +typedef struct xen_kexec_range {
  25.118 +    int range;
  25.119 +    int nr;
  25.120 +    unsigned long size;
  25.121 +    unsigned long start;
  25.122 +} xen_kexec_range_t;
  25.123 +
  25.124 +#endif /* _XEN_PUBLIC_KEXEC_H */
  25.125 +
  25.126 +/*
  25.127 + * Local variables:
  25.128 + * mode: C
  25.129 + * c-set-style: "BSD"
  25.130 + * c-basic-offset: 4
  25.131 + * tab-width: 4
  25.132 + * indent-tabs-mode: nil
  25.133 + * End:
  25.134 + */
    26.1 --- a/xen/include/xen/elf.h	Wed Nov 29 23:40:40 2006 +0000
    26.2 +++ b/xen/include/xen/elf.h	Thu Nov 30 12:38:50 2006 +0000
    26.3 @@ -452,18 +452,12 @@ unsigned int elf_hash(const unsigned cha
    26.4  /*
    26.5   * Note Definitions
    26.6   */
    26.7 -typedef struct {
    26.8 -	Elf32_Word namesz;
    26.9 -	Elf32_Word descsz;
   26.10 -	Elf32_Word type;
   26.11 -} Elf32_Note;
   26.12  
   26.13  typedef struct {
   26.14 -	Elf64_Half namesz;
   26.15 -	Elf64_Half descsz;
   26.16 -	Elf64_Half type;
   26.17 -} Elf64_Note;
   26.18 -
   26.19 +	u32 namesz;
   26.20 +	u32 descsz;
   26.21 +	u32 type;
   26.22 +} Elf_Note; /* same format for both 32-bit and 64-bit ELF */
   26.23  
   26.24  #if defined(ELFSIZE)
   26.25  #define CONCAT(x,y)	__CONCAT(x,y)
   26.26 @@ -486,7 +480,6 @@ typedef struct {
   26.27  #define Elf_Addr	Elf32_Addr
   26.28  #define Elf_Off		Elf32_Off
   26.29  #define Elf_Nhdr	Elf32_Nhdr
   26.30 -#define Elf_Note	Elf32_Note
   26.31  
   26.32  #define ELF_R_SYM	ELF32_R_SYM
   26.33  #define ELF_R_TYPE	ELF32_R_TYPE
   26.34 @@ -511,7 +504,6 @@ typedef struct {
   26.35  #define Elf_Addr	Elf64_Addr
   26.36  #define Elf_Off		Elf64_Off
   26.37  #define Elf_Nhdr	Elf64_Nhdr
   26.38 -#define Elf_Note	Elf64_Note
   26.39  
   26.40  #define ELF_R_SYM	ELF64_R_SYM
   26.41  #define ELF_R_TYPE	ELF64_R_TYPE
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/xen/include/xen/elfcore.h	Thu Nov 30 12:38:50 2006 +0000
    27.3 @@ -0,0 +1,137 @@
    27.4 +/******************************************************************************
    27.5 + * elfcore.h
    27.6 + *
    27.7 + * Based heavily on include/linux/elfcore.h from Linux 2.6.16
    27.8 + * Naming scheeme based on include/xen/elf.h (not include/linux/elfcore.h)
    27.9 + *
   27.10 + */
   27.11 +
   27.12 +#ifndef __ELFCOREC_H__
   27.13 +#define __ELFCOREC_H__
   27.14 +
   27.15 +#include <xen/types.h>
   27.16 +#include <xen/elf.h>
   27.17 +#include <asm/elf.h>
   27.18 +#include <public/xen.h>
   27.19 +
   27.20 +#define NT_PRSTATUS     1
   27.21 +
   27.22 +typedef struct
   27.23 +{
   27.24 +    int signo;                       /* signal number */
   27.25 +    int code;                        /* extra code */
   27.26 +    int errno;                       /* errno */
   27.27 +} ELF_Signifo;
   27.28 +
   27.29 +/* These seem to be the same length on all architectures on Linux */
   27.30 +typedef int ELF_Pid;
   27.31 +typedef struct {
   27.32 +	long tv_sec;
   27.33 +	long tv_usec;
   27.34 +} ELF_Timeval;
   27.35 +
   27.36 +/*
   27.37 + * Definitions to generate Intel SVR4-like core files.
   27.38 + * These mostly have the same names as the SVR4 types with "elf_"
   27.39 + * tacked on the front to prevent clashes with linux definitions,
   27.40 + * and the typedef forms have been avoided.  This is mostly like
   27.41 + * the SVR4 structure, but more Linuxy, with things that Linux does
   27.42 + * not support and which gdb doesn't really use excluded.
   27.43 + */
   27.44 +typedef struct
   27.45 +{
   27.46 +    ELF_Signifo pr_info;         /* Info associated with signal */
   27.47 +    short pr_cursig;             /* Current signal */
   27.48 +    unsigned long pr_sigpend;    /* Set of pending signals */
   27.49 +    unsigned long pr_sighold;    /* Set of held signals */
   27.50 +    ELF_Pid pr_pid;
   27.51 +    ELF_Pid pr_ppid;
   27.52 +    ELF_Pid pr_pgrp;
   27.53 +    ELF_Pid pr_sid;
   27.54 +    ELF_Timeval pr_utime;        /* User time */
   27.55 +    ELF_Timeval pr_stime;        /* System time */
   27.56 +    ELF_Timeval pr_cutime;       /* Cumulative user time */
   27.57 +    ELF_Timeval pr_cstime;       /* Cumulative system time */
   27.58 +    ELF_Gregset pr_reg;          /* GP registers - from asm header file */
   27.59 +    int pr_fpvalid;              /* True if math co-processor being used.  */
   27.60 +} ELF_Prstatus;
   27.61 +
   27.62 +/*
   27.63 + * The following data structures provide 64-bit ELF notes. In theory it should 
   27.64 + * be possible to support both 64-bit and 32-bit ELF files, but to keep it 
   27.65 + * simple we only do 64-bit.
   27.66 + *
   27.67 + * Please note that the current code aligns the 64-bit notes in the same
   27.68 + * way as Linux does. We are not following the 64-bit ELF spec, no one does.
   27.69 + *
   27.70 + * We are avoiding two problems by restricting us to 64-bit notes only:
   27.71 + * - Alignment of notes change with the word size. Ick.
   27.72 + * - We would need to tell kexec-tools which format we are using in the
   27.73 + *   hypervisor to make sure the right ELF format is generated.
   27.74 + *   That requires infrastructure. Let's not.
   27.75 + */
   27.76 +
   27.77 +#define ALIGN(x, n) ((x + ((1 << n) - 1)) / (1 << n))
   27.78 +#define PAD32(x) u32 pad_data[ALIGN(x, 2)]
   27.79 +
   27.80 +#define TYPEDEF_NOTE(type, strlen, desctype)    \
   27.81 +    typedef struct {                            \
   27.82 +        union {                                 \
   27.83 +            struct {                            \
   27.84 +                Elf_Note note;                  \
   27.85 +                unsigned char name[strlen];     \
   27.86 +            } note;                             \
   27.87 +            PAD32(sizeof(Elf_Note) + strlen);   \
   27.88 +        } note;                                 \
   27.89 +        union {                                 \
   27.90 +            desctype desc;                      \
   27.91 +            PAD32(sizeof(desctype));            \
   27.92 +        } desc;                                 \
   27.93 +    } __attribute__ ((packed)) type
   27.94 +
   27.95 +#define CORE_STR                "CORE"
   27.96 +#define CORE_STR_LEN            5 /* including terminating zero */
   27.97 +
   27.98 +TYPEDEF_NOTE(crash_note_core_t, CORE_STR_LEN, ELF_Prstatus);
   27.99 +
  27.100 +#define XEN_STR                 "Xen"
  27.101 +#define XEN_STR_LEN             4 /* including terminating zero */
  27.102 +
  27.103 +TYPEDEF_NOTE(crash_note_xen_core_t, XEN_STR_LEN, crash_xen_core_t);
  27.104 +
  27.105 +typedef struct {
  27.106 +    unsigned long xen_major_version;
  27.107 +    unsigned long xen_minor_version;
  27.108 +    unsigned long xen_extra_version;
  27.109 +    unsigned long xen_changeset;
  27.110 +    unsigned long xen_compiler;
  27.111 +    unsigned long xen_compile_date;
  27.112 +    unsigned long xen_compile_time;
  27.113 +    unsigned long tainted;
  27.114 +} crash_xen_info_t;
  27.115 +
  27.116 +TYPEDEF_NOTE(crash_note_xen_info_t, XEN_STR_LEN, crash_xen_info_t);
  27.117 +
  27.118 +typedef struct {
  27.119 +    crash_note_core_t core;
  27.120 +    crash_note_xen_core_t xen_regs;
  27.121 +    crash_note_xen_info_t xen_info;
  27.122 +} __attribute__ ((packed)) crash_note_t;
  27.123 +
  27.124 +#define setup_crash_note(np, member, str, str_len, id) \
  27.125 +  np->member.note.note.note.namesz = str_len; \
  27.126 +  np->member.note.note.note.descsz = sizeof(np->member.desc.desc); \
  27.127 +  np->member.note.note.note.type = id; \
  27.128 +  memcpy(np->member.note.note.name, str, str_len)
  27.129 +
  27.130 +#endif /* __ELFCOREC_H__ */
  27.131 +
  27.132 +/*
  27.133 + * Local variables:
  27.134 + * mode: C
  27.135 + * c-set-style: "BSD"
  27.136 + * c-basic-offset: 4
  27.137 + * tab-width: 4
  27.138 + * indent-tabs-mode: nil
  27.139 + * End:
  27.140 + */
    28.1 --- a/xen/include/xen/hypercall.h	Wed Nov 29 23:40:40 2006 +0000
    28.2 +++ b/xen/include/xen/hypercall.h	Thu Nov 30 12:38:50 2006 +0000
    28.3 @@ -102,4 +102,10 @@ do_hvm_op(
    28.4      unsigned long op,
    28.5      XEN_GUEST_HANDLE(void) arg);
    28.6  
    28.7 +extern long
    28.8 +do_kexec_op(
    28.9 +    unsigned long op,
   28.10 +    int arg1,
   28.11 +    XEN_GUEST_HANDLE(void) arg);
   28.12 +
   28.13  #endif /* __XEN_HYPERCALL_H__ */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/xen/include/xen/kexec.h	Thu Nov 30 12:38:50 2006 +0000
    29.3 @@ -0,0 +1,43 @@
    29.4 +#ifndef __XEN_KEXEC_H__
    29.5 +#define __XEN_KEXEC_H__
    29.6 +
    29.7 +#include <public/kexec.h>
    29.8 +#include <asm/percpu.h>
    29.9 +#include <xen/elfcore.h>
   29.10 +
   29.11 +extern int crashing_cpu;
   29.12 +
   29.13 +typedef struct xen_kexec_reserve {
   29.14 +    unsigned long size;
   29.15 +    unsigned long start;
   29.16 +} xen_kexec_reserve_t;
   29.17 +
   29.18 +/* We have space for 4 images to support atomic update
   29.19 + * of images. This is important for CRASH images since
   29.20 + * a panic can happen at any time...
   29.21 + */
   29.22 +
   29.23 +#define KEXEC_IMAGE_DEFAULT_BASE 0
   29.24 +#define KEXEC_IMAGE_CRASH_BASE   2
   29.25 +#define KEXEC_IMAGE_NR           4
   29.26 +
   29.27 +int machine_kexec_load(int type, int slot, xen_kexec_image_t *image);
   29.28 +void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image);
   29.29 +void machine_kexec_reserved(xen_kexec_reserve_t *reservation);
   29.30 +void machine_shutdown(xen_kexec_image_t *image);
   29.31 +void machine_crash_kexec(void);
   29.32 +void machine_crash_save_cpu(void);
   29.33 +crash_xen_info_t *machine_crash_save_info(void);
   29.34 +void machine_crash_shutdown(void);
   29.35 +
   29.36 +#endif /* __XEN_KEXEC_H__ */
   29.37 +
   29.38 +/*
   29.39 + * Local variables:
   29.40 + * mode: C
   29.41 + * c-set-style: "BSD"
   29.42 + * c-basic-offset: 4
   29.43 + * tab-width: 4
   29.44 + * indent-tabs-mode: nil
   29.45 + * End:
   29.46 + */
    30.1 --- a/xen/include/xen/mm.h	Wed Nov 29 23:40:40 2006 +0000
    30.2 +++ b/xen/include/xen/mm.h	Thu Nov 30 12:38:50 2006 +0000
    30.3 @@ -40,6 +40,7 @@ struct page_info;
    30.4  paddr_t init_boot_allocator(paddr_t bitmap_start);
    30.5  void init_boot_pages(paddr_t ps, paddr_t pe);
    30.6  unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
    30.7 +unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
    30.8  void end_boot_allocator(void);
    30.9  
   30.10  /* Generic allocator. These functions are *not* interrupt-safe. */