?? head64.s
字號:
/* * arch/s390/kernel/head.S * * S390 version * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Hartmut Penner (hp@de.ibm.com), * Martin Schwidefsky (schwidefsky@de.ibm.com), * Rob van der Heij (rvdhei@iae.nl) * * There are 5 different IPL methods * 1) load the image directly into ram at address 0 and do an PSW restart * 2) linload will load the image from address 0x10000 to memory 0x10000 * and start the code thru LPSW 0x0008000080010000 (VM only, deprecated) * 3) generate the tape ipl header, store the generated image on a tape * and ipl from it * In case of SL tape you need to IPL 5 times to get past VOL1 etc * 4) generate the vm reader ipl header, move the generated image to the * VM reader (use option NOH!) and do a ipl from reader (VM only) * 5) direct call of start by the SALIPL loader * We use the cpuid to distinguish between VM and native ipl * params for kernel are pushed to 0x10400 (see setup.h) Changes: Okt 25 2000 <rvdheij@iae.nl> added code to skip HDR and EOF to allow SL tape IPL (5 retries) changed first CCW from rewind to backspace block */#include <linux/config.h>#include <asm/setup.h>#include <asm/lowcore.h>#include <asm/offsets.h>#ifndef CONFIG_IPL .org 0 .long 0x00080000,0x80000000+startup # Just a restart PSW#else#ifdef CONFIG_IPL_TAPE#define IPL_BS 1024 .org 0 .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded .long 0x27000000,0x60000001 # by ipl to addresses 0-23. .long 0x02000000,0x20000000+IPL_BS # (a PSW and two CCWs). .long 0x00000000,0x00000000 # external old psw .long 0x00000000,0x00000000 # svc old psw .long 0x00000000,0x00000000 # program check old psw .long 0x00000000,0x00000000 # machine check old psw .long 0x00000000,0x00000000 # io old psw .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 .long 0x000a0000,0x00000058 # external new psw .long 0x000a0000,0x00000060 # svc new psw .long 0x000a0000,0x00000068 # program check new psw .long 0x000a0000,0x00000070 # machine check new psw .long 0x00080000,0x80000000+.Lioint # io new psw .org 0x100## subroutine for loading from tape# Paramters: # R1 = device number# R2 = load address.Lloader: st %r14,.Lldret la %r3,.Lorbread # r3 = address of orb la %r5,.Lirb # r5 = address of irb st %r2,.Lccwread+4 # initialize CCW data addresses lctl %c6,%c6,.Lcr6 slr %r2,%r2.Lldlp: la %r6,3 # 3 retries.Lssch: ssch 0(%r3) # load chunk of IPL_BS bytes bnz .Llderr.Lw4end: bas %r14,.Lwait4io tm 8(%r5),0x82 # do we have a problem ? bnz .Lrecov slr %r7,%r7 icm %r7,3,10(%r5) # get residual count lcr %r7,%r7 la %r7,IPL_BS(%r7) # IPL_BS-residual=#bytes read ar %r2,%r7 # add to total size tm 8(%r5),0x01 # found a tape mark ? bnz .Ldone l %r0,.Lccwread+4 # update CCW data addresses ar %r0,%r7 st %r0,.Lccwread+4 b .Lldlp.Ldone: l %r14,.Lldret br %r14 # r2 contains the total size.Lrecov: bas %r14,.Lsense # do the sensing bct %r6,.Lssch # dec. retry count & branch b .Llderr## Sense subroutine#.Lsense: st %r14,.Lsnsret la %r7,.Lorbsense ssch 0(%r7) # start sense command bnz .Llderr bas %r14,.Lwait4io l %r14,.Lsnsret tm 8(%r5),0x82 # do we have a problem ? bnz .Llderr br %r14## Wait for interrupt subroutine#.Lwait4io: lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number bne .Lwait4io tsch 0(%r5) slr %r0,%r0 tm 8(%r5),0x82 # do we have a problem ? bnz .Lwtexit tm 8(%r5),0x04 # got device end ? bz .Lwait4io.Lwtexit: br %r14.Llderr: lpsw .Lcrash .align 8.Lorbread: .long 0x00000000,0x0080ff00,.Lccwread .align 8.Lorbsense: .long 0x00000000,0x0080ff00,.Lccwsense .align 8.Lccwread: .long 0x02200000+IPL_BS,0x00000000.Lccwsense: .long 0x04200001,0x00000000.Lwaitpsw: .long 0x020a0000,0x80000000+.Lioint.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.Lcr6: .long 0xff000000 .align 8.Lcrash:.long 0x000a0000,0x00000000.Lldret:.long 0.Lsnsret: .long 0#endif /* CONFIG_IPL_TAPE */#ifdef CONFIG_IPL_VM#define IPL_BS 0x730 .org 0 .long 0x00080000,0x80000000+iplstart # The first 24 bytes are loaded .long 0x02000018,0x60000050 # by ipl to addresses 0-23. .long 0x02000068,0x60000050 # (a PSW and two CCWs). .fill 80-24,1,0x40 # bytes 24-79 are discarded !! .long 0x020000f0,0x60000050 # The next 160 byte are loaded .long 0x02000140,0x60000050 # to addresses 0x18-0xb7 .long 0x02000190,0x60000050 # They form the continuation .long 0x020001e0,0x60000050 # of the CCW program started .long 0x02000230,0x60000050 # by ipl and load the range .long 0x02000280,0x60000050 # 0x0f0-0x730 from the image .long 0x020002d0,0x60000050 # to the range 0x0f0-0x730 .long 0x02000320,0x60000050 # in memory. At the end of .long 0x02000370,0x60000050 # the channel program the PSW .long 0x020003c0,0x60000050 # at location 0 is loaded. .long 0x02000410,0x60000050 # Initial processing starts .long 0x02000460,0x60000050 # at 0xf0 = iplstart. .long 0x020004b0,0x60000050 .long 0x02000500,0x60000050 .long 0x02000550,0x60000050 .long 0x020005a0,0x60000050 .long 0x020005f0,0x60000050 .long 0x02000640,0x60000050 .long 0x02000690,0x60000050 .long 0x020006e0,0x20000050 .org 0xf0## subroutine for loading cards from the reader#.Lloader: la %r3,.Lorb # r2 = address of orb into r2 la %r5,.Lirb # r4 = address of irb la %r6,.Lccws la %r7,20.Linit: st %r2,4(%r6) # initialize CCW data addresses la %r2,0x50(%r2) la %r6,8(%r6) bct 7,.Linit lctl %c6,%c6,.Lcr6 # set IO subclass mask slr %r2,%r2.Lldlp: ssch 0(%r3) # load chunk of 1600 bytes bnz .Llderr.Lwait4irq: mvc 0x78(8),.Lnewpsw # set up IO interrupt psw lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number bne .Lwait4irq tsch 0(%r5) slr %r0,%r0 ic %r0,8(%r5) # get device status chi %r0,8 # channel end ? be .Lcont chi %r0,12 # channel end + device end ? be .Lcont l %r0,4(%r5) s %r0,8(%r3) # r0/8 = number of ccws executed mhi %r0,10 # *10 = number of bytes in ccws lh %r3,10(%r5) # get residual count sr %r0,%r3 # #ccws*80-residual=#bytes read ar %r2,%r0 br %r14 # r2 contains the total size.Lcont: ahi %r2,0x640 # add 0x640 to total size la %r6,.Lccws la %r7,20.Lincr: l %r0,4(%r6) # update CCW data addresses ahi %r0,0x640 st %r0,4(%r6) ahi %r6,8 bct 7,.Lincr b .Lldlp.Llderr: lpsw .Lcrash .align 8.Lorb: .long 0x00000000,0x0080ff00,.Lccws.Lirb: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.Lcr6: .long 0xff000000.Lloadp:.long 0,0 .align 8.Lcrash:.long 0x000a0000,0x00000000.Lnewpsw: .long 0x00080000,0x80000000+.Lioint.Lwaitpsw: .long 0x020a0000,0x80000000+.Lioint .align 8.Lccws: .rept 19 .long 0x02600050,0x00000000 .endr .long 0x02200050,0x00000000#endif /* CONFIG_IPL_VM */iplstart: lh %r1,0xb8 # test if subchannel number bct %r1,.Lnoload # is valid l %r1,0xb8 # load ipl subchannel number la %r2,IPL_BS # load start address bas %r14,.Lloader # load rest of ipl image larl %r12,_pstart # pointer to parameter area st %r1,IPL_DEVICE+4-PARMAREA(%r12) # store ipl device number## load parameter file from ipl device#.Lagain1: l %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp bas %r14,.Lloader # load parameter file ltr %r2,%r2 # got anything ? bz .Lnopf chi %r2,895 bnh .Lnotrunc la %r2,895.Lnotrunc: l %r4,INITRD_START+4-PARMAREA(%r12) clc 0(3,%r4),.L_hdr # if it is HDRx bz .Lagain1 # skip dataset header clc 0(3,%r4),.L_eof # if it is EOFx bz .Lagain1 # skip dateset trailer la %r5,0(%r4,%r2) lr %r3,%r2.Lidebc: tm 0(%r5),0x80 # high order bit set ? bo .Ldocv # yes -> convert from EBCDIC ahi %r5,-1 bct %r3,.Lidebc b .Lnocv.Ldocv: l %r3,.Lcvtab tr 0(256,%r4),0(%r3) # convert parameters to ascii tr 256(256,%r4),0(%r3) tr 512(256,%r4),0(%r3) tr 768(122,%r4),0(%r3).Lnocv: la %r3,COMMAND_LINE-PARMAREA(%r12) # load adr. of command line mvc 0(256,%r3),0(%r4) mvc 256(256,%r3),256(%r4) mvc 512(256,%r3),512(%r4) mvc 768(122,%r3),768(%r4) slr %r0,%r0 b .Lcntlp.Ldelspc: ic %r0,0(%r2,%r3) chi %r0,0x20 # is it a space ? be .Lcntlp ahi %r2,1 b .Leolp.Lcntlp: brct %r2,.Ldelspc.Leolp: slr %r0,%r0 stc %r0,0(%r2,%r3) # terminate buffer.Lnopf:## load ramdisk from ipl device#.Lagain2: l %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk bas %r14,.Lloader # load ramdisk st %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk ltr %r2,%r2 bnz .Lrdcont st %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it.Lrdcont: l %r2,INITRD_START+4-PARMAREA(%r12) clc 0(3,%r2),.L_hdr # skip HDRx and EOFx bz .Lagain2 clc 0(3,%r2),.L_eof bz .Lagain2#ifdef CONFIG_IPL_VM## reset files in VM reader# stidp __LC_CPUID # store cpuid tm __LC_CPUID,0xff # running VM ? bno .Lnoreset la %r2,.Lreset lhi %r3,26 .long 0x83230008.Lnoreset:#endif ## everything loaded, go for it#.Lnoload: l %r1,.Lstartup br %r1.Lstartup: .long startup.Lcvtab:.long _ebcasc # ebcdic to ascii table.Lreset:.byte 0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40 .byte 0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6 .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold".L_eof: .long 0xc5d6c600 /* C'EOF' */.L_hdr: .long 0xc8c4d900 /* C'HDR' */#endif /* CONFIG_IPL */## SALIPL loader support. Based on a patch by Rob van der Heij.# This entry point is called directly from the SALIPL loader and# doesn't need a builtin ipl record.# .org 0x800 .globl startstart: stm %r0,%r15,0x07b0 # store registers basr %r12,%r0.base: l %r11,.parm l %r8,.cmd # pointer to command buffer ltr %r9,%r9 # do we have SALIPL parameters? bp .sk8x8 mvc 0(64,%r8),0x00b0 # copy saved registers xc 64(240-64,%r8),0(%r8) # remainder of buffer tr 0(64,%r8),.lowcase
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -