kexec on ia64
PATCH 1/1 kexec on ia64
I have been able to get kexec working on ia64. I am attaching the kernel
patch and kexec-tools patch. For the kernel patch, start with 2.6.8
kernel from kernel.org, apply ia64 patch
<http://www.kernel.org/pub/linux/kernel/ports/ia64/v2.6/linux-2.6.8-ia64-040901.diff.bz2>, apply Eric' 2.6.8.1-kexec3 patch <http://www.xmission.com/~ebiederm/files/kexec/2.6.8.1-kexec3> and apply attached 2.6.8.1-kexec3-ia64.diff patch. For kexec-tools, apply attached kexec-tools-1.98-ia64.diff patch to Eric's kexec-tools 1.98 sources <http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.98.tgz>.
At this point, I have done minimal testing. Here is what I know does not work currently:
1. No support for initrd for kexec'd kernel
2. No support for new kernel parameters for kexec'd kernel.
3. If a kernel is booted up with "mem=" or "max_addr=" to restrict the amount of memory, a kernel kexec'd from this kernel will only see the same amount of memory as this one. This is not only due to the new kernel being kexec'd with the same parameter, but also becuase the EFI memory map as passed to the kernel by ELILO gets trimmed very early on by the kernel. I have tried adding code to save the memory map early on and then pass this saved memory map to kexec'd kernel, but apparently I still am not saving it early enough. I wait until bootmem allocator has been initailized so I can allocate memory to save unmolested EFI memory map in. In the process of initializing bootmem allocator, kernel calls efi-Memory_map_walk() which in turn trims the memory map. I am looking into allocating memory out of the EFI memory map before the first efi_mem_map_walk() happens, so I can save pristine EFI memmap for use later by kexec.
Here is what I have not tested yet:
1. I am not sure if ACPI subsystem is happy in kexec'd kernel. I have not seen any problems, but I have not tested it enough either.
2. Stability of kexec'd kernel over long term. It ran fine for an hour not doing much :)
Here is what I am working on next:
1. Save EFI memory map before it is trimmed.
2. Fix up /proc/iomem on ia64 so we can enable validating memory range in kexec tools.
3. Add a /proc interface to enable reboots on panic and INIT (and possibly MCA) to be kexec reboots.
4. Add initrd support.
Any feedback on these patches is welcome. Any patch to fix problems in these patches is very much appreciated :)
Signature · 9 lines
Khalid ==================================================================== Khalid Aziz Linux and Open Source Lab (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
arch/ia64/Kconfig +17 -0
@@ -278,6 +278,23 @@ little bigger and slows down execution a bit, but it is generally a good idea to turn this on. If you're unsure, say Y. +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + 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 + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + config IA64_PALINFO tristate "/proc/pal support" help
arch/ia64/kernel/Makefile +1 -0
@@ -17,6 +17,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o obj-$(CONFIG_IA64_CYCLONE) += cyclone.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o
arch/ia64/kernel/efi.c +29 -1
@@ -17,6 +17,9 @@* * Goutham Rao: <[email protected]> * Skip non-WB memory and ignore empty memory ranges. +* +* Nov 12, 2004: Added initial support for kexec +* - Khalid Aziz <[email protected]> */ #include <linux/config.h> #include <linux/module.h>
@@ -37,6 +40,10 @@extern efi_status_t efi_call_phys (void *, ...);struct efi efi; +#ifdef CONFIG_KEXEC +unsigned long kexec_reboot =0 ; +unsigned long saved_efi_memmap_size; +#endif EXPORT_SYMBOL (efi);static efi_runtime_services_t *runtime;static unsigned long mem_limit = ~0UL , max_addr = ~0UL ;
@@ -464,6 +471,9 @@* Cannot write to CRx with PSR.ic=1 */ psr =ia64_clear_ic (); +#if CONFIG_KEXEC +ia64_ptr (0x01 , vaddr & mask,IA64_GRANULE_SHIFT ); +#endif ia64_itr (0x1 ,IA64_TR_PALCODE , vaddr & mask,pte_val (pfn_pte (md->phys_addr >>PAGE_SHIFT ,PAGE_KERNEL )),IA64_GRANULE_SHIFT );
@@ -503,6 +513,14 @@if (end != cp)break ; cp = end; +#ifdef CONFIG_KEXEC + }else if (memcmp (cp,"kexec_reboot" ,12 ) ==0 ) { + cp +=12 ; + kexec_reboot =1 ; +if (end != cp) +break ; + cp = end; +#endif }else {while (*cp !=' ' && *cp) ++cp;
@@ -595,6 +613,9 @@ }#endif +#ifdef CONFIG_KEXEC + saved_efi_memmap_size = ia64_boot_param->efi_memmap_size; +#endif efi_map_pal_code ();efi_enter_virtual_mode (); }
@@ -647,10 +668,17 @@ } } - status =efi_call_phys (__va (runtime->set_virtual_address_map), +#ifdef CONFIG_KEXEC +if (kexec_reboot ==0 ) + status =efi_call_phys (__va (runtime->set_virtual_address_map), ia64_boot_param->efi_memmap_size, efi_desc_size, ia64_boot_param->efi_memdesc_version, ia64_boot_param->efi_memmap); +else { +printk (KERN_INFO "kexec'd kernel: Not virtualizing EFI\n" ); + status =EFI_SUCCESS ; + } +#endif if (status !=EFI_SUCCESS ) {printk (KERN_WARNING "warning: unable to switch EFI into virtual mode " "(status=%lu)\n" , status);
arch/ia64/kernel/entry.S +1 -1
@@ -1525,7 +1525,7 @@ data8 sys_mq_timedreceive // 1265 data8 sys_mq_notify data8 sys_mq_getsetattr - data8 sys_ni_syscall // reserved for kexec_load + data8 sys_kexec_load data8 sys_ni_syscall data8 sys_ni_syscall // 1270 data8 sys_ni_syscall
arch/ia64/kernel/machine_kexec.c +179 -0
179 lines not on this page · raw message
arch/ia64/kernel/relocate_kernel.S +228 -0
228 lines not on this page · raw message
arch/ia64/mm/contig.c +10 -0
@@ -29,6 +29,11 @@static unsigned long num_dma_physpages;#endif +#ifdef CONFIG_KEXEC +void *saved_efi_memmap; +extern unsigned long saved_efi_memmap_size; +#endif +/** * show_mem - display a memory statistics summary *
@@ -164,6 +169,11 @@/* Free all available memory, then mark bootmem-map as being in use. */ efi_memmap_walk (filter_rsvd_memory, free_bootmem);reserve_bootmem (bootmap_start, bootmap_size); +#ifdef CONFIG_KEXEC +/* Save EFI memory map for use later when kexec'ing a kernel */ + saved_efi_memmap =alloc_bootmem (saved_efi_memmap_size); +memcpy (saved_efi_memmap,__va (ia64_boot_param->efi_memmap), saved_efi_memmap_size); +#endif find_initrd (); }
arch/ia64/mm/discontig.c +11 -0
@@ -40,6 +40,11 @@static struct early_node_data mem_data[NR_NODES ]__initdata ; +#ifdef CONFIG_KEXEC +void *saved_efi_memmap; +extern unsigned long saved_efi_memmap_size; +#endif +/** * reassign_cpu_only_nodes - called from find_memory to move CPU-only nodes to a memory node *
@@ -459,6 +464,12 @@reserve_pernode_space ();initialize_pernode_data (); +#ifdef CONFIG_KEXEC +/* Save EFI memory map for use later when kexec'ing a kernel */ + saved_efi_memmap =alloc_bootmem (saved_efi_memmap_size); +memcpy (saved_efi_memmap,__va (ia64_boot_param->efi_memmap), saved_efi_memmap_size); +#endif + max_pfn = max_low_pfn;find_initrd ();
include/asm-ia64/kexec.h +14 -0
@@ -0,0 +1,14 @@ +#ifndef _ASM_IA64_KEXEC_H +#define _ASM_IA64_KEXEC_H + + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) +/* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE + +#define KEXEC_CONTROL_CODE_SIZE (8192 + 8192 + 4096) + +#endif /* _ASM_IA64_KEXEC_H */
include/asm-ia64/mmu_context.h +2 -0
@@ -203,5 +203,7 @@#define switch_mm (prev_mm,next_mm,next_task) activate_mm(prev_mm, next_mm) +extern void use_mm (struct mm_struct *mm); +# endif /* ! __ASSEMBLY__ */ #endif /* _ASM_IA64_MMU_CONTEXT_H */
kernel/sys.c +1 -1
@@ -516,7 +516,7 @@return -EINVAL ; }notifier_call_chain (&reboot_notifier_list,SYS_RESTART ,NULL ); - system_state =SYSTEM_BOOTING ; + system_state =SYSTEM_RESTART ;device_shutdown ();printk (KERN_EMERG "Starting new kernel\n" );machine_shutdown ();
Makefile.main +7 -0
@@ -22,6 +22,7 @@ BINARIES_ppc:=$(SBINDIR)/kexec BINARIES_ppc64:=$(SBINDIR)/kexec BINARIES_x86_64:=$(SBINDIR)/kexec $(BINDIR)/kexec_test +BINARIES_ia64:=$(SBINDIR)/kexec BINARIES:=$(BINARIES_$(ARCH)) TARGETS:=$(BINARIES) $(MAN_PAGES)
@@ -41,6 +42,12 @@ @echo ALPHA_AR=$(ALPHA_AR) @echo ALPHA_LD=$(ALPHA_LD) +install: + mkdir -p $(DESTDIR)/usr/sbin + install -m700 $(SBINDIR)/kexec $(DESTDIR)/usr/sbin + mkdir -p $(DESTDIR)/usr/share/man/man8 + install -m644 kexec/kexec.8 $(DESTDIR)/usr/share/man/man8 + clean: find $(OBJDIR) ! -name '*.d' -type f | xargs rm -f
kexec/Makefile +4 -0
@@ -25,6 +25,10 @@ ifeq ($(ARCH),ppc64) KEXEC_C_SRCS+= kexec/kexec-zImage-ppc64.c endif +ifeq ($(ARCH),ia64) +KEXEC_C_SRCS+= kexec/kexec-ia64.c kexec/kexec-elf64-ia64.c +KEXEC_C_SRCS+= kexec/ifdown.c +endif KEXEC_C_OBJS:= $(patsubst %.c, $(OBJDIR)/%.o, $(KEXEC_C_SRCS)) KEXEC_C_DEPS:= $(patsubst %.c, $(OBJDIR)/%.d, $(KEXEC_C_SRCS))
kexec/kexec-elf64-ia64.c +306 -0
306 lines not on this page · raw message
kexec/kexec-ia64.c +47 -0
47 lines not on this page · raw message
kexec/kexec-ia64.h +9 -0
@@ -0,0 +1,9 @@ +#ifndef KEXEC_IA64_H +#define KEXEC_IA64_H + +int elf64_ia64_probe (FILE *file); +int elf64_ia64_load (FILE *file,int argc,char **argv, +void **ret_entry,struct kexec_segment **ret_segments,int *ret_nr_segments); +void elf64_ia64_usage (void ); + +#endif /* KEXEC_IA64_H */
kexec/kexec.8 +45 -0
45 lines not on this page · raw message
kexec/kexec.c +10 -0
@@ -35,6 +35,16 @@ {int i; +#ifdef __ia64__ +/* +* /proc/iomem on ia64 does not show where all memory is. If +* that is fixed up, we can make use of that to validate +* the memory range kernel will be loade din. Until then..... +* -- Khalid Aziz +*/ +return 0 ; +#endif +for (i =0 ; i < memory_ranges; i++) {unsigned long mstart, mend;unsigned long sstart, send;
Quoted 3 lines
Here is what I am working on next:
1. Save EFI memory map before it is trimmed.
This code has been "evolving" for a long time now, more layers get addded to solve each new problem. If you get time, please step back about a half-mile and take a look at the big picture and see you you can see a better way to do the scanning and trimming and re-scanning. The overall problem statement (ignore anything except complete granules, honour the command-line arguments max_mem/max_addr, allocate a temporary bitmap for bootmem) seems like it shouldn't require such complex code :-) You can add your own new requirement to not modify the original EFI tables so that they can be re-scanned by a new kernel after kexec (new kernel might have a different granule size).
-Tony
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Tony
Tony> You can add your own new requirement to not modify the Tony> original EFI tables so that they can be re-scanned by a new Tony> kernel after kexec (new kernel might have a different granule Tony> size).
That certainly would be the right way to go about it. It would also make it less likely that something else might get confused when changing the memory map underneath it.
--david
Quoted 16 lines · Tony
Quoted 3 lines
Here is what I am working on next:
1. Save EFI memory map before it is trimmed.
This code has been "evolving" for a long time now, more layers get addded to solve each new problem. If you get time, please step back about a half-mile and take a look at the big picture and see you you can see a better way to do the scanning and trimming and re-scanning. The overall problem statement (ignore anything except complete granules, honour the command-line arguments max_mem/max_addr, allocate a temporary bitmap for bootmem) seems like it shouldn't require such complex code :-) You can add your own new requirement to not modify the original EFI tables so that they can be re-scanned by a new kernel after kexec (new kernel might have a different granule size).
Quoted 1 line
-Tony
Tony,
I definitely like this idea better. I have been talking to another developer who is struggling with efi_mem_map_walk() trimming original EFI memory map for "mem=" and "max_addr=". We have discussed separating efi_mem_map_walk() into three separate routines, one to simply walk memory map and compute the physical memory size without touching map, one to trim memory map for granule size and one to trim memory map for "mem=" and "max_addr=". This will allow us to save an untouched memory map in between calls to these routines. Now that I know you guys are open to something like this, we will pursue it further :)
Signature · 9 lines
Khalid ================================== Khalid Aziz Linux and Open Source Lab (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
I have noticed that on x86, trimming memory with "mem=" has no effect on RAM reported by /proc/iomem. I assume we want the same behavior on ia64. This would mean we definitely need to save an untrimmed EFI memory map.
--
Khalid
Quoted 13 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Tony
Tony> You can add your own new requirement to not modify the Tony> original EFI tables so that they can be re-scanned by a new Tony> kernel after kexec (new kernel might have a different granule Tony> size).
That certainly would be the right way to go about it. It would also make it less likely that something else might get confused when changing the memory map underneath it.
--david
Signature · 7 lines
================================== Khalid Aziz Linux and Open Source Lab (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
PATCH 1/1 kexec on ia64
In reply to Khalid AzizI have ported the original patch I had done for kexec on ia64 on 2.6.8 kernel and fixed a few bugs in the original patch. Attached is a patch for kernel 2.6.14-rc4. It works with normal kexec reboot on an HP rx2600. I am now working on adding support for crash kexec. I am also working on kexec on INIT which I currently have working on 2.6.10 kernel. I am porting it to 2.6.14-rc kernel.
Attached patch needs to be applied on top of iomem and efi_memmapwalk patches already in ia64 test tree (these patches attached as well for those who may need them).
Signature · 9 lines
Khalid ==================================================================== Khalid Aziz Open Source and Linux Organization (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
arch/ia64/kernel/efi.c +87 -0
@@ -923,3 +923,90 @@ efi_memmap_init(unsigned long *s, unsign *s = (u64 )kern_memmap; *e = (u64 )++k; } + +void +efi_initialize_iomem_resources (struct resource *code_resource, +struct resource *data_resource) +{ +struct resource *res; +void *efi_map_start, *efi_map_end, *p; +efi_memory_desc_t *md; +u64 efi_desc_size; +char *name; +unsigned long flags; + + efi_map_start =__va (ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + + res =NULL ; + +for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + md = p; + +if (md->num_pages ==0 )/* should not happen */ +continue ; + + flags =IORESOURCE_MEM ; +switch (md->type) { + +case EFI_MEMORY_MAPPED_IO : +case EFI_MEMORY_MAPPED_IO_PORT_SPACE : +continue ; + +case EFI_LOADER_CODE : +case EFI_LOADER_DATA : +case EFI_BOOT_SERVICES_DATA : +case EFI_BOOT_SERVICES_CODE : +case EFI_CONVENTIONAL_MEMORY : +if (md->attribute &EFI_MEMORY_WP ) { + name ="System ROM" ; + flags |=IORESOURCE_READONLY ; + }else { + name ="System RAM" ; + } +break ; + +case EFI_ACPI_MEMORY_NVS : + name ="ACPI Non-volatile Storage" ; + flags |=IORESOURCE_BUSY ; +break ; + +case EFI_UNUSABLE_MEMORY : + name ="reserved" ; + flags |=IORESOURCE_BUSY |IORESOURCE_DISABLED ; +break ; + +case EFI_RESERVED_TYPE : +case EFI_RUNTIME_SERVICES_CODE : +case EFI_RUNTIME_SERVICES_DATA : +case EFI_ACPI_RECLAIM_MEMORY : +default : + name ="reserved" ; + flags |=IORESOURCE_BUSY ; +break ; + } + +if ((res =kcalloc (1 ,sizeof (struct resource ),GFP_KERNEL )) ==NULL ) { +printk (KERN_ERR "failed to alocate resource for iomem\n" ); +return ; + } + + res->name = name; + res->start = md->phys_addr; + res->end = md->phys_addr + (md->num_pages <<EFI_PAGE_SHIFT ) -1 ; + res->flags = flags; + +if (insert_resource (&iomem_resource, res) <0 ) +kfree (res); +else { +/* +* We don't know which region contains +* kernel data so we try it repeatedly and +* let the resource manager test it. +*/ +insert_resource (res, code_resource); +insert_resource (res, data_resource); + } + } +}
arch/ia64/kernel/setup.c +29 -0
@@ -78,6 +78,19 @@ struct screen_info screen_info;unsigned long vga_console_iobase;unsigned long vga_console_membase; +static struct resource data_resource = { + .name ="Kernel data" , + .flags =IORESOURCE_BUSY |IORESOURCE_MEM +}; + +static struct resource code_resource = { + .name ="Kernel code" , + .flags =IORESOURCE_BUSY |IORESOURCE_MEM +}; +extern void efi_initialize_iomem_resources (struct resource *, +struct resource *); +extern char _text[], _edata[], _etext[]; +unsigned long ia64_max_cacheline_size;unsigned long ia64_iobase;/* virtual address for I/O accesses */ EXPORT_SYMBOL (ia64_iobase);
@@ -171,6 +184,22 @@ sort_regions (struct rsvd_region *rsvd_r } } +/* +* Request address space for all standard resources +*/ +static int __init register_memory (void ) +{ + code_resource.start =ia64_tpa (_text); + code_resource.end =ia64_tpa (_etext) -1 ; + data_resource.start =ia64_tpa (_etext); + data_resource.end =ia64_tpa (_edata) -1 ; +efi_initialize_iomem_resources (&code_resource, &data_resource); + +return 0 ; +} + +__initcall (register_memory); +/** * reserve_memory - setup reserved memory areas *
arch/ia64/kernel/efi.c +242 -181
450 lines not on this page · raw message
arch/ia64/kernel/setup.c +3 -0
@@ -211,6 +211,9 @@ reserve_memory (void) }#endif +efi_memmap_init (&rsvd_region[n].start, &rsvd_region[n].end); + n++; +/* end of memory marker */ rsvd_region[n].start = ~0UL ; rsvd_region[n].end = ~0UL ;
arch/ia64/kernel/uncached.c +6 -11
@@ -205,23 +205,18 @@ EXPORT_SYMBOL(uncached_free_page);static int __init uncached_build_memmap (unsigned long start,unsigned long end,void *arg) { -long length; -unsigned long vstart, vend; +long length = end - start;int node; - length = end - start; - vstart = start + __IA64_UNCACHED_OFFSET; - vend = end + __IA64_UNCACHED_OFFSET; -dprintk (KERN_ERR "uncached_build_memmap(%lx %lx)\n" , start, end); -memset ((char *)vstart,0 , length); +memset ((char *)start,0 , length); - node =paddr_to_nid (start); + node =paddr_to_nid (start - __IA64_UNCACHED_OFFSET); -for (; vstart < vend ; vstart +=PAGE_SIZE ) { -dprintk (KERN_INFO "sticking %lx into the pool!\n" , vstart); -gen_pool_free (uncached_pool[node], vstart,PAGE_SIZE ); +for (; start < end ; start +=PAGE_SIZE ) { +dprintk (KERN_INFO "sticking %lx into the pool!\n" , start); +gen_pool_free (uncached_pool[node], start,PAGE_SIZE ); }return 0 ;
include/asm-ia64/meminit.h +3 -1
@@ -16,10 +16,11 @@* - initrd (optional) * - command line string * - kernel code & data +* - Kernel memory map built from EFI memory map * * More could be added if necessary */ -#define IA64_MAX_RSVD_REGIONS 5 +#define IA64_MAX_RSVD_REGIONS 6struct rsvd_region {unsigned long start;/* virtual address of beginning of element */
@@ -33,6 +34,7 @@ extern void find_memory (void);extern void reserve_memory (void );extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); +extern void efi_memmap_init (unsigned long *,unsigned long *);/* * For rounding an address to the next IA64_GRANULE_SIZE or order
arch/ia64/hp/common/sba_iommu.c +22 -0
@@ -1624,6 +1624,28 @@ ioc_iova_init(struct ioc *ioc)READ_REG (ioc->ioc_hpa +IOC_IBASE ); } +#ifdef CONFIG_KEXEC +void +ioc_iova_disable (void ) +{ +struct ioc *ioc; + + ioc = ioc_list; + +while (ioc !=NULL ) { +/* Disable IOVA translation */ +WRITE_REG (ioc->ibase &0xfffffffffffffffe , ioc->ioc_hpa +IOC_IBASE ); +READ_REG (ioc->ioc_hpa +IOC_IBASE ); + +/* Clear I/O TLB of any possible entries */ +WRITE_REG (ioc->ibase | (get_iovp_order (ioc->iov_size) + iovp_shift), ioc->ioc_hpa +IOC_PCOM ); +READ_REG (ioc->ioc_hpa +IOC_PCOM ); + + ioc = ioc->next; + } +} +#endif +static void __init ioc_resource_init (struct ioc *ioc) {
arch/ia64/Kconfig +17 -0
@@ -323,6 +323,23 @@ config PERFMON little bigger and slows down execution a bit, but it is generally a good idea to turn this on. If you're unsure, say Y. +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + 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 + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + config IA64_PALINFO tristate "/proc/pal support" help
arch/ia64/kernel/crash.c +44 -0
44 lines not on this page · raw message
arch/ia64/kernel/efi.c +24 -4
@@ -38,6 +38,9 @@extern efi_status_t efi_call_phys (void *, ...);struct efi efi; +#ifdef CONFIG_KEXEC +unsigned long kexec_reboot =0 ; +#endif EXPORT_SYMBOL (efi);static efi_runtime_services_t *runtime;static unsigned long mem_limit = ~0UL , max_addr = ~0UL ;
@@ -526,6 +529,9 @@ efi_map_pal_code (void)* Cannot write to CRx with PSR.ic=1 */ psr =ia64_clear_ic (); +#ifdef CONFIG_KEXEC +ia64_ptr (0x01 ,GRANULEROUNDDOWN ((unsigned long ) pal_vaddr),IA64_GRANULE_SHIFT ); +#endif ia64_itr (0x1 ,IA64_TR_PALCODE ,GRANULEROUNDDOWN ((unsigned long ) pal_vaddr),pte_val (pfn_pte (__pa (pal_vaddr) >>PAGE_SHIFT ,PAGE_KERNEL )),IA64_GRANULE_SHIFT );
@@ -549,15 +555,22 @@ efi_init (void)if (memcmp (cp,"mem=" ,4 ) ==0 ) { cp +=4 ; mem_limit =memparse (cp, &end); -if (end != cp) -break ; cp = end; +while (*cp ==' ' ) + ++cp; }else if (memcmp (cp,"max_addr=" ,9 ) ==0 ) { cp +=9 ; max_addr =GRANULEROUNDDOWN (memparse (cp, &end)); -if (end != cp) -break ; cp = end; +while (*cp ==' ' ) + ++cp; +#ifdef CONFIG_KEXEC + }else if (memcmp (cp,"kexec_reboot" ,12 ) ==0 ) { + cp +=13 ; + kexec_reboot =1 ; +while (*cp ==' ' ) + ++cp; +#endif }else {while (*cp !=' ' && *cp) ++cp;
@@ -702,10 +715,17 @@ efi_enter_virtual_mode (void) } } +#ifdef CONFIG_KEXEC + if (kexec_reboot == 0) +#endif status =efi_call_phys (__va (runtime->set_virtual_address_map), ia64_boot_param->efi_memmap_size, efi_desc_size, ia64_boot_param->efi_memdesc_version, ia64_boot_param->efi_memmap); +#ifdef CONFIG_KEXEC + else + status =EFI_SUCCESS ; +#endif if (status !=EFI_SUCCESS ) {printk (KERN_WARNING "warning: unable to switch EFI into virtual mode " "(status=%lu)\n" , status);
arch/ia64/kernel/entry.S +1 -1
@@ -1588,7 +1588,7 @@ sys_call_table: data8 sys_mq_timedreceive // 1265 data8 sys_mq_notify data8 sys_mq_getsetattr - data8 sys_ni_syscall // reserved for kexec_load + data8 sys_kexec_load data8 sys_ni_syscall // reserved for vserver data8 sys_waitid // 1270 data8 sys_add_key
arch/ia64/kernel/machine_kexec.c +224 -0
224 lines not on this page · raw message
arch/ia64/kernel/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_PERFMON) += perfmon_defaul obj-$(CONFIG_IA64_CYCLONE) += cyclone.o obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o mca_recovery-y += mca_drv.o mca_drv_asm.o
arch/ia64/kernel/relocate_kernel.S +385 -0
385 lines not on this page · raw message
arch/ia64/kernel/smp.c +40 -0
@@ -30,6 +30,9 @@#include <linux/delay.h> #include <linux/efi.h> #include <linux/bitops.h> +#ifdef CONFIG_KEXEC +#include <linux/kexec.h> +#endif #include <asm/atomic.h> #include <asm/current.h>
@@ -84,6 +87,43 @@ unlock_ipi_calllock(void)spin_unlock_irq (&call_lock); } +#ifdef CONFIG_KEXEC +extern void kexec_fake_sal_rendez (void *start,unsigned long wake_up, +unsigned long pal_base); + +#define pte_bits 3 +#define vmlpt_bits (impl_va_bits - PAGE_SHIFT + pte_bits) +#define POW2 (n) (1ULL << (n)) + +DECLARE_PER_CPU (u64, ia64_mca_pal_base); + +/* +* Stop the CPU and put it in fake SAL rendezvous. This allows CPU to wake +* up with IPI from boot processor +*/ +void +kexec_stop_this_cpu (void *func) +{ +unsigned long pta, impl_va_bits, pal_base; + +/* +* Remove this CPU by putting it into fake SAL rendezvous +*/ +cpu_clear (smp_processor_id (), cpu_online_map); +max_xtp (); +ia64_eoi (); + +/* Disable VHPT */ + impl_va_bits =ffz (~(local_cpu_data->unimpl_va_mask | (7UL <<61 ))); + pta =POW2 (61 ) -POW2 (vmlpt_bits); +ia64_set_pta (pta | (0 <<8 ) | (vmlpt_bits <<2 ) |0 ); + +local_irq_disable (); + pal_base =__get_cpu_var (ia64_mca_pal_base); +kexec_fake_sal_rendez (func, ap_wakeup_vector, pal_base); +} +#endif +static void stop_this_cpu (void ) {
include/asm-ia64/kexec.h +22 -0
@@ -0,0 +1,22 @@ +#ifndef _ASM_IA64_KEXEC_H +#define _ASM_IA64_KEXEC_H + + +/* Maximum physical address we can use pages from */ +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) +/* Maximum address we can reach in physical address mode */ +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) +/* Maximum address we can use for the control code buffer */ +#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE + +#define KEXEC_CONTROL_CODE_SIZE (8192 + 8192 + 4096) + +/* The native architecture */ +#define KEXEC_ARCH KEXEC_ARCH_IA_64 + +#define MAX_NOTE_BYTES 1024 +typedef u32 note_buf_t [MAX_NOTE_BYTES /4 ]; + +extern note_buf_t crash_notes[]; + +#endif /* _ASM_IA64_KEXEC_H */
kernel/irq/handle.c +20 -0
@@ -100,6 +100,26 @@ fastcall int handle_IRQ_event(unsigned i }/* +* Terminate any outstanding interrupts +*/ +void terminate_irqs (void ) +{ +struct irqaction * action; +irq_desc_t *idesc; +unsigned long flags; +int i; + +for (i=0 ; i<NR_IRQS ; i++) { + idesc =irq_descp (i); + action = idesc->action; +if (!action) +continue ; +if (idesc->handler->end) + idesc->handler->end (i); + } +} + +/* * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers).
Quoted 10 lines · Khalid Aziz
I have ported the original patch I had done for kexec on ia64 on 2.6.8 kernel and fixed a few bugs in the original patch. Attached is a patch for kernel 2.6.14-rc4. It works with normal kexec reboot on an HP rx2600. I am now working on adding support for crash kexec. I am also working on kexec on INIT which I currently have working on 2.6.10 kernel. I am porting it to 2.6.14-rc kernel.
Attached patch needs to be applied on top of iomem and
efi_memmapwalkpatches already in ia64 test tree (these patches attached as well for those who may need them).
Cool. Tony, what are your plans for pushing this to Linus? Will it make 2.6.15?
Gerald
Quoted 2 lines
Cool. Tony, what are your plans for pushing this to Linus? Will it make 2.6.15?
Nanhai Zou here at Intel expressed a few concerns to me last night about Khalid's patch. I'll paste them here to speed discussion about this (as I expect Nanhai is asleep at the moment, he should be around to start commenting for himself by 4-5pm Pacific).
Quoted 7 lines
I think his patch is still not able to boot an unmodified kernel.
It appends a kernel parameter to bypass the issue, thus the second kernel need to be modified.It also hardcoded initrd logic in kernel patch.
Command line is still using old command line.
No purgatory code support etc.
Quoted 7 lines
How, I prefer to put a small and clean patch in kernel while leave most of the things in kexec-tools. That will provide more flexibility.
There are also some other issues I can see, like,
1. icache flusing miss
2. rendez code is fake, I prefer to use hotplug API.
3. Disable PCI master code should be in generic PCI driver code instead of IA64 arch code.
Nanhai has his own patches for kexec/kexec-tools, which are stuck in some Intel bureaucracy at the moment ... I'm trying to get them unstuck so that we can get some meaningful commentary from the community about both versions.
My biggest issue with both patches at the moment is that I can't see how either of them can be extended to be useful for use in crash-dump case without some significant surgery. Both of them over-write the existing kernel with the new one, which is a big problem when you'd like to dump the data space of the old kernel. Ia64 is quite happy to run a kernel loaded at any suitably aligned address ... so why not load the new kernel in some different location from the old kernel?
Including this in 2.6.15? It's possible, but it's looking like this might be a rush. Assuming Linus releases 2.6.14 by the end of this week, we only have a couple of weeks to check that this runs on all of the weird configurations. I'd need to see a lot of "tested on xxx-config ... no problems" e-mail to get confidence in this.
-Tony
Quoted 15 lines · Tony
Quoted 2 lines
Cool. Tony, what are your plans for pushing this to Linus? Will it make 2.6.15?
Nanhai Zou here at Intel expressed a few concerns to me last night about Khalid's patch. I'll paste them here to speed discussion about this (as I expect Nanhai is asleep at the moment, he should be around to start commenting for himself by 4-5pm Pacific).
Quoted 2 lines
I think his patch is still not able to boot an unmodified kernel. It appends a kernel parameter to bypass the issue, thus the second kernel need
to be modified.
Quoted 3 lines
It also hardcoded initrd logic in kernel patch.
Command line is still using old command line.
No purgatory code support etc.
I agree that is an issue that should be addressed. It would be nice if there was a kernel option to not virtually map EFI. Reusing a supplied virtual address is also good, but it means we can't boot an unpatched kernel.
Quoted 15 lines
Quoted 1 line
How, I prefer to put a small and clean patch in kernel while leave most of the
things in kexec-tools.
Quoted 6 lines
That will provide more flexibility.
There are also some other issues I can see, like,
1. icache flusing miss
2. rendez code is fake, I prefer to use hotplug API.
3. Disable PCI master code should be in generic PCI driver code instead ofIA64 arch code.
Nanhai has his own patches for kexec/kexec-tools, which are stuck in some Intel bureaucracy at the moment ... I'm trying to get them unstuck so that we can get some meaningful commentary from the community about both versions.
Quoted 8 lines
My biggest issue with both patches at the moment is that I can't see how either of them can be extended to be useful for use in crash-dump case without some significant surgery. Both of them over-write the existing kernel with the new one, which is a big problem when you'd like to dump the data space of the old kernel. Ia64 is quite happy to run a kernel loaded at any suitably aligned address ... so why not load the new kernel in some different location from the old kernel?
Interesting. This should be a decision made by kexec-tools, not by the kernel. On x86 the kernel just verifies we load the crash kernel into the reserved chunk of the address space. I haven't looked closely enough to see if the architecture part has fixed address assumptions yet.
Tony what were you seeing that made you conclude that the code would always load over the existing kernel?
I also didn't see the trivial patch to put the 32bit compat support in. It's not terribly important or useful but there is no reason not to include it.
Eric
Quoted 8 lines · Eric W. Biederman
Interesting. This should be a decision made by kexec-tools, not by the kernel. On x86 the kernel just verifies we load the crash kernel into the reserved chunk of the address space. I haven't looked closely enough to see if the architecture part has fixed address assumptions yet.
Tony what were you seeing that made you conclude that the code would always load over the existing kernel?
Ok .. kexectools should be able to make a decision about where to load the new kernel based on what it finds in /proc/iomem (and in the Elf header of the new kernel). I don't know enough Elf (elvish? :-) to know whether the Elf header we currently generate for a kernel describes things in a way that would convey that it is OK to drop the image at any (suitably aligned) address, or whether there will have to be some ia64 specific magic in the kexectools to choose the load address.
Quoted 3 lines
I also didn't see the trivial patch to put the 32bit compat support in. It's not terribly important or useful but there is no reason not to include it.
Usefullness is a key here. The kexectools definitely include some architecture specific components. So taking the x86 version of the "kexec" binary onto an ia64 system isn't going to be very useful even if the kernel did happen to have an ia32 entry point for kexec enabled. Building an ia32 binary, but with all the ia64 specific parts enabled would seem to be _challenging_ (Nanhai's version has purgatory/arch/ia64/entry.S!). Perhaps there might be a better outlet for that much creativity? [Which is another way of saying that I'm not interested in seeing a patch to enable the ia32 kexec entry point on ia64 ... so don't waste any time creating one].
-Tony
Quoted 11 lines · Tony
Quoted 2 lines
Cool. Tony, what are your plans for pushing this to Linus? Will it make 2.6.15?
Nanhai Zou here at Intel expressed a few concerns to me last night about Khalid's patch. I'll paste them here to speed discussion about this (as I expect Nanhai is asleep at the moment, he should be around to start commenting for himself by 4-5pm Pacific).
Quoted 2 lines
I think his patch is still not able to boot an unmodified kernel.
It appends a kernel parameter to bypass the issue, thus the second kernel need to be modified.
True. The only time I use this parameter is to determine whether to virtualize EFI or not. EFI does not respond well to being virtualized once it has been virtualized already. So the kernel needs to know if EFI has already been virtualized by previous kernel. It is possible to pass this information to the next kernel as a command line parameter, as I have done, or in one of the kexec segments. One way or the other, kernel needs to know this. I have not found a way around it. If there is one, I would like to hear about it. That will make enable unmodified kernel to be booted.
Quoted 1 line
Quoted 1 line
It also hardcoded initrd logic in kernel patch.
I could not find a better way to pass initrd image to ia64 kernel since it is not placed in a fixed location. Using a fixed kexec segment looked fairly logical to me. Alternative would be to add a type field to struct kexec_segment, then kernel can determine which segment holds initrd image without having to use a fixed kexec segment.
Quoted 1 line
Quoted 1 line
Command line is still using old command line.
Please explain.
Quoted 8 lines
Quoted 8 lines
No purgatory code support etc.
How, I prefer to put a small and clean patch in kernel while leave most of the things in kexec-tools. That will provide more flexibility.
There are also some other issues I can see, like,
1. icache flusing miss
2. rendez code is fake, I prefer to use hotplug API.
That would be preferable, and would be a good enhancement over current code if it can be made to work reliably. I was planning to look into it after initial implementation (I wrote initial implementation before CPU hotplug API was available).
Quoted 1 line
Quoted 1 line
3. Disable PCI master code should be in generic PCI driver code instead of IA64 arch code.
Agreed. This is part of some of the cleanup that can still be done.
Quoted 23 lines
Nanhai has his own patches for kexec/kexec-tools, which are stuck in some Intel bureaucracy at the moment ... I'm trying to get them unstuck so that we can get some meaningful commentary from the community about both versions.
My biggest issue with both patches at the moment is that I can't see how either of them can be extended to be useful for use in crash-dump case without some significant surgery. Both of them over-write the existing kernel with the new one, which is a big problem when you'd like to dump the data space of the old kernel. Ia64 is quite happy to run a kernel loaded at any suitably aligned address ... so why not load the new kernel in some different location from the old kernel?
Including this in 2.6.15? It's possible, but it's looking like this might be a rush. Assuming Linus releases 2.6.14 by the end of this week, we only have a couple of weeks to check that this runs on all of the weird configurations. I'd need to see a lot of "tested on xxx-config ... no problems" e-mail to get confidence in this.
-Tony
Signature · 9 lines
Khalid ================================== Khalid Aziz Open Source and Linux Organization (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
Hi Khalid,
Quoted 42 lines · Khalid Aziz
Quoted 1 line · Tony
Quoted 1 line
Cool. Tony, what are your plans for pushing this to Linus? Will
it make
Quoted 4 lines
Quoted 1 line
2.6.15?
Nanhai Zou here at Intel expressed a few concerns to me last night about Khalid's patch. I'll paste them here to speed discussion
about
Quoted 5 lines
this (as I expect Nanhai is asleep at the moment, he should be around to start commenting for himself by 4-5pm Pacific).
Quoted 2 lines
I think his patch is still not able to boot an unmodified kernel. It appends a kernel parameter to bypass the issue, thus the second
kernel need to be modified.
Quoted 1 line
True. The only time I use this parameter is to determine whether to virtualize EFI or not. EFI does not respond well to being virtualized once it has been virtualized already. So the kernel needs to know if EFI
has already been virtualized by previous kernel. It is possible to pass
this information to the next kernel as a command line parameter, as I have done, or in one of the kexec segments. One way or the other, kernel
needs to know this. I have not found a way around it. If there is one, I
would like to hear about it. That will make enable unmodified kernel to
be booted.Quoted 1 line
Quoted 1 line
It also hardcoded initrd logic in kernel patch.
I could not find a better way to pass initrd image to ia64 kernel since
it is not placed in a fixed location. Using a fixed kexec segment looked
fairly logical to me. Alternative would be to add a type field to structkexec_segment, then kernel can determine which segment holds initrd image without having to use a fixed kexec segment.
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Command line is still using old command line.
Please explain.
Sorry, I see how your patch can deal with command line. I missed themachine_kexec_prepare part at the first look. However I prefer to put command line and initrd logic to kexec tools instead of hack on segment index.
Quoted 37 lines
Quoted 3 lines
Quoted 3 lines
No purgatory code support etc.
How, I prefer to put a small and clean patch in kernel while leave
most of the things in kexec-tools.
Quoted 5 lines
Quoted 5 lines
That will provide more flexibility.
There are also some other issues I can see, like,
1. icache flusing miss
2. rendez code is fake, I prefer to use hotplug API.That would be preferable, and would be a good enhancement over current code if it can be made to work reliably. I was planning to look into it
after initial implementation (I wrote initial implementation before CPU
hotplug API was available).Quoted 1 line
Quoted 1 line
3. Disable PCI master code should be in generic PCI driver code
instead of IA64 arch code.
Agreed. This is part of some of the cleanup that can still be done.
Quoted 15 lines
Nanhai has his own patches for kexec/kexec-tools, which are stuck in some Intel bureaucracy at the moment ... I'm trying to get them unstuck so that we can get some meaningful commentary from the community about both versions.
My biggest issue with both patches at the moment is that I can't see how either of them can be extended to be useful for use in crash-dump case without some significant surgery. Both of them over-write the existing kernel with the new one, which is a big problem when you'd like to dump the data space of the old kernel. Ia64 is quite happy to run a kernel loaded at any suitably aligned address ... so why not load the new kernel in some different location from the old kernel?
Quoted 12 lines
Quoted 8 lines
Including this in 2.6.15? It's possible, but it's looking like this might be a rush. Assuming Linus releases 2.6.14 by the end of this week, we only have a couple of weeks to check that this runs on all of the weird configurations. I'd need to see a lot of "tested on xxx-config ... no problems" e-mail to get confidence in this.
-Tony
Signature · 1 line
Khalid
As Tony said, I have my kexec and kexec-tools patches
solved those issues. It can boots any unmodified kernel. But they are pending at Intel bureaucracy.
Hope I can send out them to community for comments soon.
Thanks
Zou Nan hai
Quoted 10 lines · Tony
Quoted 8 lines · Eric W. Biederman
Interesting. This should be a decision made by kexec-tools, not by the kernel. On x86 the kernel just verifies we load the crash kernel into the reserved chunk of the address space. I haven't looked closely enough to see if the architecture part has fixed address assumptions yet.
Tony what were you seeing that made you conclude that the code would always load over the existing kernel?
Quoted 7 lines
Ok .. kexectools should be able to make a decision about where to load the new kernel based on what it finds in
/proc/iomem(and in the Elf header of the new kernel). I don't know enough Elf (elvish? :-) to know whether the Elf header we currently generate for a kernel describes things in a way that would convey that it is OK to drop the image at any (suitably aligned) address, or whether there will have to be some ia64 specific magic in the kexectools to choose the load address.
I don't think ld can be talked into setting ET_REL instead ET_EXEC right now, without building as a shared library. (readelf -a on the kernel will tell you) but since that is a general problem it is likely worth an extra flag to /sbin/kexec to tell it to assume an ELF executable is relocatable even if it doesn't say ET_REL.
Quoted 4 lines
Quoted 3 lines
I also didn't see the trivial patch to put the 32bit compat support in. It's not terribly important or useful but there is no reason not to include it.
Quoted 10 lines
Usefullness is a key here. The kexectools definitely include some architecture specific components. So taking the x86 version of the "kexec" binary onto an ia64 system isn't going to be very useful even if the kernel did happen to have an ia32 entry point for kexec enabled. Building an ia32 binary, but with all the ia64 specific parts enabled would seem to be _challenging_ (Nanhai's version has
purgatory/arch/ia64/entry.S!). Perhaps there might be a better outlet for that much creativity? [Which is another way of saying that I'm not interested in seeing a patch to enable the ia32 kexec entry point on ia64 ... so don't waste any time creating one].
I know of at least one application that before it flashes your rom chip checks to see if you have kexec in your kernel. And it does that by calling sys_kexec and seeing if it gets -EINVAL instead of -ENOSYS. At least with kexec present it knows that if something terribly goes wrong it has the chance to load another kernel, in the event the mtd drivers in the kernel don't handle some subtle hardware bug. That application can safely be distributed as a 32bit binary on i386, x86_64, and ia64.
I'm not quite certain what the build issues that would be involved but it wouldn't surprise one of the architectures that normally run a 32bit user space with a 64bit kernel happened to solve the issue. So I only expect to use the code that comes pretty much for free.
The kernel side of the implementation already exists and I suspect it is as useful as any other ia32 compat syscall entry point on the ia64 kernel. I care as this is a completeness issue and I don't see a reason not to enable the kernel side.
Eric
Quoted 4 lines · Zou Nan hai
As Tony said, I have my kexec and kexec-tools patches
solved those issues. It can boots any unmodified kernel. But they are pending at Intel bureaucracy.
Can you give us some idea of how you got around the EFI virtualization issue?
Signature · 9 lines
Khalid ================================== Khalid Aziz Open Source and Linux Organization (970)898-9214 Hewlett-Packard [email protected] Fort Collins, CO "The Linux kernel is subject to relentless development" - Alessandro Rubini
Quoted 8 lines · Khalid Aziz
Quoted 4 lines · Zou Nan hai
As Tony said, I have my kexec and kexec-tools patches
solved those issues. It can boots any unmodified kernel. But they are pending at Intel bureaucracy.Can you give us some idea of how you got around the EFI virtualization issue?
I patched the EFI bootparam pointer in purgatory code to an empty dummy
function.
Zou Nan hai