2005-06-26 01:58:11 +04:00
/*
* arch / s390 / kernel / machine_kexec . c
*
2006-12-04 17:40:33 +03:00
* Copyright IBM Corp . 2005 , 2006
2005-06-26 01:58:11 +04:00
*
2006-12-04 17:40:33 +03:00
* Author ( s ) : Rolf Adelsberger ,
* Heiko Carstens < heiko . carstens @ de . ibm . com >
2005-06-26 01:58:11 +04:00
*/
# include <linux/device.h>
# include <linux/mm.h>
# include <linux/kexec.h>
# include <linux/delay.h>
2007-02-05 23:16:47 +03:00
# include <linux/reboot.h>
2006-02-12 04:56:01 +03:00
# include <asm/cio.h>
# include <asm/setup.h>
2005-06-26 01:58:11 +04:00
# include <asm/pgtable.h>
# include <asm/pgalloc.h>
# include <asm/system.h>
2006-02-12 04:56:01 +03:00
# include <asm/smp.h>
2006-12-04 17:40:26 +03:00
# include <asm/reset.h>
2007-03-06 01:35:45 +03:00
# include <asm/ipl.h>
2005-06-26 01:58:11 +04:00
2006-12-04 17:40:33 +03:00
typedef void ( * relocate_kernel_t ) ( kimage_entry_t * , unsigned long ) ;
2005-06-26 01:58:11 +04:00
2006-06-26 20:57:34 +04:00
extern const unsigned char relocate_kernel [ ] ;
extern const unsigned long long relocate_kernel_len ;
2005-06-26 01:58:11 +04:00
2006-12-04 17:40:33 +03:00
int machine_kexec_prepare ( struct kimage * image )
2005-06-26 01:58:11 +04:00
{
2006-12-04 17:40:33 +03:00
void * reboot_code_buffer ;
2005-06-26 01:58:11 +04:00
2007-03-06 01:35:45 +03:00
/* Can't replace kernel image since it is read-only. */
if ( ipl_flags & IPL_NSS_VALID )
return - ENOSYS ;
2005-06-26 01:58:11 +04:00
/* We don't support anything but the default image type for now. */
if ( image - > type ! = KEXEC_TYPE_DEFAULT )
return - EINVAL ;
/* Get the destination where the assembler code should be copied to.*/
2006-12-04 17:40:33 +03:00
reboot_code_buffer = ( void * ) page_to_phys ( image - > control_code_page ) ;
2005-06-26 01:58:11 +04:00
/* Then copy it */
2006-12-04 17:40:33 +03:00
memcpy ( reboot_code_buffer , relocate_kernel , relocate_kernel_len ) ;
2005-06-26 01:58:11 +04:00
return 0 ;
}
2006-12-04 17:40:33 +03:00
void machine_kexec_cleanup ( struct kimage * image )
2005-06-26 01:58:11 +04:00
{
}
2006-12-04 17:40:33 +03:00
void machine_shutdown ( void )
2005-06-26 01:58:11 +04:00
{
}
2006-12-04 17:40:33 +03:00
void machine_kexec ( struct kimage * image )
2005-06-26 01:58:11 +04:00
{
relocate_kernel_t data_mover ;
2006-12-04 17:40:33 +03:00
smp_send_stop ( ) ;
2006-12-04 17:40:40 +03:00
pfault_fini ( ) ;
2006-12-04 17:40:26 +03:00
s390_reset_system ( ) ;
2006-12-04 17:40:33 +03:00
data_mover = ( relocate_kernel_t ) page_to_phys ( image - > control_code_page ) ;
2005-06-26 01:58:11 +04:00
/* Call the moving routine */
2006-12-04 17:40:33 +03:00
( * data_mover ) ( & image - > head , image - > start ) ;
for ( ; ; ) ;
2005-06-26 01:58:11 +04:00
}