OpenCloudOS-Kernel/arch/s390/kernel/head_kdump.S

120 lines
2.8 KiB
ArmAsm

/*
* S390 kdump lowlevel functions (new kernel)
*
* Copyright IBM Corp. 2011
* Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
*/
#define DATAMOVER_ADDR 0x4000
#define COPY_PAGE_ADDR 0x6000
#ifdef CONFIG_CRASH_DUMP
#
# kdump entry (new kernel - not yet relocated)
#
# Note: This code has to be position independent
#
.align 2
.Lep_startup_kdump:
lhi %r1,2 # mode 2 = esame (dump)
sigp %r1,%r0,0x12 # Switch to esame mode
sam64 # Switch to 64 bit addressing
basr %r13,0
.Lbase:
larl %r2,.Lbase_addr # Check, if we have been
lg %r2,0(%r2) # already relocated:
clgr %r2,%r13 #
jne .Lrelocate # No : Start data mover
lghi %r2,0 # Yes: Start kdump kernel
brasl %r14,startup_kdump_relocated
.Lrelocate:
larl %r4,startup
lg %r2,0x418(%r4) # Get kdump base
lg %r3,0x420(%r4) # Get kdump size
larl %r10,.Lcopy_start # Source of data mover
lghi %r8,DATAMOVER_ADDR # Target of data mover
mvc 0(256,%r8),0(%r10) # Copy data mover code
agr %r8,%r2 # Copy data mover to
mvc 0(256,%r8),0(%r10) # reserved mem
lghi %r14,DATAMOVER_ADDR # Jump to copied data mover
basr %r14,%r14
.Lbase_addr:
.quad .Lbase
#
# kdump data mover code (runs at address DATAMOVER_ADDR)
#
# r2: kdump base address
# r3: kdump size
#
.Lcopy_start:
basr %r13,0 # Base
0:
lgr %r11,%r2 # Save kdump base address
lgr %r12,%r2
agr %r12,%r3 # Compute kdump end address
lghi %r5,0
lghi %r10,COPY_PAGE_ADDR # Load copy page address
1:
mvc 0(256,%r10),0(%r5) # Copy old kernel to tmp
mvc 0(256,%r5),0(%r11) # Copy new kernel to old
mvc 0(256,%r11),0(%r10) # Copy tmp to new
aghi %r11,256
aghi %r5,256
clgr %r11,%r12
jl 1b
lg %r14,.Lstartup_kdump-0b(%r13)
basr %r14,%r14 # Start relocated kernel
.Lstartup_kdump:
.long 0x00000000,0x00000000 + startup_kdump_relocated
.Lcopy_end:
#
# Startup of kdump (relocated new kernel)
#
.align 2
startup_kdump_relocated:
basr %r13,0
0:
mvc 0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
mvc 464(16,%r0),.Lpgm_psw-0b(%r13) # Setup pgm check PSW
lhi %r1,1 # Start new kernel
diag %r1,%r1,0x308 # with diag 308
.Lno_diag308: # No diag 308
sam31 # Switch to 31 bit addr mode
sr %r1,%r1 # Erase register r1
sr %r2,%r2 # Erase register r2
sigp %r1,%r2,0x12 # Switch to 31 bit arch mode
lpsw 0 # Start new kernel...
.align 8
.Lrestart_psw:
.long 0x00080000,0x80000000 + startup
.Lpgm_psw:
.quad 0x0000000180000000,0x0000000000000000 + .Lno_diag308
#else
.align 2
.Lep_startup_kdump:
#ifdef CONFIG_64BIT
larl %r13,startup_kdump_crash
lpswe 0(%r13)
.align 8
startup_kdump_crash:
.quad 0x0002000080000000,0x0000000000000000 + startup_kdump_crash
#else
basr %r13,0
0: lpsw startup_kdump_crash-0b(%r13)
.align 8
startup_kdump_crash:
.long 0x000a0000,0x00000000 + startup_kdump_crash
#endif /* CONFIG_64BIT */
#endif /* CONFIG_CRASH_DUMP */