: kexec: framework and i386
PATCH 1/1 : kexec: framework and i386
kexec: framework and i386
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
* I don't believe that kdump works yet
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedes hypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
in entry.S on init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!
Prepared with the assistance of my colleague Magnus Damm
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/crash-xen.c new file +15 -0
@@ -0,0 +1,15 @@ +/* +* Architecture specific (i386-xen) functions for kexec based crash dumps. +* +* Created by: Horms <[email protected]> +* +*/ + +#include <linux/kernel.h> /* For printk */ + +void machine_crash_shutdown (struct pt_regs *regs) +{ +/* XXX: This should do something */ +printk ("xen-kexec: Need to turn of other CPUS in " +"machine_crash_shutdown()\n" ); +}
linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec-xen.c new file +80 -0
80 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +5 -0
@@ -38,6 +38,11 @@ extern void ctrl_alt_del(void);*/ #define SHUTDOWN_HALT 4 +void machine_shutdown (void ) +{ +printk ("machine_shutdown: does nothing\n" ); +} +void machine_emergency_restart (void ) {/* We really want to get pending console data out before we die. */
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +9 -0
@@ -37,6 +37,8 @@# error "please don't include this file directly"#endif +#include <xen/interface/kexec.h> +#define __STR (x) #x#define STR (x) __STR(x)
@@ -329,6 +331,13 @@ HYPERVISOR_nmi_op( return _hypercall2(int, nmi_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,kexec_arg_t * arg) +{ +return _hypercall2 (int, kexec_op, op, arg); +} +#endif /* __HYPERCALL_H__ */ /*
バイナリー・ファイル/dev/nullとto-work/linux-2.6.16-xen/kernel/.kexec.c.swpは違います
xen/arch/x86/x86_32/Makefile +1 -0
@@ -5,6 +5,7 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/entry.S +2 -0
@@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_acm_op .long do_nmi_op .long do_arch_sched_op + .long do_kexec /* 30 */ .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -683,6 +684,7 @@ ENTRY(hypercall_args_table) .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_kexec */ /* 30 */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c new file +168 -0
168 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-y += trace.o obj-y += timer.o obj-y += vsprintf.o obj-y += xmalloc.o +obj-y += kexec.o obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o
xen/common/kexec.c new file +54 -0
54 lines not on this page · raw message
xen/include/asm-x86/hypercall.h +6 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <public/kexec.h> extern long do_set_trap_table(
@@ -79,6 +80,11 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op, +GUEST_HANDLE (kexec_arg_t) uarg); +#ifdef __x86_64__ extern long
xen/include/public/kexec.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* kexec.h: Xen kexec +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _XEN_PUBLIC_KEXEC_H +#define _XEN_PUBLIC_KEXEC_H + +/* +* Scratch space for passing arguments to the kexec hypercall +*/ +typedef struct kexec_arg { +union { +struct { +unsigned long data;/* Not sure what this should be yet */ + } helper; +struct { +unsigned long indirection_page; +unsigned long reboot_code_buffer; +unsigned long start_address; +const char *relocate_new_kernel; +unsigned int relocate_new_kernel_size; + } kexec; + } u; +}kexec_arg_t ; +DEFINE_GUEST_HANDLE (kexec_arg_t); + +#endif + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/xen.h +8 -0
@@ -60,6 +60,7 @@#define __HYPERVISOR_acm_op 27#define __HYPERVISOR_nmi_op 28#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_kexec_op 30/* * VIRTUAL INTERRUPTS
@@ -206,6 +207,13 @@ DEFINE_GUEST_HANDLE(mmuext_op_t);#define VMASST_TYPE_writable_pagetables 2#define MAX_VMASST_TYPE 2 +/* +* Commands to HYPERVISOR_kexec(). +*/ +#define KEXEC_CMD_kexec 0 +#define KEXEC_CMD_kexec_prepare 1 +#define KEXEC_CMD_kexec_cleanup 2 +#ifndef __ASSEMBLY__typedef uint16_t domid_t ;
buildconfigs/linux-defconfig_xen_x86_32 +1 -0
@@ -184,6 +184,7 @@ CONFIG_HZ_100=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 CONFIG_HOTPLUG_CPU=y
Quoted 6 lines · Horms
kexec: framework and i386
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
Quoted 16 lines
Some notes:
*machine_kexec_cleanup()andmachine_kexec_prepare()don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage.
* Only works for UP, asmachine_shutdownis not implemented yet
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
* I don't believe that kdump works yet
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedeshypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!
I was looking at doing the same but focusing more on kdump initially. However, the more I understood kexec/kdump and the more I understood the hypervisor and xend, I realized they both were solving the same problem in two different ways.
Instead I was trying to focus on a domain0 failover/backup copy. By utilizing xend to set up all the infrastructure of loading the image/initrd, I all I had to do was set a flag in the hypervisor letting it know this was a second copy of another domain0.
Upon reboot/crash, the hypervisor could then look to see if there is a second copy of a domain0 and if so run that copy (which would perform the same functionality as kexec AND kdump - minus the memory hole).
This has the advantage (if done correctly) of not having to reboot the domainU kernels (which is a _huge_ win). The only penalty is dealing with the couple of seconds when the domain0 switches block/net driver control to the other domain0 and any dropped transactions.
The infrastructure in xen is there, I am slowing weeding through the lower layers to set the right bits and such. Unfortunately, I can't commit all my time to this little project but this is the direction I am trying to head towards. (Any help would be great!)
Like I said, this is my 2cents. I just thought this approach would be a better fit with xen, than trying to drag the whole kexec/kdump layer inside the hypervisor. Opinions are welcomed.
Cheers,
Don
Hi Don,
Quoted 47 lines
Quoted 6 lines
kexec: framework and i386
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
Quoted 16 lines
Some notes:
*machine_kexec_cleanup()andmachine_kexec_prepare()don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage.
* Only works for UP, asmachine_shutdownis not implemented yet
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
* I don't believe that kdump works yet
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedeshypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!I was looking at doing the same but focusing more on kdump initially. However, the more I understood kexec/kdump and the more I understood the hypervisor and xend, I realized they both were solving the same problem in two different ways.
Instead I was trying to focus on a domain0 failover/backup copy. By utilizing xend to set up all the infrastructure of loading the image/initrd, I all I had to do was set a flag in the hypervisor letting it know this was a second copy of another domain0.
Upon reboot/crash, the hypervisor could then look to see if there is a second copy of a domain0 and if so run that copy (which would perform the same functionality as kexec AND kdump - minus the memory hole).
This has the advantage (if done correctly) of not having to reboot the domainU kernels (which is a _huge_ win). The only penalty is dealing with the couple of seconds when the domain0 switches block/net driver control to the other domain0 and any dropped transactions.
The infrastructure in xen is there, I am slowing weeding through the lower layers to set the right bits and such. Unfortunately, I can't commit all my time to this little project but this is the direction I am trying to head towards. (Any help would be great!)
Quoted 6 lines
Like I said, this is my 2cents. I just thought this approach would be a better fit with xen, than trying to drag the whole kexec/kdump layer inside the hypervisor. Opinions are welcomed.
Cheers,
Don
Would you let me confirm my understanding is correct?
You prefer kexec/kdump approach to take over a crashed domain0 than HA approach where the backup domain stands by. This is because the former can reset its whole hardware while it would be harder with the latter, right?
Thanks,
Hirokazu Takahashi.
Quoted 57 lines · Hirokazu Takahashi
Hi Don,
Quoted 47 lines
Quoted 6 lines
kexec: framework and i386
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
Quoted 16 lines
Some notes:
*machine_kexec_cleanup()andmachine_kexec_prepare()don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage.
* Only works for UP, asmachine_shutdownis not implemented yet
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
* I don't believe that kdump works yet
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedeshypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!I was looking at doing the same but focusing more on kdump initially. However, the more I understood kexec/kdump and the more I understood the hypervisor and xend, I realized they both were solving the same problem in two different ways.
Instead I was trying to focus on a domain0 failover/backup copy. By utilizing xend to set up all the infrastructure of loading the image/initrd, I all I had to do was set a flag in the hypervisor letting it know this was a second copy of another domain0.
Upon reboot/crash, the hypervisor could then look to see if there is a second copy of a domain0 and if so run that copy (which would perform the same functionality as kexec AND kdump - minus the memory hole).
This has the advantage (if done correctly) of not having to reboot the domainU kernels (which is a _huge_ win). The only penalty is dealing with the couple of seconds when the domain0 switches block/net driver control to the other domain0 and any dropped transactions.
The infrastructure in xen is there, I am slowing weeding through the lower layers to set the right bits and such. Unfortunately, I can't commit all my time to this little project but this is the direction I am trying to head towards. (Any help would be great!)
Quoted 6 lines
Like I said, this is my 2cents. I just thought this approach would be a better fit with xen, than trying to drag the whole kexec/kdump layer inside the hypervisor. Opinions are welcomed.
Cheers,
Don
Quoted 7 lines
Would you let me confirm my understanding is correct?
You prefer kexec/kdump approach to take over a crashed domain0 than HA approach where the backup domain stands by. This is because the former can reset its whole hardware while it would be harder with the latter, right?
Actually the opposite. I prefer the HA approach over kexec/kdump. It seemed like it gave more flexibility (reset dom0 or the whole machine).
As much as I would like to see kexec/kdump in xen, for some reason it just doesn't make sense to me.
Cheers,
Don
Quoted 3 lines
Thanks,
Hirokazu Takahashi.
Hi Don, Hi all,
The key reason why I think that kexec/kdump does makes sense for xen, at least to some extent, is for the case where the hypervisor goes into a bad state, and you actually want to get rid of it and kdump into something else for forensics. There is also the advantage that by kexecing xen, you get access to the entire physical machine, either for crash-dump analysis, or because *gasp* you want to get out of xen for some other crazy reason :) And, on hardware that takes forever and a day to reboot, I believe that doing a kexec will be quite useful for hypervisor development.
I would also like to note, that while my patch does involve moving parts of kexec/kdump into the hypervisor, and more similar parts need to be added in order to support other architectures, it is by no means all of kexec/kdump.
Signature · 1 line
Horms
Quoted 11 lines · Horms
Hi Don, Hi all,
The key reason why I think that kexec/kdump does makes sense for xen, at least to some extent, is for the case where the hypervisor goes into a bad state, and you actually want to get rid of it and kdump into something else for forensics. There is also the advantage that by kexecing xen, you get access to the entire physical machine, either for crash-dump analysis, or because *gasp* you want to get out of xen for some other crazy reason :) And, on hardware that takes forever and a day to reboot, I believe that doing a kexec will be quite useful for hypervisor development.
I guess I never thought about it from the hypervisor prospective. ;) Part of my concern was that the hypervisor had a bunch of this functionality built-in (like mapping memory and loading cpu context).
However, after re-reading some of the kexec code, you don't use the hypervisor to load a new kernel into memory? And I don't know enough about the low level bits to understand if hypercall to load vcpu context would be useful.
Quoted 5 lines
I would also like to note, that while my patch does involve moving parts of kexec/kdump into the hypervisor, and more similar parts need to be added in order to support other architectures, it is by no means all of kexec/kdump.
I understand what you are saying now. The first patch you sent I skimmed through and immediately thought you were trying to moving most parts down into the hypervisor. Upon reviewing it again, it doesn't seem as intrusive. :)
Cheers,
Don
Hi,
Quoted 3 lines
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
First you need some more security checks. On a first quick look it seems you can zap and takeover the whole machine from within a domU by kexec-booting the machine.
Second I think we'll need a new kexec flag to indicate we'll go zap the physical machine, not the virtual machine. I'm looking into the later, and I think we'll be able to do both at some point in the future. Maybe it is enougth to care about dom0 (physical machine kexec) vs. domU (virtual machine kexec) only though. We certainly don't want allow domUs kexec the whole machine, and virtual machine kexec for dom0 doesn't make that much sense given how tight xen and dom0 work hand-in-hand.
Quoted 2 lines
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
Yep, actually _alot_ of the kexec magic happens in userspace.
cheers,
Gerd
Signature · 3 lines
Gerd 'just married' Hoffmann <[email protected]> I'm the hacker formerly known as Gerd Knorr. http://www.suse.de/~kraxel/just-married.jpeg
Quoted 9 lines · Gerd Hoffmann
Hi,
Quoted 3 lines
Here is a first cut of kexec for dom0/xen, which will actually kexec the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
First you need some more security checks. On a first quick look it seems you can zap and takeover the whole machine from within a domU by kexec-booting the machine.
Yes, I think you are right, I had completely forgotten about that.
Quoted 7 lines
Second I think we'll need a new kexec flag to indicate we'll go zap the physical machine, not the virtual machine. I'm looking into the later, and I think we'll be able to do both at some point in the future. Maybe it is enougth to care about dom0 (physical machine kexec) vs. domU (virtual machine kexec) only though. We certainly don't want allow domUs kexec the whole machine, and virtual machine kexec for dom0 doesn't make that much sense given how tight xen and dom0 work hand-in-hand.
Sounds fine by me. The focus of what I was trying to achive is to zap the entire physical machine, which is what the current code does. I am actually most interested in kdump, though its not working yet. In any case a flag makes perfect sense. Though it might make sense to add it when more flexible incarnations of kexec are added.
Quoted 4 lines
Quoted 2 lines
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
Yep, actually _alot_ of the kexec magic happens in userspace.
Yes, I became aware of that along the way. I'm pretty confident that the way I have done things, if you fixed up user-space kexec so that linux -> xen worked, then xen -> xen would also work.
Signature · 1 line
Horms
kexec: framework and i386
Hi,
here is a second take at this patch. The main changes over the predecessor are that kdump now works, mfns are used instead of pfns (was wrong before), and some code has been moved about. The code still uses the basic approach of moving architecture specific opperations into the hypervisor.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet
* I don't believe that kdump works yet
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedes hypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
in entry.S on init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!
Prepared with the assistance of my colleague Magnus Damm
buildconfigs/linux-defconfig_xen_x86_32 +1 -0
@@ -183,6 +183,7 @@ CONFIG_HZ_100=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 CONFIG_HOTPLUG_CPU=y
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -92,7 +92,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +1 -1
@@ -59,7 +59,7 @@ pci-dma-y += ../../i386/kernel/pci-dma microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o quirks-y := ../../i386/kernel/quirks-xen.o -n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o +n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o machine_kexec.o crash.o include $(srctree)/scripts/Makefile.xen
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +85 -0
97 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +9 -0
@@ -37,6 +37,8 @@# error "please don't include this file directly"#endif +#include <xen/interface/kexec.h> +#define __STR (x) #x#define STR (x) __STR(x)
@@ -329,6 +331,13 @@ HYPERVISOR_nmi_op( return _hypercall2(int, nmi_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,kexec_arg_t * arg) +{ +return _hypercall2 (int, kexec_op, op, arg); +} +#endif /* __HYPERCALL_H__ */ /*
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +9 -0
@@ -41,6 +41,8 @@# error "please don't include this file directly"#endif +#include <xen/interface/kexec.h> +#define __STR (x) #x#define STR (x) __STR(x)
@@ -330,6 +332,13 @@ HYPERVISOR_nmi_op( return _hypercall2(int, nmi_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,kexec_arg_t * arg) +{ +return _hypercall2 (int, kexec_op, op, arg); +} +#endif /* __HYPERCALL_H__ */ /*
xen/arch/x86/x86_32/Makefile +1 -0
@@ -5,6 +5,7 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/entry.S +2 -0
@@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_acm_op .long do_nmi_op .long do_arch_sched_op + .long do_kexec /* 30 */ .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -683,6 +684,7 @@ ENTRY(hypercall_args_table) .byte 1 /* do_acm_op */ .byte 2 /* do_nmi_op */ .byte 2 /* do_arch_sched_op */ + .byte 2 /* do_kexec */ /* 30 */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c new file +168 -0
168 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-y += trace.o obj-y += timer.o obj-y += vsprintf.o obj-y += xmalloc.o +obj-y += kexec.o obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o
xen/common/kexec.c new file +58 -0
58 lines not on this page · raw message
xen/include/asm-x86/hypercall.h +6 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <public/kexec.h> extern long do_set_trap_table(
@@ -79,6 +80,11 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op, +GUEST_HANDLE (kexec_arg_t) uarg); +#ifdef __x86_64__ extern long
xen/include/public/kexec.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* kexec.h: Xen kexec +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _XEN_PUBLIC_KEXEC_H +#define _XEN_PUBLIC_KEXEC_H + +/* +* Scratch space for passing arguments to the kexec hypercall +*/ +typedef struct kexec_arg { +union { +struct { +unsigned long data;/* Not sure what this should be yet */ + } helper; +struct { +unsigned long indirection_page; +unsigned long reboot_code_buffer; +unsigned long start_address; +const char *relocate_new_kernel; +unsigned int relocate_new_kernel_size; + } kexec; + } u; +}kexec_arg_t ; +DEFINE_GUEST_HANDLE (kexec_arg_t); + +#endif + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/xen.h +8 -0
@@ -60,6 +60,7 @@#define __HYPERVISOR_acm_op 27#define __HYPERVISOR_nmi_op 28#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_kexec_op 30/* * VIRTUAL INTERRUPTS
@@ -206,6 +207,13 @@ DEFINE_GUEST_HANDLE(mmuext_op_t);#define VMASST_TYPE_writable_pagetables 2#define MAX_VMASST_TYPE 2 +/* +* Commands to HYPERVISOR_kexec(). +*/ +#define KEXEC_CMD_kexec 0 +#define KEXEC_CMD_kexec_prepare 1 +#define KEXEC_CMD_kexec_cleanup 2 +#ifndef __ASSEMBLY__typedef uint16_t domid_t ;
Quoted 2 lines · Horms
kexec: framework and i386
[snip]
Quoted 7 lines
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedes
hypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!
Hi,
I am a bit concerned that this patch is going to start rotting if I can't at least track the current xen-unstable.hg, or better still get it merged.
I would really appreciate it if someone could take moments to comment on the hypercall problem. Is adding a new hypercall, as the current patch does, the best way? If so could someone point me to how to increase the hypercall table size. If not, is it best to piggyback of the dom0_op hypercall? Or is there some other prefered option?
Signature · 1 line
Horms
PATCH 1/1 : kexec: framework and i386 (Take IV)
Hi,
here is the latest update of the kexec xen/dom0 patch.
Signature · 987 lines
Horms
kexec: framework and i386
This is an implementation of kexec for dom0/xen, that allows
kexecing of the physical machine from xen. The approach taken is
to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do
anything in i386. So while this patch adds a framework for them,
I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that
kexec-tools needs updating, but I have not investigated yet
* Kdump works by first copying the kernel into dom0 segments
and relocating them later in xen, the same way that kexec does
The only difference is that the relocation is made into
an area reserved by xen
* Kdump reservation is made using the xen command line parameters,
kdump_megabytes and kdump_megabytes_base, rather than
the linux option crashkernel, which is now ignored.
Two parameters are used instead of one to simplify parsing.
This can be cleaned up later if desired. But the reservation
seems to need to be made by xen to make sure that it happens
early enough.
* This patch uses dom0_op for hypercalls
Highlights since the previous posted version:
* Use dom0_op instead of a new kexec hypercall
- the hypercall table is currently full, so there is no where to
put a new kexec hypercall
- This kexec patch makes sense for dom0 at this stage
* Kernel notes are filled in for kdump
- UP only, this patch does not support SMP kdump yet
* Share x86 code between x86_64 and x86_32
(though x86_64 is not finished and not included in this patch)
* Doesn't break x86_64 build
Prepared by Horms and Magnus Damm
Signed-Off-By: Magnus Damm <[email protected]>
Signed-Off-By: Horms <[email protected]>
linux-2.6-xen-sparse/arch/i386/Kconfig | 2
linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 26 ++
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 +++++++++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 78 +++++++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 7
ref-linux-2.6.16/drivers/base/cpu.c | 4
ref-linux-2.6.16/kernel/kexec.c | 52 ++++-
xen/arch/x86/Makefile | 1
xen/arch/x86/dom0_ops.c | 33 +++
xen/arch/x86/machine_kexec.c | 174 +++++++++++++++++
xen/arch/x86/setup.c | 75 ++++++-
xen/common/page_alloc.c | 33 ++-
xen/include/public/dom0_ops.h | 23 ++
xen/include/public/xen.h | 8
xen/include/xen/mm.h | 1
17 files changed, 585 insertions(+), 33 deletions(-)
--- x/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ x/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL && !X86_XEN
+ depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
--- x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
@@ -92,7 +92,7 @@ include $(srctree)/scripts/Makefile.xen
obj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o
-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o
+n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen))
obj-y := $(call cherrypickxen, $(obj-y))
--- x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
@@ -68,6 +68,10 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/dom0_ops.h>
+#endif
+
/* Forward Declaration. */
void __init find_max_pfn(void);
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (
* after a kernel panic.
*/
else if (!memcmp(from, "crashkernel=", 12)) {
+#ifndef CONFIG_XEN
unsigned long size, base;
size = memparse(from+12, &from);
if (*from == '@') {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early (
crashk_res.start = base;
crashk_res.end = base + size - 1;
}
+#else
+ printk("Ignoring crashkernel command line, "
+ "parameter will be supplied by xen\n");
+#endif
}
#endif
#ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,23 @@ void __init setup_bootmem_allocator(void
}
#endif
#ifdef CONFIG_KEXEC
+#ifndef CONFIG_XEN
if (crashk_res.start != crashk_res.end)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
+#else
+ {
+ dom0_op_t op;
+ op.cmd = DOM0_KEXEC;
+ op.u.kexec.op = KEXEC_CMD_reserve;
+ BUG_ON(HYPERVISOR_dom0_op(&op));
+ if (op.u.kexec.u.reserve.size) {
+ crashk_res.start = op.u.kexec.u.reserve.start;
+ crashk_res.end = op.u.kexec.u.reserve.start +
+ op.u.kexec.u.reserve.size - 1;
+ }
+ }
+#endif
#endif
if (!xen_feature(XENFEAT_auto_translated_physmap))
@@ -1395,6 +1418,9 @@ legacy_init_iomem_resources(struct resou
res->end = map[i].end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
free_bootmem(__pa(map), PAGE_SIZE);
--- x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/crash.c
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific (i386-xen) functions for kexec based crash dumps.
+ *
+ * Created by: Horms <[email protected]>
+ *
+ */
+
+#include <linux/kernel.h> /* For printk */
+
+/* XXX: final_note(), crash_save_this_cpu() and crash_save_self()
+ * are copied from arch/i386/kernel/crash.c, might be good to either
+ * the original functions non-static and use them, or just
+ * merge this this into that file.
+ */
+#include <linux/elf.h> /* For struct elf_note */
+#include <linux/elfcore.h> /* For struct elf_prstatus */
+#include <linux/kexec.h> /* crash_notes */
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* XXX: This should do something */
+ printk("xen-kexec: Need to turn of other CPUS in "
+ "machine_crash_shutdown()\n");
+ crash_save_self(regs);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,78 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Created By: Horms <[email protected]>
+ *
+ * Losely based on arch/i386/kernel/machine_kexec.c
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/dom0_ops.h>
+#include <linux/mm.h>
+#include <asm/hypercall.h>
+
+const extern unsigned char relocate_new_kernel[];
+extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ struct dom0_op op;
+ op.cmd = DOM0_KEXEC;
+ op.u.kexec.op = KEXEC_CMD_kexec_prepare;
+ op.u.kexec.u.helper.data = 0;
+ return HYPERVISOR_dom0_op(&op);
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+ struct dom0_op op;
+ op.cmd = DOM0_KEXEC;
+ op.u.kexec.op = KEXEC_CMD_kexec_cleanup;
+ op.u.kexec.u.helper.data = 0;
+ HYPERVISOR_dom0_op(&op);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ struct dom0_op op;
+ op.cmd = DOM0_KEXEC;
+ op.u.kexec.op = KEXEC_CMD_kexec;
+ op.u.kexec.u.kexec.indirection_page = image->head;
+ op.u.kexec.u.kexec.reboot_code_buffer =
+ pfn_to_mfn(page_to_pfn(image->control_code_page)) << PAGE_SHIFT;
+ op.u.kexec.u.kexec.start_address = image->start;
+ op.u.kexec.u.kexec.relocate_new_kernel = relocate_new_kernel;
+ op.u.kexec.u.kexec.relocate_new_kernel_size = relocate_new_kernel_size;
+ HYPERVISOR_dom0_op(&op);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
+++ x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
@@ -370,6 +370,13 @@ static int __init setup_shutdown_event(v
subsys_initcall(setup_shutdown_event);
+#ifdef CONFIG_KEXEC
+void machine_shutdown(void)
+{
+ printk("machine_shutdown: does nothing\n");
+}
+#endif
+
/*
* Local variables:
* c-file-style: "linux"
--- x/ref-linux-2.6.16/drivers/base/cpu.c
+++ x/ref-linux-2.6.16/drivers/base/cpu.c
@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s
* boot up and this data does not change there after. Hence this
* operation should be safe. No locking required.
*/
+#ifndef CONFIG_XEN
addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+#else
+ addr = virt_to_machine(per_cpu_ptr(crash_notes, cpunum));
+#endif
rc = sprintf(buf, "%Lx\n", addr);
return rc;
}
--- x/ref-linux-2.6.16/kernel/kexec.c
+++ x/ref-linux-2.6.16/kernel/kexec.c
@@ -38,6 +38,20 @@ struct resource crashk_res = {
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
+/* Kexec needs to know about the actually physical addresss.
+ * But in xen, a physical address is a pseudo-physical addresss. */
+#ifndef CONFIG_XEN
+#define kexec_page_to_pfn(page) page_to_pfn(page)
+#define kexec_pfn_to_page(pfn) pfn_to_page(pfn)
+#define kexec_virt_to_phys(addr) virt_to_phys(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(addr)
+#else
+#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page))
+#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn))
+#define kexec_virt_to_phys(addr) virt_to_machine(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
+#endif
+
int kexec_should_crash(struct task_struct *p)
{
if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_
pages = kimage_alloc_pages(GFP_KERNEL, order);
if (!pages)
break;
- pfn = page_to_pfn(pages);
+ pfn = kexec_page_to_pfn(pages);
epfn = pfn + count;
addr = pfn << PAGE_SHIFT;
eaddr = epfn << PAGE_SHIFT;
@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_
return pages;
}
+#ifndef CONFIG_XEN
static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
unsigned int order)
{
@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c
}
/* If I don't overlap any segments I have found my hole! */
if (i == image->nr_segments) {
- pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
break;
}
}
@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages(
return pages;
}
+#else /* !CONFIG_XEN */
+struct page *kimage_alloc_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ return kimage_alloc_normal_control_pages(image, order);
+}
+#endif
static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
{
@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimag
return -ENOMEM;
ind_page = page_address(page);
- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
image->entry = ind_page;
image->last_entry = ind_page +
((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag
#define for_each_kimage_entry(image, ptr, entry) \
for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
ptr = (entry & IND_INDIRECTION)? \
- phys_to_virt((entry & PAGE_MASK)): ptr +1)
+ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
static void kimage_free_entry(kimage_entry_t entry)
{
struct page *page;
- page = pfn_to_page(entry >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
kimage_free_pages(page);
}
@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st
* have a match.
*/
list_for_each_entry(page, &image->dest_pages, lru) {
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
if (addr == destination) {
list_del(&page->lru);
return page;
@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(st
if (!page)
return NULL;
/* If the page cannot be used file it away */
- if (page_to_pfn(page) >
+ if (kexec_page_to_pfn(page) >
(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
list_add(&page->lru, &image->unuseable_pages);
continue;
}
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
/* If it is the destination page we want use it */
if (addr == destination)
@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(st
struct page *old_page;
old_addr = *old & PAGE_MASK;
- old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
copy_highpage(page, old_page);
*old = addr | (*old & ~PAGE_MASK);
@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st
result = -ENOMEM;
goto out;
}
- result = kimage_add_page(image, page_to_pfn(page)
+ result = kimage_add_page(image, kexec_page_to_pfn(page)
<< PAGE_SHIFT);
if (result < 0)
goto out;
@@ -811,6 +833,7 @@ out:
return result;
}
+#ifndef CONFIG_XEN
static int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)
{
@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(str
char *ptr;
size_t uchunk, mchunk;
- page = pfn_to_page(maddr >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
if (page == 0) {
result = -ENOMEM;
goto out;
@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki
return result;
}
+#else /* CONFIG_XEN */
+static int kimage_load_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ return kimage_load_normal_segment(image, segment);
+}
+#endif
/*
* Exec Kernel system call: for obvious reasons only root may call it.
--- x/xen/arch/x86/Makefile
+++ x/xen/arch/x86/Makefile
@@ -38,6 +38,7 @@ obj-y += trampoline.o
obj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.o
ifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
--- x/xen/arch/x86/dom0_ops.c
+++ x/xen/arch/x86/dom0_ops.c
@@ -29,6 +29,13 @@
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+extern int machine_kexec_prepare(struct dom0_kexec *arg);
+extern void machine_kexec_cleanup(struct dom0_kexec *arg);
+extern void machine_kexec(struct dom0_kexec *arg);
+
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
@@ -445,6 +452,32 @@ long arch_do_dom0_op(struct dom0_op *op,
}
break;
+ case DOM0_KEXEC:
+ switch(op->u.kexec.op) {
+ case KEXEC_CMD_kexec:
+ machine_kexec(&op->u.kexec);
+ ret = -EINVAL; /* Not Reached */
+ break;
+ case KEXEC_CMD_kexec_prepare:
+ ret = machine_kexec_prepare(&op->u.kexec);
+ break;
+ case KEXEC_CMD_kexec_cleanup:
+ machine_kexec_cleanup(&op->u.kexec);
+ ret = 0;
+ break;
+ case KEXEC_CMD_reserve:
+ op->u.kexec.u.reserve.size = opt_kdump_megabytes << 20;
+ op->u.kexec.u.reserve.start = opt_kdump_megabytes_base << 20;
+ if ( unlikely(copy_to_guest(u_dom0_op, op, 1) != 0) )
+ {
+ printk("arch_do_dom0_op: kexec: copy_to_guest failed");
+ return -EFAULT;
+ }
+ ret = 0;
+ break;
+ }
+ break;
+
default:
ret = -ENOSYS;
break;
--- /dev/null
+++ x/xen/arch/x86/machine_kexec.c
@@ -0,0 +1,174 @@
+/******************************************************************************
+ * arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/domain_page.h>
+#include <xen/timer.h>
+#include <xen/sched.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <public/xen.h>
+#include <public/dom0_ops.h>
+
+#ifdef CONFIG_X86_32
+
+typedef asmlinkage void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae);
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#ifndef CONFIG_X86_PAE
+
+static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long mfn;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level2 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ write_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level2);
+}
+
+#else
+static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ int mfn;
+ intpte_t *pgtable_level3;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level3 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[l3_table_offset(address)],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level3);
+}
+#endif
+
+static void kexec_load_segments(void)
+{
+#define __SSTR(X) #X
+#define SSTR(X) __SSTR(X)
+ __asm__ __volatile__ (
+ "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n"
+ "\tmovl %%eax,%%ds\n"
+ "\tmovl %%eax,%%es\n"
+ "\tmovl %%eax,%%fs\n"
+ "\tmovl %%eax,%%gs\n"
+ "\tmovl %%eax,%%ss\n"
+ ::: "eax", "memory");
+#undef SSTR
+#undef __SSTR
+}
+
+#define kexec_load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+static void kexec_set_idt(void *newidt, __u16 limit)
+{
+ struct Xgt_desc_struct curidt;
+
+ /* ia32 supports unaliged loads & stores */
+ curidt.size = limit;
+ curidt.address = (unsigned long)newidt;
+
+ kexec_load_idt(&curidt);
+
+};
+
+#define kexec_load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+static void kexec_set_gdt(void *newgdt, __u16 limit)
+{
+ struct Xgt_desc_struct curgdt;
+
+ /* ia32 supports unaligned loads & stores */
+ curgdt.size = limit;
+ curgdt.address = (unsigned long)newgdt;
+
+ kexec_load_gdt(&curgdt);
+};
+
+#endif
+
+int machine_kexec_prepare(struct dom0_kexec *arg)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct dom0_kexec *arg)
+{
+}
+
+void machine_kexec(struct dom0_kexec *arg)
+{
+#ifdef CONFIG_X86_32
+ relocate_new_kernel_t rnk;
+
+ local_irq_disable();
+
+ identity_map_page(arg->u.kexec.reboot_code_buffer);
+
+ copy_from_user((void *)arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.relocate_new_kernel,
+ arg->u.kexec.relocate_new_kernel_size);
+
+ kexec_load_segments();
+
+ kexec_set_gdt(__va(0),0);
+
+ kexec_set_idt(__va(0),0);
+
+ rnk = (relocate_new_kernel_t) arg->u.kexec.reboot_code_buffer;
+
+ (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.start_address, cpu_has_pae);
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -37,6 +37,11 @@ static unsigned int opt_xenheap_megabyte
integer_param("xenheap_megabytes", opt_xenheap_megabytes);
#endif
+unsigned int opt_kdump_megabytes = 0;
+integer_param("kdump_megabytes", opt_kdump_megabytes);
+unsigned int opt_kdump_megabytes_base = 0;
+integer_param("kdump_megabytes_base", opt_kdump_megabytes_base);
+
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);
@@ -159,6 +164,20 @@ void discard_initial_images(void)
init_domheap_pages(initial_images_start, initial_images_end);
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char *cmdline;
@@ -289,15 +308,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -344,6 +356,51 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ if (opt_kdump_megabytes) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = opt_kdump_megabytes_base << 20;
+ kdump_size = opt_kdump_megabytes << 20;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
printk("System RAM: %luMB (%lukB)\n",
--- x/xen/common/page_alloc.c
+++ x/xen/common/page_alloc.c
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t
}
}
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+ unsigned long i;
+
+ for ( i = 0; i < nr_pfns; i++ )
+ if ( allocated_in_map(pfn_at + i) )
+ break;
+
+ if ( i == nr_pfns )
+ {
+ map_alloc(pfn_at, nr_pfns);
+ return pfn_at;
+ }
+
+ return 0;
+}
+
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{
- unsigned long pg, i;
+ unsigned long pg, i = 0;
for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
{
- for ( i = 0; i < nr_pfns; i++ )
- if ( allocated_in_map(pg + i) )
- break;
-
- if ( i == nr_pfns )
- {
- map_alloc(pg, nr_pfns);
- return pg;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- x/xen/include/public/dom0_ops.h
+++ x/xen/include/public/dom0_ops.h
@@ -472,6 +472,28 @@ typedef struct dom0_hypercall_init {
} dom0_hypercall_init_t;
DEFINE_GUEST_HANDLE(dom0_hypercall_init_t);
+#define DOM0_KEXEC 49
+typedef struct dom0_kexec{
+ unsigned long op;
+ union {
+ struct {
+ unsigned long data; /* Not sure what this should be yet */
+ } helper;
+ struct {
+ unsigned long indirection_page;
+ unsigned long reboot_code_buffer;
+ unsigned long start_address;
+ const char *relocate_new_kernel;
+ unsigned int relocate_new_kernel_size;
+ } kexec;
+ struct {
+ unsigned long size;
+ unsigned long start;
+ } reserve;
+ } u;
+} dom0_kexec_t;
+DEFINE_GUEST_HANDLE(dom0_kexec_t);
+
typedef struct dom0_op {
uint32_t cmd;
uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
@@ -513,6 +535,7 @@ typedef struct dom0_op {
struct dom0_irq_permission irq_permission;
struct dom0_iomem_permission iomem_permission;
struct dom0_hypercall_init hypercall_init;
+ struct dom0_kexec kexec;
uint8_t pad[128];
} u;
} dom0_op_t;
--- x/xen/include/public/xen.h
+++ x/xen/include/public/xen.h
@@ -215,6 +215,14 @@ DEFINE_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_writable_pagetables 2
#define MAX_VMASST_TYPE 2
+/*
+ * Operations for kexec.
+ */
+#define KEXEC_CMD_kexec 0
+#define KEXEC_CMD_kexec_prepare 1
+#define KEXEC_CMD_kexec_cleanup 2
+#define KEXEC_CMD_reserve 3
+
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
--- x/xen/include/xen/mm.h
+++ x/xen/include/xen/mm.h
@@ -40,6 +40,7 @@ struct page_info;
paddr_t init_boot_allocator(paddr_t bitmap_start);
void init_boot_pages(paddr_t ps, paddr_t pe);
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
void end_boot_allocator(void);
/* Generic allocator. These functions are *not* interrupt-safe. */Hi, Horms and Mark
This is good work!
It is very necessary for debugging hypervisor or domain0. I'm not clear at some points.
1. Is this feature available on uni-processor machine?
2. Could you explain more detail usage?
Mark, what do you think about this kdump implementation?
Best Regards,
Akio Takebe
Quoted 33 lines · Horms
Quoted 2 lines
kexec: framework and i386
[snip]
Quoted 7 lines
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedes
hypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!Hi,
I am a bit concerned that this patch is going to start rotting if I can't at least track the current xen-unstable.hg, or better still get it merged.
I would really appreciate it if someone could take moments to comment on the hypercall problem. Is adding a new hypercall, as the current patch does, the best way? If so could someone point me to how to increase the hypercall table size. If not, is it best to piggyback of the
dom0_ophypercall? Or is there some other prefered option?Signature · 6 lines
Horms _______________________________________________ Xen-devel mailing list [email protected] http://lists.xensource.com/xen-devel
Quoted 7 lines · Akio Takebe
Hi, Horms and Mark
This is good work!
It is very necessary for debugging hypervisor or domain0. I'm not clear at some points.1. Is this feature available on uni-processor machine?
At this stage only uni-processor is supported. However, the framework supports SMP, and Magnus and I are planning to fill in those bits soon. Actually, this is the next thing on my list of things to do.
Quoted 1 line
2. Could you explain more detail usage?
The usage is mostly the same as kexec in the Linux kernel. You can kexec from xen into another kernel by using kexec -l, kexec -e, as per linux.
kexec -l /boot/vmlinux --append "ro root=/dev/hda..." kexec -e
And you can load a kernel that will be run on system crash using kexec -p. This is discussed at some length in Documentation/kdump/kdump.txt of the linux source tree. Those instructions can be followed verbatim for xen.
The main difference with kdump, is that instead of using the crashdump command line option to linux, you use the kdump_megabytes and kdump_megabytes_base command line options to xen. When running xen the crashdump linux command line option is ignored.
The reason for moving the option from linux to xen is that it seems that the memory needs to be reserved by xen before it starts dom0. The reason that there are two options instead of one is for simplicity. Linux provides infastructure to read the more complex compound option, xen does not. This can be changed if it is a problem.
In summary, for kdump "linux crashdump=64M@16M" becomes "xen kdump_megabytes=64 kdump_megabytes_base=16"
The other main point to note for users is that while the following transition is possible: xen -> linux. But xen -> xen and linux -> xen is currently not possible. This is because kexec-tool, the user-space component of kexec does not understand enough about xen, and thus needs to be enhanced in order to make this possible.
Quoted 5 lines
Mark, what do you think about this kdump implementation?
Best Regards,
Akio Takebe
Signature · 1 line
Horms
Hi, Horms
Thank you for your kind explanation.
I have a small question.
Is this kdump called only when domain0 panic?
When Xen/Hypervisor panic, is this kdump called?
I think it is necessary for dump feature to be called via NMI handler and panic(). (as linux code)
Best Regards,
Akio Takebe
Quoted 2 lines
This is good work!
It is very necessary for debugging hypervisor or domain0.
Agreed.
Quoted 1 line
Mark, what do you think about this kdump implementation?
I think kdump, in general, is a nifty solution for supporting crashdumps, since using a separate kernel for crashdumps gives you the best possible opportunity to complete them successfully.
Integrating with the Linux crashdump infrastructure seems like a good idea. It doesn't stop other dom0 OSes using their own crashdump infrastructure, but with kdump we have a chance of getting a dump even if Xen itself crashes (whilst admittedly rare, such crashes are something you'd want to get debugged quickly!)
So, essentially, I think the idea is good - I'll try and take a look through the code.
Cheers,
Mark
Quoted 36 lines
Best Regards,
Akio Takebe
Quoted 32 lines · Horms
Quoted 1 line
kexec: framework and i386
[snip]
Quoted 7 lines
* This patch was prepared against xen-unstable.hg 9514 As of today (9574) two new hypercalls have been added. I rediffed and moved the kexec hypercall to 33. However this exceedes
hypercall_NR, which is currently 32.
I tried increasing this, but the dom0 now crashes
inentry.Son init. Even after rebuilding both xen and the kernel completely from scratch after a make distclean. Help!!Hi,
I am a bit concerned that this patch is going to start rotting if I can't at least track the current xen-unstable.hg, or better still get it merged.
I would really appreciate it if someone could take moments to comment on the hypercall problem. Is adding a new hypercall, as the current patch does, the best way? If so could someone point me to how to increase the hypercall table size. If not, is it best to piggyback of the
dom0_ophypercall? Or is there some other prefered option?--
Horms_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Signature · 4 lines
Dave: Just a question. What use is a unicyle with no seat? And no pedals! Mark: To answer a question with a question: What use is a skateboard? Dave: Skateboards have wheels. Mark: My wheel has a wheel!
Hi, Mark
Thank you for your comments!
Quoted 11 lines
I think kdump, in general, is a nifty solution for supporting crashdumps, since using a separate kernel for crashdumps gives you the best possible opportunity to complete them successfully.
Integrating with the Linux crashdump infrastructure seems like a good idea. It doesn't stop other dom0 OSes using their own crashdump infrastructure, but
with kdump we have a chance of getting a dump even if Xen itself crashes (whilst admittedly rare, such crashes are something you'd want to get debugged quickly!)
Yes, I also agree.
Quoted 3 lines
So, essentially, I think the idea is good - I'll try and take a look through the code.
I also try to read a new patch.
http://lists.xensource.com/archives/html/xen-devel/2006-04/msg00968.html
Can kexec hypecll use Hypercall 11 or 30?
I think using not hypercall but dom0_op is good idea because using kexec is rare. :-)
Best Regards,
Akio Takebe
Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
Quoted 3 lines · Akio Takebe
Can kexec hypecll use Hypercall 11 or 30?
I think using not hypercall butdom0_opis good idea because using kexec is rare. :-)
I think Rusty's xen share also had a similar problem caused by the hypercall number conflict.
Xen/ia64 with virtual physical model also needs a hypercall number for its own use.
Currently it large enough (=256) that it is unlikly to be used by xen/x86.
Is there any convension about how to take hypercall number? At least hypercall numbers for arch-specific purpose and experimental purpose should be defined.
Signature · 1 line
yamahata
Re: Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
Quoted 9 lines · Isaku Yamahata
I think Rusty's xen share also had a similar problem caused by the hypercall number conflict.
Xen/ia64 with virtual physical model also needs a hypercall number for its own use.
Currently it large enough (=256) that it is unlikly to be used by xen/x86.Is there any convension about how to take hypercall number? At least hypercall numbers for arch-specific purpose and experimental purpose should be defined.
The list of __HYPERVISOR_* defines in public/xen.h in the main xen repository is the canonical place. For hypercalls in our tree, simply grabbing the next number in sequence usually makes sense. I'm not sure whether having structure to the hypercall numbers makes sense (e.g., a range for arch-specific usage) -- if so then maybe allocating from 64 upwards would make sense.
-- Keir
Re: Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
Quoted 6 lines · Keir Fraser
The list of __HYPERVISOR_* defines in
public/xen.hin the main xen repository is the canonical place. For hypercalls in our tree, simply grabbing the next number in sequence usually makes sense. I'm not sure whether having structure to the hypercall numbers makes sense (e.g., a range for arch-specific usage) -- if so then maybe allocating from 64 upwards would make sense.
Won't having discontigous regions of hcalls break the NR_hypercall masking check?
Cheers,
Muli
Re: Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
In reply to Keir FraserQuoted 14 lines · Keir Fraser
Quoted 10 lines · Isaku Yamahata
I think Rusty's xen share also had a similar problem caused by the hypercall number conflict.
Xen/ia64 with virtual physical model also needs a hypercall number for its own use.
Currently it large enough (=256) that it is unlikly to be used by xen/x86.Is there any convension about how to take hypercall number? At least hypercall numbers for arch-specific purpose and experimental purpose should be defined.
Quoted 6 lines
The list of __HYPERVISOR_* defines in
public/xen.hin the main xen repository is the canonical place. For hypercalls in our tree, simply grabbing the next number in sequence usually makes sense. I'm not sure whether having structure to the hypercall numbers makes sense (e.g., a range for arch-specific usage) -- if so then maybe allocating from 64 upwards would make sense.
There is a small problem, in that for x86_32 at least the hypercall table is currently full with 32 entries (well, the last time I checked anyway), and my attempts to extend it were futile. Could you give me some advice on how to increase its size?
Signature · 1 line
Horms
Re: Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
Quoted 4 lines · Horms
There is a small problem, in that for
x86_32at least the hypercall table is currently full with 32 entries (well, the last time I checked anyway), and my attempts to extend it were futile. Could you give me some advice on how to increase its size?
Double NR_hypercalls in include/asm-x86/config.h.
-- Keir
Re: [PATCH]: kexec: framework and i386 Take V
Quoted 9 lines · Keir Fraser
Quoted 4 lines · Horms
There is a small problem, in that for
x86_32at least the hypercall table is currently full with 32 entries (well, the last time I checked anyway), and my attempts to extend it were futile. Could you give me some advice on how to increase its size?Double
NR_hypercallsininclude/asm-x86/config.h.
Thanks, the new version of the kexec patch below does just that. I did try that before, but for some reason it didn't work, most likely because it was Friday afternoon at the time.
Also, this patch takes hypercall 32, which conflicts with Yamahata-san's ia64 hypercall. Should I move to 33 and submit a patch that just does hypercall reservation as he did?
Signature · 1,118 lines
Horms http://www.vergenet.net/~horms/
kexec: framework and i386
This is an implementation of kexec for dom0/xen, that allows
kexecing of the physical machine from xen. The approach taken is
to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do
anything in i386. So while this patch adds a framework for them,
I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that
kexec-tools needs updating, but I have not investigated yet
* Kdump works by first copying the kernel into dom0 segments
and relocating them later in xen, the same way that kexec does
The only difference is that the relocation is made into
an area reserved by xen
* Kdump reservation is made using the xen command line parameters,
kdump_megabytes and kdump_megabytes_base, rather than
the linux option crashkernel, which is now ignored.
Two parameters are used instead of one to simplify parsing.
This can be cleaned up later if desired. But the reservation
seems to need to be made by xen to make sure that it happens
early enough.
* This patch uses a new kexec hypercall
Highlights since the previous posted version:
* Use new kexec hypercall instead of dom0_op
- hypercall table is expanded to 64 entries
Prepared by Horms and Magnus Damm
Signed-Off-By: Magnus Damm <[email protected]>
Signed-Off-By: Horms <[email protected]>
linux-2.6-xen-sparse/arch/i386/Kconfig | 2
linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 24 +
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 +++++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 73 ++++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 7
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10
ref-linux-2.6.16/drivers/base/cpu.c | 4
ref-linux-2.6.16/kernel/kexec.c | 52 ++
xen/arch/x86/Makefile | 1
xen/arch/x86/dom0_ops.c | 3
xen/arch/x86/machine_kexec.c | 174 ++++++++++
xen/arch/x86/setup.c | 75 +++-
xen/arch/x86/x86_32/entry.S | 2
xen/common/Makefile | 1
xen/common/kexec.c | 71 ++++
xen/common/page_alloc.c | 33 +
xen/include/asm-x86/config.h | 2
xen/include/asm-x86/hypercall.h | 5
xen/include/public/kexec.h | 43 ++
xen/include/public/xen.h | 9
xen/include/xen/mm.h | 1
23 files changed, 659 insertions(+), 34 deletions(-)
--- x/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ x/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL && !X86_XEN
+ depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
--- x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen
obj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o
-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o
+n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen))
obj-y := $(call cherrypickxen, $(obj-y))
--- x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
@@ -68,6 +68,10 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
+
/* Forward Declaration. */
void __init find_max_pfn(void);
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (
* after a kernel panic.
*/
else if (!memcmp(from, "crashkernel=", 12)) {
+#ifndef CONFIG_XEN
unsigned long size, base;
size = memparse(from+12, &from);
if (*from == '@') {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early (
crashk_res.start = base;
crashk_res.end = base + size - 1;
}
+#else
+ printk("Ignoring crashkernel command line, "
+ "parameter will be supplied by xen\n");
+#endif
}
#endif
#ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,21 @@ void __init setup_bootmem_allocator(void
}
#endif
#ifdef CONFIG_KEXEC
+#ifndef CONFIG_XEN
if (crashk_res.start != crashk_res.end)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
+#else
+ {
+ struct kexec_arg xen_kexec_arg;
+ BUG_ON(HYPERVISOR_kexec(KEXEC_CMD_reserve, &xen_kexec_arg));
+ if (xen_kexec_arg.u.reserve.size) {
+ crashk_res.start = xen_kexec_arg.u.reserve.start;
+ crashk_res.end = xen_kexec_arg.u.reserve.start +
+ xen_kexec_arg.u.reserve.size - 1;
+ }
+ }
+#endif
#endif
if (!xen_feature(XENFEAT_auto_translated_physmap))
@@ -1395,6 +1416,9 @@ legacy_init_iomem_resources(struct resou
res->end = map[i].end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
free_bootmem(__pa(map), PAGE_SIZE);
--- x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/crash.c
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific (i386-xen) functions for kexec based crash dumps.
+ *
+ * Created by: Horms <[email protected]>
+ *
+ */
+
+#include <linux/kernel.h> /* For printk */
+
+/* XXX: final_note(), crash_save_this_cpu() and crash_save_self()
+ * are copied from arch/i386/kernel/crash.c, might be good to either
+ * the original functions non-static and use them, or just
+ * merge this this into that file.
+ */
+#include <linux/elf.h> /* For struct elf_note */
+#include <linux/elfcore.h> /* For struct elf_prstatus */
+#include <linux/kexec.h> /* crash_notes */
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* XXX: This should do something */
+ printk("xen-kexec: Need to turn of other CPUS in "
+ "machine_crash_shutdown()\n");
+ crash_save_self(regs);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,73 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Created By: Horms <[email protected]>
+ *
+ * Losely based on arch/i386/kernel/machine_kexec.c
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/mm.h>
+#include <asm/hypercall.h>
+
+const extern unsigned char relocate_new_kernel[];
+extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ return HYPERVISOR_kexec(KEXEC_CMD_kexec_prepare, &hypercall_arg);
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec_cleanup, &hypercall_arg);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.kexec.indirection_page = image->head;
+ hypercall_arg.u.kexec.reboot_code_buffer =
+ pfn_to_mfn(page_to_pfn(image->control_code_page)) << PAGE_SHIFT;
+ hypercall_arg.u.kexec.start_address = image->start;
+ hypercall_arg.u.kexec.relocate_new_kernel = relocate_new_kernel;
+ hypercall_arg.u.kexec.relocate_new_kernel_size =
+ relocate_new_kernel_size;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec, &hypercall_arg);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
+++ x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
@@ -370,6 +370,13 @@ static int __init setup_shutdown_event(v
subsys_initcall(setup_shutdown_event);
+#ifdef CONFIG_KEXEC
+void machine_shutdown(void)
+{
+ printk("machine_shutdown: does nothing\n");
+}
+#endif
+
/*
* Local variables:
* c-file-style: "linux"
--- x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
+++ x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
@@ -37,6 +37,8 @@
# error "please don't include this file directly"
#endif
+#include <xen/interface/kexec.h>
+
#define __STR(x) #x
#define STR(x) __STR(x)
@@ -343,6 +345,14 @@ HYPERVISOR_xenoprof_op(
return _hypercall2(int, xenoprof_op, op, arg);
}
+static inline int
+HYPERVISOR_kexec(
+ unsigned long op, kexec_arg_t * arg)
+{
+ return _hypercall2(int, kexec_op, op, arg);
+}
+
+
#endif /* __HYPERCALL_H__ */
--- x/ref-linux-2.6.16/drivers/base/cpu.c
+++ x/ref-linux-2.6.16/drivers/base/cpu.c
@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s
* boot up and this data does not change there after. Hence this
* operation should be safe. No locking required.
*/
+#ifndef CONFIG_XEN
addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+#else
+ addr = virt_to_machine(per_cpu_ptr(crash_notes, cpunum));
+#endif
rc = sprintf(buf, "%Lx\n", addr);
return rc;
}
--- x/ref-linux-2.6.16/kernel/kexec.c
+++ x/ref-linux-2.6.16/kernel/kexec.c
@@ -38,6 +38,20 @@ struct resource crashk_res = {
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
+/* Kexec needs to know about the actually physical addresss.
+ * But in xen, a physical address is a pseudo-physical addresss. */
+#ifndef CONFIG_XEN
+#define kexec_page_to_pfn(page) page_to_pfn(page)
+#define kexec_pfn_to_page(pfn) pfn_to_page(pfn)
+#define kexec_virt_to_phys(addr) virt_to_phys(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(addr)
+#else
+#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page))
+#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn))
+#define kexec_virt_to_phys(addr) virt_to_machine(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
+#endif
+
int kexec_should_crash(struct task_struct *p)
{
if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_
pages = kimage_alloc_pages(GFP_KERNEL, order);
if (!pages)
break;
- pfn = page_to_pfn(pages);
+ pfn = kexec_page_to_pfn(pages);
epfn = pfn + count;
addr = pfn << PAGE_SHIFT;
eaddr = epfn << PAGE_SHIFT;
@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_
return pages;
}
+#ifndef CONFIG_XEN
static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
unsigned int order)
{
@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c
}
/* If I don't overlap any segments I have found my hole! */
if (i == image->nr_segments) {
- pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
break;
}
}
@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages(
return pages;
}
+#else /* !CONFIG_XEN */
+struct page *kimage_alloc_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ return kimage_alloc_normal_control_pages(image, order);
+}
+#endif
static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
{
@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimag
return -ENOMEM;
ind_page = page_address(page);
- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
image->entry = ind_page;
image->last_entry = ind_page +
((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag
#define for_each_kimage_entry(image, ptr, entry) \
for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
ptr = (entry & IND_INDIRECTION)? \
- phys_to_virt((entry & PAGE_MASK)): ptr +1)
+ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
static void kimage_free_entry(kimage_entry_t entry)
{
struct page *page;
- page = pfn_to_page(entry >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
kimage_free_pages(page);
}
@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st
* have a match.
*/
list_for_each_entry(page, &image->dest_pages, lru) {
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
if (addr == destination) {
list_del(&page->lru);
return page;
@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(st
if (!page)
return NULL;
/* If the page cannot be used file it away */
- if (page_to_pfn(page) >
+ if (kexec_page_to_pfn(page) >
(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
list_add(&page->lru, &image->unuseable_pages);
continue;
}
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
/* If it is the destination page we want use it */
if (addr == destination)
@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(st
struct page *old_page;
old_addr = *old & PAGE_MASK;
- old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
copy_highpage(page, old_page);
*old = addr | (*old & ~PAGE_MASK);
@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st
result = -ENOMEM;
goto out;
}
- result = kimage_add_page(image, page_to_pfn(page)
+ result = kimage_add_page(image, kexec_page_to_pfn(page)
<< PAGE_SHIFT);
if (result < 0)
goto out;
@@ -811,6 +833,7 @@ out:
return result;
}
+#ifndef CONFIG_XEN
static int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)
{
@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(str
char *ptr;
size_t uchunk, mchunk;
- page = pfn_to_page(maddr >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
if (page == 0) {
result = -ENOMEM;
goto out;
@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki
return result;
}
+#else /* CONFIG_XEN */
+static int kimage_load_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ return kimage_load_normal_segment(image, segment);
+}
+#endif
/*
* Exec Kernel system call: for obvious reasons only root may call it.
--- x/xen/arch/x86/Makefile
+++ x/xen/arch/x86/Makefile
@@ -38,6 +38,7 @@ obj-y += trampoline.o
obj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.o
ifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
--- x/xen/arch/x86/dom0_ops.c
+++ x/xen/arch/x86/dom0_ops.c
@@ -29,6 +29,9 @@
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
--- /dev/null
+++ x/xen/arch/x86/machine_kexec.c
@@ -0,0 +1,174 @@
+/******************************************************************************
+ * arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/domain_page.h>
+#include <xen/timer.h>
+#include <xen/sched.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <public/xen.h>
+#include <public/kexec.h>
+
+#ifdef CONFIG_X86_32
+
+typedef asmlinkage void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae);
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#ifndef CONFIG_X86_PAE
+
+static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long mfn;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level2 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ write_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level2);
+}
+
+#else
+static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ int mfn;
+ intpte_t *pgtable_level3;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level3 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[l3_table_offset(address)],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level3);
+}
+#endif
+
+static void kexec_load_segments(void)
+{
+#define __SSTR(X) #X
+#define SSTR(X) __SSTR(X)
+ __asm__ __volatile__ (
+ "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n"
+ "\tmovl %%eax,%%ds\n"
+ "\tmovl %%eax,%%es\n"
+ "\tmovl %%eax,%%fs\n"
+ "\tmovl %%eax,%%gs\n"
+ "\tmovl %%eax,%%ss\n"
+ ::: "eax", "memory");
+#undef SSTR
+#undef __SSTR
+}
+
+#define kexec_load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+static void kexec_set_idt(void *newidt, __u16 limit)
+{
+ struct Xgt_desc_struct curidt;
+
+ /* ia32 supports unaliged loads & stores */
+ curidt.size = limit;
+ curidt.address = (unsigned long)newidt;
+
+ kexec_load_idt(&curidt);
+
+};
+
+#define kexec_load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+static void kexec_set_gdt(void *newgdt, __u16 limit)
+{
+ struct Xgt_desc_struct curgdt;
+
+ /* ia32 supports unaligned loads & stores */
+ curgdt.size = limit;
+ curgdt.address = (unsigned long)newgdt;
+
+ kexec_load_gdt(&curgdt);
+};
+
+#endif
+
+int machine_kexec_prepare(struct kexec_arg *arg)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kexec_arg *arg)
+{
+}
+
+void machine_kexec(struct kexec_arg *arg)
+{
+#ifdef CONFIG_X86_32
+ relocate_new_kernel_t rnk;
+
+ local_irq_disable();
+
+ identity_map_page(arg->u.kexec.reboot_code_buffer);
+
+ copy_from_user((void *)arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.relocate_new_kernel,
+ arg->u.kexec.relocate_new_kernel_size);
+
+ kexec_load_segments();
+
+ kexec_set_gdt(__va(0),0);
+
+ kexec_set_idt(__va(0),0);
+
+ rnk = (relocate_new_kernel_t) arg->u.kexec.reboot_code_buffer;
+
+ (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.start_address, cpu_has_pae);
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -38,6 +38,11 @@ static unsigned int opt_xenheap_megabyte
integer_param("xenheap_megabytes", opt_xenheap_megabytes);
#endif
+unsigned int opt_kdump_megabytes = 0;
+integer_param("kdump_megabytes", opt_kdump_megabytes);
+unsigned int opt_kdump_megabytes_base = 0;
+integer_param("kdump_megabytes_base", opt_kdump_megabytes_base);
+
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);
@@ -192,6 +197,20 @@ static void percpu_free_unused_areas(voi
__pa(__per_cpu_end));
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char __cmdline[] = "", *cmdline = __cmdline;
@@ -327,15 +346,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -383,6 +395,51 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ if (opt_kdump_megabytes) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = opt_kdump_megabytes_base << 20;
+ kdump_size = opt_kdump_megabytes << 20;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
printk("System RAM: %luMB (%lukB)\n",
--- x/xen/arch/x86/x86_32/entry.S
+++ x/xen/arch/x86/x86_32/entry.S
@@ -646,6 +646,7 @@ ENTRY(hypercall_table)
.long do_arch_sched_op
.long do_callback_op /* 30 */
.long do_xenoprof_op
+ .long do_kexec
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -683,6 +684,7 @@ ENTRY(hypercall_args_table)
.byte 2 /* do_arch_sched_op */
.byte 2 /* do_callback_op */ /* 30 */
.byte 2 /* do_xenoprof_op */
+ .byte 2 /* do_kexec */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
--- x/xen/common/Makefile
+++ x/xen/common/Makefile
@@ -7,6 +7,7 @@ obj-y += event_channel.o
obj-y += grant_table.o
obj-y += kernel.o
obj-y += keyhandler.o
+obj-y += kexec.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.o
--- /dev/null
+++ x/xen/common/kexec.c
@@ -0,0 +1,71 @@
+/*
+ * Achitecture independent kexec code for Xen
+ *
+ * At this statge, just a switch for the kexec hypercall into
+ * architecture dependent code.
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <public/xen.h>
+#include <public/kexec.h>
+
+extern int machine_kexec_prepare(struct kexec_arg *arg);
+extern void machine_kexec_cleanup(struct kexec_arg *arg);
+extern void machine_kexec(struct kexec_arg *arg);
+
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
+int do_kexec(unsigned long op,
+ GUEST_HANDLE(kexec_arg_t) uarg)
+{
+ struct kexec_arg arg;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if ( op != KEXEC_CMD_reserve &&
+ unlikely(copy_from_guest(&arg, uarg, 1) != 0) )
+ {
+ printk("do_kexec: __copy_from_guest failed");
+ return -EFAULT;
+ }
+
+ switch(op) {
+ case KEXEC_CMD_kexec:
+ machine_kexec(&arg);
+ return -EINVAL; /* Not Reached */
+ case KEXEC_CMD_kexec_prepare:
+ return machine_kexec_prepare(&arg);
+ case KEXEC_CMD_kexec_cleanup:
+ machine_kexec_cleanup(&arg);
+ return 0;
+ case KEXEC_CMD_reserve:
+ arg.u.reserve.size = opt_kdump_megabytes << 20;
+ arg.u.reserve.start = opt_kdump_megabytes_base << 20;
+ if ( unlikely(copy_to_guest(uarg, &arg, 1) != 0) )
+ {
+ printk("do_kexec: copy_to_guest failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
--- x/xen/common/page_alloc.c
+++ x/xen/common/page_alloc.c
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t
}
}
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+ unsigned long i;
+
+ for ( i = 0; i < nr_pfns; i++ )
+ if ( allocated_in_map(pfn_at + i) )
+ break;
+
+ if ( i == nr_pfns )
+ {
+ map_alloc(pfn_at, nr_pfns);
+ return pfn_at;
+ }
+
+ return 0;
+}
+
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{
- unsigned long pg, i;
+ unsigned long pg, i = 0;
for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
{
- for ( i = 0; i < nr_pfns; i++ )
- if ( allocated_in_map(pg + i) )
- break;
-
- if ( i == nr_pfns )
- {
- map_alloc(pg, nr_pfns);
- return pg;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- x/xen/include/asm-x86/config.h
+++ x/xen/include/asm-x86/config.h
@@ -66,7 +66,7 @@
#define barrier() __asm__ __volatile__("": : :"memory")
/* A power-of-two value greater than or equal to number of hypercalls. */
-#define NR_hypercalls 32
+#define NR_hypercalls 64
#if NR_hypercalls & (NR_hypercalls - 1)
#error "NR_hypercalls must be a power-of-two value"
--- x/xen/include/asm-x86/hypercall.h
+++ x/xen/include/asm-x86/hypercall.h
@@ -6,6 +6,7 @@
#define __ASM_X86_HYPERCALL_H__
#include <public/physdev.h>
+#include <public/kexec.h>
extern long
do_set_trap_table(
@@ -79,6 +80,10 @@ extern long
arch_do_vcpu_op(
int cmd, struct vcpu *v, GUEST_HANDLE(void) arg);
+extern int
+do_kexec(
+ unsigned long op, GUEST_HANDLE(kexec_arg_t) uarg);
+
#ifdef __x86_64__
extern long
--- /dev/null
+++ x/xen/include/public/kexec.h
@@ -0,0 +1,43 @@
+/*
+ * kexec.h: Xen kexec
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+/*
+ * Scratch space for passing arguments to the kexec hypercall
+ */
+typedef struct kexec_arg {
+ union {
+ struct {
+ unsigned long data; /* Not sure what this should be yet */
+ } helper;
+ struct {
+ unsigned long indirection_page;
+ unsigned long reboot_code_buffer;
+ unsigned long start_address;
+ const char *relocate_new_kernel;
+ unsigned int relocate_new_kernel_size;
+ } kexec;
+ struct {
+ unsigned long size;
+ unsigned long start;
+ } reserve;
+ } u;
+} kexec_arg_t;
+DEFINE_GUEST_HANDLE(kexec_arg_t);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/include/public/xen.h
+++ x/xen/include/public/xen.h
@@ -62,6 +62,7 @@
#define __HYPERVISOR_sched_op 29
#define __HYPERVISOR_callback_op 30
#define __HYPERVISOR_xenoprof_op 31
+#define __HYPERVISOR_kexec_op 32
/*
* VIRTUAL INTERRUPTS
@@ -215,6 +216,14 @@ DEFINE_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_writable_pagetables 2
#define MAX_VMASST_TYPE 2
+/*
+ * Operations for kexec.
+ */
+#define KEXEC_CMD_kexec 0
+#define KEXEC_CMD_kexec_prepare 1
+#define KEXEC_CMD_kexec_cleanup 2
+#define KEXEC_CMD_reserve 3
+
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
--- x/xen/include/xen/mm.h
+++ x/xen/include/xen/mm.h
@@ -40,6 +40,7 @@ struct page_info;
paddr_t init_boot_allocator(paddr_t bitmap_start);
void init_boot_pages(paddr_t ps, paddr_t pe);
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
void end_boot_allocator(void);
/* Generic allocator. These functions are *not* interrupt-safe. */PATCH 1/1 : kexec: framework and i386 (Take VI)
Hi,
I will be out of the office until next Monday, so here is the latest and greatest before I go. Tested against 9896, should also work fine with tip (9903).
Signature · 1,203 lines
Horms http://www.vergenet.net/~horms/
kexec: framework and i386
This is an implementation of kexec for dom0/xen, that allows
kexecing of the physical machine from xen. The approach taken is
to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do
anything in i386. So while this patch adds a framework for them,
I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that
kexec-tools needs updating, but I have not investigated yet
* Kdump works by first copying the kernel into dom0 segments
and relocating them later in xen, the same way that kexec does
The only difference is that the relocation is made into
an area reserved by xen
* Kdump reservation is made using the xen command line parameters,
kdump_megabytes and kdump_megabytes_base, rather than
the linux option crashkernel, which is now ignored.
Two parameters are used instead of one to simplify parsing.
This can be cleaned up later if desired. But the reservation
seems to need to be made by xen to make sure that it happens
early enough.
* This patch uses a new kexec hypercall
Highlights since the previous posted version:
* SMP kexec (not kdump yet)
* Split x86_32 specific xen code out
Prepared by Horms and Magnus Damm
Signed-Off-By: Magnus Damm <[email protected]>
Signed-Off-By: Horms <[email protected]>
linux-2.6-xen-sparse/arch/i386/Kconfig | 2
linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 24 +
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 ++++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 73 +++
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10
ref-linux-2.6.16/drivers/base/cpu.c | 4
ref-linux-2.6.16/kernel/kexec.c | 52 +-
xen/arch/x86/Makefile | 1
xen/arch/x86/dom0_ops.c | 3
xen/arch/x86/machine_kexec.c | 27 +
xen/arch/x86/setup.c | 75 +++
xen/arch/x86/x86_32/Makefile | 1
xen/arch/x86/x86_32/entry.S | 2
xen/arch/x86/x86_32/machine_kexec.c | 206 ++++++++++
xen/arch/x86/x86_64/Makefile | 1
xen/arch/x86/x86_64/machine_kexec.c | 24 +
xen/common/Makefile | 1
xen/common/kexec.c | 73 +++
xen/common/page_alloc.c | 33 +
xen/include/asm-x86/hypercall.h | 5
xen/include/public/kexec.h | 46 ++
xen/include/public/xen.h | 9
xen/include/xen/mm.h | 1
25 files changed, 741 insertions(+), 33 deletions(-)
--- x/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ x/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL && !X86_XEN
+ depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
--- x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen
obj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o
-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o
+n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen))
obj-y := $(call cherrypickxen, $(obj-y))
--- x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
@@ -68,6 +68,10 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
+
/* Forward Declaration. */
void __init find_max_pfn(void);
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (
* after a kernel panic.
*/
else if (!memcmp(from, "crashkernel=", 12)) {
+#ifndef CONFIG_XEN
unsigned long size, base;
size = memparse(from+12, &from);
if (*from == '@') {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early (
crashk_res.start = base;
crashk_res.end = base + size - 1;
}
+#else
+ printk("Ignoring crashkernel command line, "
+ "parameter will be supplied by xen\n");
+#endif
}
#endif
#ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,21 @@ void __init setup_bootmem_allocator(void
}
#endif
#ifdef CONFIG_KEXEC
+#ifndef CONFIG_XEN
if (crashk_res.start != crashk_res.end)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
+#else
+ {
+ struct kexec_arg xen_kexec_arg;
+ BUG_ON(HYPERVISOR_kexec(KEXEC_CMD_reserve, &xen_kexec_arg));
+ if (xen_kexec_arg.u.reserve.size) {
+ crashk_res.start = xen_kexec_arg.u.reserve.start;
+ crashk_res.end = xen_kexec_arg.u.reserve.start +
+ xen_kexec_arg.u.reserve.size - 1;
+ }
+ }
+#endif
#endif
if (!xen_feature(XENFEAT_auto_translated_physmap))
@@ -1395,6 +1416,9 @@ legacy_init_iomem_resources(struct resou
res->end = map[i].end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
free_bootmem(__pa(map), PAGE_SIZE);
--- x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/crash.c
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific (i386-xen) functions for kexec based crash dumps.
+ *
+ * Created by: Horms <[email protected]>
+ *
+ */
+
+#include <linux/kernel.h> /* For printk */
+
+/* XXX: final_note(), crash_save_this_cpu() and crash_save_self()
+ * are copied from arch/i386/kernel/crash.c, might be good to either
+ * the original functions non-static and use them, or just
+ * merge this this into that file.
+ */
+#include <linux/elf.h> /* For struct elf_note */
+#include <linux/elfcore.h> /* For struct elf_prstatus */
+#include <linux/kexec.h> /* crash_notes */
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* XXX: This should do something */
+ printk("xen-kexec: Need to turn of other CPUS in "
+ "machine_crash_shutdown()\n");
+ crash_save_self(regs);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,73 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Created By: Horms <[email protected]>
+ *
+ * Losely based on arch/i386/kernel/machine_kexec.c
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/mm.h>
+#include <asm/hypercall.h>
+
+const extern unsigned char relocate_new_kernel[];
+extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ return HYPERVISOR_kexec(KEXEC_CMD_kexec_prepare, &hypercall_arg);
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec_cleanup, &hypercall_arg);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.kexec.indirection_page = image->head;
+ hypercall_arg.u.kexec.reboot_code_buffer =
+ pfn_to_mfn(page_to_pfn(image->control_code_page)) << PAGE_SHIFT;
+ hypercall_arg.u.kexec.start_address = image->start;
+ hypercall_arg.u.kexec.relocate_new_kernel = relocate_new_kernel;
+ hypercall_arg.u.kexec.relocate_new_kernel_size =
+ relocate_new_kernel_size;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec, &hypercall_arg);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
+++ x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
@@ -37,6 +37,8 @@
# error "please don't include this file directly"
#endif
+#include <xen/interface/kexec.h>
+
#define __STR(x) #x
#define STR(x) __STR(x)
@@ -357,6 +359,14 @@ HYPERVISOR_xenoprof_op(
return _hypercall2(int, xenoprof_op, op, arg);
}
+static inline int
+HYPERVISOR_kexec(
+ unsigned long op, kexec_arg_t * arg)
+{
+ return _hypercall2(int, kexec_op, op, arg);
+}
+
+
#endif /* __HYPERCALL_H__ */
--- x/ref-linux-2.6.16/drivers/base/cpu.c
+++ x/ref-linux-2.6.16/drivers/base/cpu.c
@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s
* boot up and this data does not change there after. Hence this
* operation should be safe. No locking required.
*/
+#ifndef CONFIG_XEN
addr = __pa(per_cpu_ptr(crash_notes, cpunum));
+#else
+ addr = virt_to_machine(per_cpu_ptr(crash_notes, cpunum));
+#endif
rc = sprintf(buf, "%Lx\n", addr);
return rc;
}
--- x/ref-linux-2.6.16/kernel/kexec.c
+++ x/ref-linux-2.6.16/kernel/kexec.c
@@ -38,6 +38,20 @@ struct resource crashk_res = {
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
+/* Kexec needs to know about the actually physical addresss.
+ * But in xen, a physical address is a pseudo-physical addresss. */
+#ifndef CONFIG_XEN
+#define kexec_page_to_pfn(page) page_to_pfn(page)
+#define kexec_pfn_to_page(pfn) pfn_to_page(pfn)
+#define kexec_virt_to_phys(addr) virt_to_phys(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(addr)
+#else
+#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page))
+#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn))
+#define kexec_virt_to_phys(addr) virt_to_machine(addr)
+#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
+#endif
+
int kexec_should_crash(struct task_struct *p)
{
if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_
pages = kimage_alloc_pages(GFP_KERNEL, order);
if (!pages)
break;
- pfn = page_to_pfn(pages);
+ pfn = kexec_page_to_pfn(pages);
epfn = pfn + count;
addr = pfn << PAGE_SHIFT;
eaddr = epfn << PAGE_SHIFT;
@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_
return pages;
}
+#ifndef CONFIG_XEN
static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
unsigned int order)
{
@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c
}
/* If I don't overlap any segments I have found my hole! */
if (i == image->nr_segments) {
- pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
break;
}
}
@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages(
return pages;
}
+#else /* !CONFIG_XEN */
+struct page *kimage_alloc_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ return kimage_alloc_normal_control_pages(image, order);
+}
+#endif
static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
{
@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimag
return -ENOMEM;
ind_page = page_address(page);
- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
image->entry = ind_page;
image->last_entry = ind_page +
((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag
#define for_each_kimage_entry(image, ptr, entry) \
for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
ptr = (entry & IND_INDIRECTION)? \
- phys_to_virt((entry & PAGE_MASK)): ptr +1)
+ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
static void kimage_free_entry(kimage_entry_t entry)
{
struct page *page;
- page = pfn_to_page(entry >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
kimage_free_pages(page);
}
@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st
* have a match.
*/
list_for_each_entry(page, &image->dest_pages, lru) {
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
if (addr == destination) {
list_del(&page->lru);
return page;
@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(st
if (!page)
return NULL;
/* If the page cannot be used file it away */
- if (page_to_pfn(page) >
+ if (kexec_page_to_pfn(page) >
(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
list_add(&page->lru, &image->unuseable_pages);
continue;
}
- addr = page_to_pfn(page) << PAGE_SHIFT;
+ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
/* If it is the destination page we want use it */
if (addr == destination)
@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(st
struct page *old_page;
old_addr = *old & PAGE_MASK;
- old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
copy_highpage(page, old_page);
*old = addr | (*old & ~PAGE_MASK);
@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st
result = -ENOMEM;
goto out;
}
- result = kimage_add_page(image, page_to_pfn(page)
+ result = kimage_add_page(image, kexec_page_to_pfn(page)
<< PAGE_SHIFT);
if (result < 0)
goto out;
@@ -811,6 +833,7 @@ out:
return result;
}
+#ifndef CONFIG_XEN
static int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)
{
@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(str
char *ptr;
size_t uchunk, mchunk;
- page = pfn_to_page(maddr >> PAGE_SHIFT);
+ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
if (page == 0) {
result = -ENOMEM;
goto out;
@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki
return result;
}
+#else /* CONFIG_XEN */
+static int kimage_load_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ return kimage_load_normal_segment(image, segment);
+}
+#endif
/*
* Exec Kernel system call: for obvious reasons only root may call it.
--- x/xen/arch/x86/Makefile
+++ x/xen/arch/x86/Makefile
@@ -39,6 +39,7 @@ obj-y += trampoline.o
obj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.o
ifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
--- x/xen/arch/x86/dom0_ops.c
+++ x/xen/arch/x86/dom0_ops.c
@@ -29,6 +29,9 @@
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
--- /dev/null
+++ x/xen/arch/x86/machine_kexec.c
@@ -0,0 +1,27 @@
+/******************************************************************************
+ * arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ */
+
+#include <public/kexec.h>
+
+int machine_kexec_prepare(struct kexec_arg *arg)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kexec_arg *arg)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -38,6 +38,11 @@ static unsigned int opt_xenheap_megabyte
integer_param("xenheap_megabytes", opt_xenheap_megabytes);
#endif
+unsigned int opt_kdump_megabytes = 0;
+integer_param("kdump_megabytes", opt_kdump_megabytes);
+unsigned int opt_kdump_megabytes_base = 0;
+integer_param("kdump_megabytes_base", opt_kdump_megabytes_base);
+
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);
@@ -192,6 +197,20 @@ static void percpu_free_unused_areas(voi
__pa(__per_cpu_end));
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char __cmdline[] = "", *cmdline = __cmdline;
@@ -327,15 +346,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -383,6 +395,51 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ if (opt_kdump_megabytes) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = opt_kdump_megabytes_base << 20;
+ kdump_size = opt_kdump_megabytes << 20;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
printk("System RAM: %luMB (%lukB)\n",
--- x/xen/arch/x86/x86_32/Makefile
+++ x/xen/arch/x86/x86_32/Makefile
@@ -3,5 +3,6 @@ obj-y += entry.o
obj-y += mm.o
obj-y += seg_fixup.o
obj-y += traps.o
+obj-y += machine_kexec.o
obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
--- x/xen/arch/x86/x86_32/entry.S
+++ x/xen/arch/x86/x86_32/entry.S
@@ -648,6 +648,7 @@ ENTRY(hypercall_table)
.long do_xenoprof_op
.long do_event_channel_op
.long do_physdev_op
+ .long do_kexec
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table)
.byte 2 /* do_xenoprof_op */
.byte 2 /* do_event_channel_op */
.byte 2 /* do_physdev_op */
+ .byte 2 /* do_kexec */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
--- /dev/null
+++ x/xen/arch/x86/x86_32/machine_kexec.c
@@ -0,0 +1,206 @@
+/******************************************************************************
+ * arch/x86/x86_32/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/domain_page.h>
+#include <xen/timer.h>
+#include <xen/sched.h>
+#include <xen/reboot.h>
+#include <xen/console.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <public/xen.h>
+#include <public/kexec.h>
+
+static void __machine_kexec(struct kexec_arg *arg);
+
+typedef asmlinkage void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae);
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#ifndef CONFIG_X86_PAE
+
+static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long mfn;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level2 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ write_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level2);
+}
+
+#else
+static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ int mfn;
+ intpte_t *pgtable_level3;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level3 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[l3_table_offset(address)],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level3);
+}
+#endif
+
+static void kexec_load_segments(void)
+{
+#define __SSTR(X) #X
+#define SSTR(X) __SSTR(X)
+ __asm__ __volatile__ (
+ "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n"
+ "\tmovl %%eax,%%ds\n"
+ "\tmovl %%eax,%%es\n"
+ "\tmovl %%eax,%%fs\n"
+ "\tmovl %%eax,%%gs\n"
+ "\tmovl %%eax,%%ss\n"
+ ::: "eax", "memory");
+#undef SSTR
+#undef __SSTR
+}
+
+#define kexec_load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+static void kexec_set_idt(void *newidt, __u16 limit)
+{
+ struct Xgt_desc_struct curidt;
+
+ /* ia32 supports unaliged loads & stores */
+ curidt.size = limit;
+ curidt.address = (unsigned long)newidt;
+
+ kexec_load_idt(&curidt);
+
+};
+
+#define kexec_load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+static void kexec_set_gdt(void *newgdt, __u16 limit)
+{
+ struct Xgt_desc_struct curgdt;
+
+ /* ia32 supports unaligned loads & stores */
+ curgdt.size = limit;
+ curgdt.address = (unsigned long)newgdt;
+
+ kexec_load_gdt(&curgdt);
+};
+
+static void __machine_shutdown(void *data)
+{
+ struct kexec_arg *arg = (struct kexec_arg *)data;
+
+ printk("__machine_shutdown: cpu=%u\n", smp_processor_id());
+
+ watchdog_disable();
+ console_start_sync();
+
+ smp_send_stop();
+
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+
+ __machine_kexec(arg);
+}
+
+void machine_shutdown(struct kexec_arg *arg)
+{
+ int reboot_cpu_id;
+ cpumask_t reboot_cpu;
+
+
+ reboot_cpu_id = 0;
+
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map))
+ reboot_cpu_id = smp_processor_id();
+
+ if (reboot_cpu_id != smp_processor_id()) {
+ cpus_clear(reboot_cpu);
+ cpu_set(reboot_cpu_id, reboot_cpu);
+ on_selected_cpus(reboot_cpu, __machine_shutdown, arg, 1, 0);
+ for (;;)
+ ; /* nothing */
+ }
+ else
+ __machine_shutdown(arg);
+ BUG();
+}
+
+static void __machine_kexec(struct kexec_arg *arg)
+{
+ relocate_new_kernel_t rnk;
+
+ local_irq_disable();
+
+ identity_map_page(arg->u.kexec.reboot_code_buffer);
+
+ copy_from_user((void *)arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.relocate_new_kernel,
+ arg->u.kexec.relocate_new_kernel_size);
+
+ kexec_load_segments();
+ kexec_set_gdt(__va(0),0);
+ kexec_set_idt(__va(0),0);
+
+ rnk = (relocate_new_kernel_t) arg->u.kexec.reboot_code_buffer;
+ (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.start_address, cpu_has_pae);
+}
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ machine_shutdown(arg);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/x86_64/Makefile
+++ x/xen/arch/x86/x86_64/Makefile
@@ -1,3 +1,4 @@
obj-y += entry.o
obj-y += mm.o
obj-y += traps.o
+obj-y += machine_kexec.o
--- /dev/null
+++ x/xen/arch/x86/x86_64/machine_kexec.c
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * arch/x86/x86_64/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <public/kexec.h>
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ printk("machine_kexec: not implemented\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/common/Makefile
+++ x/xen/common/Makefile
@@ -7,6 +7,7 @@ obj-y += event_channel.o
obj-y += grant_table.o
obj-y += kernel.o
obj-y += keyhandler.o
+obj-y += kexec.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.o
--- /dev/null
+++ x/xen/common/kexec.c
@@ -0,0 +1,73 @@
+/*
+ * Achitecture independent kexec code for Xen
+ *
+ * At this statge, just a switch for the kexec hypercall into
+ * architecture dependent code.
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <public/xen.h>
+#include <public/kexec.h>
+
+extern int machine_kexec_prepare(struct kexec_arg *arg);
+extern void machine_kexec_cleanup(struct kexec_arg *arg);
+extern void machine_kexec(struct kexec_arg *arg);
+
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
+int do_kexec(unsigned long op,
+ XEN_GUEST_HANDLE(kexec_arg_t) uarg)
+{
+ struct kexec_arg arg;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if (op == KEXEC_CMD_reserve)
+ {
+ arg.u.reserve.size = opt_kdump_megabytes << 20;
+ arg.u.reserve.start = opt_kdump_megabytes_base << 20;
+ if ( unlikely(copy_to_guest(uarg, &arg, 1) != 0) )
+ {
+ printk("do_kexec: copy_to_guest failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+ if ( unlikely(copy_from_guest(&arg, uarg, 1) != 0) )
+ {
+ printk("do_kexec: __copy_from_guest failed");
+ return -EFAULT;
+ }
+
+ switch(op) {
+ case KEXEC_CMD_kexec:
+ machine_kexec(&arg);
+ return -EINVAL; /* Not Reached */
+ case KEXEC_CMD_kexec_prepare:
+ return machine_kexec_prepare(&arg);
+ case KEXEC_CMD_kexec_cleanup:
+ machine_kexec_cleanup(&arg);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
--- x/xen/common/page_alloc.c
+++ x/xen/common/page_alloc.c
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t
}
}
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+ unsigned long i;
+
+ for ( i = 0; i < nr_pfns; i++ )
+ if ( allocated_in_map(pfn_at + i) )
+ break;
+
+ if ( i == nr_pfns )
+ {
+ map_alloc(pfn_at, nr_pfns);
+ return pfn_at;
+ }
+
+ return 0;
+}
+
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{
- unsigned long pg, i;
+ unsigned long pg, i = 0;
for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
{
- for ( i = 0; i < nr_pfns; i++ )
- if ( allocated_in_map(pg + i) )
- break;
-
- if ( i == nr_pfns )
- {
- map_alloc(pg, nr_pfns);
- return pg;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- x/xen/include/asm-x86/hypercall.h
+++ x/xen/include/asm-x86/hypercall.h
@@ -6,6 +6,7 @@
#define __ASM_X86_HYPERCALL_H__
#include <public/physdev.h>
+#include <public/kexec.h>
extern long
do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern long
arch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg);
+extern int
+do_kexec(
+ unsigned long op, XEN_GUEST_HANDLE(kexec_arg_t) uarg);
+
#ifdef __x86_64__
extern long
--- /dev/null
+++ x/xen/include/public/kexec.h
@@ -0,0 +1,46 @@
+/*
+ * kexec.h: Xen kexec public
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+#include <xen/types.h>
+#include <public/xen.h>
+
+/*
+ * Scratch space for passing arguments to the kexec hypercall
+ */
+typedef struct kexec_arg {
+ union {
+ struct {
+ unsigned long data; /* Not sure what this should be yet */
+ } helper;
+ struct {
+ unsigned long indirection_page;
+ unsigned long reboot_code_buffer;
+ unsigned long start_address;
+ const char *relocate_new_kernel;
+ unsigned int relocate_new_kernel_size;
+ } kexec;
+ struct {
+ unsigned long size;
+ unsigned long start;
+ } reserve;
+ } u;
+} kexec_arg_t;
+DEFINE_XEN_GUEST_HANDLE(kexec_arg_t);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/include/public/xen.h
+++ x/xen/include/public/xen.h
@@ -64,6 +64,7 @@
#define __HYPERVISOR_xenoprof_op 31
#define __HYPERVISOR_event_channel_op 32
#define __HYPERVISOR_physdev_op 33
+#define __HYPERVISOR_kexec_op 34
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
@@ -238,6 +239,14 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_writable_pagetables 2
#define MAX_VMASST_TYPE 2
+/*
+ * Operations for kexec.
+ */
+#define KEXEC_CMD_kexec 0
+#define KEXEC_CMD_kexec_prepare 1
+#define KEXEC_CMD_kexec_cleanup 2
+#define KEXEC_CMD_reserve 3
+
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
--- x/xen/include/xen/mm.h
+++ x/xen/include/xen/mm.h
@@ -40,6 +40,7 @@ struct page_info;
paddr_t init_boot_allocator(paddr_t bitmap_start);
void init_boot_pages(paddr_t ps, paddr_t pe);
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
void end_boot_allocator(void);
/* Generic allocator. These functions are *not* interrupt-safe. */Re: [PATCH]: kexec: framework and i386 (Take VI)
Hi, Simon and Magnus
I have one question.
When Xen is panic, I seemed kexec is not called.
Only when dom0 is panic, kexec is called.
But in the case of nmi=dom0, can we use kexec by pushing NMI button? Am I righit?
I'll use your patch soon, and report. :-)
Best Regards,
Akio Takebe
Re: [PATCH]: kexec: framework and i386 (Take VI)
Quoted 5 lines · Akio Takebe
Hi, Simon and Magnus
I have one question.
When Xen is panic, I seemed kexec is not called.
Only when dom0 is panic, kexec is called.
That is a good point.
Quoted 2 lines
But in the case of nmi=dom0, can we use kexec by pushing NMI button? Am I righit?
Probably, I will have to investigate a little further. Though, I'm not sure that I have ever seen an NMI button. Are you thinking about the INIT button on some ia64 boxes? That is a bit different to NMI on x86.
Quoted 1 line
I'll use your patch soon, and report. :-)
Thanks
Signature · 1 line
Horms http://www.vergenet.net/~horms/
Re: [PATCH]: kexec: framework and i386 (Take VI)
Hi, Horms
Thank you for your reply.
Quoted 9 lines · Akio Takebe
Quoted 5 lines
Hi, Simon and Magnus
I have one question.
When Xen is panic, I seemed kexec is not called.
Only when dom0 is panic, kexec is called.That is a good point.
Quoted 7 lines
Quoted 2 lines
But in the case of nmi=dom0, can we use kexec by pushing NMI button? Am I righit?
Probably, I will have to investigate a little further. Though, I'm not sure that I have ever seen an NMI button. Are you thinking about the INIT button on some ia64 boxes? That is a bit different to NMI on x86.
I said about the NMI bottun on x86.
Many x86 servers (not PC) have a NMI bottun
like many ia64 servers have a INIT bottun.
Best Regards,
Akio Takebe
Re: [PATCH]: kexec: framework and i386 (Take VI)
Quoted 16 lines · Akio Takebe
Hi, Horms
Thank you for your reply.
Quoted 12 lines · Akio Takebe
Quoted 5 lines
Hi, Simon and Magnus
I have one question.
When Xen is panic, I seemed kexec is not called.
Only when dom0 is panic, kexec is called.That is a good point.
Quoted 2 lines
But in the case of nmi=dom0, can we use kexec by pushing NMI button? Am I righit?
Quoted 7 lines
Quoted 4 lines
Probably, I will have to investigate a little further. Though, I'm not sure that I have ever seen an NMI button. Are you thinking about the INIT button on some ia64 boxes? That is a bit different to NMI on x86.
I said about the NMI bottun on x86.
Many x86 servers (not PC) have a NMI bottun
like many ia64 servers have a INIT bottun.
Ok thanks, I haven't seen such a machine.
I'll look into simulating it in software.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
Re: [PATCH]: kexec: framework and i386 (Take VI)
Quoted 4 lines
Ok thanks, I haven't seen such a machine.
I'll look into simulating it in software.
I have x86 server with NMI button.
If necessary, I can test it :-)
Best Regards,
Akio Takebe
Re: Re: [PATCH]: kexec: framework and i386 (Take VI)
I didn't get Horms' (I presume that's who is quoted below) original mail so I'll reply to this one.
Quoted 2 lines
Quoted 2 lines
Ok thanks, I haven't seen such a machine.
I'll look into simulating it in software.
There is code in xen/arch/x86/nmi.c:do_nmi_trigger(). You can trigger it with the 'n' keyhandler.
Ian.
Re: Re: [PATCH]: kexec: framework and i386 (Take VI)
Quoted 8 lines · Ian Campbell
I didn't get Horms' (I presume that's who is quoted below) original mail so I'll reply to this one.
Quoted 2 lines
Quoted 2 lines
Ok thanks, I haven't seen such a machine.
I'll look into simulating it in software.There is code in xen/arch/x86/nmi.c:do_nmi_trigger(). You can trigger it with the 'n' keyhandler.
Thanks, I will use that technique.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
Re: Re: [PATCH]: kexec: framework and i386 (Take VI)
In reply to Akio TakebeHi,
I tested about NMI button with your patch.
I got coredump including all memory!
We always use dom0's coredump by using Horms's and Magnus's patch. :-)
FYI, I used the following grub.conf
and /proc/sys/kernel/unknown_nmi_panic=1
title Xen 3.0 kexec
root (hd0,0)
kernel /xen-3.0.gz dom0_mem=256M kdump_megabytes=64 kdump_megabytes_base=32 nmi=dom0 nosmp
module /vmlinuz-2.6-xen ro root=LABEL=/ rhgb nosmp
module /initrd-2.6-xen.imgBest Regards,
Akio Takebe
Quoted 21 lines
Hi, Simon and Magnus
I have one question.
When Xen is panic, I seemed kexec is not called.
Only when dom0 is panic, kexec is called.
But in the case of nmi=dom0, can we use kexec by pushing NMI button? Am I righit?I'll use your patch soon, and report. :-)
Best Regards,
Akio Takebe
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: [PATCH]: kexec: framework and i386 (Take VI)
In reply to Simon Horman [Horms]Hi, Horms
Why you modify ref-linux-2.6.16/kernel/{drivers/base/cpu.c, kernel/kexec.c }? I tried to patch your kexec patch, I fail to patch it.
How do you do patch?
I think you can make a patch in patches/linux-2.6.16/ if you would modify these.
Best Regards,
Akio Takebe
Quoted 1,231 lines
Hi,
I will be out of the office until next Monday, so here is the latest and greatest before I go. Tested against 9896, should also work fine with tip (9903).
Signature · 66 lines
Horms http://www.vergenet.net/~ horms/ kexec: framework and i386 This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall. Some notes: * machine_kexec_cleanup() and machine_kexec_prepare() don't do anything in i386. So while this patch adds a framework for them, I am not sure what parameters are needs at this stage. * Only works for UP, as machine_shutdown is not implemented yet * kexecing into xen does not seem to work, I think that kexec-tools needs updating, but I have not investigated yet * Kdump works by first copying the kernel into dom0 segments and relocating them later in xen, the same way that kexec does The only difference is that the relocation is made into an area reserved by xen * Kdump reservation is made using the xen command line parameters, kdump_megabytes and kdump_megabytes_base, rather than the linux option crashkernel, which is now ignored. Two parameters are used instead of one to simplify parsing. This can be cleaned up later if desired. But the reservation seems to need to be made by xen to make sure that it happens early enough. * This patch uses a new kexec hypercall Highlights since the previous posted version: * SMP kexec (not kdump yet) * Split x86_32 specific xen code out Prepared by Horms and Magnus Damm Signed-Off-By: Magnus Damm <[email protected]> Signed-Off-By: Horms <[email protected]> linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 24 + linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 ++++ linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 73 +++ linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10 ref-linux-2.6.16/drivers/base/cpu.c | 4 ref-linux-2.6.16/kernel/kexec.c | 52 +- xen/arch/x86/Makefile | 1 xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 27 + xen/arch/x86/setup.c | 75 +++ xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 206 ++++ ++++++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 24 + xen/common/Makefile | 1 xen/common/kexec.c | 73 +++ xen/common/page_alloc.c | 33 + xen/include/asm-x86/hypercall.h | 5 xen/include/public/kexec.h | 46 ++ xen/include/public/xen.h | 9 xen/include/xen/mm.h | 1 25 files changed, 741 insertions(+), 33 deletions(-)linux-2.6-xen-sparse/arch/i386/Kconfig +0
-0@@ -726,7 +726,7 @@ source kernel/Kconfig.hzconfig KEXEC
bool "kexec system call (EXPERIMENTAL)"linux-2.6-xen-sparse/arch/i386/Kconfig +1
-1- depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTALhelp
kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a rebootlinux-2.6-xen-sparse/arch/i386/kernel/Makefile +0
-0@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xenobj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.olinux-2.6-xen-sparse/arch/i386/kernel/Makefile +1
-1-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +24
-0@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {@@ -942,6 +947,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE @@ -1318,9 +1327,21 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +struct kexec_arg xen_kexec_arg; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_reserve, &xen_kexec_arg)); +if (xen_kexec_arg.u.reserve.size) { + crashk_res.start = xen_kexec_arg.u.reserve.start; + crashk_res.end = xen_kexec_arg.u.reserve.start + + xen_kexec_arg.u.reserve.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))@@ -1395,6 +1416,9 @@ legacy_init_iomem_resources(struct resou res->end = map[i].end -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif }free_bootmem (__pa (map),PAGE_SIZE );linux-2.6-xen-sparse/drivers/xen/core/Makefile +0
-0@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.oobj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.olinux-2.6-xen-sparse/drivers/xen/core/Makefile +1
-0+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.olinux-2.6-xen-sparse/drivers/xen/core/crash.c new file +98
-0@@ -0,0 +1,98 @@ +/* +* Architecture specific (i386-xen) functions for kexec based crash dumps. +* +* Created by: Horms <[email protected]> +* +*/ + +#include <linux/kernel.h> /* For printk */ + +/* XXX: final_note(), crash_save_this_cpu() and crash_save_self() +* are copied from arch/i386/kernel/crash.c, might be good to either +* the original functions non-static and use them, or just +* merge this this into that file. +*/ +#include <linux/elf.h> /* For struct elf_note */ +#include <linux/elfcore.h> /* For struct elf_prstatus */ +#include <linux/kexec.h> /* crash_notes */ + +static u32 *append_elf_note (u32 *buf,char *name,unsigned type,void *data, +size_t data_len) +{ +struct elf_note note; + + note.n_namesz =strlen (name) +1 ; + note.n_descsz = data_len; + note.n_type = type; +memcpy (buf, ¬e,sizeof (note)); + buf += (sizeof (note) +3 )/4 ; +memcpy (buf, name, note.n_namesz); + buf += (note.n_namesz +3 )/4 ; +memcpy (buf, data, note.n_descsz); + buf += (note.n_descsz +3 )/4 ; + +return buf; +} + +static void final_note (u32 *buf) +{ +struct elf_note note; + + note.n_namesz =0 ; + note.n_descsz =0 ; + note.n_type =0 ; +memcpy (buf, ¬e,sizeof (note)); +} + +static void crash_save_this_cpu (struct pt_regs *regs,int cpu) +{ +struct elf_prstatus prstatus; +u32 *buf; + +if ((cpu <0 ) || (cpu >=NR_CPUS )) +return ; + +/* Using ELF notes here is opportunistic. +* I need a well defined structure format +* for the data I pass, and I need tags +* on the data to indicate what information I have +* squirrelled away. ELF notes happen to provide +* all of that that no need to invent something new. +*/ + buf = (u32 *)per_cpu_ptr (crash_notes, cpu); +if (!buf) +return ; +memset (&prstatus,0 ,sizeof (prstatus)); + prstatus.pr_pid = current->pid; +elf_core_copy_regs (&prstatus.pr_reg, regs); + buf =append_elf_note (buf,"CORE" ,NT_PRSTATUS , &prstatus, +sizeof (prstatus)); +final_note (buf); +} + +static void crash_save_self (struct pt_regs *regs) +{ +int cpu; + + cpu =smp_processor_id (); +crash_save_this_cpu (regs, cpu); +} + + +void machine_crash_shutdown (struct pt_regs *regs) +{ +/* XXX: This should do something */ +printk ("xen-kexec: Need to turn of other CPUS in " +"machine_crash_shutdown()\n" ); +crash_save_self (regs); +} + +/* +* Local variables: +* c-file-style: "linux" +* indent-tabs-mode: t +* c-indent-level: 8 +* c-basic-offset: 8 +* tab-width: 8 +* End: +*/ linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +73
-0@@ -0,0 +1,73 @@ +/* +* machine_kexec.c - handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <linux/kexec.h> +#include <xen/interface/kexec.h> +#include <linux/mm.h> +#include <asm/hypercall.h> + +const extern unsigned char relocate_new_kernel[]; +extern unsigned int relocate_new_kernel_size; + +/* +* A architecture hook called to validate the +* proposed image and prepare the control pages +* as needed. The pages for KEXEC_CONTROL_CODE_SIZE +* have been allocated, but the segments have yet +* been copied into the kernel. +* +* Do what every setup is needed on image and the +* reboot code buffer to allow us to avoid allocations +* later. +* +* Currently nothing. +*/ +int machine_kexec_prepare (struct kimage *image) +{ +kexec_arg_t hypercall_arg; + hypercall_arg.u.helper.data =NULL ; +return HYPERVISOR_kexec (KEXEC_CMD_kexec_prepare, &hypercall_arg); +} + +/* +* Undo anything leftover by machine_kexec_prepare +* when an image is freed. +*/ +void machine_kexec_cleanup (struct kimage *image) +{ +kexec_arg_t hypercall_arg; + hypercall_arg.u.helper.data =NULL ; +HYPERVISOR_kexec (KEXEC_CMD_kexec_cleanup, &hypercall_arg); +} + +/* +* Do not allocate memory (or fail in any way) in machine_kexec(). +* We are past the point of no return, committed to rebooting now. +*/ +NORET_TYPE void machine_kexec(struct kimage *image) +{ +kexec_arg_t hypercall_arg; + hypercall_arg.u.kexec.indirection_page = image->head; + hypercall_arg.u.kexec.reboot_code_buffer = +pfn_to_mfn (page_to_pfn (image->control_code_page)) <<PAGE_SHIFT ; + hypercall_arg.u.kexec.start_address = image->start; + hypercall_arg.u.kexec.relocate_new_kernel = relocate_new_kernel; + hypercall_arg.u.kexec.relocate_new_kernel_size = + relocate_new_kernel_size; +HYPERVISOR_kexec (KEXEC_CMD_kexec, &hypercall_arg); +} + +/* +* Local variables: +* c-file-style: "linux" +* indent-tabs-mode: t +* c-indent-level: 8 +* c-basic-offset: 8 +* tab-width: 8 +* End: +*/ linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +10
-0@@ -37,6 +37,8 @@# error "please don't include this file directly"#endif +#include <xen/interface/kexec.h> +#define __STR (x) #x#define STR (x) __STR(x)@@ -357,6 +359,14 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,kexec_arg_t * arg) +{ +return _hypercall2 (int, kexec_op, op, arg); +} + +#endif /* __HYPERCALL_H__ */ ref-linux-2.6.16/drivers/base/cpu.c +4
-0@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s* boot up and this data does not change there after. Hence this * operation should be safe. No locking required. */ +#ifndef CONFIG_XEN addr =__pa (per_cpu_ptr (crash_notes, cpunum)); +#else + addr =virt_to_machine (per_cpu_ptr (crash_notes, cpunum)); +#endif rc =sprintf (buf,"%Lx\n" , addr);return rc; }ref-linux-2.6.16/kernel/kexec.c +41
-11@@ -38,6 +38,20 @@ struct resource crashk_res = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; +/* Kexec needs to know about the actually physical addresss. +* But in xen, a physical address is a pseudo-physical addresss. */ +#ifndef CONFIG_XEN +#define kexec_page_to_pfn (page) page_to_pfn(page) +#define kexec_pfn_to_page (pfn) pfn_to_page(pfn) +#define kexec_virt_to_phys (addr) virt_to_phys(addr) +#define kexec_phys_to_virt (addr) phys_to_virt(addr) +#else +#define kexec_page_to_pfn (page) pfn_to_mfn(page_to_pfn(page)) +#define kexec_pfn_to_page (pfn) pfn_to_page(mfn_to_pfn(pfn)) +#define kexec_virt_to_phys (addr) virt_to_machine(addr) +#define kexec_phys_to_virt (addr) phys_to_virt(machine_to_phys(addr)) +#endif +int kexec_should_crash (struct task_struct *p) {if (in_interrupt () || !p->pid || p->pid ==1 || panic_on_oops)@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_ pages =kimage_alloc_pages (GFP_KERNEL , order);if (!pages)break ; - pfn =page_to_pfn (pages); + pfn =kexec_page_to_pfn (pages); epfn = pfn + count; addr = pfn <<PAGE_SHIFT ; eaddr = epfn <<PAGE_SHIFT ;@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_return pages; } +#ifndef CONFIG_XEN static struct page *kimage_alloc_crash_control_pages (struct kimage *image,unsigned int order) {@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c }/* If I don't overlap any segments I have found my hole! */ if (i == image->nr_segments) { - pages =pfn_to_page (hole_start >>PAGE_SHIFT ); + pages =kexec_pfn_to_page (hole_start >>PAGE_SHIFT );break ; } }@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages( return pages; } +#else /* !CONFIG_XEN */ +struct page *kimage_alloc_control_pages (struct kimage *image, +unsigned int order) +{ +return kimage_alloc_normal_control_pages (image, order); +} +#endif static int kimage_add_entry (struct kimage *image,kimage_entry_t entry) {@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimagreturn -ENOMEM ; ind_page =page_address (page); - *image->entry =virt_to_phys (ind_page) |IND_INDIRECTION ; + *image->entry =kexec_virt_to_phys (ind_page) |IND_INDIRECTION ; image->entry = ind_page; image->last_entry = ind_page + ((PAGE_SIZE /sizeof (kimage_entry_t)) -1 );@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag#define for_each_kimage_entry (image, ptr, entry) \ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ ptr = (entry & IND_INDIRECTION)? \ - phys_to_virt((entry & PAGE_MASK)): ptr +1) + kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)static void kimage_free_entry (kimage_entry_t entry) {struct page *page; - page =pfn_to_page (entry >>PAGE_SHIFT ); + page =kexec_pfn_to_page (entry >>PAGE_SHIFT );kimage_free_pages (page); }@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st* have a match. */ list_for_each_entry (page, &image->dest_pages, lru) { - addr =page_to_pfn (page) <<PAGE_SHIFT ; + addr =kexec_page_to_pfn (page) <<PAGE_SHIFT ;if (addr == destination) {list_del (&page->lru);return page;@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(stif (!page)return NULL ;/* If the page cannot be used file it away */ -if (page_to_pfn (page) > +if (kexec_page_to_pfn (page) > (KEXEC_SOURCE_MEMORY_LIMIT >>PAGE_SHIFT )) {list_add (&page->lru, &image->unuseable_pages);continue ; } - addr =page_to_pfn (page) <<PAGE_SHIFT ; + addr =kexec_page_to_pfn (page) <<PAGE_SHIFT ;/* If it is the destination page we want use it */ if (addr == destination)@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(ststruct page *old_page; old_addr = *old &PAGE_MASK ; - old_page =pfn_to_page (old_addr >>PAGE_SHIFT ); + old_page =kexec_pfn_to_page (old_addr >>PAGE_SHIFT );copy_highpage (page, old_page); *old = addr | (*old & ~PAGE_MASK );@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st result = -ENOMEM ; goto out; } - result =kimage_add_page (image,page_to_pfn (page) + result =kimage_add_page (image,kexec_page_to_pfn (page) <<PAGE_SHIFT );if (result <0 ) goto out;@@ -811,6 +833,7 @@ out:return result; } +#ifndef CONFIG_XEN static int kimage_load_crash_segment (struct kimage *image,struct kexec_segment *segment) {@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(strchar *ptr;size_t uchunk, mchunk; - page =pfn_to_page (maddr >>PAGE_SHIFT ); + page =kexec_pfn_to_page (maddr >>PAGE_SHIFT );if (page ==0 ) { result = -ENOMEM ; goto out;@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki return result; } +#else /* CONFIG_XEN */ +static int kimage_load_segment (struct kimage *image, +struct kexec_segment *segment) +{ +return kimage_load_normal_segment (image, segment); +} +#endif /* * Exec Kernel system call: for obvious reasons only root may call it. xen/arch/x86/Makefile +0
-0@@ -39,6 +39,7 @@ obj-y += trampoline.oobj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.oifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.oxen/arch/x86/dom0_ops.c +3
-0@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000xen/arch/x86/machine_kexec.c new file +1
-0@@ -0,0 +1,27 @@ +/************************************************************************* *****
+ *arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ */xen/arch/x86/machine_kexec.c new file +21
-0+ +#include <public/kexec.h> + +int machine_kexec_prepare (struct kexec_arg *arg) +{ +return 0 ; +} + +void machine_kexec_cleanup (struct kexec_arg *arg) +{ +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ xen/arch/x86/setup.c +21
-9@@ -38,6 +38,11 @@ static unsigned int opt_xenheap_megabyteinteger_param ("xenheap_megabytes" , opt_xenheap_megabytes);#endif +unsigned int opt_kdump_megabytes =0 ; +integer_param ("kdump_megabytes" , opt_kdump_megabytes); +unsigned int opt_kdump_megabytes_base =0 ; +integer_param ("kdump_megabytes_base" , opt_kdump_megabytes_base); +/* opt_nosmp: If true, secondary processors are ignored. */ static int opt_nosmp =0 ;boolean_param ("nosmp" , opt_nosmp);@@ -192,6 +197,20 @@ static void percpu_free_unused_areas(voi __pa(__per_cpu_end)); } +void __init move_memory (unsigned long dst, +unsigned long src_start,unsigned long src_end) +{ +#if defined(CONFIG_X86_32 ) +memmove ((void *)dst,/* use low mapping */ + (void *)src_start,/* use low mapping */ + src_end - src_start); +#elif defined(CONFIG_X86_64 ) +memmove (__va (dst), +__va (src_start), + src_end - src_start); +#endif +} +void __init __start_xen (multiboot_info_t *mbi) {char __cmdline[] ="" , *cmdline = __cmdline;@@ -327,15 +346,8 @@ void __init __start_xen(multiboot_info_t initial_images_start = xenheap_phys_end; initial_images_end = initial_images_start + modules_length; -#if defined(CONFIG_X86_32 ) -memmove ((void *)initial_images_start,/* use low mapping */ - (void *)mod[0 ].mod_start,/* use low mapping */ - mod[mbi->mods_count-1 ].mod_end - mod[0 ].mod_start); -#elif defined(CONFIG_X86_64 ) -memmove (__va (initial_images_start), -__va (mod[0 ].mod_start), - mod[mbi->mods_count-1 ].mod_end - mod[0 ].mod_start); -#endif +move_memory (initial_images_start, + mod[0 ].mod_start, mod[mbi->mods_count-1 ].mod_end);/* Initialise boot-time allocator with all RAM situated after modules. */ xenheap_phys_start = init_boot_allocator(__pa(&_end));xen/arch/x86/setup.c +45
-0@@ -383,6 +395,51 @@ void __init __start_xen(multiboot_info_t#endif } +if (opt_kdump_megabytes) { +unsigned long kdump_start, kdump_size, k; + +/* mark images pages as free for now */ + +init_boot_pages (initial_images_start, initial_images_end); + + kdump_start = opt_kdump_megabytes_base <<20 ; + kdump_size = opt_kdump_megabytes <<20 ; + +printk ("Kdump: %luMB (%lukB) at 0x%lx\n" , + kdump_size >>20 , + kdump_size >>10 , + kdump_start); + +if ((kdump_start & ~PAGE_MASK ) || (kdump_size & ~PAGE_MASK )) +panic ("Kdump parameters not page aligned\n" ); + + kdump_start >>=PAGE_SHIFT ; + kdump_size >>=PAGE_SHIFT ; + +/* allocate pages for Kdump memory area */ + + k =alloc_boot_pages_at (kdump_size, kdump_start); + +if (k != kdump_start) +panic ("Unable to reserve Kdump memory\n" ); + +/* allocate pages for relocated initial images */ + + k = ((initial_images_end - initial_images_start) & ~PAGE_MASK ) ?1 :0 ; + k += (initial_images_end - initial_images_start) >>PAGE_SHIFT ; + + k =alloc_boot_pages (k,1 ); + +if (!k) +panic ("Unable to allocate initial images memory\n" ); + +move_memory (k <<PAGE_SHIFT , initial_images_start, initial_images_end); + + initial_images_end -= initial_images_start; + initial_images_start = k <<PAGE_SHIFT ; + initial_images_end += initial_images_start; + } +memguard_init ();printk("System RAM: %luMB (%lukB)\n",xen/arch/x86/x86_32/Makefile +0
-0@@ -3,5 +3,6 @@ obj-y += entry.oobj-y += mm.o
obj-y += seg_fixup.o
obj-y += traps.o
+obj-y += machine_kexec.oobj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/entry.S +2
-0@@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_xenoprof_op .long do_event_channel_op .long do_physdev_op + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 2 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endrxen/arch/x86/x86_32/machine_kexec.c new file +1
-0@@ -0,0 +1,206 @@ +/************************************************************************* *****
+ *arch/x86/x86_32/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily onarch/i386/machine_kexec.cfrom Linux 2.6.16
+ */xen/arch/x86/x86_32/machine_kexec.c new file +43
-0+ +#include <xen/config.h> +#include <xen/types.h> +#include <xen/domain_page.h> +#include <xen/timer.h> +#include <xen/sched.h> +#include <xen/reboot.h> +#include <xen/console.h> +#include <asm/page.h> +#include <asm/flushtlb.h> +#include <public/xen.h> +#include <public/kexec.h> + +static void __machine_kexec (struct kexec_arg *arg); + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned int has_pae); + +#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) + +#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) +#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) +#define L2_ATTR (_PAGE_PRESENT) + +#ifndef CONFIG_X86_PAE + +static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED; + +static void identity_map_page (unsigned long address) +{ +unsigned long mfn; +u32 *pgtable_level2; + +/* Find the current page table */ + mfn =read_cr3 () >>PAGE_SHIFT ; + pgtable_level2 =map_domain_page (mfn); + +/* Identity map the page table entry */ + pgtable_level1[l1_table_offset (address)] = address |L0_ATTR ; + pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) |
L1_ATTR;xen/arch/x86/x86_32/machine_kexec.c new file +25
-0+ +/* Flush the tlb so the new mapping takes effect. +* Global tlb entries are not flushed but that is not an issue. +*/ +write_cr3 (mfn <<PAGE_SHIFT ); + +unmap_domain_page (pgtable_level2); +} + +#else +static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED; +static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED; + +static void identity_map_page (unsigned long address) +{ +int mfn; +intpte_t *pgtable_level3; + +/* Find the current page table */ + mfn =read_cr3 () >>PAGE_SHIFT ; + pgtable_level3 =map_domain_page (mfn); + +/* Identity map the page table entry */ + pgtable_level1[l1_table_offset (address)] = address |L0_ATTR ; + pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) |
L1_ATTR;xen/arch/x86/x86_32/machine_kexec.c new file +131
-0+set_64bit (&pgtable_level3[l3_table_offset (address)], +__pa (pgtable_level2) |L2_ATTR ); + +/* Flush the tlb so the new mapping takes effect. +* Global tlb entries are not flushed but that is not an issue. +*/ +load_cr3 (mfn <<PAGE_SHIFT ); + +unmap_domain_page (pgtable_level3); +} +#endif + +static void kexec_load_segments (void ) +{ +#define __SSTR (X ) #X +#define SSTR (X ) __SSTR(X) + __asm__ __volatile__ ( + "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n" +"\t1:\n" + "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n" +"\tmovl %%eax,%%ds\n" +"\tmovl %%eax,%%es\n" +"\tmovl %%eax,%%fs\n" +"\tmovl %%eax,%%gs\n" +"\tmovl %%eax,%%ss\n" + ::: "eax", "memory"); +#undef SSTR +#undef __SSTR +} + +#define kexec_load_idt (dtr) __asm__ __volatile("lidt %0"::"m" (*dtr)) +static void kexec_set_idt (void *newidt,__u16 limit) +{ +struct Xgt_desc_struct curidt; + +/* ia32 supports unaliged loads & stores */ + curidt.size = limit; + curidt.address = (unsigned long )newidt; + +kexec_load_idt (&curidt); + +}; + +#define kexec_load_gdt (dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr)) +static void kexec_set_gdt (void *newgdt,__u16 limit) +{ +struct Xgt_desc_struct curgdt; + +/* ia32 supports unaligned loads & stores */ + curgdt.size = limit; + curgdt.address = (unsigned long )newgdt; + +kexec_load_gdt (&curgdt); +}; + +static void __machine_shutdown (void *data) +{ +struct kexec_arg *arg = (struct kexec_arg *)data; + +printk ("__machine_shutdown: cpu=%u\n" ,smp_processor_id ()); + +watchdog_disable (); +console_start_sync (); + +smp_send_stop (); + +#ifdef CONFIG_X86_IO_APIC +disable_IO_APIC (); +#endif + +__machine_kexec (arg); +} + +void machine_shutdown (struct kexec_arg *arg) +{ +int reboot_cpu_id; +cpumask_t reboot_cpu; + + + reboot_cpu_id =0 ; + +if (!cpu_isset (reboot_cpu_id, cpu_online_map)) + reboot_cpu_id =smp_processor_id (); + +if (reboot_cpu_id !=smp_processor_id ()) { +cpus_clear (reboot_cpu); +cpu_set (reboot_cpu_id, reboot_cpu); +on_selected_cpus (reboot_cpu, __machine_shutdown, arg,1 ,0 ); +for (;;) + ;/* nothing */ + } +else +__machine_shutdown (arg); +BUG (); +} + +static void __machine_kexec (struct kexec_arg *arg) +{ +relocate_new_kernel_t rnk; + +local_irq_disable (); + +identity_map_page (arg->u.kexec.reboot_code_buffer); + +copy_from_user ((void *)arg->u.kexec.reboot_code_buffer, + arg->u.kexec.relocate_new_kernel, + arg->u.kexec.relocate_new_kernel_size); + +kexec_load_segments (); +kexec_set_gdt (__va (0 ),0 ); +kexec_set_idt (__va (0 ),0 ); + + rnk = (relocate_new_kernel_t ) arg->u.kexec.reboot_code_buffer; + (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer, + arg->u.kexec.start_address, cpu_has_pae); +} + +void machine_kexec (struct kexec_arg *arg) +{ +machine_shutdown (arg); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ xen/arch/x86/x86_64/Makefile +0
-0@@ -1,3 +1,4 @@obj-y += entry.o
obj-y += mm.o
obj-y += traps.oxen/arch/x86/x86_64/Makefile +1
-0+obj-y += machine_kexec.oxen/arch/x86/x86_64/machine_kexec.c new file +1
-0@@ -0,0 +1,24 @@ +/************************************************************************* *****
+ *arch/x86/x86_64/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily onarch/i386/machine_kexec.cfrom Linux 2.6.16
+ */xen/arch/x86/x86_64/machine_kexec.c new file +17
-0+ +#include <public/kexec.h> + +void machine_kexec (struct kexec_arg *arg) +{ +printk ("machine_kexec: not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ xen/common/Makefile +0
-0@@ -7,6 +7,7 @@ obj-y += event_channel.oobj-y += grant_table.o
obj-y += kernel.o
obj-y += keyhandler.o
+obj-y += kexec.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.oxen/common/kexec.c new file +73
-0@@ -0,0 +1,73 @@ +/* +* Achitecture independent kexec code for Xen +* +* At this statge, just a switch for the kexec hypercall into +* architecture dependent code. +* +* Created By: Horms <[email protected]> +*/ + +#include <xen/lib.h> +#include <xen/errno.h> +#include <xen/guest_access.h> +#include <xen/sched.h> +#include <public/xen.h> +#include <public/kexec.h> + +extern int machine_kexec_prepare (struct kexec_arg *arg); +extern void machine_kexec_cleanup (struct kexec_arg *arg); +extern void machine_kexec (struct kexec_arg *arg); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +int do_kexec (unsigned long op, +XEN_GUEST_HANDLE (kexec_arg_t) uarg) +{ +struct kexec_arg arg; + +if ( !IS_PRIV (current->domain) ) +return -EPERM ; + +if (op == KEXEC_CMD_reserve) + { + arg.u.reserve.size = opt_kdump_megabytes <<20 ; + arg.u.reserve.start = opt_kdump_megabytes_base <<20 ; +if (unlikely (copy_to_guest (uarg, &arg,1 ) !=0 ) ) + { +printk ("do_kexec: copy_to_guest failed" ); +return -EFAULT ; + } +return 0 ; + } + +if (unlikely (copy_from_guest (&arg, uarg,1 ) !=0 ) ) + { +printk ("do_kexec: __copy_from_guest failed" ); +return -EFAULT ; + } + +switch (op) { +case KEXEC_CMD_kexec: +machine_kexec (&arg); +return -EINVAL ;/* Not Reached */ +case KEXEC_CMD_kexec_prepare: +return machine_kexec_prepare (&arg); +case KEXEC_CMD_kexec_cleanup: +machine_kexec_cleanup (&arg); +return 0 ; + } + +return -EINVAL ; +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +xen/common/page_alloc.c +17
-0@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long
alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{xen/common/page_alloc.c +5
-11-unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i;}
xen/include/asm-x86/hypercall.h +1
-0@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <public/kexec.h> extern long
do_event_channel_op_compat(xen/include/asm-x86/hypercall.h +0
-0@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg);xen/include/asm-x86/hypercall.h +4
-0+extern int +do_kexec ( +unsigned long op,XEN_GUEST_HANDLE (kexec_arg_t) uarg); +#ifdef
__x86_64__extern long
xen/include/public/kexec.h new file +46
-0@@ -0,0 +1,46 @@ +/* +* kexec.h: Xen kexec public +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _XEN_PUBLIC_KEXEC_H +#define _XEN_PUBLIC_KEXEC_H + +#include <xen/types.h> +#include <public/xen.h> + +/* +* Scratch space for passing arguments to the kexec hypercall +*/ +typedef struct kexec_arg { +union { +struct { +unsigned long data;/* Not sure what this should be yet */ + } helper; +struct { +unsigned long indirection_page; +unsigned long reboot_code_buffer; +unsigned long start_address; +const char *relocate_new_kernel; +unsigned int relocate_new_kernel_size; + } kexec; +struct { +unsigned long size; +unsigned long start; + } reserve; + } u; +}kexec_arg_t ; +DEFINE_XEN_GUEST_HANDLE (kexec_arg_t); + +#endif + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ xen/include/public/xen.h +9
-0@@ -64,6 +64,7 @@#define __HYPERVISOR_xenoprof_op 31#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_kexec_op 34/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48@@ -238,6 +239,14 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);#define VMASST_TYPE_writable_pagetables 2#define MAX_VMASST_TYPE 2 +/* +* Operations for kexec. +*/ +#define KEXEC_CMD_kexec 0 +#define KEXEC_CMD_kexec_prepare 1 +#define KEXEC_CMD_kexec_cleanup 2 +#define KEXEC_CMD_reserve 3 +#ifndef __ASSEMBLY__typedef uint16_t domid_t ;xen/include/xen/mm.h +0
-0@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long
alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned longalloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
voidend_boot_allocator(void);/* Generic allocator. These functions are *not* interrupt-safe. */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: [PATCH]: kexec: framework and i386 (Take VI)
Quoted 5 lines · Akio Takebe
Hi, Horms
Why you modify
ref-linux-2.6.16/kernel/{drivers/base/cpu.c,kernel/kexec.c}? I tried to patch your kexec patch, I fail to patch it.
How do you do patch?
Sorry, the drivers/base/cpu.c portion is just an artifact of xen's build system which modifies that file on build, but doesn't unmodify it on distclean. It shouldn't have been included in my patch.
kernel/kexec.c needs to be modified primarily so that mfns are used instead of pfns. Again because of strangeness in the the xen build system, this patch is a bit odd as it patches a file not covered by a xen checkout (even though its needed for a xen build). If you run the following before applying the patch it should apply.
make prep-kernels clean kclean
make -C linux-2.6.16-xen distclean
Quoted 2 lines
I think you can make a patch in patches/linux-2.6.16/ if you would modify these.
Yes, that is probably the best way forward, I'll work on breaking it out in that manner.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
PATCH 1/1 : kexec: framework and i386 (Take VII)
Quoted 7 lines · Horms
Quoted 2 lines · Akio Takebe
I think you can make a patch in patches/linux-2.6.16/ if you would modify these.
Yes, that is probably the best way forward, I'll work on breaking it out in that manner.
Hi Takebe-san,
here is an updated version of the patch which moves portions into patches/linux-2.6.16/ as you suggested. It also moves to xen-unstable 9969 / Linux 2.6.16.13 and has some minor build fixes, for problems that crept into the previous patch.
Signature · 1,227 lines
Horms http://www.vergenet.net/~horms/
kexec: framework and i386
This is an implementation of kexec for dom0/xen, that allows
kexecing of the physical machine from xen. The approach taken is
to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do
anything in i386. So while this patch adds a framework for them,
I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that
kexec-tools needs updating, but I have not investigated yet
* Kdump works by first copying the kernel into dom0 segments
and relocating them later in xen, the same way that kexec does
The only difference is that the relocation is made into
an area reserved by xen
* Kdump reservation is made using the xen command line parameters,
kdump_megabytes and kdump_megabytes_base, rather than
the linux option crashkernel, which is now ignored.
Two parameters are used instead of one to simplify parsing.
This can be cleaned up later if desired. But the reservation
seems to need to be made by xen to make sure that it happens
early enough.
The tested values are kdump_megabytes=16, kdump_megabytes_base=32
(kdump_megabytes_base=16 does not seem to work)
* This patch uses a new kexec hypercall
* SMP Kexec works, Kdump is next on the list
Highlights since the previous posted version:
* Diff now applies to a xen checkout from hg
(previously it assumed that the kernel was unpacked)
- xen-unstable-hg 9660 / Linux 2.6.16.13
* Added machine_shutdown, which disapperared in the previous release of
this patch
* Fixed include problems in kexec.h
Prepared by Horms and Magnus Damm
Signed-Off-By: Magnus Damm <[email protected]>
Signed-Off-By: Horms <[email protected]>
linux-2.6-xen-sparse/arch/i386/Kconfig | 2
linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 24 +
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 ++++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 73 +++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10
linux-2.6.16.13/kexec.patch | 175 ++++++++
xen/arch/x86/Makefile | 1
xen/arch/x86/dom0_ops.c | 3
xen/arch/x86/machine_kexec.c | 28 +
xen/arch/x86/setup.c | 75 +++
xen/arch/x86/x86_32/Makefile | 1
xen/arch/x86/x86_32/entry.S | 2
xen/arch/x86/x86_32/machine_kexec.c | 205 ++++++++++
xen/arch/x86/x86_64/Makefile | 1
xen/arch/x86/x86_64/machine_kexec.c | 25 +
xen/common/Makefile | 1
xen/common/kexec.c | 73 +++
xen/common/page_alloc.c | 33 +
xen/include/asm-x86/hypercall.h | 6
xen/include/public/kexec.h | 45 ++
xen/include/public/xen.h | 9
xen/include/xen/mm.h | 1
25 files changed, 876 insertions(+), 22 deletions(-)
--- x/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ x/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL && !X86_XEN
+ depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
--- x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen
obj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o
-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o
+n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen))
obj-y := $(call cherrypickxen, $(obj-y))
--- x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
@@ -68,6 +68,10 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
+
/* Forward Declaration. */
void __init find_max_pfn(void);
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (
* after a kernel panic.
*/
else if (!memcmp(from, "crashkernel=", 12)) {
+#ifndef CONFIG_XEN
unsigned long size, base;
size = memparse(from+12, &from);
if (*from == '@') {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early (
crashk_res.start = base;
crashk_res.end = base + size - 1;
}
+#else
+ printk("Ignoring crashkernel command line, "
+ "parameter will be supplied by xen\n");
+#endif
}
#endif
#ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,21 @@ void __init setup_bootmem_allocator(void
}
#endif
#ifdef CONFIG_KEXEC
+#ifndef CONFIG_XEN
if (crashk_res.start != crashk_res.end)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
+#else
+ {
+ struct kexec_arg xen_kexec_arg;
+ BUG_ON(HYPERVISOR_kexec(KEXEC_CMD_reserve, &xen_kexec_arg));
+ if (xen_kexec_arg.u.reserve.size) {
+ crashk_res.start = xen_kexec_arg.u.reserve.start;
+ crashk_res.end = xen_kexec_arg.u.reserve.start +
+ xen_kexec_arg.u.reserve.size - 1;
+ }
+ }
+#endif
#endif
if (!xen_feature(XENFEAT_auto_translated_physmap))
@@ -1395,6 +1416,9 @@ legacy_init_iomem_resources(struct resou
res->end = map[i].end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
free_bootmem(__pa(map), PAGE_SIZE);
--- x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/crash.c
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific (i386-xen) functions for kexec based crash dumps.
+ *
+ * Created by: Horms <[email protected]>
+ *
+ */
+
+#include <linux/kernel.h> /* For printk */
+
+/* XXX: final_note(), crash_save_this_cpu() and crash_save_self()
+ * are copied from arch/i386/kernel/crash.c, might be good to either
+ * the original functions non-static and use them, or just
+ * merge this this into that file.
+ */
+#include <linux/elf.h> /* For struct elf_note */
+#include <linux/elfcore.h> /* For struct elf_prstatus */
+#include <linux/kexec.h> /* crash_notes */
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* XXX: This should do something */
+ printk("xen-kexec: Need to turn of other CPUS in "
+ "machine_crash_shutdown()\n");
+ crash_save_self(regs);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,73 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Created By: Horms <[email protected]>
+ *
+ * Losely based on arch/i386/kernel/machine_kexec.c
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/mm.h>
+#include <asm/hypercall.h>
+
+const extern unsigned char relocate_new_kernel[];
+extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ return HYPERVISOR_kexec(KEXEC_CMD_kexec_prepare, &hypercall_arg);
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec_cleanup, &hypercall_arg);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.kexec.indirection_page = image->head;
+ hypercall_arg.u.kexec.reboot_code_buffer =
+ pfn_to_mfn(page_to_pfn(image->control_code_page)) << PAGE_SHIFT;
+ hypercall_arg.u.kexec.start_address = image->start;
+ hypercall_arg.u.kexec.relocate_new_kernel = relocate_new_kernel;
+ hypercall_arg.u.kexec.relocate_new_kernel_size =
+ relocate_new_kernel_size;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec, &hypercall_arg);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
+++ x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
@@ -66,6 +66,10 @@ void machine_power_off(void)
HYPERVISOR_shutdown(SHUTDOWN_poweroff);
}
+#ifdef CONFIG_KEXEC
+void machine_shutdown(void) { }
+#endif
+
int reboot_thru_bios = 0; /* for dmi_scan.c */
EXPORT_SYMBOL(machine_restart);
EXPORT_SYMBOL(machine_halt);
--- x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
+++ x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
@@ -39,6 +39,8 @@
# error "please don't include this file directly"
#endif
+#include <xen/interface/kexec.h>
+
#define __STR(x) #x
#define STR(x) __STR(x)
@@ -359,6 +361,14 @@ HYPERVISOR_xenoprof_op(
return _hypercall2(int, xenoprof_op, op, arg);
}
+static inline int
+HYPERVISOR_kexec(
+ unsigned long op, kexec_arg_t * arg)
+{
+ return _hypercall2(int, kexec_op, op, arg);
+}
+
+
#endif /* __HYPERCALL_H__ */
--- x/xen/arch/x86/Makefile
+++ x/xen/arch/x86/Makefile
@@ -39,6 +39,7 @@ obj-y += trampoline.o
obj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.o
ifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
--- x/xen/arch/x86/dom0_ops.c
+++ x/xen/arch/x86/dom0_ops.c
@@ -29,6 +29,9 @@
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
--- /dev/null
+++ x/xen/arch/x86/machine_kexec.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ */
+
+#include <xen/types.h>
+#include <public/kexec.h>
+
+int machine_kexec_prepare(struct kexec_arg *arg)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kexec_arg *arg)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -38,6 +38,11 @@ static unsigned int opt_xenheap_megabyte
integer_param("xenheap_megabytes", opt_xenheap_megabytes);
#endif
+unsigned int opt_kdump_megabytes = 0;
+integer_param("kdump_megabytes", opt_kdump_megabytes);
+unsigned int opt_kdump_megabytes_base = 0;
+integer_param("kdump_megabytes_base", opt_kdump_megabytes_base);
+
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);
@@ -192,6 +197,20 @@ static void percpu_free_unused_areas(voi
__pa(__per_cpu_end));
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char __cmdline[] = "", *cmdline = __cmdline;
@@ -327,15 +346,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -383,6 +395,51 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ if (opt_kdump_megabytes) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = opt_kdump_megabytes_base << 20;
+ kdump_size = opt_kdump_megabytes << 20;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
printk("System RAM: %luMB (%lukB)\n",
--- x/xen/arch/x86/x86_32/Makefile
+++ x/xen/arch/x86/x86_32/Makefile
@@ -3,5 +3,6 @@ obj-y += entry.o
obj-y += mm.o
obj-y += seg_fixup.o
obj-y += traps.o
+obj-y += machine_kexec.o
obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
--- x/xen/arch/x86/x86_32/entry.S
+++ x/xen/arch/x86/x86_32/entry.S
@@ -648,6 +648,7 @@ ENTRY(hypercall_table)
.long do_xenoprof_op
.long do_event_channel_op
.long do_physdev_op
+ .long do_kexec
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table)
.byte 2 /* do_xenoprof_op */
.byte 2 /* do_event_channel_op */
.byte 2 /* do_physdev_op */
+ .byte 2 /* do_kexec */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
--- /dev/null
+++ x/xen/arch/x86/x86_32/machine_kexec.c
@@ -0,0 +1,205 @@
+/******************************************************************************
+ * arch/x86/x86_32/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/domain_page.h>
+#include <xen/timer.h>
+#include <xen/sched.h>
+#include <xen/reboot.h>
+#include <xen/console.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <public/kexec.h>
+
+static void __machine_kexec(struct kexec_arg *arg);
+
+typedef asmlinkage void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae);
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#ifndef CONFIG_X86_PAE
+
+static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long mfn;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level2 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ write_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level2);
+}
+
+#else
+static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ int mfn;
+ intpte_t *pgtable_level3;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level3 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[l3_table_offset(address)],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level3);
+}
+#endif
+
+static void kexec_load_segments(void)
+{
+#define __SSTR(X) #X
+#define SSTR(X) __SSTR(X)
+ __asm__ __volatile__ (
+ "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n"
+ "\tmovl %%eax,%%ds\n"
+ "\tmovl %%eax,%%es\n"
+ "\tmovl %%eax,%%fs\n"
+ "\tmovl %%eax,%%gs\n"
+ "\tmovl %%eax,%%ss\n"
+ ::: "eax", "memory");
+#undef SSTR
+#undef __SSTR
+}
+
+#define kexec_load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+static void kexec_set_idt(void *newidt, __u16 limit)
+{
+ struct Xgt_desc_struct curidt;
+
+ /* ia32 supports unaliged loads & stores */
+ curidt.size = limit;
+ curidt.address = (unsigned long)newidt;
+
+ kexec_load_idt(&curidt);
+
+};
+
+#define kexec_load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+static void kexec_set_gdt(void *newgdt, __u16 limit)
+{
+ struct Xgt_desc_struct curgdt;
+
+ /* ia32 supports unaligned loads & stores */
+ curgdt.size = limit;
+ curgdt.address = (unsigned long)newgdt;
+
+ kexec_load_gdt(&curgdt);
+};
+
+static void __machine_shutdown(void *data)
+{
+ struct kexec_arg *arg = (struct kexec_arg *)data;
+
+ printk("__machine_shutdown: cpu=%u\n", smp_processor_id());
+
+ watchdog_disable();
+ console_start_sync();
+
+ smp_send_stop();
+
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+
+ __machine_kexec(arg);
+}
+
+void machine_shutdown(struct kexec_arg *arg)
+{
+ int reboot_cpu_id;
+ cpumask_t reboot_cpu;
+
+
+ reboot_cpu_id = 0;
+
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map))
+ reboot_cpu_id = smp_processor_id();
+
+ if (reboot_cpu_id != smp_processor_id()) {
+ cpus_clear(reboot_cpu);
+ cpu_set(reboot_cpu_id, reboot_cpu);
+ on_selected_cpus(reboot_cpu, __machine_shutdown, arg, 1, 0);
+ for (;;)
+ ; /* nothing */
+ }
+ else
+ __machine_shutdown(arg);
+ BUG();
+}
+
+static void __machine_kexec(struct kexec_arg *arg)
+{
+ relocate_new_kernel_t rnk;
+
+ local_irq_disable();
+
+ identity_map_page(arg->u.kexec.reboot_code_buffer);
+
+ copy_from_user((void *)arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.relocate_new_kernel,
+ arg->u.kexec.relocate_new_kernel_size);
+
+ kexec_load_segments();
+ kexec_set_gdt(__va(0),0);
+ kexec_set_idt(__va(0),0);
+
+ rnk = (relocate_new_kernel_t) arg->u.kexec.reboot_code_buffer;
+ (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.start_address, cpu_has_pae);
+}
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ machine_shutdown(arg);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/x86_64/Makefile
+++ x/xen/arch/x86/x86_64/Makefile
@@ -1,3 +1,4 @@
obj-y += entry.o
obj-y += mm.o
obj-y += traps.o
+obj-y += machine_kexec.o
--- /dev/null
+++ x/xen/arch/x86/x86_64/machine_kexec.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * arch/x86/x86_64/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/types.h>
+#include <public/kexec.h>
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ printk("machine_kexec: not implemented\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/common/Makefile
+++ x/xen/common/Makefile
@@ -7,6 +7,7 @@ obj-y += event_channel.o
obj-y += grant_table.o
obj-y += kernel.o
obj-y += keyhandler.o
+obj-y += kexec.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.o
--- /dev/null
+++ x/xen/common/kexec.c
@@ -0,0 +1,73 @@
+/*
+ * Achitecture independent kexec code for Xen
+ *
+ * At this statge, just a switch for the kexec hypercall into
+ * architecture dependent code.
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+#include <public/kexec.h>
+
+extern int machine_kexec_prepare(struct kexec_arg *arg);
+extern void machine_kexec_cleanup(struct kexec_arg *arg);
+extern void machine_kexec(struct kexec_arg *arg);
+
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
+int do_kexec(unsigned long op,
+ XEN_GUEST_HANDLE(kexec_arg_t) uarg)
+{
+ struct kexec_arg arg;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if (op == KEXEC_CMD_reserve)
+ {
+ arg.u.reserve.size = opt_kdump_megabytes << 20;
+ arg.u.reserve.start = opt_kdump_megabytes_base << 20;
+ if ( unlikely(copy_to_guest(uarg, &arg, 1) != 0) )
+ {
+ printk("do_kexec: copy_to_guest failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+ if ( unlikely(copy_from_guest(&arg, uarg, 1) != 0) )
+ {
+ printk("do_kexec: __copy_from_guest failed");
+ return -EFAULT;
+ }
+
+ switch(op) {
+ case KEXEC_CMD_kexec:
+ machine_kexec(&arg);
+ return -EINVAL; /* Not Reached */
+ case KEXEC_CMD_kexec_prepare:
+ return machine_kexec_prepare(&arg);
+ case KEXEC_CMD_kexec_cleanup:
+ machine_kexec_cleanup(&arg);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
--- x/xen/common/page_alloc.c
+++ x/xen/common/page_alloc.c
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t
}
}
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+ unsigned long i;
+
+ for ( i = 0; i < nr_pfns; i++ )
+ if ( allocated_in_map(pfn_at + i) )
+ break;
+
+ if ( i == nr_pfns )
+ {
+ map_alloc(pfn_at, nr_pfns);
+ return pfn_at;
+ }
+
+ return 0;
+}
+
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{
- unsigned long pg, i;
+ unsigned long pg, i = 0;
for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
{
- for ( i = 0; i < nr_pfns; i++ )
- if ( allocated_in_map(pg + i) )
- break;
-
- if ( i == nr_pfns )
- {
- map_alloc(pg, nr_pfns);
- return pg;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- x/xen/include/asm-x86/hypercall.h
+++ x/xen/include/asm-x86/hypercall.h
@@ -6,6 +6,8 @@
#define __ASM_X86_HYPERCALL_H__
#include <public/physdev.h>
+#include <xen/types.h>
+#include <public/kexec.h>
extern long
do_event_channel_op_compat(
@@ -87,6 +89,10 @@ extern long
arch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg);
+extern int
+do_kexec(
+ unsigned long op, XEN_GUEST_HANDLE(kexec_arg_t) uarg);
+
#ifdef __x86_64__
extern long
--- /dev/null
+++ x/xen/include/public/kexec.h
@@ -0,0 +1,45 @@
+/*
+ * kexec.h: Xen kexec public
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+#include "xen.h"
+
+/*
+ * Scratch space for passing arguments to the kexec hypercall
+ */
+typedef struct kexec_arg {
+ union {
+ struct {
+ unsigned long data; /* Not sure what this should be yet */
+ } helper;
+ struct {
+ unsigned long indirection_page;
+ unsigned long reboot_code_buffer;
+ unsigned long start_address;
+ const char *relocate_new_kernel;
+ unsigned int relocate_new_kernel_size;
+ } kexec;
+ struct {
+ unsigned long size;
+ unsigned long start;
+ } reserve;
+ } u;
+} kexec_arg_t;
+DEFINE_XEN_GUEST_HANDLE(kexec_arg_t);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/include/public/xen.h
+++ x/xen/include/public/xen.h
@@ -64,6 +64,7 @@
#define __HYPERVISOR_xenoprof_op 31
#define __HYPERVISOR_event_channel_op 32
#define __HYPERVISOR_physdev_op 33
+#define __HYPERVISOR_kexec_op 34
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
@@ -238,6 +239,14 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_writable_pagetables 2
#define MAX_VMASST_TYPE 2
+/*
+ * Operations for kexec.
+ */
+#define KEXEC_CMD_kexec 0
+#define KEXEC_CMD_kexec_prepare 1
+#define KEXEC_CMD_kexec_cleanup 2
+#define KEXEC_CMD_reserve 3
+
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
--- x/xen/include/xen/mm.h
+++ x/xen/include/xen/mm.h
@@ -40,6 +40,7 @@ struct page_info;
paddr_t init_boot_allocator(paddr_t bitmap_start);
void init_boot_pages(paddr_t ps, paddr_t pe);
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
void end_boot_allocator(void);
/* Generic allocator. These functions are *not* interrupt-safe. */
--- /dev/null 2006-05-08 18:31:14.283785672 +0900
+++ x/linux-2.6.16.13/kexec.patch 2006-05-09 10:19:10.000000000 +0900
@@ -0,0 +1,175 @@
+--- x/ref-linux-2.6.16.13/drivers/base/cpu.c
++++ x/ref-linux-2.6.16.13/drivers/base/cpu.c
+@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s
+ * boot up and this data does not change there after. Hence this
+ * operation should be safe. No locking required.
+ */
++#ifndef CONFIG_XEN
+ addr = __pa(per_cpu_ptr(crash_notes, cpunum));
++#else
++ addr = virt_to_machine(per_cpu_ptr(crash_notes, cpunum));
++#endif
+ rc = sprintf(buf, "%Lx\n", addr);
+ return rc;
+ }
+--- x/ref-linux-2.6.16.13/kernel/kexec.c
++++ x/ref-linux-2.6.16.13/kernel/kexec.c
+@@ -38,6 +38,20 @@ struct resource crashk_res = {
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+
++/* Kexec needs to know about the actually physical addresss.
++ * But in xen, a physical address is a pseudo-physical addresss. */
++#ifndef CONFIG_XEN
++#define kexec_page_to_pfn(page) page_to_pfn(page)
++#define kexec_pfn_to_page(pfn) pfn_to_page(pfn)
++#define kexec_virt_to_phys(addr) virt_to_phys(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(addr)
++#else
++#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page))
++#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn))
++#define kexec_virt_to_phys(addr) virt_to_machine(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
++#endif
++
+ int kexec_should_crash(struct task_struct *p)
+ {
+ if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_
+ pages = kimage_alloc_pages(GFP_KERNEL, order);
+ if (!pages)
+ break;
+- pfn = page_to_pfn(pages);
++ pfn = kexec_page_to_pfn(pages);
+ epfn = pfn + count;
+ addr = pfn << PAGE_SHIFT;
+ eaddr = epfn << PAGE_SHIFT;
+@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_
+ return pages;
+ }
+
++#ifndef CONFIG_XEN
+ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+ unsigned int order)
+ {
+@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c
+ }
+ /* If I don't overlap any segments I have found my hole! */
+ if (i == image->nr_segments) {
+- pages = pfn_to_page(hole_start >> PAGE_SHIFT);
++ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
+ break;
+ }
+ }
+@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages(
+
+ return pages;
+ }
++#else /* !CONFIG_XEN */
++struct page *kimage_alloc_control_pages(struct kimage *image,
++ unsigned int order)
++{
++ return kimage_alloc_normal_control_pages(image, order);
++}
++#endif
+
+ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+ {
+@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimag
+ return -ENOMEM;
+
+ ind_page = page_address(page);
+- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
++ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
+ image->entry = ind_page;
+ image->last_entry = ind_page +
+ ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag
+ #define for_each_kimage_entry(image, ptr, entry) \
+ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+ ptr = (entry & IND_INDIRECTION)? \
+- phys_to_virt((entry & PAGE_MASK)): ptr +1)
++ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
+
+ static void kimage_free_entry(kimage_entry_t entry)
+ {
+ struct page *page;
+
+- page = pfn_to_page(entry >> PAGE_SHIFT);
++ page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
+ kimage_free_pages(page);
+ }
+
+@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st
+ * have a match.
+ */
+ list_for_each_entry(page, &image->dest_pages, lru) {
+- addr = page_to_pfn(page) << PAGE_SHIFT;
++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+ if (addr == destination) {
+ list_del(&page->lru);
+ return page;
+@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(st
+ if (!page)
+ return NULL;
+ /* If the page cannot be used file it away */
+- if (page_to_pfn(page) >
++ if (kexec_page_to_pfn(page) >
+ (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+ list_add(&page->lru, &image->unuseable_pages);
+ continue;
+ }
+- addr = page_to_pfn(page) << PAGE_SHIFT;
++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+
+ /* If it is the destination page we want use it */
+ if (addr == destination)
+@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(st
+ struct page *old_page;
+
+ old_addr = *old & PAGE_MASK;
+- old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
++ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
+ copy_highpage(page, old_page);
+ *old = addr | (*old & ~PAGE_MASK);
+
+@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st
+ result = -ENOMEM;
+ goto out;
+ }
+- result = kimage_add_page(image, page_to_pfn(page)
++ result = kimage_add_page(image, kexec_page_to_pfn(page)
+ << PAGE_SHIFT);
+ if (result < 0)
+ goto out;
+@@ -811,6 +833,7 @@ out:
+ return result;
+ }
+
++#ifndef CONFIG_XEN
+ static int kimage_load_crash_segment(struct kimage *image,
+ struct kexec_segment *segment)
+ {
+@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(str
+ char *ptr;
+ size_t uchunk, mchunk;
+
+- page = pfn_to_page(maddr >> PAGE_SHIFT);
++ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
+ if (page == 0) {
+ result = -ENOMEM;
+ goto out;
+@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki
+
+ return result;
+ }
++#else /* CONFIG_XEN */
++static int kimage_load_segment(struct kimage *image,
++ struct kexec_segment *segment)
++{
++ return kimage_load_normal_segment(image, segment);
++}
++#endif
+
+ /*
+ * Exec Kernel system call: for obvious reasons only root may call it.PATCH 1/1 : kexec: framework and i386 (Take VIII)
Quoted 9 lines · Horms
Quoted 7 lines · Horms
Quoted 2 lines · Akio Takebe
I think you can make a patch in patches/linux-2.6.16/ if you would modify these.
Yes, that is probably the best way forward, I'll work on breaking it out in that manner.
Quoted 6 lines
Hi Takebe-san,
here is an updated version of the patch which moves portions into patches/linux-2.6.16/ as you suggested. It also moves to xen-unstable 9969 / Linux 2.6.16.13 and has some minor build fixes, for problems that crept into the previous patch.
Sorry, this mornin's patch had the internal patch in the wrong location and with the wrong diff level.
Signature · 1,238 lines
Horms http://www.vergenet.net/~horms/
kexec: framework and i386
This is an implementation of kexec for dom0/xen, that allows
kexecing of the physical machine from xen. The approach taken is
to move the architecture-dependant kexec code into a new hypercall.
Some notes:
* machine_kexec_cleanup() and machine_kexec_prepare() don't do
anything in i386. So while this patch adds a framework for them,
I am not sure what parameters are needs at this stage.
* Only works for UP, as machine_shutdown is not implemented yet
* kexecing into xen does not seem to work, I think that
kexec-tools needs updating, but I have not investigated yet
* Kdump works by first copying the kernel into dom0 segments
and relocating them later in xen, the same way that kexec does
The only difference is that the relocation is made into
an area reserved by xen
* Kdump reservation is made using the xen command line parameters,
kdump_megabytes and kdump_megabytes_base, rather than
the linux option crashkernel, which is now ignored.
Two parameters are used instead of one to simplify parsing.
This can be cleaned up later if desired. But the reservation
seems to need to be made by xen to make sure that it happens
early enough.
The tested values are kdump_megabytes=16, kdump_megabytes_base=32
(kdump_megabytes_base=16 does not seem to work)
* This patch uses a new kexec hypercall
* SMP Kexec works, Kdump is next on the list
Highlights since the previous posted version:
* Diff now applies to a xen checkout from hg
(previously it assumed that the kernel was unpacked)
- xen-unstable-hg 9660 / Linux 2.6.16.13
* Added machine_shutdown, which disapperared in the previous release of
this patch
* Fixed include problems in kexec.h
Prepared by Horms and Magnus Damm
Signed-Off-By: Magnus Damm <[email protected]>
Signed-Off-By: Horms <[email protected]>
buildconfigs/linux-defconfig_xen_x86_32 | 1
linux-2.6-xen-sparse/arch/i386/Kconfig | 2
linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 24 +
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1
linux-2.6-xen-sparse/drivers/xen/core/crash.c | 98 ++++
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 73 +++
linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10
patches/linux-2.6.16.13/kexec.patch | 175 ++++++++
xen/arch/x86/Makefile | 1
xen/arch/x86/dom0_ops.c | 3
xen/arch/x86/machine_kexec.c | 28 +
xen/arch/x86/setup.c | 75 +++
xen/arch/x86/x86_32/Makefile | 1
xen/arch/x86/x86_32/entry.S | 2
xen/arch/x86/x86_32/machine_kexec.c | 205 ++++++++++
xen/arch/x86/x86_64/Makefile | 1
xen/arch/x86/x86_64/machine_kexec.c | 25 +
xen/common/Makefile | 1
xen/common/kexec.c | 73 +++
xen/common/page_alloc.c | 33 +
xen/include/asm-x86/hypercall.h | 6
xen/include/public/kexec.h | 45 ++
xen/include/public/xen.h | 9
xen/include/xen/mm.h | 1
26 files changed, 877 insertions(+), 22 deletions(-)
--- x/buildconfigs/linux-defconfig_xen_x86_32
+++ x/buildconfigs/linux-defconfig_xen_x86_32
@@ -184,6 +184,7 @@ CONFIG_MTRR=y
CONFIG_REGPARM=y
CONFIG_SECCOMP=y
CONFIG_HZ_100=y
+CONFIG_KEXEC=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=100
--- x/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ x/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
- depends on EXPERIMENTAL && !X86_XEN
+ depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
--- x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/Makefile
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen
obj-y += fixup.o
microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o
-n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o
+n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o
obj-y := $(call filterxen, $(obj-y), $(n-obj-xen))
obj-y := $(call cherrypickxen, $(obj-y))
--- x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
+++ x/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
@@ -68,6 +68,10 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
+
/* Forward Declaration. */
void __init find_max_pfn(void);
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (
* after a kernel panic.
*/
else if (!memcmp(from, "crashkernel=", 12)) {
+#ifndef CONFIG_XEN
unsigned long size, base;
size = memparse(from+12, &from);
if (*from == '@') {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early (
crashk_res.start = base;
crashk_res.end = base + size - 1;
}
+#else
+ printk("Ignoring crashkernel command line, "
+ "parameter will be supplied by xen\n");
+#endif
}
#endif
#ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,21 @@ void __init setup_bootmem_allocator(void
}
#endif
#ifdef CONFIG_KEXEC
+#ifndef CONFIG_XEN
if (crashk_res.start != crashk_res.end)
reserve_bootmem(crashk_res.start,
crashk_res.end - crashk_res.start + 1);
+#else
+ {
+ struct kexec_arg xen_kexec_arg;
+ BUG_ON(HYPERVISOR_kexec(KEXEC_CMD_reserve, &xen_kexec_arg));
+ if (xen_kexec_arg.u.reserve.size) {
+ crashk_res.start = xen_kexec_arg.u.reserve.start;
+ crashk_res.end = xen_kexec_arg.u.reserve.start +
+ xen_kexec_arg.u.reserve.size - 1;
+ }
+ }
+#endif
#endif
if (!xen_feature(XENFEAT_auto_translated_physmap))
@@ -1395,6 +1416,9 @@ legacy_init_iomem_resources(struct resou
res->end = map[i].end - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
free_bootmem(__pa(map), PAGE_SIZE);
--- x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
+++ x/linux-2.6-xen-sparse/drivers/xen/core/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o
obj-$(CONFIG_SMP) += smpboot.o
obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o
obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/crash.c
@@ -0,0 +1,98 @@
+/*
+ * Architecture specific (i386-xen) functions for kexec based crash dumps.
+ *
+ * Created by: Horms <[email protected]>
+ *
+ */
+
+#include <linux/kernel.h> /* For printk */
+
+/* XXX: final_note(), crash_save_this_cpu() and crash_save_self()
+ * are copied from arch/i386/kernel/crash.c, might be good to either
+ * the original functions non-static and use them, or just
+ * merge this this into that file.
+ */
+#include <linux/elf.h> /* For struct elf_note */
+#include <linux/elfcore.h> /* For struct elf_prstatus */
+#include <linux/kexec.h> /* crash_notes */
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, ¬e, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, ¬e, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = (u32*)per_cpu_ptr(crash_notes, cpu);
+ if (!buf)
+ return;
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_save_self(struct pt_regs *regs)
+{
+ int cpu;
+
+ cpu = smp_processor_id();
+ crash_save_this_cpu(regs, cpu);
+}
+
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* XXX: This should do something */
+ printk("xen-kexec: Need to turn of other CPUS in "
+ "machine_crash_shutdown()\n");
+ crash_save_self(regs);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- /dev/null
+++ x/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -0,0 +1,73 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Created By: Horms <[email protected]>
+ *
+ * Losely based on arch/i386/kernel/machine_kexec.c
+ */
+
+#include <linux/kexec.h>
+#include <xen/interface/kexec.h>
+#include <linux/mm.h>
+#include <asm/hypercall.h>
+
+const extern unsigned char relocate_new_kernel[];
+extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ return HYPERVISOR_kexec(KEXEC_CMD_kexec_prepare, &hypercall_arg);
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.helper.data = NULL;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec_cleanup, &hypercall_arg);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ kexec_arg_t hypercall_arg;
+ hypercall_arg.u.kexec.indirection_page = image->head;
+ hypercall_arg.u.kexec.reboot_code_buffer =
+ pfn_to_mfn(page_to_pfn(image->control_code_page)) << PAGE_SHIFT;
+ hypercall_arg.u.kexec.start_address = image->start;
+ hypercall_arg.u.kexec.relocate_new_kernel = relocate_new_kernel;
+ hypercall_arg.u.kexec.relocate_new_kernel_size =
+ relocate_new_kernel_size;
+ HYPERVISOR_kexec(KEXEC_CMD_kexec, &hypercall_arg);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
--- x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
+++ x/linux-2.6-xen-sparse/drivers/xen/core/reboot.c
@@ -66,6 +66,10 @@ void machine_power_off(void)
HYPERVISOR_shutdown(SHUTDOWN_poweroff);
}
+#ifdef CONFIG_KEXEC
+void machine_shutdown(void) { }
+#endif
+
int reboot_thru_bios = 0; /* for dmi_scan.c */
EXPORT_SYMBOL(machine_restart);
EXPORT_SYMBOL(machine_halt);
--- x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
+++ x/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
@@ -39,6 +39,8 @@
# error "please don't include this file directly"
#endif
+#include <xen/interface/kexec.h>
+
#define __STR(x) #x
#define STR(x) __STR(x)
@@ -359,6 +361,14 @@ HYPERVISOR_xenoprof_op(
return _hypercall2(int, xenoprof_op, op, arg);
}
+static inline int
+HYPERVISOR_kexec(
+ unsigned long op, kexec_arg_t * arg)
+{
+ return _hypercall2(int, kexec_op, op, arg);
+}
+
+
#endif /* __HYPERCALL_H__ */
--- x/xen/arch/x86/Makefile
+++ x/xen/arch/x86/Makefile
@@ -39,6 +39,7 @@ obj-y += trampoline.o
obj-y += traps.o
obj-y += usercopy.o
obj-y += x86_emulate.o
+obj-y += machine_kexec.o
ifneq ($(pae),n)
obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
--- x/xen/arch/x86/dom0_ops.c
+++ x/xen/arch/x86/dom0_ops.c
@@ -29,6 +29,9 @@
#include <asm/mtrr.h>
#include "cpu/mtrr/mtrr.h"
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
#define TRC_DOM0OP_ENTER_BASE 0x00020000
#define TRC_DOM0OP_LEAVE_BASE 0x00030000
--- /dev/null
+++ x/xen/arch/x86/machine_kexec.c
@@ -0,0 +1,28 @@
+/******************************************************************************
+ * arch/x86/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ */
+
+#include <xen/types.h>
+#include <public/kexec.h>
+
+int machine_kexec_prepare(struct kexec_arg *arg)
+{
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kexec_arg *arg)
+{
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/setup.c
+++ x/xen/arch/x86/setup.c
@@ -38,6 +38,11 @@ static unsigned int opt_xenheap_megabyte
integer_param("xenheap_megabytes", opt_xenheap_megabytes);
#endif
+unsigned int opt_kdump_megabytes = 0;
+integer_param("kdump_megabytes", opt_kdump_megabytes);
+unsigned int opt_kdump_megabytes_base = 0;
+integer_param("kdump_megabytes_base", opt_kdump_megabytes_base);
+
/* opt_nosmp: If true, secondary processors are ignored. */
static int opt_nosmp = 0;
boolean_param("nosmp", opt_nosmp);
@@ -192,6 +197,20 @@ static void percpu_free_unused_areas(voi
__pa(__per_cpu_end));
}
+void __init move_memory(unsigned long dst,
+ unsigned long src_start, unsigned long src_end)
+{
+#if defined(CONFIG_X86_32)
+ memmove((void *)dst, /* use low mapping */
+ (void *)src_start, /* use low mapping */
+ src_end - src_start);
+#elif defined(CONFIG_X86_64)
+ memmove(__va(dst),
+ __va(src_start),
+ src_end - src_start);
+#endif
+}
+
void __init __start_xen(multiboot_info_t *mbi)
{
char __cmdline[] = "", *cmdline = __cmdline;
@@ -327,15 +346,8 @@ void __init __start_xen(multiboot_info_t
initial_images_start = xenheap_phys_end;
initial_images_end = initial_images_start + modules_length;
-#if defined(CONFIG_X86_32)
- memmove((void *)initial_images_start, /* use low mapping */
- (void *)mod[0].mod_start, /* use low mapping */
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#elif defined(CONFIG_X86_64)
- memmove(__va(initial_images_start),
- __va(mod[0].mod_start),
- mod[mbi->mods_count-1].mod_end - mod[0].mod_start);
-#endif
+ move_memory(initial_images_start,
+ mod[0].mod_start, mod[mbi->mods_count-1].mod_end);
/* Initialise boot-time allocator with all RAM situated after modules. */
xenheap_phys_start = init_boot_allocator(__pa(&_end));
@@ -383,6 +395,51 @@ void __init __start_xen(multiboot_info_t
#endif
}
+ if (opt_kdump_megabytes) {
+ unsigned long kdump_start, kdump_size, k;
+
+ /* mark images pages as free for now */
+
+ init_boot_pages(initial_images_start, initial_images_end);
+
+ kdump_start = opt_kdump_megabytes_base << 20;
+ kdump_size = opt_kdump_megabytes << 20;
+
+ printk("Kdump: %luMB (%lukB) at 0x%lx\n",
+ kdump_size >> 20,
+ kdump_size >> 10,
+ kdump_start);
+
+ if ((kdump_start & ~PAGE_MASK) || (kdump_size & ~PAGE_MASK))
+ panic("Kdump parameters not page aligned\n");
+
+ kdump_start >>= PAGE_SHIFT;
+ kdump_size >>= PAGE_SHIFT;
+
+ /* allocate pages for Kdump memory area */
+
+ k = alloc_boot_pages_at(kdump_size, kdump_start);
+
+ if (k != kdump_start)
+ panic("Unable to reserve Kdump memory\n");
+
+ /* allocate pages for relocated initial images */
+
+ k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0;
+ k += (initial_images_end - initial_images_start) >> PAGE_SHIFT;
+
+ k = alloc_boot_pages(k, 1);
+
+ if (!k)
+ panic("Unable to allocate initial images memory\n");
+
+ move_memory(k << PAGE_SHIFT, initial_images_start, initial_images_end);
+
+ initial_images_end -= initial_images_start;
+ initial_images_start = k << PAGE_SHIFT;
+ initial_images_end += initial_images_start;
+ }
+
memguard_init();
printk("System RAM: %luMB (%lukB)\n",
--- x/xen/arch/x86/x86_32/Makefile
+++ x/xen/arch/x86/x86_32/Makefile
@@ -3,5 +3,6 @@ obj-y += entry.o
obj-y += mm.o
obj-y += seg_fixup.o
obj-y += traps.o
+obj-y += machine_kexec.o
obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
--- x/xen/arch/x86/x86_32/entry.S
+++ x/xen/arch/x86/x86_32/entry.S
@@ -648,6 +648,7 @@ ENTRY(hypercall_table)
.long do_xenoprof_op
.long do_event_channel_op
.long do_physdev_op
+ .long do_kexec
.rept NR_hypercalls-((.-hypercall_table)/4)
.long do_ni_hypercall
.endr
@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table)
.byte 2 /* do_xenoprof_op */
.byte 2 /* do_event_channel_op */
.byte 2 /* do_physdev_op */
+ .byte 2 /* do_kexec */
.rept NR_hypercalls-(.-hypercall_args_table)
.byte 0 /* do_ni_hypercall */
.endr
--- /dev/null
+++ x/xen/arch/x86/x86_32/machine_kexec.c
@@ -0,0 +1,205 @@
+/******************************************************************************
+ * arch/x86/x86_32/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/domain_page.h>
+#include <xen/timer.h>
+#include <xen/sched.h>
+#include <xen/reboot.h>
+#include <xen/console.h>
+#include <asm/page.h>
+#include <asm/flushtlb.h>
+#include <public/kexec.h>
+
+static void __machine_kexec(struct kexec_arg *arg);
+
+typedef asmlinkage void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae);
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#ifndef CONFIG_X86_PAE
+
+static u32 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long mfn;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level2 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ write_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level2);
+}
+
+#else
+static u64 pgtable_level1[L1_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+static u64 pgtable_level2[L2_PAGETABLE_ENTRIES] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ int mfn;
+ intpte_t *pgtable_level3;
+
+ /* Find the current page table */
+ mfn = read_cr3() >> PAGE_SHIFT;
+ pgtable_level3 = map_domain_page(mfn);
+
+ /* Identity map the page table entry */
+ pgtable_level1[l1_table_offset(address)] = address | L0_ATTR;
+ pgtable_level2[l2_table_offset(address)] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[l3_table_offset(address)],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(mfn << PAGE_SHIFT);
+
+ unmap_domain_page(pgtable_level3);
+}
+#endif
+
+static void kexec_load_segments(void)
+{
+#define __SSTR(X) #X
+#define SSTR(X) __SSTR(X)
+ __asm__ __volatile__ (
+ "\tljmp $"SSTR(__HYPERVISOR_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"SSTR(__HYPERVISOR_DS)",%%eax\n"
+ "\tmovl %%eax,%%ds\n"
+ "\tmovl %%eax,%%es\n"
+ "\tmovl %%eax,%%fs\n"
+ "\tmovl %%eax,%%gs\n"
+ "\tmovl %%eax,%%ss\n"
+ ::: "eax", "memory");
+#undef SSTR
+#undef __SSTR
+}
+
+#define kexec_load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+static void kexec_set_idt(void *newidt, __u16 limit)
+{
+ struct Xgt_desc_struct curidt;
+
+ /* ia32 supports unaliged loads & stores */
+ curidt.size = limit;
+ curidt.address = (unsigned long)newidt;
+
+ kexec_load_idt(&curidt);
+
+};
+
+#define kexec_load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+static void kexec_set_gdt(void *newgdt, __u16 limit)
+{
+ struct Xgt_desc_struct curgdt;
+
+ /* ia32 supports unaligned loads & stores */
+ curgdt.size = limit;
+ curgdt.address = (unsigned long)newgdt;
+
+ kexec_load_gdt(&curgdt);
+};
+
+static void __machine_shutdown(void *data)
+{
+ struct kexec_arg *arg = (struct kexec_arg *)data;
+
+ printk("__machine_shutdown: cpu=%u\n", smp_processor_id());
+
+ watchdog_disable();
+ console_start_sync();
+
+ smp_send_stop();
+
+#ifdef CONFIG_X86_IO_APIC
+ disable_IO_APIC();
+#endif
+
+ __machine_kexec(arg);
+}
+
+void machine_shutdown(struct kexec_arg *arg)
+{
+ int reboot_cpu_id;
+ cpumask_t reboot_cpu;
+
+
+ reboot_cpu_id = 0;
+
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map))
+ reboot_cpu_id = smp_processor_id();
+
+ if (reboot_cpu_id != smp_processor_id()) {
+ cpus_clear(reboot_cpu);
+ cpu_set(reboot_cpu_id, reboot_cpu);
+ on_selected_cpus(reboot_cpu, __machine_shutdown, arg, 1, 0);
+ for (;;)
+ ; /* nothing */
+ }
+ else
+ __machine_shutdown(arg);
+ BUG();
+}
+
+static void __machine_kexec(struct kexec_arg *arg)
+{
+ relocate_new_kernel_t rnk;
+
+ local_irq_disable();
+
+ identity_map_page(arg->u.kexec.reboot_code_buffer);
+
+ copy_from_user((void *)arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.relocate_new_kernel,
+ arg->u.kexec.relocate_new_kernel_size);
+
+ kexec_load_segments();
+ kexec_set_gdt(__va(0),0);
+ kexec_set_idt(__va(0),0);
+
+ rnk = (relocate_new_kernel_t) arg->u.kexec.reboot_code_buffer;
+ (*rnk)(arg->u.kexec.indirection_page, arg->u.kexec.reboot_code_buffer,
+ arg->u.kexec.start_address, cpu_has_pae);
+}
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ machine_shutdown(arg);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/arch/x86/x86_64/Makefile
+++ x/xen/arch/x86/x86_64/Makefile
@@ -1,3 +1,4 @@
obj-y += entry.o
obj-y += mm.o
obj-y += traps.o
+obj-y += machine_kexec.o
--- /dev/null
+++ x/xen/arch/x86/x86_64/machine_kexec.c
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * arch/x86/x86_64/machine_kexec.c
+ *
+ * Created By: Horms
+ *
+ * Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16
+ */
+
+#include <xen/types.h>
+#include <public/kexec.h>
+
+void machine_kexec(struct kexec_arg *arg)
+{
+ printk("machine_kexec: not implemented\n");
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/common/Makefile
+++ x/xen/common/Makefile
@@ -7,6 +7,7 @@ obj-y += event_channel.o
obj-y += grant_table.o
obj-y += kernel.o
obj-y += keyhandler.o
+obj-y += kexec.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.o
--- /dev/null
+++ x/xen/common/kexec.c
@@ -0,0 +1,73 @@
+/*
+ * Achitecture independent kexec code for Xen
+ *
+ * At this statge, just a switch for the kexec hypercall into
+ * architecture dependent code.
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/guest_access.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+#include <public/kexec.h>
+
+extern int machine_kexec_prepare(struct kexec_arg *arg);
+extern void machine_kexec_cleanup(struct kexec_arg *arg);
+extern void machine_kexec(struct kexec_arg *arg);
+
+extern unsigned int opt_kdump_megabytes;
+extern unsigned int opt_kdump_megabytes_base;
+
+int do_kexec(unsigned long op,
+ XEN_GUEST_HANDLE(kexec_arg_t) uarg)
+{
+ struct kexec_arg arg;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if (op == KEXEC_CMD_reserve)
+ {
+ arg.u.reserve.size = opt_kdump_megabytes << 20;
+ arg.u.reserve.start = opt_kdump_megabytes_base << 20;
+ if ( unlikely(copy_to_guest(uarg, &arg, 1) != 0) )
+ {
+ printk("do_kexec: copy_to_guest failed");
+ return -EFAULT;
+ }
+ return 0;
+ }
+
+ if ( unlikely(copy_from_guest(&arg, uarg, 1) != 0) )
+ {
+ printk("do_kexec: __copy_from_guest failed");
+ return -EFAULT;
+ }
+
+ switch(op) {
+ case KEXEC_CMD_kexec:
+ machine_kexec(&arg);
+ return -EINVAL; /* Not Reached */
+ case KEXEC_CMD_kexec_prepare:
+ return machine_kexec_prepare(&arg);
+ case KEXEC_CMD_kexec_cleanup:
+ machine_kexec_cleanup(&arg);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
--- x/xen/common/page_alloc.c
+++ x/xen/common/page_alloc.c
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t
}
}
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at)
+{
+ unsigned long i;
+
+ for ( i = 0; i < nr_pfns; i++ )
+ if ( allocated_in_map(pfn_at + i) )
+ break;
+
+ if ( i == nr_pfns )
+ {
+ map_alloc(pfn_at, nr_pfns);
+ return pfn_at;
+ }
+
+ return 0;
+}
+
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
{
- unsigned long pg, i;
+ unsigned long pg, i = 0;
for ( pg = 0; (pg + nr_pfns) < max_page; pg += pfn_align )
{
- for ( i = 0; i < nr_pfns; i++ )
- if ( allocated_in_map(pg + i) )
- break;
-
- if ( i == nr_pfns )
- {
- map_alloc(pg, nr_pfns);
- return pg;
- }
+ i = alloc_boot_pages_at(nr_pfns, pg);
+ if (i != 0)
+ break;
}
- return 0;
+ return i;
}
--- x/xen/include/asm-x86/hypercall.h
+++ x/xen/include/asm-x86/hypercall.h
@@ -6,6 +6,8 @@
#define __ASM_X86_HYPERCALL_H__
#include <public/physdev.h>
+#include <xen/types.h>
+#include <public/kexec.h>
extern long
do_event_channel_op_compat(
@@ -87,6 +89,10 @@ extern long
arch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg);
+extern int
+do_kexec(
+ unsigned long op, XEN_GUEST_HANDLE(kexec_arg_t) uarg);
+
#ifdef __x86_64__
extern long
--- /dev/null
+++ x/xen/include/public/kexec.h
@@ -0,0 +1,45 @@
+/*
+ * kexec.h: Xen kexec public
+ *
+ * Created By: Horms <[email protected]>
+ */
+
+#ifndef _XEN_PUBLIC_KEXEC_H
+#define _XEN_PUBLIC_KEXEC_H
+
+#include "xen.h"
+
+/*
+ * Scratch space for passing arguments to the kexec hypercall
+ */
+typedef struct kexec_arg {
+ union {
+ struct {
+ unsigned long data; /* Not sure what this should be yet */
+ } helper;
+ struct {
+ unsigned long indirection_page;
+ unsigned long reboot_code_buffer;
+ unsigned long start_address;
+ const char *relocate_new_kernel;
+ unsigned int relocate_new_kernel_size;
+ } kexec;
+ struct {
+ unsigned long size;
+ unsigned long start;
+ } reserve;
+ } u;
+} kexec_arg_t;
+DEFINE_XEN_GUEST_HANDLE(kexec_arg_t);
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--- x/xen/include/public/xen.h
+++ x/xen/include/public/xen.h
@@ -64,6 +64,7 @@
#define __HYPERVISOR_xenoprof_op 31
#define __HYPERVISOR_event_channel_op 32
#define __HYPERVISOR_physdev_op 33
+#define __HYPERVISOR_kexec_op 34
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
@@ -238,6 +239,14 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
#define VMASST_TYPE_writable_pagetables 2
#define MAX_VMASST_TYPE 2
+/*
+ * Operations for kexec.
+ */
+#define KEXEC_CMD_kexec 0
+#define KEXEC_CMD_kexec_prepare 1
+#define KEXEC_CMD_kexec_cleanup 2
+#define KEXEC_CMD_reserve 3
+
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
--- x/xen/include/xen/mm.h
+++ x/xen/include/xen/mm.h
@@ -40,6 +40,7 @@ struct page_info;
paddr_t init_boot_allocator(paddr_t bitmap_start);
void init_boot_pages(paddr_t ps, paddr_t pe);
unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
+unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at);
void end_boot_allocator(void);
/* Generic allocator. These functions are *not* interrupt-safe. */
--- /dev/null 2006-05-09 15:32:30.399072192 +0900
+++ x/patches/linux-2.6.16.13/kexec.patch 2006-05-09 18:03:46.000000000 +0900
@@ -0,0 +1,175 @@
+--- x/drivers/base/cpu.c
++++ x/drivers/base/cpu.c
+@@ -101,7 +101,11 @@ static ssize_t show_crash_notes(struct s
+ * boot up and this data does not change there after. Hence this
+ * operation should be safe. No locking required.
+ */
++#ifndef CONFIG_XEN
+ addr = __pa(per_cpu_ptr(crash_notes, cpunum));
++#else
++ addr = virt_to_machine(per_cpu_ptr(crash_notes, cpunum));
++#endif
+ rc = sprintf(buf, "%Lx\n", addr);
+ return rc;
+ }
+--- x/kernel/kexec.c
++++ x/kernel/kexec.c
+@@ -38,6 +38,20 @@ struct resource crashk_res = {
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+ };
+
++/* Kexec needs to know about the actually physical addresss.
++ * But in xen, a physical address is a pseudo-physical addresss. */
++#ifndef CONFIG_XEN
++#define kexec_page_to_pfn(page) page_to_pfn(page)
++#define kexec_pfn_to_page(pfn) pfn_to_page(pfn)
++#define kexec_virt_to_phys(addr) virt_to_phys(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(addr)
++#else
++#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page))
++#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn))
++#define kexec_virt_to_phys(addr) virt_to_machine(addr)
++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
++#endif
++
+ int kexec_should_crash(struct task_struct *p)
+ {
+ if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+@@ -403,7 +417,7 @@ static struct page *kimage_alloc_normal_
+ pages = kimage_alloc_pages(GFP_KERNEL, order);
+ if (!pages)
+ break;
+- pfn = page_to_pfn(pages);
++ pfn = kexec_page_to_pfn(pages);
+ epfn = pfn + count;
+ addr = pfn << PAGE_SHIFT;
+ eaddr = epfn << PAGE_SHIFT;
+@@ -437,6 +451,7 @@ static struct page *kimage_alloc_normal_
+ return pages;
+ }
+
++#ifndef CONFIG_XEN
+ static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+ unsigned int order)
+ {
+@@ -490,7 +505,7 @@ static struct page *kimage_alloc_crash_c
+ }
+ /* If I don't overlap any segments I have found my hole! */
+ if (i == image->nr_segments) {
+- pages = pfn_to_page(hole_start >> PAGE_SHIFT);
++ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
+ break;
+ }
+ }
+@@ -517,6 +532,13 @@ struct page *kimage_alloc_control_pages(
+
+ return pages;
+ }
++#else /* !CONFIG_XEN */
++struct page *kimage_alloc_control_pages(struct kimage *image,
++ unsigned int order)
++{
++ return kimage_alloc_normal_control_pages(image, order);
++}
++#endif
+
+ static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+ {
+@@ -532,7 +554,7 @@ static int kimage_add_entry(struct kimag
+ return -ENOMEM;
+
+ ind_page = page_address(page);
+- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
++ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
+ image->entry = ind_page;
+ image->last_entry = ind_page +
+ ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+@@ -593,13 +615,13 @@ static int kimage_terminate(struct kimag
+ #define for_each_kimage_entry(image, ptr, entry) \
+ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+ ptr = (entry & IND_INDIRECTION)? \
+- phys_to_virt((entry & PAGE_MASK)): ptr +1)
++ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
+
+ static void kimage_free_entry(kimage_entry_t entry)
+ {
+ struct page *page;
+
+- page = pfn_to_page(entry >> PAGE_SHIFT);
++ page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
+ kimage_free_pages(page);
+ }
+
+@@ -686,7 +708,7 @@ static struct page *kimage_alloc_page(st
+ * have a match.
+ */
+ list_for_each_entry(page, &image->dest_pages, lru) {
+- addr = page_to_pfn(page) << PAGE_SHIFT;
++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+ if (addr == destination) {
+ list_del(&page->lru);
+ return page;
+@@ -701,12 +723,12 @@ static struct page *kimage_alloc_page(st
+ if (!page)
+ return NULL;
+ /* If the page cannot be used file it away */
+- if (page_to_pfn(page) >
++ if (kexec_page_to_pfn(page) >
+ (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+ list_add(&page->lru, &image->unuseable_pages);
+ continue;
+ }
+- addr = page_to_pfn(page) << PAGE_SHIFT;
++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+
+ /* If it is the destination page we want use it */
+ if (addr == destination)
+@@ -729,7 +751,7 @@ static struct page *kimage_alloc_page(st
+ struct page *old_page;
+
+ old_addr = *old & PAGE_MASK;
+- old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
++ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
+ copy_highpage(page, old_page);
+ *old = addr | (*old & ~PAGE_MASK);
+
+@@ -779,7 +801,7 @@ static int kimage_load_normal_segment(st
+ result = -ENOMEM;
+ goto out;
+ }
+- result = kimage_add_page(image, page_to_pfn(page)
++ result = kimage_add_page(image, kexec_page_to_pfn(page)
+ << PAGE_SHIFT);
+ if (result < 0)
+ goto out;
+@@ -811,6 +833,7 @@ out:
+ return result;
+ }
+
++#ifndef CONFIG_XEN
+ static int kimage_load_crash_segment(struct kimage *image,
+ struct kexec_segment *segment)
+ {
+@@ -833,7 +856,7 @@ static int kimage_load_crash_segment(str
+ char *ptr;
+ size_t uchunk, mchunk;
+
+- page = pfn_to_page(maddr >> PAGE_SHIFT);
++ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
+ if (page == 0) {
+ result = -ENOMEM;
+ goto out;
+@@ -881,6 +904,13 @@ static int kimage_load_segment(struct ki
+
+ return result;
+ }
++#else /* CONFIG_XEN */
++static int kimage_load_segment(struct kimage *image,
++ struct kexec_segment *segment)
++{
++ return kimage_load_normal_segment(image, segment);
++}
++#endif
+
+ /*
+ * Exec Kernel system call: for obvious reasons only root may call it.Re: [PATCH]: kexec: framework and i386 (Take VIII)
Quoted 11 lines
Quoted 7 lines
Hi Takebe-san,
here is an updated version of the patch which moves portions into patches/linux-2.6.16/ as you suggested. It also moves to xen-unstable 9969 / Linux 2.6.16.13 and has some minor build fixes, for problems that crept into the previous patch.
Sorry, this mornin's patch had the internal patch in the wrong location and with the wrong diff level.
Hi, Horms
Thank you for sending your new patch.
This patch is good compilation. :)
I try and repot soon.
Best Regards
Akio Takebe
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Hi, Keir
I tried Horms's kexec patch and Kazuo's tools.
And I could get coredump of dom0!
By using this feature, we can debug dom0 with gdbserver-xen to the same way as domU.
I think that this is very useful.
Xen don't have dump feature yet,
and this feature don't affect performace, stability, and so on. We think this feature is necessary for trouble-shooting xen.
Could Keir apply this feature?
or more comments?
Best Regards,
Akio Takebe
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Quoted 11 lines · Akio Takebe
I tried Horms's kexec patch and Kazuo's tools.
And I could get coredump of dom0!
By using this feature, we can debug dom0 with gdbserver-xen to the same way as domU.
I think that this is very useful.
Xen don't have dump feature yet,
and this feature don't affect performace, stability, and so on. We think this feature is necessary for trouble-shooting xen.Could Keir apply this feature?
or more comments?
Can it kexec to Xen yet?
-- Keir
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Hi,
No, it can kexec only to kdump kernel.
I think we need to update kexec-tools for kexecing Xen. (e.g. to load xen,dom0 and initrd)
Am I right, Horms?
But this feature is good as coredump feature.
Even if cannot kexec to Xen, I believe this is important feature.
Best Regards,
Akio Takebe
Quoted 24 lines · Akio Takebe
Quoted 10 lines
I tried Horms's kexec patch and Kazuo's tools.
And I could get coredump of dom0!
By using this feature, we can debug dom0 with gdbserver-xen to the same way as domU.
I think that this is very useful.
Xen don't have dump feature yet,
and this feature don't affect performace, stability, and so on. We think this feature is necessary for trouble-shooting xen.Quoted 2 lines
Could Keir apply this feature?
or more comments?Can it kexec to Xen yet?
-- Keir
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Quoted 4 lines · Akio Takebe
No, it can kexec only to kdump kernel.
I think we need to update kexec-tools for kexecing Xen. (e.g. to load xen,dom0 and initrd)
Am I right, Horms?
kexec-tools support multiboot format these days. So if kexec is added to Xen then we should support kexec'ing to Xen, or we need a good explanation why we can't.
-- Keir
Quoted 2 lines
But this feature is good as coredump feature.
Even if cannot kexec to Xen, I believe this is important feature.
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Quoted 11 lines · Keir Fraser
Quoted 4 lines · Akio Takebe
No, it can kexec only to kdump kernel.
I think we need to update kexec-tools for kexecing Xen. (e.g. to load xen,dom0 and initrd)
Am I right, Horms?kexec-tools support multiboot format these days. So if kexec is added to Xen then we should support kexec'ing to Xen, or we need a good explanation why we can't.
No it can't kexec into xen yet. I haven't looked into this in depth but I suspect that kexec-tools needs to be updated as Takebe-san suggests. As you mention kexec-tools does support multiboot so I suspect that it is not much work. I will look into it and get back to you. I take it that you would like this to be working before merging?
In semi-related news, I will post an updated version of the patch in the next day or so. This is able to capture all of xen's CPUs on kdump and kdump on xen crash. This means that feature-wise in terms of xen/kernel code the x86_32 port is pretty much complete. I would be really excited to get this merged so more eyes can go over the code and we can get some good feedback and testing.
My colleague Magnus has x86_64 port is well under way, however we are having a few problems relating to the approach he has taken to page table handling on kexec. I am hoping to take a crack at ia64 in the near future, though I suspect that x86_32 bug fixes and other merge-related work will delay that a little.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
Re: Re: [PATCH]: kexec: framework and i386 (Take VIII)
Quoted 9 lines · Horms
Quoted 8 lines · Keir Fraser
Quoted 4 lines · Akio Takebe
No, it can kexec only to kdump kernel.
I think we need to update kexec-tools for kexecing Xen. (e.g. to load xen,dom0 and initrd)
Am I right, Horms?
Quoted 5 lines
Quoted 3 lines
kexec-tools support multiboot format these days. So if kexec is added to Xen then we should support kexec'ing to Xen, or we need a good explanation why we can't.
No it can't kexec into xen yet.
I'm happy to report that with some more testing, as long as kexec-tool is compiled with zlib support I can kexec linux->xen and xen->xen. Actually, zlib might not be neccessary if both xen and linux are uncompressed. In any case, for reference, here is a kexec command line that works for me.
kexec -l -t multiboot-x86 --append="console=com1 sync_console conswitch=bb com1=115200,8n1,0x3f8 dom0_mem=48000" /root/xen --module="/root/vmlinuz-xen root=/dev/hda1 ro console=ttyS0,115200 clock=pit ip=on apm=power-off" --module=/tmp/initramfs_data.cpio
I will post an updated patch today or tomorrow and at that time I will outline the immediate targets for further development. For now, I'd like to ask that you don't merge what I have posted, as there are some invasive changes coming up with regards to page table handling, but I sould be able to provide a patch that includes those changes within the next week as the code is already done, it just needs to be cleaned up a bit and merged with the kexec patch.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
Re: Re: [PATCH]: kexec: framework and i386 (Take IX)
Hi,
as promised earlier in the day, here is an update on the kexec/kdump patch. The main changes are that SMP now works, and the dumping of cpu registers for kdump has been moved into the hypervisor so as to allow all CPUs to be captured, not just dom0's VCPUs.
Also, as mentioned earlier in the day linux->xen and xen->xen kexec does work, contrary to what I previously reported.
I have also broken the patch out into generic, x86 and x86_32 patches which need to be applied in that order. This was done to allow other architectures to be worked on more easily. By that, I mean it makes it easier for my colleagues and I to work together. It should also make it easier to review the code. If a monolithic patch is desired please let me know as it is very easy for me to produce one.
I hope to make the next round available within the next few (working) days. This will change page table handling around a bit (only for kexec/kdump not for the rest of the time) so as to avoid trampling the page tables, which is a problem for kdump as it destroys data that might otherwise be analysed. My colleague Magnus Damm is working on having his approach addoped by Linux kdump.
Beyond that, Magnus has also been working on a x86_64 port, though that is not quite working. And I plan to start on ia64 soon.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 48 ++ linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 100 ++++++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 27 + patches/linux-2.6.16.13/kexec.patch | 274 +++++++++++++++++ xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 + xen/arch/x86/machine_kexec.c | 51 +++ xen/common/Makefile | 1 xen/common/kexec.c | 183 +++++++++++ xen/common/page_alloc.c | 33 +- xen/drivers/char/console.c | 3 xen/include/asm-x86/kexec.h | 32 + xen/include/public/kexec.h | 48 ++ xen/include/public/xen.h | 12 xen/include/xen/elfcore.h | 73 ++++ xen/include/xen/kexec.h | 33 ++ xen/include/xen/mm.h | 1 19 files changed, 941 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -9,3 +9,4 @@ obj-$(CONFIG_NET) += skbuff.o obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +48 -0
48 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +100 -0
100 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -66,6 +66,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +27 -0
@@ -0,0 +1,27 @@ +/* +* include/asm-i386/kexec-xen.h +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _I386_KEXEC_XEN_H +#define _I386_KEXEC_XEN_H + +static inline void crash_translate_regs (struct pt_regs *linux_regs, +struct cpu_user_regs *xen_regs) +{ +printk ("STUB: include/asm-i386/kexec-xen.h: crash_translate_regs: " +"not implemented\n" ); +} + +#endif /* _I386_KEXEC_XEN_H */ + +/* +* Local variables: +* c-file-style: "linux" +* indent-tabs-mode: t +* c-indent-level: 8 +* c-basic-offset: 8 +* tab-width: 8 +* End: +*/
xen/arch/x86/Makefile +2 -0
@@ -39,6 +39,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o ifneq ($(pae),n) obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: arch/x86/crash.c: machine_crash_shutdown: not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +51 -0
51 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +183 -0
183 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -677,6 +677,7 @@ void panic(const char *fmt, ...)unsigned long flags;static spinlock_t lock =SPIN_LOCK_UNLOCKED ;extern void machine_restart (char *); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -696,6 +697,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +watchdog_disable ();mdelay (5000 );machine_restart (0 );
xen/include/asm-x86/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " +"not implemented\n" ); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +48 -0
48 lines not on this page · raw message
xen/include/public/xen.h +12 -0
@@ -64,6 +64,7 @@#define __HYPERVISOR_xenoprof_op 31#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_kexec_op 34/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48
@@ -238,6 +239,17 @@ DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);#define VMASST_TYPE_writable_pagetables 2#define MAX_VMASST_TYPE 2 +/* +* Operations for kexec. +*/ +#define KEXEC_CMD_kexec 0 +#define KEXEC_CMD_kexec_prepare 1 +#define KEXEC_CMD_kexec_cleanup 2 +#define KEXEC_CMD_kexec_load 3 +#define KEXEC_CMD_kexec_unload 4 +#define KEXEC_CMD_kexec_reserve 5 +#define KEXEC_CMD_kexec_crash_note 6 +#ifndef __ASSEMBLY__typedef uint16_t domid_t ;
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_prepare (int type,struct kexec_arg *arg); +void machine_kexec_cleanup (int type,struct kexec_arg *arg); +void machine_kexec_reserved (struct kexec_arg *arg); +void machine_kexec (struct kexec_arg *arg); +void machine_shutdown (struct kexec_arg *arg); +void machine_crash_shutdown (struct cpu_user_regs *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/kexec.patch new file +274 -0
274 lines not on this page · raw message
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
xen/arch/x86/crash.c | 171 ++++++++++++++++++++++++++++++++++- xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 58 +++++++++-- xen/arch/x86/setup.c | 75 +++++++++++++-- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 27 +++++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 28 +++++ xen/common/kexec.c | 3 xen/include/asm-x86/elf.h | 27 +++++ xen/include/asm-x86/hypercall.h | 6 + xen/include/asm-x86/kexec.h | 14 +- xen/include/asm-x86/x86_32/elf.h | 30 ++++++ xen/include/asm-x86/x86_32/kexec.h | 51 ++++++++++ xen/include/asm-x86/x86_64/elf.h | 30 ++++++ xen/include/asm-x86/x86_64/kexec.h | 50 ++++++++++ 16 files changed, 542 insertions(+), 33 deletions(-)
xen/arch/x86/crash.c +168 -3
184 lines not on this page · raw message
xen/arch/x86/dom0_ops.c +3 -0
@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000
xen/arch/x86/machine_kexec.c +45 -13
84 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (struct kexec_arg *arg) +{ +printk ("STUB: arch/x86/x86_32/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +28 -0
@@ -0,0 +1,28 @@ +/* +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stubs */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (struct kexec_arg *arg) +{ +printk ("STUB: arch/x86/x86_64/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/common/kexec.c +2 -1
@@ -99,7 +99,8 @@ int do_kexec(unsigned long op, int type,case KEXEC_CMD_kexec_crash_note:return get_crash_note (uarg);case KEXEC_CMD_kexec_reserve: -machine_kexec_reserved (&tmp_arg); + tmp_arg.u.reserve.size = opt_kdump_megabytes <<20 ; + tmp_arg.u.reserve.start = opt_kdump_megabytes_base <<20 ;if (unlikely (copy_to_guest (uarg, &tmp_arg,1 ) !=0 ) ) {printk ("do_kexec (CMD_kexec_reserve): copy_to_guest failed\n" );
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/hypercall.h +6 -0
@@ -6,6 +6,8 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> +#include <public/kexec.h> extern long do_event_channel_op_compat(
@@ -87,6 +89,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,XEN_GUEST_HANDLE (kexec_arg_t) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -7
@@ -8,16 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " -"not implemented\n" ); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +51 -0
51 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_64/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +50 -0
50 lines not on this page · raw message
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 1 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 25 + linux-2.6-xen-sparse/drivers/xen/core/crash.c | 2 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 19 + linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10 patches/linux-2.6.16.13/kexec-x86_32.patch | 12 xen/arch/x86/machine_kexec.c | 6 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 143 +++++++++- xen/include/asm-x86/x86_32/elf.h | 34 +- xen/include/asm-x86/x86_32/kexec.h | 68 +++- xen/include/xen/kexec.h | 1 14 files changed, 281 insertions(+), 46 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +1 -0
@@ -184,6 +184,7 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o machine_kexec.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +25 -0
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -932,6 +936,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -942,6 +947,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +struct kexec_arg xen_kexec_arg; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &xen_kexec_arg)); +if (xen_kexec_arg.u.reserve.size) { + crashk_res.start = xen_kexec_arg.u.reserve.start; + crashk_res.end = xen_kexec_arg.u.reserve.start + + xen_kexec_arg.u.reserve.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1395,6 +1417,9 @@ legacy_init_iomem_resources(struct resou res->end = map[i].end -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif }free_bootmem (__pa (map),PAGE_SIZE );
linux-2.6-xen-sparse/drivers/xen/core/crash.c +1 -1
@@ -1,5 +1,5 @@/* -* Architecture independent functions for kexec based crash dumps in xen. +* Architecture specific (i386-xen) functions for kexec based crash dumps. * * Created by: Horms <[email protected]> *
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h +17 -2
@@ -7,11 +7,26 @@#ifndef _I386_KEXEC_XEN_H#define _I386_KEXEC_XEN_H +#include <asm/ptrace.h> +#include <asm/types.h> +#include <xen/interface/arch-x86_32.h> +static inline void crash_translate_regs (struct pt_regs *linux_regs,struct cpu_user_regs *xen_regs) { -printk ("STUB: include/asm-i386/kexec-xen.h: crash_translate_regs: " -"not implemented\n" ); + xen_regs->ebx = linux_regs->ebx; + xen_regs->ecx = linux_regs->ecx; + xen_regs->edx = linux_regs->edx; + xen_regs->esi = linux_regs->esi; + xen_regs->edi = linux_regs->edi; + xen_regs->ebp = linux_regs->ebp; + xen_regs->eax = linux_regs->eax; + xen_regs->esp = linux_regs->esp; + xen_regs->ss = linux_regs->xss; + xen_regs->cs = linux_regs->xcs; + xen_regs->ds = linux_regs->xds; + xen_regs->es = linux_regs->xes; + xen_regs->eflags = linux_regs->eflags; }#endif /* _I386_KEXEC_XEN_H */
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +10 -0
@@ -39,6 +39,8 @@# error "please don't include this file directly"#endif +#include <xen/interface/kexec.h> +#define __STR (x) #x#define STR (x) __STR(x)
@@ -359,6 +361,14 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,int type,kexec_arg_t * arg) +{ +return _hypercall3 (int, kexec_op, op, type, arg); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/machine_kexec.c +0 -6
@@ -25,12 +25,6 @@ void machine_kexec_cleanup(int type, str { } -void machine_kexec_reserved (struct kexec_arg *arg) -{ - arg->u.reserve.size = opt_kdump_megabytes <<20 ; - arg->u.reserve.start = opt_kdump_megabytes_base <<20 ; -} -static void __machine_shutdown (void *data) {struct kexec_arg *arg = (struct kexec_arg *)data;
xen/arch/x86/x86_32/entry.S +2 -0
@@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_xenoprof_op .long do_event_channel_op .long do_physdev_op + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +135 -8
154 lines not on this page · raw message
xen/include/asm-x86/x86_32/elf.h +27 -7
@@ -3,19 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ - "not implemented\n") - +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -19
91 lines not on this page · raw message
xen/include/xen/kexec.h +0 -1
@@ -14,7 +14,6 @@ DECLARE_PER_CPU (note_buf_t, crash_notesint machine_kexec_prepare (int type,struct kexec_arg *arg);void machine_kexec_cleanup (int type,struct kexec_arg *arg); -void machine_kexec_reserved (struct kexec_arg *arg);void machine_kexec (struct kexec_arg *arg);void machine_shutdown (struct kexec_arg *arg);void machine_crash_shutdown (struct cpu_user_regs *regs);
patches/linux-2.6.16.13/kexec-x86_32.patch new file +12 -0
@@ -0,0 +1,12 @@ +--- x/arch/i386/kernel/crash.c ++++ x/arch/i386/kernel/crash.c +@@ -175,9 +175,5 @@ void machine_crash_shutdown(struct pt_re + /* Make a note of crashing cpu. Will be used in NMI callback.*/ + crashing_cpu = smp_processor_id(); + nmi_shootdown_cpus(); +- lapic_shutdown(); +-#if defined(CONFIG_X86_IO_APIC) +- disable_IO_APIC(); +-#endif + crash_save_self(regs); + }
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: Re: [PATCH]: kexec: framework and i386 (Take IX)
Quoted 4 lines · Horms
as promised earlier in the day, here is an update on the kexec/kdump patch. The main changes are that SMP now works, and the dumping of cpu registers for kdump has been moved into the hypervisor so as to allow all CPUs to be captured, not just dom0's VCPUs.
Just looking at the generic patch:
* Define KEXEC_CMD_* in your public kexec.h header, not xen.h.
* Don't pack all the different arg structs into a union -- the union
will change in size if you ever add a bigger argument substructure, plus it's ugly. Split them out and put a comment by each KEXEC_CMD_* definition explaining what its argument parameter points at (see other header files like vcpu.h for an example).
* Can you explain the need for all the changesin your kexec.patch? I
guess there are some virt_to_phys address translations that need fixing up, but you also scatter a few hypercalls around in there (e.g., in base/cpu.c) -- can they not be handled more cleanly, or is kexec-on-xen somehow more special than kexec on any native architecture?
-- Keir
Re: Re: [PATCH]: kexec: framework and i386 (Take IX)
Quoted 8 lines · Keir Fraser
Quoted 4 lines · Horms
as promised earlier in the day, here is an update on the kexec/kdump patch. The main changes are that SMP now works, and the dumping of cpu registers for kdump has been moved into the hypervisor so as to allow all CPUs to be captured, not just dom0's VCPUs.
Quoted 12 lines
Just looking at the generic patch:
* Define KEXEC_CMD_* in your publickexec.hheader, notxen.h.
* Don't pack all the different arg structs into a union -- the union
will change in size if you ever add a bigger argument substructure, plus it's ugly. Split them out and put a comment by each KEXEC_CMD_* definition explaining what its argument parameter points at (see other header files likevcpu.hfor an example).
* Can you explain the need for all the changesin your kexec.patch? I
guess there are somevirt_to_physaddress translations that need fixing up, but you also scatter a few hypercalls around in there (e.g., inbase/cpu.c) -- can they not be handled more cleanly, or is kexec-on-xen somehow more special than kexec on any native architecture?
Hi Keir,
thanks for your suggestions, I'll address these and send a more detailed reply a little later.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
PATCH 1/1 kexec: framework and i386 (Take X)
Hi,
sorry for the somewhat long delay between sending updates. I'm happy to announce tenth take of the kexec/kdump patch. I'll address Keir's questions from the 9th release below, but first I would like to quickly summarise the patches.
Kexec/kdump is implemented by moving the privelaged portions (and related plumbing where needed) from linux into the hypervisor. This is primarily done by implementing kexec's architecture independent hooks as hypercalls.
Both Kexec is working for x86_32 and x86_64 for SMP and UP. Kdump is also working for SMP and UP on x86_32. x86_64 may work, but still needs more attention. In particular the register saving code has not been implemented.
These patches also include some reworking of kexec's internals in order that the page table is not mangled on kdump. These changes also make x86_64 kexec/kdump somewhat easier to implement. Collectively this is the pagetable_a approach developed by my colleague Magnus Damm, and he is working with the linux kexec maintainers to get it merged there.
The code is broken out into four patches. They should apply cleanly to xen-unstable.hg 10151.
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,
the basic plumbing for kexec/kdump
2. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
This would not be needed for ppc or ia64, but neither have been written yet.
We are planning to commence work on ia64 soon.
* Depends on 1
3. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump for x86_32
* Depends on 2 (and 1)
4. 51.2.31.2-kexec-x86_64-upstream.patch
* * Kexec/kdump for x86_64
* Depends on 2 (and 1)
Quoted 9 lines · Horms
Quoted 8 lines · Keir Fraser
Quoted 4 lines · Horms
as promised earlier in the day, here is an update on the kexec/kdump patch. The main changes are that SMP now works, and the dumping of cpu registers for kdump has been moved into the hypervisor so as to allow all CPUs to be captured, not just dom0's VCPUs.
Quoted 7 lines
Quoted 7 lines
Just looking at the generic patch:
* Define KEXEC_CMD_* in your publickexec.hheader, notxen.h.
* Don't pack all the different arg structs into a union -- the union
will change in size if you ever add a bigger argument substructure, plus it's ugly. Split them out and put a comment by each KEXEC_CMD_* definition explaining what its argument parameter points at (see other header files likevcpu.hfor an example).
I have changed both of these things.
Quoted 5 lines
Quoted 5 lines
* Can you explain the need for all the changesin your kexec.patch? I
guess there are somevirt_to_physaddress translations that need fixing up, but you also scatter a few hypercalls around in there (e.g., inbase/cpu.c) -- can they not be handled more cleanly, or is kexec-on-xen somehow more special than kexec on any native architecture?
Sure. There are several areas of change, I will address them one by one. If I have missed any, please let me know
* pfn vs mfn
Linux kexec works in pfns, but as kexec needs to work in real mode in Xen mfns are needed. This change should be fairly obvious, though more invasive than I would have liked.
* get_crash_notes
When a kernel is loaded for kexec or kdump part of the work is done in user-space. In particular the elf header is created in user-space and it needs to know the location of the elf notes where the registers are saved on crash dump. As only xen knows where all the CPUs the notes are handled by the hypervisor and a hypercall is used by get_crash_notes() to get the address of the notes which is exposed to userspace as required by kexec-tool.
It is worth noting that only dom0's vcpus are exposed to user space, however all CPUs notes will be written by xen. In practice I stronly suspect that a customised tool will be needed to analyise crash dumps, well the xen specific parts anyway, and such a tool should be able to find the crash notes that are not in the elf header.
Actually, I'm not really sure why the crash notes need to be in the elf header at all. In essence this code is really just there to keep kexec-tool happy and avoid having to modify it. To that end I am happy to say that neither kexec-tool nor the target kernel (crash or kexec kernel) need to be modified in order to kexec or kdump from xen.
* xen_machine_kexec_load and xen_machine_kexec_unload
It was originally hoped that the machine_kexec_prepare and machine_kexec_cleanup hooks could be used, however it turns out that the place that they are called in is not very useful for xen. Well, on x86_32 and x86_64 at least. So instead xen_machine_kexec_load and xen_machine_kexec_unload were added.
xen_machine_kexec_load loads the kernel into xen. It is at this time that all preparation is work is done. Leavking xen_machine_kexec as just a trigger. xen_machine_kexec_unload reverses the work of xen_machine_kexec_load.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 48 + linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 84 ++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch | 85 ++ patches/linux-2.6.16.13/kexec-generic.patch | 294 ++++++++++ xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 xen/arch/x86/machine_kexec.c | 51 + xen/common/Makefile | 1 xen/common/kexec.c | 188 ++++++ xen/common/page_alloc.c | 33 - xen/drivers/char/console.c | 3 xen/include/asm-x86/kexec.h | 32 + xen/include/public/kexec.h | 85 ++ xen/include/public/xen.h | 1 xen/include/xen/elfcore.h | 73 ++ xen/include/xen/kexec.h | 33 + xen/include/xen/mm.h | 1 19 files changed, 1034 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -10,3 +10,4 @@ obj-$(CONFIG_SMP) += smpboot.o obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o obj-$(CONFIG_SYSFS) += hypervisor_sysfs.o obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +48 -0
48 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +84 -0
84 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -67,6 +67,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
xen/arch/x86/Makefile +2 -0
@@ -39,6 +39,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o ifneq ($(pae),n) obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: arch/x86/crash.c: machine_crash_shutdown: not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +51 -0
51 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +188 -0
188 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -677,6 +677,7 @@ void panic(const char *fmt, ...)unsigned long flags;static spinlock_t lock =SPIN_LOCK_UNLOCKED ;extern void machine_restart (char *); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -696,6 +697,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +watchdog_disable ();mdelay (5000 );machine_restart (0 );
xen/include/asm-x86/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " +"not implemented\n" ); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +85 -0
85 lines not on this page · raw message
xen/include/public/xen.h +1 -0
@@ -64,6 +64,7 @@#define __HYPERVISOR_xenoprof_op 31#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_kexec_op 34/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_load (int type,xen_kexec_image_t *image); +void machine_kexec_unload (int type,xen_kexec_image_t *image); +void machine_kexec_reserved (xen_kexec_reserve_t *reservation); +void machine_kexec (xen_kexec_image_t *image); +void machine_shutdown (xen_kexec_image_t *image); +void machine_crash_shutdown (cpu_user_regs_t *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/kexec-generic.patch new file +294 -0
294 lines not on this page · raw message
patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch new file +85 -0
85 lines not on this page · raw message
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 14 + xen/arch/x86/crash.c | 171 ++++++++++++++++- xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 150 +++++++++++++- xen/arch/x86/setup.c | 75 ++++++- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 27 ++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 28 ++ xen/include/asm-x86/elf.h | 27 ++ xen/include/asm-x86/fixmap.h | 1 xen/include/asm-x86/hypercall.h | 5 xen/include/asm-x86/kexec.h | 14 - xen/include/asm-x86/x86_32/elf.h | 30 ++ xen/include/asm-x86/x86_32/kexec.h | 51 +++++ xen/include/asm-x86/x86_64/elf.h | 30 ++ xen/include/asm-x86/x86_64/kexec.h | 50 ++++ xen/include/public/kexec.h | 2 18 files changed, 649 insertions(+), 31 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c +14 -0
@@ -23,7 +23,21 @@ static inline unsigned long machine_addrstatic void setup_hypercall_arg (xen_kexec_image_t *xki,struct kimage *image) { +#if defined(CONFIG_X86_32 ) || defined(CONFIG_X86_64 ) +struct kimage_arch *arch = &image->arch_data; +int k, n =sizeof (arch->page_table_a) /sizeof (arch->page_table_a[0 ]); + +memset (xki,0 ,sizeof (*xki)); + +for (k =0 ; k < n; k++) + xki->page_table_a[k] =machine_address (arch->page_table_a[k]); + +#ifdef CONFIG_X86_64 + xki->page_table_b =machine_address (arch->page_table_b); +#endif +#else memset (xki,0 ,sizeof (*xki)); +#endif xki->indirection_page = image->head; xki->reboot_code_buffer =
xen/arch/x86/crash.c +168 -3
184 lines not on this page · raw message
xen/arch/x86/dom0_ops.c +3 -0
@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000
xen/arch/x86/machine_kexec.c +138 -12
176 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: arch/x86/x86_32/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +28 -0
@@ -0,0 +1,28 @@ +/* +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stubs */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: arch/x86/x86_64/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/fixmap.h +1 -0
@@ -32,6 +32,7 @@ enum fixed_addresses {FIX_ACPI_END =FIX_ACPI_BEGIN +FIX_ACPI_PAGES -1 ,FIX_HPET_BASE ,FIX_CYCLONE_TIMER , +FIX_KEXEC_PAGE , __end_of_fixed_addresses };
xen/include/asm-x86/hypercall.h +5 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> extern long do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,unsigned arg1,XEN_GUEST_HANDLE (void ) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -7
@@ -8,16 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " -"not implemented\n" ); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +51 -0
51 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_64/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +50 -0
50 lines not on this page · raw message
xen/include/public/kexec.h +2 -0
@@ -43,6 +43,8 @@*/ #define KEXEC_CMD_kexec_load 1 typedef struct xen_kexec_image { + unsigned long page_table_a[7]; + unsigned long page_table_b; unsigned long indirection_page; unsigned long reboot_code_buffer; unsigned long start_address;
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 4 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 28 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 42 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch | 457 ++++++++++ xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 28 xen/include/asm-x86/x86_32/elf.h | 34 xen/include/asm-x86/x86_32/kexec.h | 68 + 11 files changed, 635 insertions(+), 40 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +3 -1
@@ -184,10 +184,11 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 -# CONFIG_CRASH_DUMP is not set +CONFIG_CRASH_DUMP=y CONFIG_PHYSICAL_START=0x100000 CONFIG_HOTPLUG_CPU=y
@@ -2774,6 +2775,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +25 -3
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -941,6 +945,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -951,6 +956,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1320,9 +1329,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1378,6 +1400,9 @@ legacy_init_iomem_resources(struct e820e res->end = res->start + e820[i].size -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif #ifndef CONFIG_XEN if (e820[i].type ==E820_RAM ) {/*
@@ -1387,9 +1412,6 @@ legacy_init_iomem_resources(struct e820e*/ request_resource (res, code_resource); request_resource(res, data_resource); -#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); -#endif }#endif }
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +42 -0
42 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +8 -0
@@ -359,5 +359,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/x86_32/entry.S +2 -0
@@ -648,6 +648,7 @@ ENTRY(hypercall_table) .long do_xenoprof_op .long do_event_channel_op .long do_physdev_op + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -687,6 +688,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +20 -8
@@ -1,19 +1,31 @@ -/* +/****************************************************************************** * arch/x86/x86_32/machine_kexec.c -* Handle transition of Linux booting another kernel -* -* Created By: Horms <[email protected]> +* +* Created By: Horms * -* Should be losely based on arch/i386/kernel/machine_kexec.c +* Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16 */ -#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> +#include <asm/processor.h> + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long has_pae);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: arch/x86/x86_32/machine_kexec.c: machine_kexec: " -"not implemented\n" ); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + (unsigned long )cpu_has_pae); }/*
xen/include/asm-x86/x86_32/elf.h +27 -7
@@ -3,19 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ - "not implemented\n") - +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -19
91 lines not on this page · raw message
patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch new file +457 -0
457 lines not on this page · raw message
kexec: x86_64
This is the x86_64 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_64 | 2 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 26 linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h | 30 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch | 421 ++++++++++ patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch | 116 ++ xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/machine_kexec.c | 16 11 files changed, 621 insertions(+), 5 deletions(-)
buildconfigs/linux-defconfig_xen_x86_64 +2 -0
@@ -139,6 +139,8 @@ CONFIG_SWIOTLB=y CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
linux-2.6-xen-sparse/arch/x86_64/Kconfig +1 -1
@@ -433,7 +433,7 @@ config X86_MCE_AMD config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_64_XEN + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +1 -1
@@ -59,7 +59,7 @@ pci-dma-y += ../../i386/kernel/pci-dma microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o quirks-y := ../../i386/kernel/quirks-xen.o -n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o +n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o crash.o include $(srctree)/scripts/Makefile.xen
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +26 -0
@@ -79,6 +79,10 @@#include <asm/mach-xen/setup_arch_post.h> #include <xen/interface/memory.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +extern unsigned long start_pfn;extern struct edid_info edid_info;
@@ -446,6 +450,7 @@ static __init void parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -456,6 +461,10 @@ static __init void parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif
@@ -810,10 +819,23 @@ void __init setup_arch(char **cmdline_p)#endif #endif /* !CONFIG_XEN */ #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end) {reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); } +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif paging_init ();
@@ -972,6 +994,10 @@ void __init setup_arch(char **cmdline_p)iommu_hole_init ();#endif +#ifdef CONFIG_KEXEC +request_resource (&ioport_resource, &crashk_res); +#endif +#ifdef CONFIG_XEN {struct physdev_set_iopl set_iopl;
linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* include/asm-x86_64/kexec-xen.h +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _X86_64_KEXEC_XEN_H +#define _X86_64_KEXEC_XEN_H + +#include <asm/ptrace.h> +#include <asm/types.h> +#include <xen/interface/arch-x86_64.h> + +static inline void crash_translate_regs (struct pt_regs *linux_regs, +struct cpu_user_regs *xen_regs) +{ +#warning Implement me! +} + +#endif /* _X86_64_KEXEC_XEN_H */ + +/* +* Local variables: +* c-file-style: "linux" +* indent-tabs-mode: t +* c-indent-level: 8 +* c-basic-offset: 8 +* tab-width: 8 +* End: +*/
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +7 -0
@@ -360,4 +360,11 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} +#endif /* __HYPERCALL_H__ */
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h +2 -0
@@ -90,6 +90,8 @@ extern unsigned long profile_pc(struct p#define profile_pc (regs) instruction_pointer(regs)#endif +#include <linux/compiler.h> +void signal_fault (struct pt_regs *regs,void __user *frame,char *where);struct task_struct ;
xen/arch/x86/x86_64/entry.S +2 -0
@@ -556,6 +556,7 @@ ENTRY(hypercall_table) .quad do_xenoprof_op .quad do_event_channel_op .quad do_physdev_op + .quad do_kexec .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr
@@ -595,6 +596,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_64/machine_kexec.c +13 -3
@@ -7,14 +7,24 @@* Should be losely based on arch/x86_64/kernel/machine_kexec.c */ -#include <xen/lib.h> /* for printk() used in stubs */ #include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> + +typedef void (*relocate_new_kernel_t )(unsigned long indirection_page, +unsigned long control_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long page_table_b);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: arch/x86/x86_64/machine_kexec.c: machine_kexec: " -"not implemented\n" ); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + image->page_table_b); }/*
patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch new file +421 -0
122 lines not on this page · raw message
patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch new file +116 -0
116 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
Re: [PATCH] kexec: framework and i386 (Take X)
Hi, Horms
When I tried your patch, I had compile errors. If you use xchg(), you should get return value of xchg(). The above compile error occurre at the below part.
+void crash_kexec(struct cpu_user_regs *regs)
+{
+ int locked;
+
+ locked = xchg(&kexec_crash_lock, 1);
+ if (locked)
+ return;
+ __crash_kexec(regs);
+ xchg(&kexec_crash_lock, 0); <-------------this one
+}
+
+static int get_crash_note(int vcpuid, XEN_GUEST_HANDLE(void) uarg) +{
+ struct domain *domain = current->domain; + unsigned long crash_note; + struct vcpu *vcpu; + int locked;
+
+ if (vcpuid < 0 || vcpuid > MAX_VIRT_CPUS)
+ return -EINVAL;
+
+ if ( ! (vcpu = domain->vcpu[vcpuid]) )
+ return -EINVAL;
+
+ locked = xchg(&kexec_crash_lock, 1);
+ if (locked)
+ {+ printk("do_kexec: (CMD_kexec_crash_note): dump is locked\n");
+ return -EFAULT;
+ }
+ crash_note = __pa((unsigned long)per_cpu(crash_notes, vcpu->
processor));
+ xchg(&kexec_crash_lock, 0); <-------------this one
+
+ if ( unlikely(copy_to_guest(uarg, &crash_note, 1) != 0) )
+ {
+ printk("do_kexec: (CMD_kexec_crash_note): copy_to_guest failed
\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int do_kexec(unsigned long op, int arg1, XEN_GUEST_HANDLE(void) uarg) +{
+ xen_kexec_image_t *image; + int locked; + int *image_set; + int status = -EINVAL;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ switch (op)
+ {
+ case KEXEC_CMD_kexec_crash_note:+ return get_crash_note(arg1, uarg);
+ case KEXEC_CMD_kexec_reserve:
+ return get_reserve(uarg);
+ }
+
+ /* For all other ops, arg1 is the type of kexec, that is
+ * KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH */
+ if (arg1 == KEXEC_TYPE_CRASH)
+ {
+ image = &kexec_crash_image;
+ image_set = &kexec_crash_image_set;
+ locked = xchg(&kexec_crash_lock, 1);
+ if (locked)
+ {
+ printk("do_kexec: dump is locked\n");
+ return -EFAULT;
+ }
+ }
+ else
+ {+ image = &kexec_image;
+ image_set = &kexec_image_set;
+ }
+
+ switch(op) {
+ case KEXEC_CMD_kexec:
+ BUG_ON(!*image_set);
+ status = __do_kexec(arg1, uarg, image);
+ break;
+ case KEXEC_CMD_kexec_load:
+ BUG_ON(*image_set);
+ if ( unlikely(copy_from_guest(image, uarg, 1) != 0) )
+ {+ printk("do_kexec (CMD_kexec_load): copy_from_guest failed\n
");
+ status = -EFAULT;
+ break;
+ } + *image_set = 1; + status = machine_kexec_load(arg1, image); + break; + case KEXEC_CMD_kexec_unload: + BUG_ON(!*image_set); + *image_set = 0; + machine_kexec_unload(arg1, image); + status = 0; + break;
+ }
+
+ if (arg1 == KEXEC_TYPE_CRASH)
+ xchg(&kexec_crash_lock, 0); <-------------this one
+ return status;
+}
+
Best Regards,
Akio Takebe
Re: [PATCH] kexec: framework and i386 (Take XI)
In reply to HormsQuoted 38 lines · Horms
Hi,
sorry for the somewhat long delay between sending updates. I'm happy to announce tenth take of the kexec/kdump patch. I'll address Keir's questions from the 9th release below, but first I would like to quickly summarise the patches.
Kexec/kdump is implemented by moving the privelaged portions (and related plumbing where needed) from linux into the hypervisor. This is primarily done by implementing kexec's architecture independent hooks as hypercalls.
Both Kexec is working for
x86_32andx86_64for SMP and UP. Kdump is also working for SMP and UP onx86_32.x86_64may work, but still needs more attention. In particular the register saving code has not been implemented.These patches also include some reworking of kexec's internals in order that the page table is not mangled on kdump. These changes also make
x86_64kexec/kdump somewhat easier to implement. Collectively this is thepagetable_aapproach developed by my colleague Magnus Damm, and he is working with the linux kexec maintainers to get it merged there.The code is broken out into four patches. They should apply cleanly to xen-unstable.hg 10151.
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,the basic plumbing for kexec/kdump
2. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
This would not be needed for ppc or ia64, but neither have been written yet.
We are planning to commence work on ia64 soon.
* Depends on 1
Quoted 7 lines
3. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump forx86_32
* Depends on 2 (and 1)4. 51.2.31.2-kexec-x86_64-upstream.patch
* * Kexec/kdump forx86_64
* Depends on 2 (and 1)
Hi,
here is a modest update to the kexec patches, broken out as per the description above. The changes are:
* Kconfig: don't allow kexec to be build for a non-privelaged domain as this makes no sense at this time.
* fix a gcc compilation error that became apparent in
gcc (GCC) 4.1.2 20060604 (prerelease) (Debian 4.1.1-2). There is a warning produced that causes the build to fail because of the use of -Werror when compiling the hypervisor. The warning relates to kexec's use of xchg as a simple locking mechanism and not always using the return value as it isn't of any value.
* Record dom0's cr3 in vmcore for analysis by crash
https://www.redhat.com/archives/crash-utility/2006-June/msg00015.html
* Upport from xen-unstable.hg 10151 to 10352, which is the current tree at present. This involved fixing two minor diffing issues, nothing more.
Signature · 1 line
Horms http://www.vergenet.net/~horms/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 48 + linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 84 ++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch | 85 ++ patches/linux-2.6.16.13/kexec-generic.patch | 294 ++++++++++ xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 xen/arch/x86/machine_kexec.c | 51 + xen/common/Makefile | 1 xen/common/kexec.c | 211 +++++++ xen/common/page_alloc.c | 33 - xen/drivers/char/console.c | 3 xen/include/asm-x86/kexec.h | 32 + xen/include/public/kexec.h | 85 ++ xen/include/public/xen.h | 1 xen/include/xen/elfcore.h | 73 ++ xen/include/xen/kexec.h | 33 + xen/include/xen/mm.h | 1 19 files changed, 1057 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -12,3 +12,4 @@ obj-$(CONFIG_IA64) += xenia64_init.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_REBOOT) += reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +48 -0
48 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +84 -0
84 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -67,6 +67,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
xen/arch/x86/Makefile +2 -0
@@ -39,6 +39,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o ifneq ($(pae),n) obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: arch/x86/crash.c: machine_crash_shutdown: not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +51 -0
51 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +211 -0
211 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -680,6 +680,7 @@ void panic(const char *fmt, ...)unsigned long flags;static DEFINE_SPINLOCK (lock);extern void machine_restart (char *); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -699,6 +700,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +watchdog_disable ();mdelay (5000 );machine_restart (0 );
xen/include/asm-x86/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " +"not implemented\n" ); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +85 -0
85 lines not on this page · raw message
xen/include/public/xen.h +1 -0
@@ -64,6 +64,7 @@#define __HYPERVISOR_xenoprof_op 31#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_kexec_op 34/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/* +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_load (int type,xen_kexec_image_t *image); +void machine_kexec_unload (int type,xen_kexec_image_t *image); +void machine_kexec_reserved (xen_kexec_reserve_t *reservation); +void machine_kexec (xen_kexec_image_t *image); +void machine_shutdown (xen_kexec_image_t *image); +void machine_crash_shutdown (cpu_user_regs_t *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/kexec-generic.patch new file +294 -0
294 lines not on this page · raw message
patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch new file +85 -0
85 lines not on this page · raw message
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 14 + xen/arch/x86/crash.c | 171 ++++++++++++++++- xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 150 +++++++++++++- xen/arch/x86/setup.c | 75 ++++++- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 27 ++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 28 ++ xen/include/asm-x86/elf.h | 27 ++ xen/include/asm-x86/fixmap.h | 1 xen/include/asm-x86/hypercall.h | 5 xen/include/asm-x86/kexec.h | 14 - xen/include/asm-x86/x86_32/elf.h | 30 ++ xen/include/asm-x86/x86_32/kexec.h | 51 +++++ xen/include/asm-x86/x86_64/elf.h | 30 ++ xen/include/asm-x86/x86_64/kexec.h | 50 ++++ xen/include/public/kexec.h | 2 xen/include/xen/elfcore.h | 3 19 files changed, 652 insertions(+), 31 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c +14 -0
@@ -23,7 +23,21 @@ static inline unsigned long machine_addrstatic void setup_hypercall_arg (xen_kexec_image_t *xki,struct kimage *image) { +#if defined(CONFIG_X86_32 ) || defined(CONFIG_X86_64 ) +struct kimage_arch *arch = &image->arch_data; +int k, n =sizeof (arch->page_table_a) /sizeof (arch->page_table_a[0 ]); + +memset (xki,0 ,sizeof (*xki)); + +for (k =0 ; k < n; k++) + xki->page_table_a[k] =machine_address (arch->page_table_a[k]); + +#ifdef CONFIG_X86_64 + xki->page_table_b =machine_address (arch->page_table_b); +#endif +#else memset (xki,0 ,sizeof (*xki)); +#endif xki->indirection_page = image->head; xki->reboot_code_buffer =
xen/arch/x86/crash.c +168 -3
184 lines not on this page · raw message
xen/arch/x86/dom0_ops.c +3 -0
@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000
xen/arch/x86/machine_kexec.c +138 -12
176 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: arch/x86/x86_32/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +28 -0
@@ -0,0 +1,28 @@ +/* +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stubs */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: arch/x86/x86_64/machine_kexec.c: machine_kexec: " +"not implemented\n" ); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/fixmap.h +1 -0
@@ -32,6 +32,7 @@ enum fixed_addresses {FIX_ACPI_END =FIX_ACPI_BEGIN +FIX_ACPI_PAGES -1 ,FIX_HPET_BASE ,FIX_CYCLONE_TIMER , +FIX_KEXEC_PAGE , __end_of_fixed_addresses };
xen/include/asm-x86/hypercall.h +5 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> extern long do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,unsigned arg1,XEN_GUEST_HANDLE (void ) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -7
@@ -8,16 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: include/asm-x86/kexec.h: crash_setup_regs: " -"not implemented\n" ); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +51 -0
51 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +30 -0
@@ -0,0 +1,30 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: include/asm-x86/x86_64/kexec.h: ELF_CORE_COPY_REGS: " \ + "not implemented\n") + + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +50 -0
50 lines not on this page · raw message
xen/include/public/kexec.h +2 -0
@@ -43,6 +43,8 @@*/ #define KEXEC_CMD_kexec_load 1 typedef struct xen_kexec_image { + unsigned long page_table_a[7]; + unsigned long page_table_b; unsigned long indirection_page; unsigned long reboot_code_buffer; unsigned long start_address;
xen/include/xen/elfcore.h +3 -0
@@ -16,6 +16,9 @@#include <public/xen.h> #define NT_PRSTATUS 1 +#define NT_XEN_DOM0_CR3 0x10000001/* XXX: Hopefully this is unused, +feel free to change to a +better/different value */ typedef struct {
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 4 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 29 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 42 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch | 457 ++++++++++ xen/arch/x86/crash.c | 47 + xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 28 xen/include/asm-x86/x86_32/elf.h | 34 xen/include/asm-x86/x86_32/kexec.h | 68 + 12 files changed, 683 insertions(+), 40 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +3 -1
@@ -184,10 +184,11 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 -# CONFIG_CRASH_DUMP is not set +CONFIG_CRASH_DUMP=y CONFIG_PHYSICAL_START=0x100000 CONFIG_HOTPLUG_CPU=y
@@ -2774,6 +2775,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +26 -3
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -941,6 +945,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -951,6 +956,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1320,9 +1329,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1378,6 +1400,10 @@ legacy_init_iomem_resources(struct e820e res->end = res->start + e820[i].size -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif +if (e820[i].type ==E820_RAM ) {/* * We don't know which RAM region contains kernel data,
@@ -1386,9 +1412,6 @@ legacy_init_iomem_resources(struct e820e*/ request_resource (res, code_resource);request_resource (res, data_resource); -#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); -#endif } } }
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +42 -0
42 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +8 -0
@@ -368,5 +368,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/crash.c +47 -0
65 lines not on this page · raw message
xen/arch/x86/x86_32/entry.S +2 -0
@@ -656,6 +656,7 @@ ENTRY(hypercall_table) .long do_xenoprof_op .long do_event_channel_op .long do_physdev_op + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -695,6 +696,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +20 -8
@@ -1,19 +1,31 @@ -/* +/****************************************************************************** * arch/x86/x86_32/machine_kexec.c -* Handle transition of Linux booting another kernel -* -* Created By: Horms <[email protected]> +* +* Created By: Horms * -* Should be losely based on arch/i386/kernel/machine_kexec.c +* Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16 */ -#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> +#include <asm/processor.h> + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long has_pae);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: arch/x86/x86_32/machine_kexec.c: machine_kexec: " -"not implemented\n" ); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + (unsigned long )cpu_has_pae); }/*
xen/include/asm-x86/x86_32/elf.h +27 -7
@@ -3,19 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: include/asm-x86/x86_32/kexec.h: ELF_CORE_COPY_REGS: " \ - "not implemented\n") - +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -19
91 lines not on this page · raw message
patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch new file +457 -0
457 lines not on this page · raw message
kexec: x86_64
This is the x86_64 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_64 | 2 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 26 linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h | 30 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch | 421 ++++++++++ patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch | 116 ++ xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/machine_kexec.c | 16 11 files changed, 621 insertions(+), 5 deletions(-)
buildconfigs/linux-defconfig_xen_x86_64 +2 -0
@@ -139,6 +139,8 @@ CONFIG_SWIOTLB=y CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
linux-2.6-xen-sparse/arch/x86_64/Kconfig +1 -1
@@ -433,7 +433,7 @@ config X86_MCE_AMD config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_64_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +1 -1
@@ -59,7 +59,7 @@ pci-dma-y += ../../i386/kernel/pci-dma microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o quirks-y := ../../i386/kernel/quirks-xen.o -n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o +n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o crash.o include $(srctree)/scripts/Makefile.xen
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +26 -0
@@ -79,6 +79,10 @@#include <asm/mach-xen/setup_arch_post.h> #include <xen/interface/memory.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +extern unsigned long start_pfn;extern struct edid_info edid_info;
@@ -446,6 +450,7 @@ static __init void parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -456,6 +461,10 @@ static __init void parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif
@@ -810,10 +819,23 @@ void __init setup_arch(char **cmdline_p)#endif #endif /* !CONFIG_XEN */ #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end) {reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); } +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif paging_init ();
@@ -972,6 +994,10 @@ void __init setup_arch(char **cmdline_p)iommu_hole_init ();#endif +#ifdef CONFIG_KEXEC +request_resource (&ioport_resource, &crashk_res); +#endif +#ifdef CONFIG_XEN {struct physdev_set_iopl set_iopl;
linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h new file +30 -0
@@ -0,0 +1,30 @@ +/* +* include/asm-x86_64/kexec-xen.h +* +* Created By: Horms <[email protected]> +*/ + +#ifndef _X86_64_KEXEC_XEN_H +#define _X86_64_KEXEC_XEN_H + +#include <asm/ptrace.h> +#include <asm/types.h> +#include <xen/interface/arch-x86_64.h> + +static inline void crash_translate_regs (struct pt_regs *linux_regs, +struct cpu_user_regs *xen_regs) +{ +#warning Implement me! +} + +#endif /* _X86_64_KEXEC_XEN_H */ + +/* +* Local variables: +* c-file-style: "linux" +* indent-tabs-mode: t +* c-indent-level: 8 +* c-basic-offset: 8 +* tab-width: 8 +* End: +*/
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +7 -0
@@ -360,4 +360,11 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} +#endif /* __HYPERCALL_H__ */
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h +2 -0
@@ -90,6 +90,8 @@ extern unsigned long profile_pc(struct p#define profile_pc (regs) instruction_pointer(regs)#endif +#include <linux/compiler.h> +void signal_fault (struct pt_regs *regs,void __user *frame,char *where);struct task_struct ;
xen/arch/x86/x86_64/entry.S +2 -0
@@ -556,6 +556,7 @@ ENTRY(hypercall_table) .quad do_xenoprof_op .quad do_event_channel_op .quad do_physdev_op + .quad do_kexec .rept NR_hypercalls-((.-hypercall_table)/8) .quad do_ni_hypercall .endr
@@ -595,6 +596,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_64/machine_kexec.c +13 -3
@@ -7,14 +7,24 @@* Should be losely based on arch/x86_64/kernel/machine_kexec.c */ -#include <xen/lib.h> /* for printk() used in stubs */ #include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> + +typedef void (*relocate_new_kernel_t )(unsigned long indirection_page, +unsigned long control_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long page_table_b);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: arch/x86/x86_64/machine_kexec.c: machine_kexec: " -"not implemented\n" ); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + image->page_table_b); }/*
patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch new file +421 -0
24 lines not on this page · raw message
patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch new file +116 -0
116 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
PATCH 1/1 kexec: framework and i386 (Take XII)
Hi,
here is another modest update of the kexec patchset for kdump. A breif summary of changes (all fairly minor):
* Forward port to xen-unstable-10650
* Move hypercall argument setup into machine specific code else its going to get messy as more architectures are added
* Don't pass kimage to the kexec_unload sub-hypercall, as its not needed
* Add ia64 stubs
* Use __FILE__ and __FUNCTION__ in stubs to make them less prone to error
* Add xen-console trigger crash_dump
The patches are currently:
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,
the basic plumbing for kexec/kdump
2. 51.1.1-kexec-trigger_crash_dump.patch
* xen-console trigger crash_dump
* Depends on 1
3. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
This would not be needed for ppc or ia64, but neither have been written yet.
We are planning to commence work on ia64 soon.
* Depends on 1
4. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump for x86_32
* Depends on 3 (and 1)
5. 51.2.31.2-kexec-x86_64-upstream.patch
* * Kexec/kdump for x86_64
* Depends on 3 (and 1)
I also have some ia64 patches, but they are still not working or complete, so I'll hold onto them for a bit longer. If anyone wants them, let me know.
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 49 + linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 78 ++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch | 85 ++ patches/linux-2.6.16.13/kexec-generic.patch | 294 ++++++++++ xen/arch/ia64/xen/Makefile | 2 xen/arch/ia64/xen/crash.c | 26 xen/arch/ia64/xen/machine_kexec.c | 46 + xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 xen/arch/x86/machine_kexec.c | 46 + xen/common/Makefile | 1 xen/common/kexec.c | 211 +++++++ xen/common/page_alloc.c | 33 - xen/drivers/char/console.c | 3 xen/include/asm-ia64/kexec.h | 32 + xen/include/asm-x86/kexec.h | 31 + xen/include/public/kexec.h | 85 ++ xen/include/public/xen.h | 1 xen/include/xen/elfcore.h | 73 ++ xen/include/xen/kexec.h | 33 + xen/include/xen/mm.h | 1 23 files changed, 1152 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_REBOOT) += reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +49 -0
49 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +78 -0
78 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -67,6 +67,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
xen/arch/ia64/xen/Makefile +2 -0
@@ -24,5 +24,7 @@ obj-y += xenmisc.o obj-y += xensetup.o obj-y += xentime.o obj-y += flushd.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(crash_debug) += gdbstub.o
xen/arch/ia64/xen/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/********************************************************************** +* arch/ia64/xen/crash.c +* +* Created By: Horms +* +*/ + +#include <xen/lib.h> /* for printk() used in stubs */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/arch/ia64/xen/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/arch/x86/Makefile +2 -0
@@ -39,6 +39,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o ifneq ($(pae),n) obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o shadow_guest32pae.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +211 -0
211 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -212,24 +212,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -717,6 +717,7 @@ void panic(const char *fmt, ...)unsigned long flags;static DEFINE_SPINLOCK (lock);extern void machine_restart (char *); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -736,6 +737,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +watchdog_disable ();mdelay (5000 );machine_restart (0 );
xen/include/asm-ia64/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-ia64/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __IA64_KEXEC_H__ +#define __IA64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __IA64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/include/asm-x86/kexec.h new file +31 -0
@@ -0,0 +1,31 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +85 -0
85 lines not on this page · raw message
xen/include/public/xen.h +1 -0
@@ -64,6 +64,7 @@#define __HYPERVISOR_xenoprof_op 31#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_kexec_op 34/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_load (int type,xen_kexec_image_t *image); +void machine_kexec_unload (int type,xen_kexec_image_t *image); +void machine_kexec_reserved (xen_kexec_reserve_t *reservation); +void machine_kexec (xen_kexec_image_t *image); +void machine_shutdown (xen_kexec_image_t *image); +void machine_crash_shutdown (cpu_user_regs_t *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/kexec-generic.patch new file +294 -0
294 lines not on this page · raw message
patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch new file +85 -0
85 lines not on this page · raw message
console: allow a crash dump to be triggered from the xen console
This feature is needed to test crash dump. It is essential for development (though developers could easily add the patch). It may also be of use for testing of the roll-out of production systems (people who don't want to add patches).
The original version of this patch triggered a panic, Keir Fraser suggested changing it to trigger a crash dump in line with a similar feature in Linux's sysrq.
Christian Limpach suggested changing the original trigger 'p' (for panic) to 'D' for dump, as p is already used by the performance counters. This patch uses 'c' for crashdump, again in line with the similar feature in Linux's sysrq. On inspection of the code, 'c' does not seem to be already taken.
xen/common/kexec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
xen/common/kexec.c +14 -0
@@ -13,6 +13,7 @@#include <xen/sched.h> #include <xen/types.h> #include <xen/kexec.h> +#include <xen/keyhandler.h> #include <public/kexec.h> DEFINE_PER_CPU (note_buf_t, crash_notes);
@@ -55,6 +56,19 @@ void crash_kexec(struct cpu_user_regs *rreturn ; } +static void do_crashdump_trigger (unsigned char key) +{ +printk ("triggering crashdump\n" ); +crash_kexec (NULL ); +} + +static __init int register_crashdump_trigger (void ) +{ +register_keyhandler ('c' , do_crashdump_trigger,"trigger a crashdump" ); +return 0 ; +} +__initcall (register_crashdump_trigger); +static int get_crash_note (int vcpuid,XEN_GUEST_HANDLE (void ) uarg) {struct domain *domain = current->domain;
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
xen/arch/x86/crash.c | 173 ++++++++++++++++++++++++++++++++++- xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 147 ++++++++++++++++++++++++++++- xen/arch/x86/setup.c | 75 +++++++++++++-- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 26 +++++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 27 +++++ xen/include/asm-x86/elf.h | 27 +++++ xen/include/asm-x86/fixmap.h | 1 xen/include/asm-x86/hypercall.h | 5 + xen/include/asm-x86/kexec.h | 13 +- xen/include/asm-x86/x86_32/elf.h | 28 +++++ xen/include/asm-x86/x86_32/kexec.h | 48 +++++++++ xen/include/asm-x86/x86_64/elf.h | 28 +++++ xen/include/asm-x86/x86_64/kexec.h | 33 ++++++ xen/include/public/kexec.h | 2 xen/include/xen/elfcore.h | 3 18 files changed, 615 insertions(+), 26 deletions(-)
xen/arch/x86/crash.c +170 -3
186 lines not on this page · raw message
xen/arch/x86/dom0_ops.c +3 -0
@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000
xen/arch/x86/machine_kexec.c +139 -8
173 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +26 -0
@@ -0,0 +1,26 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/fixmap.h +1 -0
@@ -36,6 +36,7 @@ enum fixed_addresses {FIX_ACPI_END =FIX_ACPI_BEGIN +FIX_ACPI_PAGES -1 ,FIX_HPET_BASE ,FIX_CYCLONE_TIMER , +FIX_KEXEC_PAGE , __end_of_fixed_addresses };
xen/include/asm-x86/hypercall.h +5 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> extern long do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,unsigned arg1,XEN_GUEST_HANDLE (void ) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -6
@@ -8,15 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +48 -0
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/asm-x86/x86_64/kexec.h +* +* Created By: Horms +* +* Should be based heavily on include/asm-x86_64/kexec.h from Linux 2.6.16 +* +*/ + +#ifndef __X86_64_KEXEC_H__ +#define __X86_64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h +2 -0
@@ -43,6 +43,8 @@*/ #define KEXEC_CMD_kexec_load 1 typedef struct xen_kexec_image { + unsigned long page_table_a[7]; + unsigned long page_table_b; unsigned long indirection_page; unsigned long reboot_code_buffer; unsigned long start_address;
xen/include/xen/elfcore.h +3 -0
@@ -16,6 +16,9 @@#include <public/xen.h> #define NT_PRSTATUS 1 +#define NT_XEN_DOM0_CR3 0x10000001/* XXX: Hopefully this is unused, +feel free to change to a +better/different value */ typedef struct {
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 2 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 6 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 29 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 42 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch | 485 ++++++++++ xen/arch/x86/crash.c | 47 xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 27 xen/include/asm-x86/x86_32/elf.h | 32 xen/include/asm-x86/x86_32/kexec.h | 65 + 12 files changed, 714 insertions(+), 33 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +2 -0
@@ -184,6 +184,7 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
@@ -2774,6 +2775,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +5 -1
@@ -24,7 +24,11 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o +ifdef CONFIG_XEN +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +else obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +endif obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_X86_NUMAQ) += numaq.o obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
@@ -89,7 +93,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +26 -3
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -941,6 +945,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -951,6 +956,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1320,9 +1329,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1378,6 +1400,10 @@ legacy_init_iomem_resources(struct e820e res->end = res->start + e820[i].size -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif +if (e820[i].type ==E820_RAM ) {/* * We don't know which RAM region contains kernel data,
@@ -1386,9 +1412,6 @@ legacy_init_iomem_resources(struct e820e*/ request_resource (res, code_resource);request_resource (res, data_resource); -#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); -#endif } } }
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +42 -0
42 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +8 -0
@@ -368,5 +368,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/crash.c +47 -0
65 lines not on this page · raw message
xen/arch/x86/x86_32/entry.S +2 -0
@@ -656,6 +656,7 @@ ENTRY(hypercall_table) .long do_xenoprof_op .long do_event_channel_op .long do_physdev_op + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -695,6 +696,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_xenoprof_op */ .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ + .byte 3 /* do_kexec */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +20 -7
@@ -1,18 +1,31 @@ -/* +/****************************************************************************** * arch/x86/x86_32/machine_kexec.c -* Handle transition of Linux booting another kernel -* -* Created By: Horms <[email protected]> +* +* Created By: Horms * -* Should be losely based on arch/i386/kernel/machine_kexec.c +* Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16 */ -#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> +#include <asm/processor.h> + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long has_pae);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + (unsigned long )cpu_has_pae); }/*
xen/include/asm-x86/x86_32/elf.h +27 -5
@@ -3,17 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -16
88 lines not on this page · raw message
patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch new file +485 -0
485 lines not on this page · raw message
kexec: x86_64
This is the first x86_64 release of kexec for xen/dom0. The code is in an early phase, but it compiles and kexec:ing into a Linux kernel seems to work well. Rebooting into a new kernel may work using kdump too, but register saving support is still missing.
The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_64 | 1 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 6 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 26 linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h | 30 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch | 421 ++++++++++ patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch | 151 +++ xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/machine_kexec.c | 21 xen/include/asm-x86/x86_64/elf.h | 48 + xen/include/asm-x86/x86_64/kexec.h | 33 13 files changed, 736 insertions(+), 14 deletions(-)
buildconfigs/linux-defconfig_xen_x86_64 +1 -0
@@ -139,6 +139,7 @@ CONFIG_SWIOTLB=y CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
linux-2.6-xen-sparse/arch/x86_64/Kconfig +1 -1
@@ -433,7 +433,7 @@ config X86_MCE_AMD config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_64_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +5 -1
@@ -23,7 +23,11 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o obj-$(CONFIG_X86_XEN_GENAPIC) += genapic.o genapic_xen.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \ genapic.o genapic_cluster.o genapic_flat.o +ifdef CONFIG_XEN +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +else obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o +endif obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o obj-$(CONFIG_ACPI_SLEEP) += suspend.o
@@ -59,7 +63,7 @@ pci-dma-y += ../../i386/kernel/pci-dma microcode-$(subst m,y,$(CONFIG_MICROCODE)) := ../../i386/kernel/microcode-xen.o quirks-y := ../../i386/kernel/quirks-xen.o -n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o +n-obj-xen := i8259.o reboot.o i8237.o smpboot.o trampoline.o crash.o include $(srctree)/scripts/Makefile.xen
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +26 -0
@@ -79,6 +79,10 @@#include <asm/mach-xen/setup_arch_post.h> #include <xen/interface/memory.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +extern unsigned long start_pfn;extern struct edid_info edid_info;
@@ -446,6 +450,7 @@ static __init void parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -456,6 +461,10 @@ static __init void parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif
@@ -801,10 +810,23 @@ void __init setup_arch(char **cmdline_p)#endif #endif /* !CONFIG_XEN */ #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end) {reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); } +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif paging_init ();
@@ -950,6 +972,10 @@ void __init setup_arch(char **cmdline_p)iommu_hole_init ();#endif +#ifdef CONFIG_KEXEC +request_resource (&ioport_resource, &crashk_res); +#endif +#ifdef CONFIG_XEN {
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h new file +30 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +7 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/entry.S +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/machine_kexec.c +16 -5
Lines of this file are not shown. View the raw message.
xen/include/asm-x86/x86_64/elf.h +43 -5
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/kexec.h +31 -2
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch new file +421 -0
421 lines not on this page · raw message
patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch new file +151 -0
151 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
Re: [PATCH] kexec: framework and i386 (Take XIII)
Hi,
here is a minor update of the kexec/kdump patchset. The changes since the last post are quite minimal.
* Forward port to xen-unstable-11059 from 10650
* Add powerpc stubs to 51.1-kexec-generic-upstream.patch going to get messy as more architectures are added
The patches are currently:
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,
the basic plumbing for kexec/kdump
2. 51.1.1-kexec-trigger_crash_dump.patch
* xen-console trigger crash_dump
* Depends on 1
3. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
This would not be needed for ppc or ia64, but neither have been written yet.
We are planning to commence work on ia64 soon.
* Depends on 1
4. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump for x86_32
* Depends on 3 (and 1)
5. 51.2.31.2-kexec-x86_64-upstream.patch
* * Kexec/kdump for x86_64
* Depends on 3 (and 1)
Things that are being worked on:
* Porting kexec for ia64. This is going somewhat slower than I had hoped. Partly because of my own schedule. And partly because the Linux code is flakier than I previously thought.
If anyone cares, the problem that is currently bothering me most about linux ia64 kexec is that you can usually kexec once, but twice doesn't work.
e.g. linux --kexec--> linux: ok
linux --kexec--> linux --kexec fails--> linux: not ok
* Kdump for x86_64. My colleague Magnus is working on this. But he is seeing a very strange problem where kdumping into a bzimage works, while a vmlinux does not.
Please prod him if you want more details.
Things that would be good to work on:
* PPC port
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 49 + linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 81 ++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch | 85 ++ patches/linux-2.6.16.13/kexec-generic.patch | 294 ++++++++++ xen/arch/ia64/xen/Makefile | 2 xen/arch/ia64/xen/crash.c | 26 xen/arch/ia64/xen/machine_kexec.c | 46 + xen/arch/powerpc/Makefile | 2 xen/arch/powerpc/crash.c | 26 xen/arch/powerpc/machine_kexec.c | 46 + xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 xen/arch/x86/machine_kexec.c | 46 + xen/common/Makefile | 1 xen/common/kexec.c | 211 +++++++ xen/common/page_alloc.c | 33 - xen/drivers/char/console.c | 3 xen/include/asm-ia64/kexec.h | 32 + xen/include/asm-x86/kexec.h | 31 + xen/include/public/kexec.h | 85 ++ xen/include/public/xen.h | 1 xen/include/xen/elfcore.h | 73 ++ xen/include/xen/kexec.h | 33 + xen/include/xen/mm.h | 1 26 files changed, 1229 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_REBOOT) += reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +49 -0
49 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +81 -0
81 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -65,6 +65,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
xen/arch/ia64/xen/Makefile +2 -0
@@ -25,5 +25,7 @@ obj-y += xensetup.o obj-y += xentime.o obj-y += flushd.o obj-y += privop_stat.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(crash_debug) += gdbstub.o
xen/arch/ia64/xen/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/********************************************************************** +* arch/ia64/xen/crash.c +* +* Created By: Horms +* +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/arch/ia64/xen/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/arch/powerpc/Makefile +2 -0
@@ -35,6 +35,8 @@ obj-y += setup.o obj-y += smp.o obj-y += time.o obj-y += usercopy.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(debug) += 0opt.o obj-$(crash_debug) += gdbstub.o
xen/arch/powerpc/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/********************************************************************** +* arch/powerpc/crash.c +* +* Created By: Horms +* +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/arch/powerpc/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/arch/x86/Makefile +2 -0
@@ -39,6 +39,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o ifneq ($(pae),n) obj-$(x86_32) += shadow.o shadow_public.o shadow_guest32.o shadow_guest32pae.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +211 -0
211 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -213,24 +213,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -716,6 +716,7 @@ void panic(const char *fmt, ...)char buf[128 ];unsigned long flags;static DEFINE_SPINLOCK (lock); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -738,6 +739,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +if ( opt_noreboot ) {machine_halt ();
xen/include/asm-ia64/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-ia64/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __IA64_KEXEC_H__ +#define __IA64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __IA64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/include/asm-x86/kexec.h new file +31 -0
@@ -0,0 +1,31 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +85 -0
85 lines not on this page · raw message
xen/include/public/xen.h +1 -0
@@ -67,6 +67,7 @@#define __HYPERVISOR_event_channel_op 32#define __HYPERVISOR_physdev_op 33#define __HYPERVISOR_hvm_op 34 +#define __HYPERVISOR_kexec_op 35/* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_load (int type,xen_kexec_image_t *image); +void machine_kexec_unload (int type,xen_kexec_image_t *image); +void machine_kexec_reserved (xen_kexec_reserve_t *reservation); +void machine_kexec (xen_kexec_image_t *image); +void machine_shutdown (xen_kexec_image_t *image); +void machine_crash_shutdown (cpu_user_regs_t *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/kexec-generic.patch new file +294 -0
294 lines not on this page · raw message
patches/linux-2.6.16.13/0-linux-2.6.16-kexec_page_table_a_stubs.patch new file +85 -0
85 lines not on this page · raw message
console: allow a crash dump to be triggered from the xen console
This feature is needed to test crash dump. It is essential for development (though developers could easily add the patch). It may also be of use for testing of the roll-out of production systems (people who don't want to add patches).
The original version of this patch triggered a panic, Keir Fraser suggested changing it to trigger a crash dump in line with a similar feature in Linux's sysrq.
Christian Limpach suggested changing the original trigger 'p' (for panic) to 'D' for dump, as p is already used by the performance counters. This patch uses 'c' for crashdump, again in line with the similar feature in Linux's sysrq. On inspection of the code, 'c' does not seem to be already taken.
xen/common/kexec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
xen/common/kexec.c +14 -0
@@ -13,6 +13,7 @@#include <xen/sched.h> #include <xen/types.h> #include <xen/kexec.h> +#include <xen/keyhandler.h> #include <public/kexec.h> DEFINE_PER_CPU (note_buf_t, crash_notes);
@@ -55,6 +56,19 @@ void crash_kexec(struct cpu_user_regs *rreturn ; } +static void do_crashdump_trigger (unsigned char key) +{ +printk ("triggering crashdump\n" ); +crash_kexec (NULL ); +} + +static __init int register_crashdump_trigger (void ) +{ +register_keyhandler ('c' , do_crashdump_trigger,"trigger a crashdump" ); +return 0 ; +} +__initcall (register_crashdump_trigger); +static int get_crash_note (int vcpuid,XEN_GUEST_HANDLE (void ) uarg) {struct domain *domain = current->domain;
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
xen/arch/x86/crash.c | 173 ++++++++++++++++++++++++++++++++++- xen/arch/x86/dom0_ops.c | 3 xen/arch/x86/machine_kexec.c | 147 ++++++++++++++++++++++++++++- xen/arch/x86/setup.c | 75 +++++++++++++-- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 26 +++++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 27 +++++ xen/include/asm-x86/elf.h | 27 +++++ xen/include/asm-x86/fixmap.h | 1 xen/include/asm-x86/hypercall.h | 5 + xen/include/asm-x86/kexec.h | 13 +- xen/include/asm-x86/x86_32/elf.h | 28 +++++ xen/include/asm-x86/x86_32/kexec.h | 48 +++++++++ xen/include/asm-x86/x86_64/elf.h | 28 +++++ xen/include/asm-x86/x86_64/kexec.h | 33 ++++++ xen/include/public/kexec.h | 2 xen/include/xen/elfcore.h | 3 18 files changed, 615 insertions(+), 26 deletions(-)
xen/arch/x86/crash.c +170 -3
186 lines not on this page · raw message
xen/arch/x86/dom0_ops.c +3 -0
@@ -29,6 +29,9 @@#include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; +#define TRC_DOM0OP_ENTER_BASE 0x00020000#define TRC_DOM0OP_LEAVE_BASE 0x00030000
xen/arch/x86/machine_kexec.c +139 -8
173 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +26 -0
@@ -0,0 +1,26 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/fixmap.h +1 -0
@@ -36,6 +36,7 @@ enum fixed_addresses {FIX_ACPI_END =FIX_ACPI_BEGIN +FIX_ACPI_PAGES -1 ,FIX_HPET_BASE ,FIX_CYCLONE_TIMER , +FIX_KEXEC_PAGE , __end_of_fixed_addresses };
xen/include/asm-x86/hypercall.h +5 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> extern long do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,unsigned arg1,XEN_GUEST_HANDLE (void ) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -6
@@ -8,15 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +48 -0
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/asm-x86/x86_64/kexec.h +* +* Created By: Horms +* +* Should be based heavily on include/asm-x86_64/kexec.h from Linux 2.6.16 +* +*/ + +#ifndef __X86_64_KEXEC_H__ +#define __X86_64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h +2 -0
@@ -43,6 +43,8 @@*/ #define KEXEC_CMD_kexec_load 1 typedef struct xen_kexec_image { + unsigned long page_table_a[7]; + unsigned long page_table_b; unsigned long indirection_page; unsigned long reboot_code_buffer; unsigned long start_address;
xen/include/xen/elfcore.h +3 -0
@@ -16,6 +16,9 @@#include <public/xen.h> #define NT_PRSTATUS 1 +#define NT_XEN_DOM0_CR3 0x10000001/* XXX: Hopefully this is unused, +feel free to change to a +better/different value */ typedef struct {
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 2 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 29 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 42 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch | 457 ++++++++++ patches/linux-2.6.16.13/4-linux-2.6.16-kexec_page_table_a_i386-xen.patch | 59 + xen/arch/x86/crash.c | 47 + xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 27 xen/include/asm-x86/x86_32/elf.h | 32 xen/include/asm-x86/x86_32/kexec.h | 65 + 13 files changed, 741 insertions(+), 33 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +2 -0
@@ -184,6 +184,7 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
@@ -2775,6 +2776,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +26 -3
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -941,6 +945,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -951,6 +956,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1320,9 +1329,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1378,6 +1400,10 @@ legacy_init_iomem_resources(struct e820e res->end = res->start + e820[i].size -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif +if (e820[i].type ==E820_RAM ) {/* * We don't know which RAM region contains kernel data,
@@ -1386,9 +1412,6 @@ legacy_init_iomem_resources(struct e820e*/ request_resource (res, code_resource);request_resource (res, data_resource); -#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); -#endif } } }
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +42 -0
42 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +8 -0
@@ -368,5 +368,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/crash.c +47 -0
65 lines not on this page · raw message
xen/arch/x86/x86_32/entry.S +2 -0
@@ -657,6 +657,7 @@ ENTRY(hypercall_table) .long do_event_channel_op .long do_physdev_op .long do_hvm_op /* 34 */ + .long do_kexec .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -697,6 +698,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_event_channel_op */ .byte 2 /* do_physdev_op */ .byte 2 /* do_hvm_op */ /* 34 */ + .byte 3 /* do_kexec_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +20 -7
@@ -1,18 +1,31 @@ -/* +/****************************************************************************** * arch/x86/x86_32/machine_kexec.c -* Handle transition of Linux booting another kernel -* -* Created By: Horms <[email protected]> +* +* Created By: Horms * -* Should be losely based on arch/i386/kernel/machine_kexec.c +* Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16 */ -#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> +#include <asm/processor.h> + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long has_pae);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + (unsigned long )cpu_has_pae); }/*
xen/include/asm-x86/x86_32/elf.h +27 -5
@@ -3,17 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -16
88 lines not on this page · raw message
patches/linux-2.6.16.13/1-linux-2.6.16-kexec_page_table_a_i386.patch new file +457 -0
457 lines not on this page · raw message
patches/linux-2.6.16.13/4-linux-2.6.16-kexec_page_table_a_i386-xen.patch new file +59 -0
49 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
kexec: x86_64
This is the first x86_64 release of kexec for xen/dom0. The code is in an early phase, but it compiles and kexec:ing into a Linux kernel seems to work well. Rebooting into a new kernel may work using kdump too, but register saving support is still missing.
The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_64 | 1 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 26 linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h | 49 + linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch | 421 ++++++++++ patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch | 151 +++ xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/machine_kexec.c | 21 xen/include/asm-x86/x86_64/elf.h | 48 + xen/include/asm-x86/x86_64/kexec.h | 33 13 files changed, 751 insertions(+), 14 deletions(-)
buildconfigs/linux-defconfig_xen_x86_64 +1 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/Kconfig +1 -1
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +1 -1
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +26 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h new file +49 -0
49 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +7 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/entry.S +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/machine_kexec.c +16 -5
Lines of this file are not shown. View the raw message.
xen/include/asm-x86/x86_64/elf.h +43 -5
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/kexec.h +31 -2
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/2-linux-2.6.16-kexec_page_table_a_x86_64.patch new file +421 -0
421 lines not on this page · raw message
patches/linux-2.6.16.13/3-linux-2.6.16-kexec_page_table_a_x86_64-xen.patch new file +151 -0
151 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
PATCH 1/1 kexec: framework and i386 (Take XIV)
Hi,
here is an update of the kexec/kdump patchset.
Summary:
* Up port to xen-unstable.hg-11296 (45f6ee334fcc)
- kexec hypercall number fragment is now in xen-unstable
* Make kexec_page_to_pfn and friends need to be architecture specific
- this abstraction is needed to support ia64
* Use kexec_page_to_pfn in machine_kexec_setup_load_arg()
- this abstraction is needed to support ia64
* Rename do_kexec to do_kexec_op to make it consistent with other hypercalls
* Add ppc stubs
* Add ia64 support
Architectures:
x86_32:
Seems to be working fine
x86_64:
Probably working fine, but I can't test this as dom0 refuses to boot for me on xen-unstable-11388 (50aea0ec406b). That is, even without the kexec patches. I'm not sure what the problem is and I've devicided to get these patches out rather and investigate later.
ia64:
This patchset also, for the first time, includes ia64 code. Please note that this currently does _not_ work. I am actually struggling to work out why, and would really appreaciate it if someone could cast an eye over it.
One possible area of concern is that relocate_kernel wipes out TLB entries. However many of the entries instated in arch/ia64/xen/xenasm.S:ia64_new_rr7() are not wiped. In particular, VHPT_ADDR, Shared info, and Map mapped_reg are not handled by relocate_kernel(), and the handling of current seems to be different.
There are also problems with constants inside kexec_fake_sal_rendez. However this function probably also suffers the same problems as relocate_kernel. And it is easy not ro run kexec_fake_sal_rendez by booting xen with maxcpus=1, thus avoiding calling kexec_fake_sal_rendez, which is used in cpu shutdown.
ppc:
stubs only
Patches
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,
the basic plumbing for kexec/kdump
2. 51.1.1-kexec-trigger_crash_dump.patch
* xen-console trigger crash_dump
* Depends on 1
3. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
* Depends on 1
4. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump for x86_32
* Depends on 3 (and 1)
5. 51.2.31.2-kexec-x86_64-upstream.patch
* Kexec/kdump for x86_64
* Depends on 3 (and 1)
6. 51.2.2-kexec-ia64-upstream.patch
* Kexec/kdump for ia64
* Depends 1
Discussion:
Email is always good. Also my partner in crime, Magnus Damm, will be at Xen Summit.
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
kexec: framework
This is an implementation of kexec for dom0/xen, that allows kexecing of the physical machine from xen. The approach taken is to move the architecture-dependant kexec code into a new hypercall.
This patch only includes the framework, it cann't be used without architecture dependant hooks, however the code should compile as is.
linux-2.6-xen-sparse/drivers/xen/core/Makefile | 1 linux-2.6-xen-sparse/drivers/xen/core/crash.c | 49 + linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c | 78 ++ linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 4 patches/linux-2.6.16.13/kexec-generic.patch | 283 ++++++++++ patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_stubs.patch | 85 +++ patches/linux-2.6.16.13/series | 2 xen/arch/ia64/xen/Makefile | 2 xen/arch/ia64/xen/crash.c | 26 xen/arch/ia64/xen/machine_kexec.c | 46 + xen/arch/powerpc/Makefile | 2 xen/arch/powerpc/crash.c | 26 xen/arch/powerpc/machine_kexec.c | 46 + xen/arch/x86/Makefile | 2 xen/arch/x86/crash.c | 26 xen/arch/x86/machine_kexec.c | 46 + xen/common/Makefile | 1 xen/common/kexec.c | 211 +++++++ xen/common/page_alloc.c | 33 - xen/drivers/char/console.c | 3 xen/include/asm-ia64/kexec.h | 32 + xen/include/asm-x86/kexec.h | 31 + xen/include/public/kexec.h | 85 +++ xen/include/xen/elfcore.h | 73 ++ xen/include/xen/hypercall.h | 6 xen/include/xen/kexec.h | 33 + xen/include/xen/mm.h | 1 27 files changed, 1222 insertions(+), 11 deletions(-)
linux-2.6-xen-sparse/drivers/xen/core/Makefile +1 -0
@@ -11,3 +11,4 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o obj-$(CONFIG_XEN_SKBUFF) += skbuff.o obj-$(CONFIG_XEN_REBOOT) += reboot.o obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o +obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o
linux-2.6-xen-sparse/drivers/xen/core/crash.c new file +49 -0
49 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c new file +78 -0
78 lines not on this page · raw message
linux-2.6-xen-sparse/drivers/xen/core/reboot.c +4 -0
@@ -65,6 +65,10 @@ void machine_power_off(void)HYPERVISOR_shutdown (SHUTDOWN_poweroff); } +#ifdef CONFIG_KEXEC +void machine_shutdown (void ) { } +#endif +int reboot_thru_bios =0 ;/* for dmi_scan.c */ EXPORT_SYMBOL (machine_restart);EXPORT_SYMBOL (machine_halt);
xen/arch/ia64/xen/Makefile +2 -0
@@ -25,5 +25,7 @@ obj-y += xensetup.o obj-y += xentime.o obj-y += flushd.o obj-y += privop_stat.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(crash_debug) += gdbstub.o
xen/arch/ia64/xen/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/********************************************************************** +* arch/ia64/xen/crash.c +* +* Created By: Horms +* +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/arch/ia64/xen/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/arch/powerpc/Makefile +2 -0
@@ -35,6 +35,8 @@ obj-y += setup.o obj-y += smp.o obj-y += time.o obj-y += usercopy.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(debug) += 0opt.o obj-$(crash_debug) += gdbstub.o
xen/arch/powerpc/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/********************************************************************** +* arch/powerpc/crash.c +* +* Created By: Horms +* +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/arch/powerpc/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/arch/x86/Makefile +2 -0
@@ -41,6 +41,8 @@ obj-y += trampoline.o obj-y += traps.o obj-y += usercopy.o obj-y += x86_emulate.o +obj-y += machine_kexec.o +obj-y += crash.o obj-$(crash_debug) += gdbstub.o
xen/arch/x86/crash.c new file +26 -0
@@ -0,0 +1,26 @@ +/****************************************************************************** +* arch/x86/crash.c +* +* Created By: Horms +* +* Should be based heavily on arch/i386/kernel/crash.c from Linux 2.6.16 +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +void machine_crash_shutdown (struct cpu_user_regs *regs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/machine_kexec.c new file +46 -0
46 lines not on this page · raw message
xen/common/Makefile +1 -0
@@ -7,6 +7,7 @@ obj-y += event_channel.o obj-y += grant_table.o obj-y += kernel.o obj-y += keyhandler.o +obj-y += kexec.o obj-y += lib.o obj-y += memory.o obj-y += multicall.o
xen/common/kexec.c new file +211 -0
211 lines not on this page · raw message
xen/common/page_alloc.c +22 -11
@@ -213,24 +213,35 @@ void init_boot_pages(paddr_t ps, paddr_t } } +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at) +{ +unsigned long i; + +for ( i =0 ; i < nr_pfns; i++ ) +if (allocated_in_map (pfn_at + i) ) +break ; + +if ( i == nr_pfns ) + { +map_alloc (pfn_at, nr_pfns); +return pfn_at; + } + +return 0 ; +} +unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align) { -unsigned long pg, i; +unsigned long pg, i =0 ;for ( pg =0 ; (pg + nr_pfns) < max_page; pg += pfn_align ) { -for ( i =0 ; i < nr_pfns; i++ ) -if (allocated_in_map (pg + i) ) -break ; - -if ( i == nr_pfns ) - { -map_alloc (pg, nr_pfns); -return pg; - } + i =alloc_boot_pages_at (nr_pfns, pg); +if (i !=0 ) +break ; } -return 0 ; +return i; }
xen/drivers/char/console.c +3 -0
@@ -585,6 +585,7 @@ void panic(const char *fmt, ...)char buf[128 ];unsigned long flags;static DEFINE_SPINLOCK (lock); +extern void crash_kexec (struct cpu_user_regs *regs);debugtrace_dump ();
@@ -607,6 +608,8 @@ void panic(const char *fmt, ...)debugger_trap_immediate (); +crash_kexec (NULL ); +if ( opt_noreboot ) {machine_halt ();
xen/include/asm-ia64/kexec.h new file +32 -0
@@ -0,0 +1,32 @@ +/****************************************************************************** +* include/asm-ia64/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __IA64_KEXEC_H__ +#define __IA64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __IA64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/ +
xen/include/asm-x86/kexec.h new file +31 -0
@@ -0,0 +1,31 @@ +/****************************************************************************** +* include/asm-x86/kexec.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_KEXEC_H__ +#define __X86_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h new file +85 -0
85 lines not on this page · raw message
xen/include/xen/elfcore.h new file +73 -0
73 lines not on this page · raw message
xen/include/xen/hypercall.h +6 -0
@@ -102,4 +102,10 @@ do_hvm_op( unsigned long op, XEN_GUEST_HANDLE(void) arg); +extern long +do_kexec_op ( +unsigned long op, +int arg1, +XEN_GUEST_HANDLE (void ) arg); +#endif /* __XEN_HYPERCALL_H__ */
xen/include/xen/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/xen/kexec.h - Internal archtecture independant portion +* +* Created By: Horms <[email protected]> +* +*/ + +#include <public/kexec.h> + +#define MAX_NOTE_BYTES 1024 + +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; +DECLARE_PER_CPU (note_buf_t, crash_notes); + +int machine_kexec_load (int type,xen_kexec_image_t *image); +void machine_kexec_unload (int type,xen_kexec_image_t *image); +void machine_kexec_reserved (xen_kexec_reserve_t *reservation); +void machine_kexec (xen_kexec_image_t *image); +void machine_shutdown (xen_kexec_image_t *image); +void machine_crash_shutdown (cpu_user_regs_t *regs); + +extern unsigned int opt_kdump_megabytes; +extern unsigned int opt_kdump_megabytes_base; + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/xen/mm.h +1 -0
@@ -40,6 +40,7 @@ struct page_info;paddr_t init_boot_allocator (paddr_t bitmap_start);void init_boot_pages (paddr_t ps,paddr_t pe);unsigned long alloc_boot_pages (unsigned long nr_pfns,unsigned long pfn_align); +unsigned long alloc_boot_pages_at (unsigned long nr_pfns,unsigned long pfn_at);void end_boot_allocator (void );/* Generic allocator. These functions are *not* interrupt-safe. */
patches/linux-2.6.16.13/series +2 -0
@@ -1,3 +1,5 @@ +kexec-generic.patch +linux-2.6.16-kexec_page_table_a_stubs.patch blktap-aio-16_03_06.patch device_bind.patch fix-hz-suspend.patch
patches/linux-2.6.16.13/kexec-generic.patch new file +283 -0
283 lines not on this page · raw message
patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_stubs.patch new file +85 -0
85 lines not on this page · raw message
console: allow a crash dump to be triggered from the xen console
This feature is needed to test crash dump. It is essential for development (though developers could easily add the patch). It may also be of use for testing of the roll-out of production systems (people who don't want to add patches).
The original version of this patch triggered a panic, Keir Fraser suggested changing it to trigger a crash dump in line with a similar feature in Linux's sysrq.
Christian Limpach suggested changing the original trigger 'p' (for panic) to 'D' for dump, as p is already used by the performance counters. This patch uses 'c' for crashdump, again in line with the similar feature in Linux's sysrq. On inspection of the code, 'c' does not seem to be already taken.
xen/common/kexec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
xen/common/kexec.c +14 -0
@@ -13,6 +13,7 @@#include <xen/sched.h> #include <xen/types.h> #include <xen/kexec.h> +#include <xen/keyhandler.h> #include <public/kexec.h> DEFINE_PER_CPU (note_buf_t, crash_notes);
@@ -55,6 +56,19 @@ void crash_kexec(struct cpu_user_regs *rreturn ; } +static void do_crashdump_trigger (unsigned char key) +{ +printk ("triggering crashdump\n" ); +crash_kexec (NULL ); +} + +static __init int register_crashdump_trigger (void ) +{ +register_keyhandler ('c' , do_crashdump_trigger,"trigger a crashdump" ); +return 0 ; +} +__initcall (register_crashdump_trigger); +static int get_crash_note (int vcpuid,XEN_GUEST_HANDLE (void ) uarg) {struct domain *domain = current->domain;
kexec: x86
This is the x86 component of kexec for xen.
The generic component is a prerequsite for this patch. The x86_64 or x86_32 (i386) patch is also needed
in order to use this code, however the code should compile is.
xen/arch/x86/crash.c | 173 ++++++++++++++++++++++++++++++++++- xen/arch/x86/machine_kexec.c | 145 +++++++++++++++++++++++++++-- xen/arch/x86/setup.c | 75 +++++++++++++-- xen/arch/x86/x86_32/Makefile | 1 xen/arch/x86/x86_32/machine_kexec.c | 26 +++++ xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/machine_kexec.c | 27 +++++ xen/include/asm-x86/elf.h | 27 +++++ xen/include/asm-x86/fixmap.h | 1 xen/include/asm-x86/hypercall.h | 5 + xen/include/asm-x86/kexec.h | 13 +- xen/include/asm-x86/x86_32/elf.h | 28 +++++ xen/include/asm-x86/x86_32/kexec.h | 48 +++++++++ xen/include/asm-x86/x86_64/elf.h | 28 +++++ xen/include/asm-x86/x86_64/kexec.h | 33 ++++++ xen/include/public/kexec.h | 3 xen/include/xen/elfcore.h | 3 17 files changed, 611 insertions(+), 26 deletions(-)
xen/arch/x86/crash.c +170 -3
186 lines not on this page · raw message
xen/arch/x86/machine_kexec.c +137 -8
171 lines not on this page · raw message
xen/arch/x86/setup.c +66 -9
99 lines not on this page · raw message
xen/arch/x86/x86_32/Makefile +1 -0
@@ -3,5 +3,6 @@ obj-y += entry.o obj-y += mm.o obj-y += seg_fixup.o obj-y += traps.o +obj-y += machine_kexec.o obj-$(supervisor_mode_kernel) += supervisor_mode_kernel.o
xen/arch/x86/x86_32/machine_kexec.c new file +26 -0
@@ -0,0 +1,26 @@ +/* +* arch/x86/x86_32/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/i386/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/arch/x86/x86_64/Makefile +1 -0
@@ -1,3 +1,4 @@ obj-y += entry.o obj-y += mm.o obj-y += traps.o +obj-y += machine_kexec.o
xen/arch/x86/x86_64/machine_kexec.c new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* arch/x86/x86_64/machine_kexec.c +* Handle transition of Linux booting another kernel +* +* Created By: Horms <[email protected]> +* +* Should be losely based on arch/x86_64/kernel/machine_kexec.c +*/ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/kexec.h> + +void machine_kexec (xen_kexec_image_t *image) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/elf.h new file +27 -0
@@ -0,0 +1,27 @@ +/****************************************************************************** +* include/asm-x86/elf.h +* +* Created By: Horms +* +*/ + +#ifndef __X86_ELF_H__ +#define __X86_ELF_H__ + +#ifdef __x86_64__ +#include <asm/x86_64/elf.h> +#else +#include <asm/x86_32/elf.h> +#endif + +#endif /* __X86_ELF_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/fixmap.h +1 -0
@@ -36,6 +36,7 @@ enum fixed_addresses {FIX_ACPI_END =FIX_ACPI_BEGIN +FIX_ACPI_PAGES -1 ,FIX_HPET_BASE ,FIX_CYCLONE_TIMER , +FIX_KEXEC_PAGE , __end_of_fixed_addresses };
xen/include/asm-x86/hypercall.h +5 -0
@@ -6,6 +6,7 @@#define __ASM_X86_HYPERCALL_H__#include <public/physdev.h> +#include <xen/types.h> extern long do_event_channel_op_compat(
@@ -87,6 +88,10 @@ extern longarch_do_vcpu_op ( int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg); +extern int +do_kexec ( +unsigned long op,unsigned arg1,XEN_GUEST_HANDLE (void ) uarg); +#ifdef __x86_64__ extern long
xen/include/asm-x86/kexec.h +7 -6
@@ -8,15 +8,16 @@#ifndef __X86_KEXEC_H__#define __X86_KEXEC_H__ -#include <xen/lib.h> /* for printk() used in stub */ +#include <asm/processor.h> #include <xen/types.h> +#include <xen/string.h> #include <public/xen.h> -static void crash_setup_regs (struct cpu_user_regs *newregs, -struct cpu_user_regs *oldregs) -{ -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); -} +#ifdef __x86_64__ +#include <asm/x86_64/kexec.h> +#else +#include <asm/x86_32/kexec.h> +#endif #endif /* __X86_KEXEC_H__ */
xen/include/asm-x86/x86_32/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_32/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_32_H__ +#define __X86_ELF_X86_32_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_32_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_32/kexec.h new file +48 -0
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/elf.h new file +28 -0
@@ -0,0 +1,28 @@ +/****************************************************************************** +* include/asm-x86/x86_64/elf.h +* +* Created By: Horms +* +* Should pull be based on include/asm-x86_64/elf.h:ELF_CORE_COPY_REGS +* from Linux 2.6.16 +*/ + +#ifndef __X86_ELF_X86_64_H__ +#define __X86_ELF_X86_64_H__ + +#include <xen/lib.h> /* for printk() used in stub */ + +#define ELF_CORE_COPY_REGS (pr_reg, regs) \ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); + +#endif /* __X86_ELF_X86_64_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/asm-x86/x86_64/kexec.h new file +33 -0
@@ -0,0 +1,33 @@ +/****************************************************************************** +* include/asm-x86/x86_64/kexec.h +* +* Created By: Horms +* +* Should be based heavily on include/asm-x86_64/kexec.h from Linux 2.6.16 +* +*/ + +#ifndef __X86_64_KEXEC_H__ +#define __X86_64_KEXEC_H__ + +#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> +#include <public/xen.h> + +static void crash_setup_regs (struct cpu_user_regs *newregs, +struct cpu_user_regs *oldregs) +{ +printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +} + +#endif /* __X86_64_KEXEC_H__ */ + +/* +* Local variables: +* mode: C +* c-set-style: "BSD" +* c-basic-offset: 4 +* tab-width: 4 +* indent-tabs-mode: nil +* End: +*/
xen/include/public/kexec.h +3 -0
@@ -43,6 +43,9 @@*/ #define KEXEC_CMD_kexec_load 1 typedef struct xen_kexec_image { +#if defined(__i386__) || defined(__x86_64__) + unsigned long page_table_a[7]; +#endif unsigned long indirection_page; unsigned long reboot_code_buffer; unsigned long start_address;
xen/include/xen/elfcore.h +3 -0
@@ -16,6 +16,9 @@#include <public/xen.h> #define NT_PRSTATUS 1 +#define NT_XEN_DOM0_CR3 0x10000001/* XXX: Hopefully this is unused, +feel free to change to a +better/different value */ typedef struct {
kexec: x86_32
This is the x86_32 component of kexec for xen. The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_32 | 2 linux-2.6-xen-sparse/arch/i386/Kconfig | 2 linux-2.6-xen-sparse/arch/i386/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 29 linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h | 57 + linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 8 patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_i386-xen.patch | 59 + patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_i386.patch | 457 ++++++++++ patches/linux-2.6.16.13/series | 2 xen/arch/x86/crash.c | 47 + xen/arch/x86/x86_32/entry.S | 2 xen/arch/x86/x86_32/machine_kexec.c | 27 xen/include/asm-x86/x86_32/elf.h | 32 xen/include/asm-x86/x86_32/kexec.h | 65 + 14 files changed, 758 insertions(+), 33 deletions(-)
buildconfigs/linux-defconfig_xen_x86_32 +2 -0
@@ -184,6 +184,7 @@ CONFIG_MTRR=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y +CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100
@@ -2775,6 +2776,7 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set
linux-2.6-xen-sparse/arch/i386/Kconfig +1 -1
@@ -726,7 +726,7 @@ source kernel/Kconfig.hz config KEXEC bool "kexec system call (EXPERIMENTAL)" - depends on EXPERIMENTAL && !X86_XEN + depends on EXPERIMENTAL && !XEN_UNPRIVILEGED_GUEST help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot
linux-2.6-xen-sparse/arch/i386/kernel/Makefile +1 -1
@@ -89,7 +89,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o crash.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y))
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c +26 -3
@@ -68,6 +68,10 @@#include "setup_arch_pre.h" #include <bios_ebda.h> +#ifdef CONFIG_XEN +#include <xen/interface/kexec.h> +#endif +/* Forward Declaration. */ void __init find_max_pfn (void );
@@ -939,6 +943,7 @@ static void __init parse_cmdline_early (* after a kernel panic. */ else if (!memcmp(from, "crashkernel=", 12)) { +#ifndef CONFIG_XEN unsigned long size, base; size =memparse (from+12 , &from);if (*from =='@' ) {
@@ -949,6 +954,10 @@ static void __init parse_cmdline_early ( crashk_res.start = base; crashk_res.end = base + size -1 ; } +#else +printk ("Ignoring crashkernel command line, " +"parameter will be supplied by xen\n" ); +#endif }#endif #ifdef CONFIG_PROC_VMCORE
@@ -1318,9 +1327,22 @@ void __init setup_bootmem_allocator(void }#endif #ifdef CONFIG_KEXEC +#ifndef CONFIG_XEN if (crashk_res.start != crashk_res.end)reserve_bootmem (crashk_res.start, crashk_res.end - crashk_res.start +1 ); +#else + { +xen_kexec_reserve_t reservation; +BUG_ON (HYPERVISOR_kexec (KEXEC_CMD_kexec_reserve,0 , + &reservation)); +if (reservation.size) { + crashk_res.start = reservation.start; + crashk_res.end = reservation.start + + reservation.size -1 ; + } + } +#endif #endif if (!xen_feature (XENFEAT_auto_translated_physmap))
@@ -1374,6 +1396,10 @@ legacy_init_iomem_resources(struct e820e res->end = res->start + e820[i].size -1 ; res->flags =IORESOURCE_MEM |IORESOURCE_BUSY ;request_resource (&iomem_resource, res); +#ifdef CONFIG_KEXEC +request_resource (res, &crashk_res); +#endif +if (e820[i].type ==E820_RAM ) {/* * We don't know which RAM region contains kernel data,
@@ -1382,9 +1408,6 @@ legacy_init_iomem_resources(struct e820e*/ request_resource (res, code_resource);request_resource (res, data_resource); -#ifdef CONFIG_KEXEC -request_resource (res, &crashk_res); -#endif } } }
linux-2.6-xen-sparse/include/asm-i386/kexec-xen.h new file +57 -0
57 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h +8 -0
@@ -385,5 +385,13 @@ HYPERVISOR_xenoprof_op( return _hypercall2(int, xenoprof_op, op, arg); } +static inline int +HYPERVISOR_kexec ( +unsigned long op,unsigned int arg1,void * extra_args) +{ +return _hypercall3 (int, kexec_op, op, arg1, extra_args); +} + +#endif /* __HYPERCALL_H__ */
xen/arch/x86/crash.c +47 -0
65 lines not on this page · raw message
xen/arch/x86/x86_32/entry.S +2 -0
@@ -660,6 +660,7 @@ ENTRY(hypercall_table) .long do_hvm_op .long do_sysctl /* 35 */ .long do_domctl + .long do_kexec_op .rept NR_hypercalls-((.-hypercall_table)/4) .long do_ni_hypercall .endr
@@ -702,6 +703,7 @@ ENTRY(hypercall_args_table) .byte 2 /* do_hvm_op */ .byte 1 /* do_sysctl */ /* 35 */ .byte 1 /* do_domctl */ + .byte 1 /* do_kexec_op */ .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr
xen/arch/x86/x86_32/machine_kexec.c +20 -7
@@ -1,18 +1,31 @@ -/* +/****************************************************************************** * arch/x86/x86_32/machine_kexec.c -* Handle transition of Linux booting another kernel -* -* Created By: Horms <[email protected]> +* +* Created By: Horms * -* Should be losely based on arch/i386/kernel/machine_kexec.c +* Based heavily on arch/i386/machine_kexec.c from Linux 2.6.16 */ -#include <xen/lib.h> /* for printk() used in stub */ +#include <xen/types.h> #include <public/kexec.h> +#include <asm/fixmap.h> +#include <asm/processor.h> + +typedef asmlinkage void (*relocate_new_kernel_t)( +unsigned long indirection_page, +unsigned long reboot_code_buffer, +unsigned long start_address, +unsigned long page_table_a, +unsigned long has_pae);void machine_kexec (xen_kexec_image_t *image) { -printk ("STUB: " __FILE__": %s: not implemented\n" , __FUNCTION__); +relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t )fix_to_virt (FIX_KEXEC_PAGE ); + (*rnk)(image->indirection_page, image->reboot_code_buffer, + image->start_address, image->page_table_a[0 ], + (unsigned long )cpu_has_pae); }/*
xen/include/asm-x86/x86_32/elf.h +27 -5
@@ -3,17 +3,39 @@* * Created By: Horms * -* Should pull be based on include/asm-i386/elf.h:ELF_CORE_COPY_REGS -* from Linux 2.6.16 +* Based heavily on include/asm-i386/elf.h and +* include/asm-i386/system.h from Linux 2.6.16 */ #ifndef __X86_ELF_X86_32_H__#define __X86_ELF_X86_32_H__ -#include <xen/lib.h> /* for printk() used in stub */ +/* XXX: Xen doesn't have orig_eax. For kdump, on a dom0 crash, the values +* for the crashing CPU could could be passed down from dom0, but is that +* neccessary? +* Also, I'm not sure why fs and gs are derived from the CPU +* rather than regs */ -#define ELF_CORE_COPY_REGS (pr_reg, regs) \ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +#define ELF_CORE_COPY_REGS (pr_reg, regs) do { \ + unsigned i; \ + pr_reg[0] = regs->ebx; \ + pr_reg[1] = regs->ecx; \ + pr_reg[2] = regs->edx; \ + pr_reg[3] = regs->esi; \ + pr_reg[4] = regs->edi; \ + pr_reg[5] = regs->ebp; \ + pr_reg[6] = regs->eax; \ + pr_reg[7] = regs->ds; \ + pr_reg[8] = regs->es; \ + asm volatile("mov %%fs,%0":"=rm" (i)); pr_reg[9] = i; \ + asm volatile("mov %%gs,%0":"=rm" (i)); pr_reg[10] = i; \ + pr_reg[11] = 0;/* regs->orig_eax; */ \ + pr_reg[12 ] = regs->eip; \ + pr_reg[13 ] = regs->cs; \ + pr_reg[14 ] = regs->eflags; \ + pr_reg[15 ] = regs->esp; \ + pr_reg[16 ] = regs->ss; \ +} while(0);#endif /* __X86_ELF_X86_32_H__ */
xen/include/asm-x86/x86_32/kexec.h +49 -16
88 lines not on this page · raw message
patches/linux-2.6.16.13/series +2 -0
@@ -1,5 +1,7 @@ kexec-generic.patch linux-2.6.16-kexec_page_table_a_stubs.patch +linux-2.6.16-kexec_page_table_a_i386.patch +linux-2.6.16-kexec_page_table_a_i386-xen.patch blktap-aio-16_03_06.patch device_bind.patch fix-hz-suspend.patch
patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_i386.patch new file +457 -0
457 lines not on this page · raw message
patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_i386-xen.patch new file +59 -0
43 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
kexec: x86_64
This is the first x86_64 release of kexec for xen/dom0. The code is in an early phase, but it compiles and kexec:ing into a Linux kernel seems to work well. Rebooting into a new kernel may work using kdump too, but register saving support is still missing.
The x86 component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen_x86_64 | 1 linux-2.6-xen-sparse/arch/x86_64/Kconfig | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile | 2 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 26 linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h | 64 + linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h | 2 patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_x86_64-xen.patch | 151 +++ patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_x86_64.patch | 421 ++++++++++ patches/linux-2.6.16.13/series | 2 xen/arch/x86/x86_64/entry.S | 2 xen/arch/x86/x86_64/machine_kexec.c | 21 xen/include/asm-x86/x86_64/elf.h | 48 + xen/include/asm-x86/x86_64/kexec.h | 33 xen/include/public/kexec.h | 3 15 files changed, 771 insertions(+), 14 deletions(-)
buildconfigs/linux-defconfig_xen_x86_64 +1 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/Kconfig +1 -1
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/kernel/Makefile +1 -1
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +26 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/kexec-xen.h new file +64 -0
64 lines not on this page · raw message
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h +7 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/ptrace.h +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/entry.S +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/x86/x86_64/machine_kexec.c +16 -5
Lines of this file are not shown. View the raw message.
xen/include/asm-x86/x86_64/elf.h +43 -5
48 lines not on this page · raw message
xen/include/asm-x86/x86_64/kexec.h +31 -2
Lines of this file are not shown. View the raw message.
xen/include/public/kexec.h +3 -0
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/series +2 -0
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_x86_64.patch new file +421 -0
421 lines not on this page · raw message
patches/linux-2.6.16.13/linux-2.6.16-kexec_page_table_a_x86_64-xen.patch new file +151 -0
151 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
kexec: ia64
This is the ia64 component of kexec for ia64. The generic component is a prerequsite for this patch.
buildconfigs/linux-defconfig_xen0_ia64 | 3 linux-2.6-xen-sparse/arch/ia64/Kconfig | 23 linux-2.6-xen-sparse/arch/ia64/kernel/entry.S | 2 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 7 linux-2.6-xen-sparse/include/asm-ia64/kexec-xen.h | 36 patches/linux-2.6.16.13/kexec-ia64-1.patch | 767 +++++++++++++++++++++ patches/linux-2.6.16.13/kexec-ia64-2.patch | 596 ++++++++++++++++ patches/linux-2.6.16.13/kexec-ia64-xen.patch | 266 +++++++ patches/linux-2.6.16.13/series | 3 xen/arch/ia64/asm-offsets.c | 2 xen/arch/ia64/linux-xen/smp.c | 32 xen/arch/ia64/xen/crash.c | 110 ++- xen/arch/ia64/xen/hypercall.c | 2 xen/arch/ia64/xen/machine_kexec.c | 60 + xen/include/asm-ia64/kexec.h | 62 + xen/include/asm-ia64/linux-xen/asm/smp.h | 9 xen/include/public/kexec.h | 3 17 files changed, 1965 insertions(+), 18 deletions(-)
buildconfigs/linux-defconfig_xen0_ia64 +3 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/ia64/Kconfig +23 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/arch/ia64/kernel/entry.S +1 -1
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +7 -0
Lines of this file are not shown. View the raw message.
linux-2.6-xen-sparse/include/asm-ia64/kexec-xen.h new file +36 -0
Lines of this file are not shown. View the raw message.
xen/arch/ia64/asm-offsets.c +2 -0
Lines of this file are not shown. View the raw message.
xen/arch/ia64/linux-xen/smp.c +32 -0
Lines of this file are not shown. View the raw message.
xen/arch/ia64/xen/crash.c +103 -7
110 lines not on this page · raw message
xen/arch/ia64/xen/hypercall.c +1 -1
Lines of this file are not shown. View the raw message.
xen/arch/ia64/xen/machine_kexec.c +55 -5
60 lines not on this page · raw message
xen/include/asm-ia64/kexec.h +58 -4
62 lines not on this page · raw message
xen/include/asm-ia64/linux-xen/asm/smp.h +9 -0
Lines of this file are not shown. View the raw message.
xen/include/public/kexec.h +3 -0
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/series +3 -0
Lines of this file are not shown. View the raw message.
patches/linux-2.6.16.13/kexec-ia64-1.patch new file +767 -0
767 lines not on this page · raw message
patches/linux-2.6.16.13/kexec-ia64-2.patch new file +596 -0
596 lines not on this page · raw message
patches/linux-2.6.16.13/kexec-ia64-xen.patch new file +266 -0
266 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Part of the diff is not shown here. View the raw message.
Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Horms and Magnus
Good work. :-)
I have one commet.
I believe crash_kexec should be directly called when unknown NMI is occurred.
In your patch, crash_kexec is called as the bellow.
1. unknown NMI is occurred. (e.g. by pushing NMI botton)
2. xen recieved NMI and call do_nmi.
3. xen report to dom0 by using raise_softirq(NMI_SOFTIRQ).
4. dom0 call crash_kexec of dom0.
5. crash_kexec of dom0 call crash_kexec of xen
Am I correct?
The above process is not reliable if I'm correct.
So I belive crash_kexec of xen should be directly called like the following patch.
xen/arch/x86/traps.c Thu Aug 31 17:40:19 2006 +0900 renamed from xen/arch/x86/traps.c Thu Aug 31 13:12:26 2006 +0900 +1 -0
@@ -1612,6 +1612,7 @@ asmlinkage void do_nmi(struct cpu_user_r else if ( reason & 0x40 ) io_check_error(regs); else if ( !nmi_watchdog ) + crash_kexec(NULL); unknown_nmi_error((unsigned char)(reason&0xff)); } }
What do you think about it?
Best Regards,
Akio Takebe
Quoted 88 lines
Hi,
here is an update of the kexec/kdump patchset.
Summary:
* Up port to xen-unstable.hg-11296 (
45f6ee334fcc)
- kexec hypercall number fragment is now in xen-unstable
* Makekexec_page_to_pfnand friends need to be architecture specific
- this abstraction is needed to support ia64
* Usekexec_page_to_pfninmachine_kexec_setup_load_arg()
- this abstraction is needed to support ia64
* Renamedo_kexectodo_kexec_opto make it consistent with other hypercalls
* Add ppc stubs
* Add ia64 supportArchitectures:
x86_32:Seems to be working fine
x86_64:Probably working fine, but I can't test this as dom0 refuses to boot for me on xen-unstable-11388 (
50aea0ec406b). That is, even without the kexec patches. I'm not sure what the problem is and I've devicided to get these patches out rather and investigate later.ia64:
This patchset also, for the first time, includes ia64 code. Please note that this currently does _not_ work. I am actually struggling to work out why, and would really appreaciate it if someone could cast an eye over it.
One possible area of concern is that
relocate_kernelwipes out TLB entries. However many of the entries instated in arch/ia64/xen/xenasm.S:ia64_new_rr7() are not wiped. In particular,VHPT_ADDR, Shared info, and Mapmapped_regare not handled byrelocate_kernel(), and the handling of current seems to be different.There are also problems with constants inside
kexec_fake_sal_rendez. However this function probably also suffers the same problems asrelocate_kernel. And it is easy not ro runkexec_fake_sal_rendezby booting xen with maxcpus=1, thus avoiding callingkexec_fake_sal_rendez, which is used in cpu shutdown.ppc:
stubs only
Patches
1. 51.1-kexec-generic-upstream.patch
* Common code for all architectures,
the basic plumbing for kexec/kdump2. 51.1.1-kexec-trigger_crash_dump.patch
* xen-console triggercrash_dump
* Depends on 13. 51.2.1-kexec-x86-upstream.patch
* Glue between 1, and 3 and 4.
* Depends on 14. 51.2.1.1-kexec-x86_32-upstream.patch
* Kexec/kdump forx86_32
* Depends on 3 (and 1)5. 51.2.31.2-kexec-x86_64-upstream.patch
* Kexec/kdump forx86_64
* Depends on 3 (and 1)6. 51.2.2-kexec-ia64-upstream.patch
* Kexec/kdump for ia64
* Depends 1Discussion:
Email is always good. Also my partner in crime, Magnus Damm, will be at Xen Summit.
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 31 lines · Akio Takebe
Hi, Horms and Magnus
Good work. :-)
I have one commet.I believe
crash_kexecshould be directly called when unknown NMI is occurred.
In your patch,crash_kexecis called as the bellow.
1. unknown NMI is occurred. (e.g. by pushing NMI botton)
2. xen recieved NMI and calldo_nmi.
3. xen report to dom0 by usingraise_softirq(NMI_SOFTIRQ).
4. dom0 callcrash_kexecof dom0.
5.crash_kexecof dom0 callcrash_kexecof xenAm I correct?
The above process is not reliable if I'm correct.
So I belivecrash_kexecof xen should be directly called like the following patch.diff -r
9611a5c9e1a1xen/arch/x86/traps.cxen/arch/x86/traps.c Thu Aug 31 17:40:19 2006 +0900 renamed from xen/arch/x86/traps.c Thu Aug 31 13:12:26 2006 +0900 +1
-0@@ -1612,6 +1612,7 @@ asmlinkage void do_nmi(struct cpu_user_r else if ( reason & 0x40 ) io_check_error(regs); else if ( !nmi_watchdog ) + crash_kexec(NULL); unknown_nmi_error((unsigned char)(reason&0xff)); } }
Quoted 1 line
What do you think about it?
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
xen/arch/x86/traps.c +3 -1
@@ -1611,8 +1611,10 @@mem_parity_error (regs); else if ( reason & 0x40 )io_check_error (regs); - else if ( !nmi_watchdog ) + else if ( !nmi_watchdog ) { +crash_kexec (NULL );unknown_nmi_error ((unsigned char )(reason&0xff )); + } } }
Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Horms
Quoted 2 lines
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
Oops, You're right. But I think unknown_nmi_error() is not called, because crash_kexec() is called before that.
Yes, I'll test it. :-)
Quoted 5 lines
xen/arch/x86/traps.c +0
-0@@ -1611,8 +1611,10 @@mem_parity_error (regs);
xen/arch/x86/traps.c line 1620
Quoted 10 lines
xen/arch/x86/traps.c +3
-1else if ( reason &0x40 )io_check_error (regs); -else if ( !nmi_watchdog ) +else if ( !nmi_watchdog ) { +crash_kexec (NULL );unknown_nmi_error ((unsigned char )(reason&0xff )); + } } }
Best Regards,
Akio Takebe
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 6 lines
Hi, Horms
Quoted 2 lines
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
Oops, You're right. But I think
unknown_nmi_error()is not called, becausecrash_kexec()is called before that.
Sorry.
In the only case of CONFIG_KEXEC=y, the above is right.
Best Regards,
Akio Takebe
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 8 lines · Akio Takebe
Quoted 6 lines
Hi, Horms
Quoted 2 lines
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
Oops, You're right. But I think
unknown_nmi_error()is not called, becausecrash_kexec()is called before that.Sorry.
In the only case ofCONFIG_KEXEC=y, the above is right.
Yes, I think that is the case. I will put your patch into the kexec series, as I think that it is a worthy addition.
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Horms
I tested the following patch with Horms kexec patch.
My tests is:
push NMI bottun after loading kdump kernel.
The results is:
OK, I could get vmcore
xen/arch/x86/traps.c Tue Sep 05 06:37:49 2006 +0900 renamed from xen/arch/x86/traps.c Tue Aug 22 14:59:16 2006 +0100 +5 -1
@@ -105,6 +105,8 @@ static int debug_stack_lines = 20; static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); +extern void crash_kexec(struct cpu_user_regs *regs); + #ifdef CONFIG_X86_32 #define stack_words_per_line 8 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)
@@ -1611,8 +1613,10 @@ asmlinkage void do_nmi(struct cpu_user_r mem_parity_error(regs); else if ( reason & 0x40 ) io_check_error(regs); - else if ( !nmi_watchdog ) + else if ( !nmi_watchdog ){ + crash_kexec(NULL); unknown_nmi_error((unsigned char)(reason&0xff)); + } } }
Best Regards,
Akio Takebe
Quoted 23 lines · Akio Takebe
Quoted 8 lines
Quoted 6 lines
Hi, Horms
Quoted 2 lines
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
Oops, You're right. But I think
unknown_nmi_error()is not called, becausecrash_kexec()is called before that.Sorry.
In the only case ofCONFIG_KEXEC=y, the above is right.Yes, I think that is the case. I will put your patch into the kexec series, as I think that it is a worthy addition.
Signature · 9 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/ _______________________________________________ Xen-devel mailing list [email protected] http://lists.xensource.com/xen-devel
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
[ Ian Campbell added to CC list ]
Quoted 9 lines · Akio Takebe
Hi, Horms
I tested the following patch with Horms kexec patch.
My tests is:
push NMI bottun after loading kdump kernel.The results is:
OK, I could get vmcore
Hi Takebe-san,
this patch seems ok to me, but it seems that it never went into the tree. Ian, what are your thoughts on it?
Quoted 53 lines
diff -r
b688d4a68a3exen/arch/x86/traps.cxen/arch/x86/traps.c Tue Sep 05 06:37:49 2006 +0900 renamed from xen/arch/x86/traps.c Tue Aug 22 14:59:16 2006 +0100 +5
-1@@ -105,6 +105,8 @@ static int debug_stack_lines = 20; static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); +extern void crash_kexec(struct cpu_user_regs *regs); + #ifdef CONFIG_X86_32 #define stack_words_per_line 8 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)@@ -1611,8 +1613,10 @@ asmlinkage void do_nmi(struct cpu_user_r mem_parity_error(regs); else if ( reason & 0x40 ) io_check_error(regs); - else if ( !nmi_watchdog ) + else if ( !nmi_watchdog ){ + crash_kexec(NULL); unknown_nmi_error((unsigned char)(reason&0xff)); + } } }Best Regards,
Akio Takebe
Quoted 23 lines · Akio Takebe
Quoted 8 lines
Quoted 6 lines
Hi, Horms
Quoted 2 lines
That seems like a good idea to me. Though I think you are missing { }. Can you test to see if this works?
Oops, You're right. But I think
unknown_nmi_error()is not called, becausecrash_kexec()is called before that.Sorry.
In the only case ofCONFIG_KEXEC=y, the above is right.Yes, I think that is the case. I will put your patch into the kexec series, as I think that it is a worthy addition.
Signature · 9 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/ _______________________________________________ Xen-devel mailing list [email protected] http://lists.xensource.com/xen-devel
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
Re: [Xen-devel] Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Horms and Ian
Thank you for your reply, Horms.
I forgot Signed-off-by of the patch.
Is the Signed-off-by OK, Horms?
Best Regards,
Akio Takebe
Quoted 48 lines
[ Ian Campbell added to CC list ]
Quoted 9 lines · Akio Takebe
Hi, Horms
I tested the following patch with Horms kexec patch.
My tests is:
push NMI bottun after loading kdump kernel.The results is:
OK, I could get vmcoreHi Takebe-san,
this patch seems ok to me, but it seems that it never went into the tree. Ian, what are your thoughts on it?
Quoted 29 lines
diff -r
b688d4a68a3exen/arch/x86/traps.cxen/arch/x86/traps.c Tue Sep 05 06:37:49 2006 +0900 renamed from xen/arch/x86/traps.c Tue Aug 22 14:59:16 2006 +0100 +5
-1@@ -105,6 +105,8 @@ static int debug_stack_lines = 20; static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); +extern void crash_kexec(struct cpu_user_regs *regs); + #ifdef CONFIG_X86_32 #define stack_words_per_line 8 #define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp)@@ -1611,8 +1613,10 @@ asmlinkage void do_nmi(struct cpu_user_r mem_parity_error(regs); else if ( reason & 0x40 ) io_check_error(regs); - else if ( !nmi_watchdog ) + else if ( !nmi_watchdog ){ + crash_kexec(NULL); unknown_nmi_error((unsigned char)(reason&0xff)); + } } }Best Regards,
Akio Takebe
Horms
Acked-byRe: Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 9 lines · Akio Takebe
Hi, Horms and Ian
Thank you for your reply, Horms.
I forgot Signed-off-by of the patch.Signed-off-by Horms <[email protected]>Signed-off-by Akio Takebe <[email protected]>Is the Signed-off-by OK, Horms?
Actually, i think this might be better:
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
In reply to HormsQuoted 10 lines · Horms
[ Ian Campbell added to CC list ]
Quoted 7 lines · Akio Takebe
Hi, Horms
I tested the following patch with Horms kexec patch.
My tests is:
push NMI bottun after loading kdump kernel.
Quoted 8 lines
Quoted 2 lines
The results is:
OK, I could get vmcoreHi Takebe-san,
this patch seems ok to me, but it seems that it never went into the tree. Ian, what are your thoughts on it?
The default in non-debug builds is to forward the crash to domain 0 so we'd never get here, although I'd expect domain 0 probably does a kdump itself nowadays when an NMI is received.
For debug builds I guess it does make sense. Assuming crash_kexec gracefully returns if no crash kernel has been loaded, so that the old behaviour is preserved, then the behaviour would be fine with me. Alternatively "nmi=kdump" on the command line might be nice.
Quoted 1 line
Quoted 1 line
+extern void
crash_kexec(struct cpu_user_regs *regs);
I can't find kexec_crash in xen-unstable. Is it now crash_kexec, with no parameters? Whatever the function is now called it should probably be in a header somewhere therefore no local prototype required.
Quoted 1 line
Quoted 1 line
+ else if ( !nmi_watchdog ){
Needs a space between ) and {.
Ian.
Re: [Xen-devel] Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Ian and Horms
I add the nmi=kdump option as Ian suggested.
What do you think about it?
---
xen/arch/x86/traps.c +3 -0
@@ -1897,6 +1897,7 @@ asmlinkage void io_check_error(struct cp {case 'd' :/* 'dom0' */ nmi_dom0_report (_XEN_NMIREASON_io_error); +case 'k' :/* 'kdump' */ case 'i' :/* 'ignore' */ break ;default :/* 'fatal' */
@@ -1916,6 +1917,8 @@ static void unknown_nmi_error(unsigned c {case 'd' :/* 'dom0' */ nmi_dom0_report (_XEN_NMIREASON_unknown); +case 'k' :/* 'kdump' */ +kexec_crash ();case 'i' :/* 'ignore' */ break ;default :/* 'fatal' */
Best Regards,
Akio Takebe
Re: Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 4 lines · Akio Takebe
Hi, Ian and Horms
I add the nmi=kdump option as Ian suggested.
What do you think about it?
Won't the default fatal_trap() behaviour cause you to drop into kdump code anyway? fatal_trap -> panic -> kexec_crash.
-- Keir
Re: [Xen-devel] Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Keir
Quoted 10 lines · Akio Takebe
Quoted 5 lines
Hi, Ian and Horms
I add the nmi=kdump option as Ian suggested.
What do you think about it?Won't the default
fatal_trap()behaviour cause you to drop into kdump code anyway?fatal_trap-> panic ->kexec_crash.
Oops, you're right.
All we do is just setting nmi=kdump.
Best Regards,
Akio Takebe
Re: [Xen-devel] Re: [PATCH] kexec: framework and i386 (Take XIV)
Hi, Keir
Quoted 6 lines
Hi, Keir
Quoted 4 lines · Akio Takebe
Quoted 3 lines
Hi, Ian and Horms
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
I add the nmi=kdump option as Ian suggested.
What do you think about it?Won't the default
fatal_trap()behaviour cause you to drop into kdump code anyway?fatal_trap-> panic ->kexec_crash.Oops, you're right.
All we do is just setting nmi=kdump.
Sorry, please ignore the previous mail.
Yes, as Keir said fatal_trap() should call panic.
All we do is just setting nmi=fatal.
Best Regards,
Akio Takebe
Re: [Xen-devel] [PATCH] kexec: framework and i386 (Take XIV)
In reply to HormsQuoted 6 lines · Horms
x86_64:Probably working fine, but I can't test this as dom0 refuses to boot for me on xen-unstable-11388 (
50aea0ec406b). That is, even without the kexec patches. I'm not sure what the problem is and I've devicided to get these patches out rather and investigate later.
I tried some versions of xen with kdump patches on x86_64, following is the result.
I'm sorry for it wasn't done in systematic style.
chengeset result
11414 doesn't boot 11251 doesn't boot 11134 doesn't boot
11076 boot
Signature · 1 line
Kazuo Moriwaka
Re: [PATCH] kexec: framework and i386 (Take XIV)
Quoted 13 lines · Kazuo Moriwaka
Quoted 6 lines · Horms
x86_64:Probably working fine, but I can't test this as dom0 refuses to boot for me on xen-unstable-11388 (
50aea0ec406b). That is, even without the kexec patches. I'm not sure what the problem is and I've devicided to get these patches out rather and investigate later.I tried some versions of xen with kdump patches on
x86_64, following is the result.
I'm sorry for it wasn't done in systematic style.
Quoted 5 lines
chengeset result
11414 doesn't boot 11251 doesn't boot 11134 doesn't boot11076 boot
Thanks, that is valuable information.
I am guessing that doing a bisection between 11134 and 11076 would help shed some light and what has gone astray.
Signature · 3 lines
Horms H: http://www.vergenet.net/~horms/ W: http://www.valinux.co.jp/en/
Re: Hypercall number assignment convension (was Re: Re: [PATCH]: kexec: framework and i386)
In reply to Keir FraserQuoted 6 lines · Keir Fraser
The list of __HYPERVISOR_* defines in
public/xen.hin the main xen repository is the canonical place. For hypercalls in our tree, simply grabbing the next number in sequence usually makes sense. I'm not sure whether having structure to the hypercall numbers makes sense (e.g., a range for arch-specific usage) -- if so then maybe allocating from 64 upwards would make sense.
Actually xen/ia64 requires only one hypercall number for now. I attached the patches to take one.
I'm not sure what name you prefer, so I attached two patches. Please apply which you prefer. (or invent whatever name you like.)
Signature · 1 line
yamahata
take arch-specific purpose hypercall number.
xen/include/public/xen.h +1 -0
@@ -62,6 +62,7 @@#define __HYPERVISOR_sched_op 29#define __HYPERVISOR_callback_op 30#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_arch_specific_0 32/* arch-specific purpose */ /* * VIRTUAL INTERRUPTS
take ia64 specific hypercall number.
xen/include/public/xen.h +1 -0
@@ -62,6 +62,7 @@#define __HYPERVISOR_sched_op 29#define __HYPERVISOR_callback_op 30#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_ia64_dom0vp_op 32/* ia64 only */ /* * VIRTUAL INTERRUPTS
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel