1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * Copyright IBM Corp. 1999, 2010 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Author(s): Hartmut Penner <hp@de.ibm.com> 6*4882a593Smuzhiyun * Martin Schwidefsky <schwidefsky@de.ibm.com> 7*4882a593Smuzhiyun * Rob van der Heij <rvdhei@iae.nl> 8*4882a593Smuzhiyun * Heiko Carstens <heiko.carstens@de.ibm.com> 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * There are 5 different IPL methods 11*4882a593Smuzhiyun * 1) load the image directly into ram at address 0 and do an PSW restart 12*4882a593Smuzhiyun * 2) linload will load the image from address 0x10000 to memory 0x10000 13*4882a593Smuzhiyun * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) 14*4882a593Smuzhiyun * 3) generate the tape ipl header, store the generated image on a tape 15*4882a593Smuzhiyun * and ipl from it 16*4882a593Smuzhiyun * In case of SL tape you need to IPL 5 times to get past VOL1 etc 17*4882a593Smuzhiyun * 4) generate the vm reader ipl header, move the generated image to the 18*4882a593Smuzhiyun * VM reader (use option NOH!) and do a ipl from reader (VM only) 19*4882a593Smuzhiyun * 5) direct call of start by the SALIPL loader 20*4882a593Smuzhiyun * We use the cpuid to distinguish between VM and native ipl 21*4882a593Smuzhiyun * params for kernel are pushed to 0x10400 (see setup.h) 22*4882a593Smuzhiyun * 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun#include <linux/init.h> 26*4882a593Smuzhiyun#include <linux/linkage.h> 27*4882a593Smuzhiyun#include <asm/asm-offsets.h> 28*4882a593Smuzhiyun#include <asm/thread_info.h> 29*4882a593Smuzhiyun#include <asm/page.h> 30*4882a593Smuzhiyun#include <asm/ptrace.h> 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun#define ARCH_OFFSET 4 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun__HEAD 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun#define IPL_BS 0x730 37*4882a593Smuzhiyun .org 0 38*4882a593Smuzhiyun .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded 39*4882a593Smuzhiyun .long 0x02000018,0x60000050 # by ipl to addresses 0-23. 40*4882a593Smuzhiyun .long 0x02000068,0x60000050 # (a PSW and two CCWs). 41*4882a593Smuzhiyun .fill 80-24,1,0x40 # bytes 24-79 are discarded !! 42*4882a593Smuzhiyun .long 0x020000f0,0x60000050 # The next 160 byte are loaded 43*4882a593Smuzhiyun .long 0x02000140,0x60000050 # to addresses 0x18-0xb7 44*4882a593Smuzhiyun .long 0x02000190,0x60000050 # They form the continuation 45*4882a593Smuzhiyun .long 0x020001e0,0x60000050 # of the CCW program started 46*4882a593Smuzhiyun .long 0x02000230,0x60000050 # by ipl and load the range 47*4882a593Smuzhiyun .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image 48*4882a593Smuzhiyun .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730 49*4882a593Smuzhiyun .long 0x02000320,0x60000050 # in memory. At the end of 50*4882a593Smuzhiyun .long 0x02000370,0x60000050 # the channel program the PSW 51*4882a593Smuzhiyun .long 0x020003c0,0x60000050 # at location 0 is loaded. 52*4882a593Smuzhiyun .long 0x02000410,0x60000050 # Initial processing starts 53*4882a593Smuzhiyun .long 0x02000460,0x60000050 # at 0x200 = iplstart. 54*4882a593Smuzhiyun .long 0x020004b0,0x60000050 55*4882a593Smuzhiyun .long 0x02000500,0x60000050 56*4882a593Smuzhiyun .long 0x02000550,0x60000050 57*4882a593Smuzhiyun .long 0x020005a0,0x60000050 58*4882a593Smuzhiyun .long 0x020005f0,0x60000050 59*4882a593Smuzhiyun .long 0x02000640,0x60000050 60*4882a593Smuzhiyun .long 0x02000690,0x60000050 61*4882a593Smuzhiyun .long 0x020006e0,0x20000050 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun .org __LC_RST_NEW_PSW # 0x1a0 64*4882a593Smuzhiyun .quad 0,iplstart 65*4882a593Smuzhiyun .org __LC_PGM_NEW_PSW # 0x1d0 66*4882a593Smuzhiyun .quad 0x0000000180000000,startup_pgm_check_handler 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun .org 0x200 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun# 71*4882a593Smuzhiyun# subroutine to wait for end I/O 72*4882a593Smuzhiyun# 73*4882a593Smuzhiyun.Lirqwait: 74*4882a593Smuzhiyun mvc __LC_IO_NEW_PSW(16),.Lnewpsw # set up IO interrupt psw 75*4882a593Smuzhiyun lpsw .Lwaitpsw 76*4882a593Smuzhiyun.Lioint: 77*4882a593Smuzhiyun br %r14 78*4882a593Smuzhiyun .align 8 79*4882a593Smuzhiyun.Lnewpsw: 80*4882a593Smuzhiyun .quad 0x0000000080000000,.Lioint 81*4882a593Smuzhiyun.Lwaitpsw: 82*4882a593Smuzhiyun .long 0x020a0000,0x80000000+.Lioint 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun# 85*4882a593Smuzhiyun# subroutine for loading cards from the reader 86*4882a593Smuzhiyun# 87*4882a593Smuzhiyun.Lloader: 88*4882a593Smuzhiyun la %r4,0(%r14) 89*4882a593Smuzhiyun la %r3,.Lorb # r2 = address of orb into r2 90*4882a593Smuzhiyun la %r5,.Lirb # r4 = address of irb 91*4882a593Smuzhiyun la %r6,.Lccws 92*4882a593Smuzhiyun la %r7,20 93*4882a593Smuzhiyun.Linit: 94*4882a593Smuzhiyun st %r2,4(%r6) # initialize CCW data addresses 95*4882a593Smuzhiyun la %r2,0x50(%r2) 96*4882a593Smuzhiyun la %r6,8(%r6) 97*4882a593Smuzhiyun bct 7,.Linit 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun lctl %c6,%c6,.Lcr6 # set IO subclass mask 100*4882a593Smuzhiyun slr %r2,%r2 101*4882a593Smuzhiyun.Lldlp: 102*4882a593Smuzhiyun ssch 0(%r3) # load chunk of 1600 bytes 103*4882a593Smuzhiyun bnz .Llderr 104*4882a593Smuzhiyun.Lwait4irq: 105*4882a593Smuzhiyun bas %r14,.Lirqwait 106*4882a593Smuzhiyun c %r1,__LC_SUBCHANNEL_ID # compare subchannel number 107*4882a593Smuzhiyun bne .Lwait4irq 108*4882a593Smuzhiyun tsch 0(%r5) 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun slr %r0,%r0 111*4882a593Smuzhiyun ic %r0,8(%r5) # get device status 112*4882a593Smuzhiyun chi %r0,8 # channel end ? 113*4882a593Smuzhiyun be .Lcont 114*4882a593Smuzhiyun chi %r0,12 # channel end + device end ? 115*4882a593Smuzhiyun be .Lcont 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun l %r0,4(%r5) 118*4882a593Smuzhiyun s %r0,8(%r3) # r0/8 = number of ccws executed 119*4882a593Smuzhiyun mhi %r0,10 # *10 = number of bytes in ccws 120*4882a593Smuzhiyun lh %r3,10(%r5) # get residual count 121*4882a593Smuzhiyun sr %r0,%r3 # #ccws*80-residual=#bytes read 122*4882a593Smuzhiyun ar %r2,%r0 123*4882a593Smuzhiyun 124*4882a593Smuzhiyun br %r4 # r2 contains the total size 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun.Lcont: 127*4882a593Smuzhiyun ahi %r2,0x640 # add 0x640 to total size 128*4882a593Smuzhiyun la %r6,.Lccws 129*4882a593Smuzhiyun la %r7,20 130*4882a593Smuzhiyun.Lincr: 131*4882a593Smuzhiyun l %r0,4(%r6) # update CCW data addresses 132*4882a593Smuzhiyun ahi %r0,0x640 133*4882a593Smuzhiyun st %r0,4(%r6) 134*4882a593Smuzhiyun ahi %r6,8 135*4882a593Smuzhiyun bct 7,.Lincr 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun b .Lldlp 138*4882a593Smuzhiyun.Llderr: 139*4882a593Smuzhiyun lpsw .Lcrash 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun .align 8 142*4882a593Smuzhiyun.Lorb: .long 0x00000000,0x0080ff00,.Lccws 143*4882a593Smuzhiyun.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 144*4882a593Smuzhiyun.Lcr6: .long 0xff000000 145*4882a593Smuzhiyun.Lloadp:.long 0,0 146*4882a593Smuzhiyun .align 8 147*4882a593Smuzhiyun.Lcrash:.long 0x000a0000,0x00000000 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun .align 8 150*4882a593Smuzhiyun.Lccws: .rept 19 151*4882a593Smuzhiyun .long 0x02600050,0x00000000 152*4882a593Smuzhiyun .endr 153*4882a593Smuzhiyun .long 0x02200050,0x00000000 154*4882a593Smuzhiyun 155*4882a593Smuzhiyuniplstart: 156*4882a593Smuzhiyun mvi __LC_AR_MODE_ID,1 # set esame flag 157*4882a593Smuzhiyun slr %r0,%r0 # set cpuid to zero 158*4882a593Smuzhiyun lhi %r1,2 # mode 2 = esame (dump) 159*4882a593Smuzhiyun sigp %r1,%r0,0x12 # switch to esame mode 160*4882a593Smuzhiyun bras %r13,0f 161*4882a593Smuzhiyun .fill 16,4,0x0 162*4882a593Smuzhiyun0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs 163*4882a593Smuzhiyun sam31 # switch to 31 bit addressing mode 164*4882a593Smuzhiyun lh %r1,__LC_SUBCHANNEL_ID # test if subchannel number 165*4882a593Smuzhiyun bct %r1,.Lnoload # is valid 166*4882a593Smuzhiyun l %r1,__LC_SUBCHANNEL_ID # load ipl subchannel number 167*4882a593Smuzhiyun la %r2,IPL_BS # load start address 168*4882a593Smuzhiyun bas %r14,.Lloader # load rest of ipl image 169*4882a593Smuzhiyun l %r12,.Lparm # pointer to parameter area 170*4882a593Smuzhiyun st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number 171*4882a593Smuzhiyun 172*4882a593Smuzhiyun# 173*4882a593Smuzhiyun# load parameter file from ipl device 174*4882a593Smuzhiyun# 175*4882a593Smuzhiyun.Lagain1: 176*4882a593Smuzhiyun l %r2,.Linitrd # ramdisk loc. is temp 177*4882a593Smuzhiyun bas %r14,.Lloader # load parameter file 178*4882a593Smuzhiyun ltr %r2,%r2 # got anything ? 179*4882a593Smuzhiyun bz .Lnopf 180*4882a593Smuzhiyun chi %r2,895 181*4882a593Smuzhiyun bnh .Lnotrunc 182*4882a593Smuzhiyun la %r2,895 183*4882a593Smuzhiyun.Lnotrunc: 184*4882a593Smuzhiyun l %r4,.Linitrd 185*4882a593Smuzhiyun clc 0(3,%r4),.L_hdr # if it is HDRx 186*4882a593Smuzhiyun bz .Lagain1 # skip dataset header 187*4882a593Smuzhiyun clc 0(3,%r4),.L_eof # if it is EOFx 188*4882a593Smuzhiyun bz .Lagain1 # skip dateset trailer 189*4882a593Smuzhiyun la %r5,0(%r4,%r2) 190*4882a593Smuzhiyun lr %r3,%r2 191*4882a593Smuzhiyun la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line 192*4882a593Smuzhiyun mvc 0(256,%r3),0(%r4) 193*4882a593Smuzhiyun mvc 256(256,%r3),256(%r4) 194*4882a593Smuzhiyun mvc 512(256,%r3),512(%r4) 195*4882a593Smuzhiyun mvc 768(122,%r3),768(%r4) 196*4882a593Smuzhiyun slr %r0,%r0 197*4882a593Smuzhiyun b .Lcntlp 198*4882a593Smuzhiyun.Ldelspc: 199*4882a593Smuzhiyun ic %r0,0(%r2,%r3) 200*4882a593Smuzhiyun chi %r0,0x20 # is it a space ? 201*4882a593Smuzhiyun be .Lcntlp 202*4882a593Smuzhiyun ahi %r2,1 203*4882a593Smuzhiyun b .Leolp 204*4882a593Smuzhiyun.Lcntlp: 205*4882a593Smuzhiyun brct %r2,.Ldelspc 206*4882a593Smuzhiyun.Leolp: 207*4882a593Smuzhiyun slr %r0,%r0 208*4882a593Smuzhiyun stc %r0,0(%r2,%r3) # terminate buffer 209*4882a593Smuzhiyun.Lnopf: 210*4882a593Smuzhiyun 211*4882a593Smuzhiyun# 212*4882a593Smuzhiyun# load ramdisk from ipl device 213*4882a593Smuzhiyun# 214*4882a593Smuzhiyun.Lagain2: 215*4882a593Smuzhiyun l %r2,.Linitrd # addr of ramdisk 216*4882a593Smuzhiyun st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) 217*4882a593Smuzhiyun bas %r14,.Lloader # load ramdisk 218*4882a593Smuzhiyun st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of rd 219*4882a593Smuzhiyun ltr %r2,%r2 220*4882a593Smuzhiyun bnz .Lrdcont 221*4882a593Smuzhiyun st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found 222*4882a593Smuzhiyun.Lrdcont: 223*4882a593Smuzhiyun l %r2,.Linitrd 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun clc 0(3,%r2),.L_hdr # skip HDRx and EOFx 226*4882a593Smuzhiyun bz .Lagain2 227*4882a593Smuzhiyun clc 0(3,%r2),.L_eof 228*4882a593Smuzhiyun bz .Lagain2 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun# 231*4882a593Smuzhiyun# reset files in VM reader 232*4882a593Smuzhiyun# 233*4882a593Smuzhiyun stidp .Lcpuid # store cpuid 234*4882a593Smuzhiyun tm .Lcpuid,0xff # running VM ? 235*4882a593Smuzhiyun bno .Lnoreset 236*4882a593Smuzhiyun la %r2,.Lreset 237*4882a593Smuzhiyun lhi %r3,26 238*4882a593Smuzhiyun diag %r2,%r3,8 239*4882a593Smuzhiyun la %r5,.Lirb 240*4882a593Smuzhiyun stsch 0(%r5) # check if irq is pending 241*4882a593Smuzhiyun tm 30(%r5),0x0f # by verifying if any of the 242*4882a593Smuzhiyun bnz .Lwaitforirq # activity or status control 243*4882a593Smuzhiyun tm 31(%r5),0xff # bits is set in the schib 244*4882a593Smuzhiyun bz .Lnoreset 245*4882a593Smuzhiyun.Lwaitforirq: 246*4882a593Smuzhiyun bas %r14,.Lirqwait # wait for IO interrupt 247*4882a593Smuzhiyun c %r1,__LC_SUBCHANNEL_ID # compare subchannel number 248*4882a593Smuzhiyun bne .Lwaitforirq 249*4882a593Smuzhiyun la %r5,.Lirb 250*4882a593Smuzhiyun tsch 0(%r5) 251*4882a593Smuzhiyun.Lnoreset: 252*4882a593Smuzhiyun b .Lnoload 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun# 255*4882a593Smuzhiyun# everything loaded, go for it 256*4882a593Smuzhiyun# 257*4882a593Smuzhiyun.Lnoload: 258*4882a593Smuzhiyun l %r1,.Lstartup 259*4882a593Smuzhiyun br %r1 260*4882a593Smuzhiyun 261*4882a593Smuzhiyun.Linitrd:.long _end # default address of initrd 262*4882a593Smuzhiyun.Lparm: .long PARMAREA 263*4882a593Smuzhiyun.Lstartup: .long startup 264*4882a593Smuzhiyun.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 265*4882a593Smuzhiyun .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 266*4882a593Smuzhiyun .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" 267*4882a593Smuzhiyun.L_eof: .long 0xc5d6c600 /* C'EOF' */ 268*4882a593Smuzhiyun.L_hdr: .long 0xc8c4d900 /* C'HDR' */ 269*4882a593Smuzhiyun .align 8 270*4882a593Smuzhiyun.Lcpuid:.fill 8,1,0 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun# 273*4882a593Smuzhiyun# startup-code at 0x10000, running in absolute addressing mode 274*4882a593Smuzhiyun# this is called either by the ipl loader or directly by PSW restart 275*4882a593Smuzhiyun# or linload or SALIPL 276*4882a593Smuzhiyun# 277*4882a593Smuzhiyun .org 0x10000 278*4882a593SmuzhiyunENTRY(startup) 279*4882a593Smuzhiyun j .Lep_startup_normal 280*4882a593Smuzhiyun .org EP_OFFSET 281*4882a593Smuzhiyun# 282*4882a593Smuzhiyun# This is a list of s390 kernel entry points. At address 0x1000f the number of 283*4882a593Smuzhiyun# valid entry points is stored. 284*4882a593Smuzhiyun# 285*4882a593Smuzhiyun# IMPORTANT: Do not change this table, it is s390 kernel ABI! 286*4882a593Smuzhiyun# 287*4882a593Smuzhiyun .ascii EP_STRING 288*4882a593Smuzhiyun .byte 0x00,0x01 289*4882a593Smuzhiyun# 290*4882a593Smuzhiyun# kdump startup-code at 0x10010, running in 64 bit absolute addressing mode 291*4882a593Smuzhiyun# 292*4882a593Smuzhiyun .org 0x10010 293*4882a593SmuzhiyunENTRY(startup_kdump) 294*4882a593Smuzhiyun j .Lep_startup_kdump 295*4882a593Smuzhiyun.Lep_startup_normal: 296*4882a593Smuzhiyun mvi __LC_AR_MODE_ID,1 # set esame flag 297*4882a593Smuzhiyun slr %r0,%r0 # set cpuid to zero 298*4882a593Smuzhiyun lhi %r1,2 # mode 2 = esame (dump) 299*4882a593Smuzhiyun sigp %r1,%r0,0x12 # switch to esame mode 300*4882a593Smuzhiyun bras %r13,0f 301*4882a593Smuzhiyun .fill 16,4,0x0 302*4882a593Smuzhiyun0: lmh %r0,%r15,0(%r13) # clear high-order half of gprs 303*4882a593Smuzhiyun sam64 # switch to 64 bit addressing mode 304*4882a593Smuzhiyun basr %r13,0 # get base 305*4882a593Smuzhiyun.LPG0: 306*4882a593Smuzhiyun xc 0x200(256),0x200 # partially clear lowcore 307*4882a593Smuzhiyun xc 0x300(256),0x300 308*4882a593Smuzhiyun xc 0xe00(256),0xe00 309*4882a593Smuzhiyun xc 0xf00(256),0xf00 310*4882a593Smuzhiyun lctlg %c0,%c15,.Lctl-.LPG0(%r13) # load control registers 311*4882a593Smuzhiyun stcke __LC_BOOT_CLOCK 312*4882a593Smuzhiyun mvc __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1 313*4882a593Smuzhiyun spt 6f-.LPG0(%r13) 314*4882a593Smuzhiyun mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13) 315*4882a593Smuzhiyun l %r15,.Lstack-.LPG0(%r13) 316*4882a593Smuzhiyun brasl %r14,verify_facilities 317*4882a593Smuzhiyun brasl %r14,startup_kernel 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun.Lstack: 320*4882a593Smuzhiyun .long 0x8000 + (1<<(PAGE_SHIFT+BOOT_STACK_ORDER)) - STACK_FRAME_OVERHEAD 321*4882a593Smuzhiyun .align 8 322*4882a593Smuzhiyun6: .long 0x7fffffff,0xffffffff 323*4882a593Smuzhiyun 324*4882a593Smuzhiyun.Lctl: .quad 0x04040000 # cr0: AFP registers & secondary space 325*4882a593Smuzhiyun .quad 0 # cr1: primary space segment table 326*4882a593Smuzhiyun .quad .Lduct # cr2: dispatchable unit control table 327*4882a593Smuzhiyun .quad 0 # cr3: instruction authorization 328*4882a593Smuzhiyun .quad 0xffff # cr4: instruction authorization 329*4882a593Smuzhiyun .quad .Lduct # cr5: primary-aste origin 330*4882a593Smuzhiyun .quad 0 # cr6: I/O interrupts 331*4882a593Smuzhiyun .quad 0 # cr7: secondary space segment table 332*4882a593Smuzhiyun .quad 0x0000000000008000 # cr8: access registers translation 333*4882a593Smuzhiyun .quad 0 # cr9: tracing off 334*4882a593Smuzhiyun .quad 0 # cr10: tracing off 335*4882a593Smuzhiyun .quad 0 # cr11: tracing off 336*4882a593Smuzhiyun .quad 0 # cr12: tracing off 337*4882a593Smuzhiyun .quad 0 # cr13: home space segment table 338*4882a593Smuzhiyun .quad 0xc0000000 # cr14: machine check handling off 339*4882a593Smuzhiyun .quad .Llinkage_stack # cr15: linkage stack operations 340*4882a593Smuzhiyun 341*4882a593Smuzhiyun .section .dma.data,"aw",@progbits 342*4882a593Smuzhiyun.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0 343*4882a593Smuzhiyun .long 0,0,0,0,0,0,0,0 344*4882a593Smuzhiyun.Llinkage_stack: 345*4882a593Smuzhiyun .long 0,0,0x89000000,0,0,0,0x8a000000,0 346*4882a593Smuzhiyun .align 64 347*4882a593Smuzhiyun.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0 348*4882a593Smuzhiyun .align 128 349*4882a593Smuzhiyun.Lduald:.rept 8 350*4882a593Smuzhiyun .long 0x80000000,0,0,0 # invalid access-list entries 351*4882a593Smuzhiyun .endr 352*4882a593Smuzhiyun .previous 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun#include "head_kdump.S" 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun# 357*4882a593Smuzhiyun# This program check is active immediately after kernel start 358*4882a593Smuzhiyun# and until early_pgm_check_handler is set in kernel/early.c 359*4882a593Smuzhiyun# It simply saves general/control registers and psw in 360*4882a593Smuzhiyun# the save area and does disabled wait with a faulty address. 361*4882a593Smuzhiyun# 362*4882a593SmuzhiyunENTRY(startup_pgm_check_handler) 363*4882a593Smuzhiyun stmg %r8,%r15,__LC_SAVE_AREA_SYNC 364*4882a593Smuzhiyun la %r8,4095 365*4882a593Smuzhiyun stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8) 366*4882a593Smuzhiyun stmg %r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8) 367*4882a593Smuzhiyun mvc __LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC 368*4882a593Smuzhiyun mvc __LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW 369*4882a593Smuzhiyun mvc __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW 370*4882a593Smuzhiyun ni __LC_RETURN_PSW,0xfc # remove IO and EX bits 371*4882a593Smuzhiyun ni __LC_RETURN_PSW+1,0xfb # remove MCHK bit 372*4882a593Smuzhiyun oi __LC_RETURN_PSW+1,0x2 # set wait state bit 373*4882a593Smuzhiyun larl %r9,.Lold_psw_disabled_wait 374*4882a593Smuzhiyun stg %r9,__LC_PGM_NEW_PSW+8 375*4882a593Smuzhiyun l %r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r9) 376*4882a593Smuzhiyun brasl %r14,print_pgm_check_info 377*4882a593Smuzhiyun.Lold_psw_disabled_wait: 378*4882a593Smuzhiyun la %r8,4095 379*4882a593Smuzhiyun lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8) 380*4882a593Smuzhiyun lpswe __LC_RETURN_PSW # disabled wait 381*4882a593Smuzhiyun.Ldump_info_stack: 382*4882a593Smuzhiyun .long 0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD 383*4882a593SmuzhiyunENDPROC(startup_pgm_check_handler) 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun# 386*4882a593Smuzhiyun# params at 10400 (setup.h) 387*4882a593Smuzhiyun# Must be keept in sync with struct parmarea in setup.h 388*4882a593Smuzhiyun# 389*4882a593Smuzhiyun .org PARMAREA 390*4882a593Smuzhiyun .quad 0 # IPL_DEVICE 391*4882a593Smuzhiyun .quad 0 # INITRD_START 392*4882a593Smuzhiyun .quad 0 # INITRD_SIZE 393*4882a593Smuzhiyun .quad 0 # OLDMEM_BASE 394*4882a593Smuzhiyun .quad 0 # OLDMEM_SIZE 395*4882a593Smuzhiyun .quad kernel_version # points to kernel version string 396*4882a593Smuzhiyun 397*4882a593Smuzhiyun .org COMMAND_LINE 398*4882a593Smuzhiyun .byte "root=/dev/ram0 ro" 399*4882a593Smuzhiyun .byte 0 400*4882a593Smuzhiyun 401*4882a593Smuzhiyun .org EARLY_SCCB_OFFSET 402*4882a593Smuzhiyun .fill 4096 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun .org HEAD_END 405