# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/07/27 15:57:38-07:00 jbarnes@tomahawk.engr.sgi.com # kexec update # # arch/ia64/kernel/relocate_kernel.S # 2004/07/27 15:57:30-07:00 jbarnes@tomahawk.engr.sgi.com +78 -80 # kexec update # # arch/ia64/kernel/machine_kexec.c # 2004/07/27 15:57:30-07:00 jbarnes@tomahawk.engr.sgi.com +5 -21 # kexec update # # ChangeSet # 2004/07/26 15:16:34-07:00 jbarnes@tomahawk.engr.sgi.com # kexec # # include/asm-ia64/kexec.h # 2004/07/26 15:16:25-07:00 jbarnes@tomahawk.engr.sgi.com +15 -0 # # include/asm-ia64/kexec.h # 2004/07/26 15:16:25-07:00 jbarnes@tomahawk.engr.sgi.com +0 -0 # BitKeeper file /home/jbarnes/working/linux-2.5-kexec/include/asm-ia64/kexec.h # # arch/ia64/kernel/relocate_kernel.S # 2004/07/26 15:16:24-07:00 jbarnes@tomahawk.engr.sgi.com +97 -0 # # arch/ia64/kernel/relocate_kernel.S # 2004/07/26 15:16:24-07:00 jbarnes@tomahawk.engr.sgi.com +0 -0 # BitKeeper file /home/jbarnes/working/linux-2.5-kexec/arch/ia64/kernel/relocate_kernel.S # # arch/ia64/kernel/machine_kexec.c # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +52 -0 # # include/asm-ia64/mmu_context.h # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +2 -0 # kexec # # arch/ia64/kernel/machine_kexec.c # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +0 -0 # BitKeeper file /home/jbarnes/working/linux-2.5-kexec/arch/ia64/kernel/machine_kexec.c # # arch/ia64/kernel/entry.S # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +1 -1 # kexec # # arch/ia64/kernel/efi.c # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +6 -0 # kexec # # arch/ia64/kernel/Makefile # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +1 -0 # kexec # # arch/ia64/Kconfig # 2004/07/26 15:16:23-07:00 jbarnes@tomahawk.engr.sgi.com +17 -0 # kexec # diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig 2004-07-27 15:58:47 -07:00 +++ b/arch/ia64/Kconfig 2004-07-27 15:58:47 -07:00 @@ -251,6 +251,23 @@ Say Y here if you are building a kernel for a desktop, embedded or real-time system. Say N if you are unsure. +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 on an going 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 HAVE_DEC_LOCK bool depends on (SMP || PREEMPT) diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile 2004-07-27 15:58:47 -07:00 +++ b/arch/ia64/kernel/Makefile 2004-07-27 15:58:47 -07:00 @@ -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 diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c 2004-07-27 15:58:47 -07:00 +++ b/arch/ia64/kernel/efi.c 2004-07-27 15:58:47 -07:00 @@ -198,6 +198,7 @@ #define id(arg) arg +#if 0 STUB_GET_TIME(virt, id) STUB_SET_TIME(virt, id) STUB_GET_WAKEUP_TIME(virt, id) @@ -207,6 +208,7 @@ STUB_SET_VARIABLE(virt, id) STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id) STUB_RESET_SYSTEM(virt, id) +#endif void efi_gettimeofday (struct timespec *ts) @@ -596,9 +598,12 @@ #endif efi_map_pal_code(); +#if 0 efi_enter_virtual_mode(); +#endif } +#if 0 void efi_enter_virtual_mode (void) { @@ -670,6 +675,7 @@ efi.get_next_high_mono_count = virt_get_next_high_mono_count; efi.reset_system = virt_reset_system; } +#endif /* * Walk the EFI memory map looking for the I/O port range. There can only be one entry of diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S 2004-07-27 15:58:47 -07:00 +++ b/arch/ia64/kernel/entry.S 2004-07-27 15:58:47 -07:00 @@ -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 diff -Nru a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ia64/kernel/machine_kexec.c 2004-07-27 15:58:47 -07:00 @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include + +typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, + unsigned long start_address); + +extern unsigned long ia64_load_new_kernel, ia64_load_new_kernel_end; + +void machine_kexec(struct kimage *image) +{ + unsigned long indirection_page; + unsigned long reboot_code_buffer; + relocate_new_kernel_t rnk; + + /* switch to an mm where the reboot_code_buffer is identity mapped */ + use_mm(&init_mm); + + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + /* Find the physical addresses */ + reboot_code_buffer = + page_to_pfn(image->reboot_code_pages) << PAGE_SHIFT; + indirection_page = image->head & PAGE_MASK; + + /* copy it out */ + memcpy((void *)reboot_code_buffer, (void *)ia64_load_new_kernel, + ia64_load_new_kernel_end - ia64_load_new_kernel); + + /* now call it */ + rnk = (relocate_new_kernel_t)reboot_code_buffer; + (*rnk)(indirection_page, image->start); +} diff -Nru a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ia64/kernel/relocate_kernel.S 2004-07-27 15:58:47 -07:00 @@ -0,0 +1,95 @@ +#include +#include +#include +#include + + /* Must be relocatable PIC code callable as a C function, that once + * it starts can not use the previous processes stack. + * + */ +GLOBAL_ENTRY(ia64_load_new_kernel) + /* See where I am running, and compute gp */ + mov ar.rsc=0 /* Put RSE in enforce lacy, LE mode */ + mov gp=ip /* gp == ia64_load_new_kernel */ + + /* Transition from virtual to physical mode */ + movl r8=(IA64_PSR_AC | IA64_PSR_IC | IA64_PSR_BN) + movl r9=1f + ;; + mov cr.ipsr=r8 + mov cr.iip=r9 + mov cr.ifs=r0 + ;; + rfi + ;; +1: /* Now we are in physical mode */ + + srlz.i + /* Setup the memory stack */ + add r12=(memory_stack_end - ia64_load_new_kernel),gp + /* Setup the register stack */ + add r8=(register_stack - ia64_load_new_kernel),gp + + ;; + mov ar.bspstore=r8 + ;; + loadrs + ;; + + /* Do the copies */ + mov r8=r32 + mov b6=r33 + mov r9=0 + mov r11=PAGE_SIZE + ;; + /* top, read another word for the indirection page */ +top: + ld8 r10=[r8], 8 + ;; + tbit.nz p6,p0 = r10, 0 /* Is it a destination page? */ + tbit.nz p7,p0 = r10, 1 /* Is it an indirection page? */ + tbit.nz p8,p0 = r10, 3 /* Is it the source indicator? */ + tbit.nz p9,p0 = r10, 2 /* Is it the done indicator? */ + dep.z r10 = r10, 0, 12 /* Clear the low bits of r10 */ + ;; +(p6) mov r9 = r10 /* destination addr */ +(p7) mov r8 = r10 /* indirection addr */ +(p8) br.cond.sptk.few source +(p9) br.cond.sptk.few done + br.cond.sptk.few top +source: + add r16 = r11, r10 + add r14 = 8, r10 + add r15 = 8, r9 + ;; +0: + ld8 r17 = [r10],16 + ld8 r18 = [r14],16 + ;; + st8 [r9] = r17, 16 + st8 [r15] = r18, 16 + cmp.ne p6,p0 = r16, r10 + ;; +(p6) br.cond.sptk.few 0b + br.cond.sptk.few top +done: + srlz.i + srlz.d + ;; + br.call.sptk.few b0=b6 +0: + br.cond.sptk.few 0b + + .balign 8192 + +register_stack: + .fill 8192, 1, 0 +register_stack_end: + +memory_stack: + .fill 8192, 1, 0 +memory_stack_end: + + .global ia64_load_new_kernel_end +ia64_load_new_kernel_end: +END(ia64_load_new_kernel) diff -Nru a/include/asm-ia64/kexec.h b/include/asm-ia64/kexec.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-ia64/kexec.h 2004-07-27 15:58:47 -07:00 @@ -0,0 +1,15 @@ +#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) + +/* Zone to allocate memory from */ +#define GFP_KEXEC GFP_KERNEL + +#define KEXEC_REBOOT_CODE_SIZE (8192 + 8192 + 4096) + +#endif /* _ASM_IA64_KEXEC_H */ diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h --- a/include/asm-ia64/mmu_context.h 2004-07-27 15:58:47 -07:00 +++ b/include/asm-ia64/mmu_context.h 2004-07-27 15:58:47 -07:00 @@ -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 */