diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 4 | ||||
-rw-r--r-- | arch/s390/kernel/head.S | 383 | ||||
-rw-r--r-- | arch/s390/kernel/head31.S | 336 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 543 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 8 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 29 | ||||
-rw-r--r-- | arch/s390/mm/extmem.c | 8 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 113 |
11 files changed, 403 insertions, 1033 deletions
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 98db30481d9..73a09a6ee6c 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -76,9 +76,7 @@ AFLAGS += $(aflags-y) OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start -head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o -head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o -head-y += arch/$(ARCH)/kernel/init_task.o +head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o core-y += arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \ arch/$(ARCH)/appldata/ diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 8584dd82321..7434c32bc63 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -8,9 +8,7 @@ obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o -extra-$(CONFIG_ARCH_S390_31) += head.o -extra-$(CONFIG_ARCH_S390X) += head64.o -extra-y += init_task.o vmlinux.lds +extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 9b30f4cf32c..27b07730b7b 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -288,7 +288,7 @@ sysc_sigpending: bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP bo BASED(sysc_singlestep) - b BASED(sysc_leave) # out of here, do NOT recheck + b BASED(sysc_work_loop) # # _TIF_RESTART_SVC is set, set up registers and restart svc @@ -645,7 +645,7 @@ io_sigpending: l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - b BASED(io_leave) # out of here, do NOT recheck + b BASED(io_work_loop) /* * External interrupt handler routine diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7b9b4a2ba1d..4eb71ffcf48 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -283,7 +283,7 @@ sysc_sigpending: jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP jo sysc_singlestep - j sysc_leave # out of here, do NOT recheck + j sysc_work_loop # # _TIF_RESTART_SVC is set, set up registers and restart svc @@ -684,7 +684,7 @@ io_sigpending: slgr %r3,%r3 # clear *oldset brasl %r14,do_signal # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts - j sysc_leave # out of here, do NOT recheck + j io_work_loop /* * External interrupt handler routine diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 039354d7234..d31a97c89f6 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -1,11 +1,12 @@ /* * 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) + * (C) Copyright IBM Corp. 1999, 2005 + * + * Author(s): Hartmut Penner <hp@de.ibm.com> + * Martin Schwidefsky <schwidefsky@de.ibm.com> + * Rob van der Heij <rvdhei@iae.nl> + * Heiko Carstens <heiko.carstens@de.ibm.com> * * There are 5 different IPL methods * 1) load the image directly into ram at address 0 and do an PSW restart @@ -19,12 +20,7 @@ * 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> @@ -34,6 +30,12 @@ #include <asm/thread_info.h> #include <asm/page.h> +#ifdef CONFIG_ARCH_S390X +#define ARCH_OFFSET 4 +#else +#define ARCH_OFFSET 0 +#endif + #ifndef CONFIG_IPL .org 0 .long 0x00080000,0x80000000+startup # Just a restart PSW @@ -201,7 +203,7 @@ ssch 0(%r3) # load chunk of 1600 bytes bnz .Llderr .Lwait4irq: - mvc __LC_IO_NEW_PSW(8),.Lnewpsw # set up IO interrupt psw + mvc 0x78(8),.Lnewpsw # set up IO interrupt psw lpsw .Lwaitpsw .Lioint: c %r1,0xb8 # compare subchannel number @@ -265,13 +267,13 @@ iplstart: la %r2,IPL_BS # load start address bas %r14,.Lloader # load rest of ipl image l %r12,.Lparm # pointer to parameter area - st %r1,IPL_DEVICE-PARMAREA(%r12) # store ipl device number + st %r1,IPL_DEVICE+ARCH_OFFSET-PARMAREA(%r12) # save ipl device number # # load parameter file from ipl device # .Lagain1: - l %r2,INITRD_START-PARMAREA(%r12) # use ramdisk location as temp + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp bas %r14,.Lloader # load parameter file ltr %r2,%r2 # got anything ? bz .Lnopf @@ -279,7 +281,7 @@ iplstart: bnh .Lnotrunc la %r2,895 .Lnotrunc: - l %r4,INITRD_START-PARMAREA(%r12) + l %r4,INITRD_START+ARCH_OFFSET-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 @@ -322,14 +324,14 @@ iplstart: # load ramdisk from ipl device # .Lagain2: - l %r2,INITRD_START-PARMAREA(%r12) # load adr. of ramdisk + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk bas %r14,.Lloader # load ramdisk - st %r2,INITRD_SIZE-PARMAREA(%r12) # store size of ramdisk + st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk ltr %r2,%r2 bnz .Lrdcont - st %r2,INITRD_START-PARMAREA(%r12) # no ramdisk found, null it + st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found .Lrdcont: - l %r2,INITRD_START-PARMAREA(%r12) + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) clc 0(3,%r2),.L_hdr # skip HDRx and EOFx bz .Lagain2 @@ -432,10 +434,10 @@ start: la %r3,1(%r3) .done: l %r1,.memsize - st %r3,0(%r1) + st %r3,ARCH_OFFSET(%r1) slr %r0,%r0 - st %r0,INITRD_SIZE-PARMAREA(%r11) - st %r0,INITRD_START-PARMAREA(%r11) + st %r0,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r11) + st %r0,INITRD_START+ARCH_OFFSET-PARMAREA(%r11) j startup # continue with startup .tbl: .long _ebcasc # translate table .cmd: .long COMMAND_LINE # address of command line buffer @@ -478,304 +480,23 @@ start: .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff -# -# startup-code at 0x10000, running in real mode -# this is called either by the ipl loader or directly by PSW restart -# or linload or SALIPL -# - .org 0x10000 -startup:basr %r13,0 # get base -.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) - basr %r14, %r1 - lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers - la %r12,_pstart-.LPG1(%r13) # pointer to parameter area - # move IPL device to lowcore - mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) - -# -# clear bss memory -# - l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss - l %r3,.Lbss_end-.LPG1(%r13) # end of bss - sr %r3,%r2 # length of bss - sr %r4,%r4 # - sr %r5,%r5 # set src,length and pad to zero - sr %r0,%r0 # - mvcle %r2,%r4,0 # clear mem - jo .-4 # branch back, if not finish - - l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word -.Lservicecall: - stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts - - stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 - la %r1,0x200 # set bit 22 - o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 - st %r1,.Lcr-.LPG1(%r13) - lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 - - mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw - la %r1, .Lsclph-.LPG1(%r13) - a %r1,__LC_EXT_NEW_PSW+4 # set handler - st %r1,__LC_EXT_NEW_PSW+4 - - la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff - la %r1, .Lsccb-PARMAREA(%r4) # our sccb - .insn rre,0xb2200000,%r2,%r1 # service call - ipm %r1 - srl %r1,28 # get cc code - xr %r3, %r3 - chi %r1,3 - be .Lfchunk-.LPG1(%r13) # leave - chi %r1,2 - be .Lservicecall-.LPG1(%r13) - lpsw .Lwaitsclp-.LPG1(%r13) -.Lsclph: - lh %r1,.Lsccbr-PARMAREA(%r4) - chi %r1,0x10 # 0x0010 is the sucess code - je .Lprocsccb # let's process the sccb - chi %r1,0x1f0 - bne .Lfchunk-.LPG1(%r13) # unhandled error code - c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced - bne .Lfchunk-.LPG1(%r13) # if no, give up - l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP - b .Lservicecall-.LPG1(%r13) -.Lprocsccb: - lhi %r1,0 - icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 - jnz .Lscnd - lhi %r1,0x800 # otherwise report 2GB -.Lscnd: - lhi %r3,0x800 # limit reported memory size to 2GB - cr %r1,%r3 - jl .Lno2gb - lr %r1,%r3 -.Lno2gb: - xr %r3,%r3 # same logic - ic %r3,.Lscpa1-PARMAREA(%r4) - chi %r3,0x00 - jne .Lcompmem - l %r3,.Lscpa2-PARMAREA(%r13) -.Lcompmem: - mr %r2,%r1 # mem in MB on 128-bit - l %r1,.Lonemb-.LPG1(%r13) - mr %r2,%r1 # mem size in bytes in %r3 - b .Lfchunk-.LPG1(%r13) - - .align 4 -.Lget_ipl_device_addr: - .long .Lget_ipl_device -.Lpmask: - .byte 0 -.align 8 -.Lpcext:.long 0x00080000,0x80000000 -.Lcr: - .long 0x00 # place holder for cr0 -.Lwaitsclp: - .long 0x020A0000 - .long .Lsclph -.Lrcp: - .int 0x00120001 # Read SCP forced code -.Lrcp2: - .int 0x00020001 # Read SCP code -.Lonemb: - .int 0x100000 -.Lfchunk: - -# -# find memory chunks. -# - lr %r9,%r3 # end of mem - mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) - la %r1,1 # test in increments of 128KB - sll %r1,17 - l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array - slr %r4,%r4 # set start of chunk to zero - slr %r5,%r5 # set end of chunk to zero - slr %r6,%r6 # set access code to zero - la %r10, MEMORY_CHUNKS # number of chunks -.Lloop: - tprot 0(%r5),0 # test protection of first byte - ipm %r7 - srl %r7,28 - clr %r6,%r7 # compare cc with last access code - be .Lsame-.LPG1(%r13) - b .Lchkmem-.LPG1(%r13) -.Lsame: - ar %r5,%r1 # add 128KB to end of chunk - bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop -.Lchkmem: # > 2GB or tprot got a program check - clr %r4,%r5 # chunk size > 0? - be .Lchkloop-.LPG1(%r13) - st %r4,0(%r3) # store start address of chunk - lr %r0,%r5 - slr %r0,%r4 - st %r0,4(%r3) # store size of chunk - st %r6,8(%r3) # store type of chunk - la %r3,12(%r3) - l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size - st %r5,0(%r4) # store last end to memory size - ahi %r10,-1 # update chunk number -.Lchkloop: - lr %r6,%r7 # set access code to last cc - # we got an exception or we're starting a new - # chunk , we must check if we should - # still try to find valid memory (if we detected - # the amount of available storage), and if we - # have chunks left - xr %r0,%r0 - clr %r0,%r9 # did we detect memory? - je .Ldonemem # if not, leave - chi %r10,0 # do we have chunks left? - je .Ldonemem - alr %r5,%r1 # add 128KB to end of chunk - lr %r4,%r5 # potential new chunk - clr %r5,%r9 # should we go on? - jl .Lloop -.Ldonemem: - l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags -# -# find out if we are running under VM -# - stidp __LC_CPUID # store cpuid - tm __LC_CPUID,0xff # running under VM ? - bno .Lnovm-.LPG1(%r13) - oi 3(%r12),1 # set VM flag -.Lnovm: - lh %r0,__LC_CPUID+4 # get cpu version - chi %r0,0x7490 # running on a P/390 ? - bne .Lnop390-.LPG1(%r13) - oi 3(%r12),4 # set P/390 flag -.Lnop390: - -# -# find out if we have an IEEE fpu -# - mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) - efpc %r0,0 # test IEEE extract fpc instruction - oi 3(%r12),2 # set IEEE fpu flag -.Lchkfpu: - -# -# find out if we have the CSP instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) - la %r0,0 - lr %r1,%r0 - la %r2,4 - csp %r0,%r2 # Test CSP instruction - oi 3(%r12),8 # set CSP flag -.Lchkcsp: - -# -# find out if we have the MVPG instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) - sr %r0,%r0 - la %r1,0 - la %r2,0 - mvpg %r1,%r2 # Test CSP instruction - oi 3(%r12),16 # set MVPG flag -.Lchkmvpg: - -# -# find out if we have the IDTE instruction -# - mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) - .long 0xb2b10000 # store facility list - tm 0xc8,0x08 # check bit for clearing-by-ASCE - bno .Lchkidte-.LPG1(%r13) - lhi %r1,2094 - lhi %r2,0 - .long 0xb98e2001 - oi 3(%r12),0x80 # set IDTE flag -.Lchkidte: - - lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, - # virtual and never return ... - .align 8 -.Lentry:.long 0x00080000,0x80000000 + _stext -.Lctl: .long 0x04b50002 # cr0: various things - .long 0 # cr1: primary space segment table - .long .Lduct # cr2: dispatchable unit control table - .long 0 # cr3: instruction authorization - .long 0 # cr4: instruction authorization - .long 0xffffffff # cr5: primary-aste origin - .long 0 # cr6: I/O interrupts - .long 0 # cr7: secondary space segment table - .long 0 # cr8: access registers translation - .long 0 # cr9: tracing off - .long 0 # cr10: tracing off - .long 0 # cr11: tracing off - .long 0 # cr12: tracing off - .long 0 # cr13: home space segment table - .long 0xc0000000 # cr14: machine check handling off - .long 0 # cr15: linkage stack operations -.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem -.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu -.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp -.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg -.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte -.Lmemsize:.long memory_size -.Lmchunk:.long memory_chunk -.Lmflags:.long machine_flags -.Lbss_bgn: .long __bss_start -.Lbss_end: .long _end - - .org PARMAREA-64 -.Lduct: .long 0,0,0,0,0,0,0,0 - .long 0,0,0,0,0,0,0,0 - -# -# params at 10400 (setup.h) -# - .org PARMAREA - .global _pstart -_pstart: - .long 0,0 # IPL_DEVICE - .long 0,RAMDISK_ORIGIN # INITRD_START - .long 0,RAMDISK_SIZE # INITRD_SIZE - - .org COMMAND_LINE - .byte "root=/dev/ram0 ro" - .byte 0 - .org 0x11000 -.Lsccb: - .hword 0x1000 # length, one page - .byte 0x00,0x00,0x00 - .byte 0x80 # variable response bit set -.Lsccbr: - .hword 0x00 # response code -.Lscpincr1: - .hword 0x00 -.Lscpa1: - .byte 0x00 - .fill 89,1,0 -.Lscpa2: - .int 0x00 -.Lscpincr2: - .quad 0x00 - .fill 3984,1,0 - .org 0x12000 - .global _pend -_pend: - +.macro GET_IPL_DEVICE .Lget_ipl_device: basr %r12,0 -.LPG2: l %r1,0xb8 # get sid +.LGID: l %r1,0xb8 # get sid sll %r1,15 # test if subchannel is enabled srl %r1,31 ltr %r1,%r1 bz 0(%r14) # subchannel disabled l %r1,0xb8 - la %r5,.Lipl_schib-.LPG2(%r12) + la %r5,.Lipl_schib-.LGID(%r12) stsch 0(%r5) # get schib of subchannel bnz 0(%r14) # schib not available tm 5(%r5),0x01 # devno valid? bno 0(%r14) - la %r6,ipl_parameter_flags-.LPG2(%r12) + la %r6,ipl_parameter_flags-.LGID(%r12) oi 3(%r6),0x01 # set flag - la %r2,ipl_devno-.LPG2(%r12) + la %r2,ipl_devno-.LGID(%r12) mvc 0(2,%r2),6(%r5) # store devno tm 4(%r5),0x80 # qdio capable device? bno 0(%r14) @@ -816,46 +537,10 @@ ipl_parameter_flags: .globl ipl_devno ipl_devno: .word 0 +.endm -#ifdef CONFIG_SHARED_KERNEL - .org 0x100000 +#ifdef CONFIG_ARCH_S390X +#include "head64.S" +#else +#include "head31.S" #endif - -# -# startup-code, running in virtual mode -# - .globl _stext -_stext: basr %r13,0 # get base -.LPG3: -# -# Setup stack -# - l %r15,.Linittu-.LPG3(%r13) - mvc __LC_CURRENT(4),__TI_task(%r15) - ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE - st %r15,__LC_KERNEL_STACK # set end of kernel stack - ahi %r15,-96 - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain - -# check control registers - stctl %c0,%c15,0(%r15) - oi 2(%r15),0x40 # enable sigp emergency signal - oi 0(%r15),0x10 # switch on low address protection - lctl %c0,%c15,0(%r15) - -# - lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess - l %r14,.Lstart-.LPG3(%r13) - basr %r14,%r14 # call start_kernel -# -# We returned from start_kernel ?!? PANIK -# - basr %r13,0 - lpsw .Ldw-.(%r13) # load disabled wait psw -# - .align 8 -.Ldw: .long 0x000a0000,0x00000000 -.Linittu: .long init_thread_union -.Lstart: .long start_kernel -.Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S new file mode 100644 index 00000000000..2d3b089bfb8 --- /dev/null +++ b/arch/s390/kernel/head31.S @@ -0,0 +1,336 @@ +/* + * arch/s390/kernel/head31.S + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Hartmut Penner <hp@de.ibm.com> + * Martin Schwidefsky <schwidefsky@de.ibm.com> + * Rob van der Heij <rvdhei@iae.nl> + * Heiko Carstens <heiko.carstens@de.ibm.com> + * + */ + +# +# startup-code at 0x10000, running in absolute addressing mode +# this is called either by the ipl loader or directly by PSW restart +# or linload or SALIPL +# + .org 0x10000 +startup:basr %r13,0 # get base +.LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) + basr %r14, %r1 + lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers + la %r12,_pstart-.LPG1(%r13) # pointer to parameter area + # move IPL device to lowcore + mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) + +# +# clear bss memory +# + l %r2,.Lbss_bgn-.LPG1(%r13) # start of bss + l %r3,.Lbss_end-.LPG1(%r13) # end of bss + sr %r3,%r2 # length of bss + sr %r4,%r4 + sr %r5,%r5 # set src,length and pad to zero + sr %r0,%r0 + mvcle %r2,%r4,0 # clear mem + jo .-4 # branch back, if not finish + + l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word +.Lservicecall: + stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts + + stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 + la %r1,0x200 # set bit 22 + o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 + st %r1,.Lcr-.LPG1(%r13) + lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 + + mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw + la %r1, .Lsclph-.LPG1(%r13) + a %r1,__LC_EXT_NEW_PSW+4 # set handler + st %r1,__LC_EXT_NEW_PSW+4 + + la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff + la %r1, .Lsccb-PARMAREA(%r4) # our sccb + .insn rre,0xb2200000,%r2,%r1 # service call + ipm %r1 + srl %r1,28 # get cc code + xr %r3, %r3 + chi %r1,3 + be .Lfchunk-.LPG1(%r13) # leave + chi %r1,2 + be .Lservicecall-.LPG1(%r13) + lpsw .Lwaitsclp-.LPG1(%r13) +.Lsclph: + lh %r1,.Lsccbr-PARMAREA(%r4) + chi %r1,0x10 # 0x0010 is the sucess code + je .Lprocsccb # let's process the sccb + chi %r1,0x1f0 + bne .Lfchunk-.LPG1(%r13) # unhandled error code + c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced + bne .Lfchunk-.LPG1(%r13) # if no, give up + l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP + b .Lservicecall-.LPG1(%r13) +.Lprocsccb: + lhi %r1,0 + icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 + jnz .Lscnd + lhi %r1,0x800 # otherwise report 2GB +.Lscnd: + lhi %r3,0x800 # limit reported memory size to 2GB + cr %r1,%r3 + jl .Lno2gb + lr %r1,%r3 +.Lno2gb: + xr %r3,%r3 # same logic + ic %r3,.Lscpa1-PARMAREA(%r4) + chi %r3,0x00 + jne .Lcompmem + l %r3,.Lscpa2-PARMAREA(%r13) +.Lcompmem: + mr %r2,%r1 # mem in MB on 128-bit + l %r1,.Lonemb-.LPG1(%r13) + mr %r2,%r1 # mem size in bytes in %r3 + b .Lfchunk-.LPG1(%r13) + + .align 4 +.Lget_ipl_device_addr: + .long .Lget_ipl_device +.Lpmask: + .byte 0 +.align 8 +.Lpcext:.long 0x00080000,0x80000000 +.Lcr: + .long 0x00 # place holder for cr0 +.Lwaitsclp: + .long 0x010a0000,0x80000000 + .Lsclph +.Lrcp: + .int 0x00120001 # Read SCP forced code +.Lrcp2: + .int 0x00020001 # Read SCP code +.Lonemb: + .int 0x100000 +.Lfchunk: + +# +# find memory chunks. +# + lr %r9,%r3 # end of mem + mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) + la %r1,1 # test in increments of 128KB + sll %r1,17 + l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array + slr %r4,%r4 # set start of chunk to zero + slr %r5,%r5 # set end of chunk to zero + slr %r6,%r6 # set access code to zero + la %r10, MEMORY_CHUNKS # number of chunks +.Lloop: + tprot 0(%r5),0 # test protection of first byte + ipm %r7 + srl %r7,28 + clr %r6,%r7 # compare cc with last access code + be .Lsame-.LPG1(%r13) + b .Lchkmem-.LPG1(%r13) +.Lsame: + ar %r5,%r1 # add 128KB to end of chunk + bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop +.Lchkmem: # > 2GB or tprot got a program check + clr %r4,%r5 # chunk size > 0? + be .Lchkloop-.LPG1(%r13) + st %r4,0(%r3) # store start address of chunk + lr %r0,%r5 + slr %r0,%r4 + st %r0,4(%r3) # store size of chunk + st %r6,8(%r3) # store type of chunk + la %r3,12(%r3) + l %r4,.Lmemsize-.LPG1(%r13) # address of variable memory_size + st %r5,0(%r4) # store last end to memory size + ahi %r10,-1 # update chunk number +.Lchkloop: + lr %r6,%r7 # set access code to last cc + # we got an exception or we're starting a new + # chunk , we must check if we should + # still try to find valid memory (if we detected + # the amount of available storage), and if we + # have chunks left + xr %r0,%r0 + clr %r0,%r9 # did we detect memory? + je .Ldonemem # if not, leave + chi %r10,0 # do we have chunks left? + je .Ldonemem + alr %r5,%r1 # add 128KB to end of chunk + lr %r4,%r5 # potential new chunk + clr %r5,%r9 # should we go on? + jl .Lloop +.Ldonemem: + l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags +# +# find out if we are running under VM +# + stidp __LC_CPUID # store cpuid + tm __LC_CPUID,0xff # running under VM ? + bno .Lnovm-.LPG1(%r13) + oi 3(%r12),1 # set VM flag +.Lnovm: + lh %r0,__LC_CPUID+4 # get cpu version + chi %r0,0x7490 # running on a P/390 ? + bne .Lnop390-.LPG1(%r13) + oi 3(%r12),4 # set P/390 flag +.Lnop390: + +# +# find out if we have an IEEE fpu +# + mvc __LC_PGM_NEW_PSW(8),.Lpcfpu-.LPG1(%r13) + efpc %r0,0 # test IEEE extract fpc instruction + oi 3(%r12),2 # set IEEE fpu flag +.Lchkfpu: + +# +# find out if we have the CSP instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpccsp-.LPG1(%r13) + la %r0,0 + lr %r1,%r0 + la %r2,4 + csp %r0,%r2 # Test CSP instruction + oi 3(%r12),8 # set CSP flag +.Lchkcsp: + +# +# find out if we have the MVPG instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpcmvpg-.LPG1(%r13) + sr %r0,%r0 + la %r1,0 + la %r2,0 + mvpg %r1,%r2 # Test CSP instruction + oi 3(%r12),16 # set MVPG flag +.Lchkmvpg: + +# +# find out if we have the IDTE instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) + .long 0xb2b10000 # store facility list + tm 0xc8,0x08 # check bit for clearing-by-ASCE + bno .Lchkidte-.LPG1(%r13) + lhi %r1,2094 + lhi %r2,0 + .long 0xb98e2001 + oi 3(%r12),0x80 # set IDTE flag +.Lchkidte: + + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, + # virtual and never return ... + .align 8 +.Lentry:.long 0x00080000,0x80000000 + _stext +.Lctl: .long 0x04b50002 # cr0: various things + .long 0 # cr1: primary space segment table + .long .Lduct # cr2: dispatchable unit control table + .long 0 # cr3: instruction authorization + .long 0 # cr4: instruction authorization + .long 0xffffffff # cr5: primary-aste origin + .long 0 # cr6: I/O interrupts + .long 0 # cr7: secondary space segment table + .long 0 # cr8: access registers translation + .long 0 # cr9: tracing off + .long 0 # cr10: tracing off + .long 0 # cr11: tracing off + .long 0 # cr12: tracing off + .long 0 # cr13: home space segment table + .long 0xc0000000 # cr14: machine check handling off + .long 0 # cr15: linkage stack operations +.Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem +.Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu +.Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp +.Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg +.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte +.Lmemsize:.long memory_size +.Lmchunk:.long memory_chunk +.Lmflags:.long machine_flags +.Lbss_bgn: .long __bss_start +.Lbss_end: .long _end + + .org PARMAREA-64 +.Lduct: .long 0,0,0,0,0,0,0,0 + .long 0,0,0,0,0,0,0,0 + +# +# params at 10400 (setup.h) +# + .org PARMAREA + .global _pstart +_pstart: + .long 0,0 # IPL_DEVICE + .long 0,RAMDISK_ORIGIN # INITRD_START + .long 0,RAMDISK_SIZE # INITRD_SIZE + + .org COMMAND_LINE + .byte "root=/dev/ram0 ro" + .byte 0 + .org 0x11000 +.Lsccb: + .hword 0x1000 # length, one page + .byte 0x00,0x00,0x00 + .byte 0x80 # variable response bit set +.Lsccbr: + .hword 0x00 # response code +.Lscpincr1: + .hword 0x00 +.Lscpa1: + .byte 0x00 + .fill 89,1,0 +.Lscpa2: + .int 0x00 +.Lscpincr2: + .quad 0x00 + .fill 3984,1,0 + .org 0x12000 + .global _pend +_pend: + + GET_IPL_DEVICE + +#ifdef CONFIG_SHARED_KERNEL + .org 0x100000 +#endif + +# +# startup-code, running in virtual mode +# + .globl _stext +_stext: basr %r13,0 # get base +.LPG3: +# +# Setup stack +# + l %r15,.Linittu-.LPG3(%r13) + mvc __LC_CURRENT(4),__TI_task(%r15) + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE + st %r15,__LC_KERNEL_STACK # set end of kernel stack + ahi %r15,-96 + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + +# check control registers + stctl %c0,%c15,0(%r15) + oi 2(%r15),0x40 # enable sigp emergency signal + oi 0(%r15),0x10 # switch on low address protection + lctl %c0,%c15,0(%r15) + +# + lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess + l %r14,.Lstart-.LPG3(%r13) + basr %r14,%r14 # call start_kernel +# +# We returned from start_kernel ?!? PANIK +# + basr %r13,0 + lpsw .Ldw-.(%r13) # load disabled wait psw +# + .align 8 +.Ldw: .long 0x000a0000,0x00000000 +.Linittu:.long init_thread_union +.Lstart:.long start_kernel +.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 193aafa72f5..f08c06f45d5 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -1,482 +1,17 @@ /* - * arch/s390/kernel/head.S + * arch/s390/kernel/head64.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) + * (C) Copyright IBM Corp. 1999,2005 + * + * Author(s): Hartmut Penner <hp@de.ibm.com> + * Martin Schwidefsky <schwidefsky@de.ibm.com> + * Rob van der Heij <rvdhei@iae.nl> + * Heiko Carstens <heiko.carstens@de.ibm.com> * - * 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/asm-offsets.h> -#include <asm/thread_info.h> -#include <asm/page.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 - diag %r2,%r3,8 - la %r5,.Lirb - stsch 0(%r5) # check if irq is pending - tm 30(%r5),0x0f # by verifying if any of the - bnz .Lwaitforirq # activity or status control - tm 31(%r5),0xff # bits is set in the schib - bz .Lnoreset -.Lwaitforirq: - mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw -.Lwaitrdrirq: - lpsw .Lrdrwaitpsw -.Lrdrint: - c %r1,0xb8 # compare subchannel number - bne .Lwaitrdrirq - la %r5,.Lirb - tsch 0(%r5) -.Lnoreset: - b .Lnoload - - .align 8 -.Lrdrnewpsw: - .long 0x00080000,0x80000000+.Lrdrint -.Lrdrwaitpsw: - .long 0x020a0000,0x80000000+.Lrdrint -#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 start -start: - 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 - b .gotr -.sk8x8: - mvc 0(240,%r8),0(%r9) # copy iplparms into buffer -.gotr: - l %r10,.tbl # EBCDIC to ASCII table - tr 0(240,%r8),0(%r10) - stidp __LC_CPUID # Are we running on VM maybe - cli __LC_CPUID,0xff - bnz .test - .long 0x83300060 # diag 3,0,x'0060' - storage size - b .done -.test: - mvc 0x68(8),.pgmnw # set up pgm check handler - l %r2,.fourmeg - lr %r3,%r2 - bctr %r3,%r0 # 4M-1 -.loop: iske %r0,%r3 - ar %r3,%r2 -.pgmx: - sr %r3,%r2 - la %r3,1(%r3) -.done: - l %r1,.memsize - st %r3,4(%r1) - slr %r0,%r0 - st %r0,INITRD_SIZE+4-PARMAREA(%r11) - st %r0,INITRD_START+4-PARMAREA(%r11) - j startup # continue with startup -.tbl: .long _ebcasc # translate table -.cmd: .long COMMAND_LINE # address of command line buffer -.parm: .long PARMAREA -.fourmeg: .long 0x00400000 # 4M -.pgmnw: .long 0x00080000,.pgmx -.memsize: .long memory_size -.lowcase: - .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 - .byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f - .byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 - .byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f - .byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 - .byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f - .byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 - .byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f - .byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 - .byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f - .byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 - .byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f - .byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 - .byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f - .byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 - .byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f - - .byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 - .byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f - .byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 - .byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f - .byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 - .byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf - .byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 - .byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf - .byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87 # .abcdefg - .byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf # hi - .byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 # .jklmnop - .byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf # qr - .byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 # ..stuvwx - .byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef # yz - .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 - .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff - -# -# startup-code at 0x10000, running in real mode +# startup-code at 0x10000, running in absolute addressing mode # this is called either by the ipl loader or directly by PSW restart # or linload or SALIPL # @@ -530,7 +65,7 @@ startup:basr %r13,0 # get base be .Lfchunk-.LPG1(%r13) # leave chi %r1,2 be .Lservicecall-.LPG1(%r13) - lpsw .Lwaitsclp-.LPG1(%r13) + lpswe .Lwaitsclp-.LPG1(%r13) .Lsclph: lh %r1,.Lsccbr-PARMAREA(%r4) chi %r1,0x10 # 0x0010 is the sucess code @@ -567,8 +102,7 @@ startup:basr %r13,0 # get base .Lcr: .quad 0x00 # place holder for cr0 .Lwaitsclp: - .long 0x020A0000 - .quad .Lsclph + .quad 0x0102000180000000,.Lsclph .Lrcp: .int 0x00120001 # Read SCP forced code .Lrcp2: @@ -751,62 +285,7 @@ _pstart: .global _pend _pend: -.Lget_ipl_device: - basr %r12,0 -.LPG2: l %r1,0xb8 # get sid - sll %r1,15 # test if subchannel is enabled - srl %r1,31 - ltr %r1,%r1 - bz 0(%r14) # subchannel disabled - l %r1,0xb8 - la %r5,.Lipl_schib-.LPG2(%r12) - stsch 0(%r5) # get schib of subchannel - bnz 0(%r14) # schib not available - tm 5(%r5),0x01 # devno valid? - bno 0(%r14) - la %r6,ipl_parameter_flags-.LPG2(%r12) - oi 3(%r6),0x01 # set flag - la %r2,ipl_devno-.LPG2(%r12) - mvc 0(2,%r2),6(%r5) # store devno - tm 4(%r5),0x80 # qdio capable device? - bno 0(%r14) - oi 3(%r6),0x02 # set flag - - # copy ipl parameters - - lhi %r0,4096 - l %r2,20(%r0) # get address of parameter list - lhi %r3,IPL_PARMBLOCK_ORIGIN - st %r3,20(%r0) - lhi %r4,1 - cr %r2,%r3 # start parameters < destination ? - jl 0f - lhi %r1,1 # copy direction is upwards - j 1f -0: lhi %r1,-1 # copy direction is downwards - ar %r2,%r0 - ar %r3,%r0 - ar %r2,%r1 - ar %r3,%r1 -1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters - ar %r3,%r1 - ar %r2,%r1 - sr %r0,%r4 - jne 1b - b 0(%r14) - - .align 4 -.Lipl_schib: - .rept 13 - .long 0 - .endr - - .globl ipl_parameter_flags -ipl_parameter_flags: - .long 0 - .globl ipl_devno -ipl_devno: - .word 0 + GET_IPL_DEVICE #ifdef CONFIG_SHARED_KERNEL .org 0x100000 diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 9a1d95894f3..c36353e8c14 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -237,6 +237,8 @@ int sysctl_hz_timer = 1; */ static inline void stop_hz_timer(void) { + unsigned long flags; + unsigned long seq, next; __u64 timer, todval; if (sysctl_hz_timer != 0) @@ -257,7 +259,11 @@ static inline void stop_hz_timer(void) * This cpu is going really idle. Set up the clock comparator * for the next event. */ - timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; + next = next_timer_interrupt(); + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + timer = (__u64)(next - jiffies) + jiffies_64; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) { diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6b8703ec2ae..c5bd36fae56 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -57,7 +57,6 @@ int sysctl_userprocess_debug = 0; extern pgm_check_handler_t do_protection_exception; extern pgm_check_handler_t do_dat_exception; -extern pgm_check_handler_t do_pseudo_page_fault; #ifdef CONFIG_PFAULT extern int pfault_init(void); extern void pfault_fini(void); @@ -676,20 +675,6 @@ asmlinkage void kernel_stack_overflow(struct pt_regs * regs) panic("Corrupt kernel stack, can't continue."); } -#ifndef CONFIG_ARCH_S390X -static int -pagex_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - if (MACHINE_IS_VM) - cpcmd("SET PAGEX OFF", NULL, 0, NULL); - return NOTIFY_DONE; -} - -static struct notifier_block pagex_reboot_notifier = { - .notifier_call = &pagex_reboot_event, -}; -#endif - /* init is done in lowcore.S and head.S */ void __init trap_init(void) @@ -717,9 +702,7 @@ void __init trap_init(void) pgm_check_table[0x11] = &do_dat_exception; pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; -#ifndef CONFIG_ARCH_S390X - pgm_check_table[0x14] = &do_pseudo_page_fault; -#else /* CONFIG_ARCH_S390X */ +#ifdef CONFIG_ARCH_S390X pgm_check_table[0x38] = &do_dat_exception; pgm_check_table[0x39] = &do_dat_exception; pgm_check_table[0x3A] = &do_dat_exception; @@ -731,12 +714,10 @@ void __init trap_init(void) pgm_check_table[0x40] = &do_monitor_call; if (MACHINE_IS_VM) { +#ifdef CONFIG_PFAULT /* - * First try to get pfault pseudo page faults going. - * If this isn't available turn on pagex page faults. + * Try to get pfault pseudo page faults going. */ -#ifdef CONFIG_PFAULT - /* request the 0x2603 external interrupt */ if (register_early_external_interrupt(0x2603, pfault_interrupt, &ext_int_pfault) != 0) panic("Couldn't request external interrupt 0x2603"); @@ -748,9 +729,5 @@ void __init trap_init(void) unregister_early_external_interrupt(0x2603, pfault_interrupt, &ext_int_pfault); #endif -#ifndef CONFIG_ARCH_S390X - register_reboot_notifier(&pagex_reboot_notifier); - cpcmd("SET PAGEX ON", NULL, 0, NULL); -#endif } } diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index c5348108ca3..506a33b51e4 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -234,8 +234,8 @@ query_segment_type (struct dcss_segment *seg) rc = 0; out_free: - if (qin) kfree(qin); - if (qout) kfree(qout); + kfree(qin); + kfree(qout); return rc; } @@ -394,7 +394,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long segtype_string[seg->vm_segtype]); goto out; out_free: - kfree (seg); + kfree(seg); out: return rc; } @@ -505,7 +505,7 @@ segment_modify_shared (char *name, int do_nonshared) list_del(&seg->list); dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy); - kfree (seg); + kfree(seg); out_unlock: spin_unlock(&dcss_lock); return rc; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 856a971759b..64e32da7775 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -352,115 +352,6 @@ void do_dat_exception(struct pt_regs *regs, unsigned long error_code) do_exception(regs, error_code & 0xff, 0); } -#ifndef CONFIG_ARCH_S390X - -typedef struct _pseudo_wait_t { - struct _pseudo_wait_t *next; - wait_queue_head_t queue; - unsigned long address; - int resolved; -} pseudo_wait_t; - -static pseudo_wait_t *pseudo_lock_queue = NULL; -static spinlock_t pseudo_wait_spinlock; /* spinlock to protect lock queue */ - -/* - * This routine handles 'pagex' pseudo page faults. - */ -asmlinkage void -do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code) -{ - pseudo_wait_t wait_struct; - pseudo_wait_t *ptr, *last, *next; - unsigned long address; - - /* - * get the failing address - * more specific the segment and page table portion of - * the address - */ - address = S390_lowcore.trans_exc_code & 0xfffff000; - - if (address & 0x80000000) { - /* high bit set -> a page has been swapped in by VM */ - address &= 0x7fffffff; - spin_lock(&pseudo_wait_spinlock); - last = NULL; - ptr = pseudo_lock_queue; - while (ptr != NULL) { - next = ptr->next; - if (address == ptr->address) { - /* - * This is one of the processes waiting - * for the page. Unchain from the queue. - * There can be more than one process - * waiting for the same page. VM presents - * an initial and a completion interrupt for - * every process that tries to access a - * page swapped out by VM. - */ - if (last == NULL) - pseudo_lock_queue = next; - else - last->next = next; - /* now wake up the process */ - ptr->resolved = 1; - wake_up(&ptr->queue); - } else - last = ptr; - ptr = next; - } - spin_unlock(&pseudo_wait_spinlock); - } else { - /* Pseudo page faults in kernel mode is a bad idea */ - if (!(regs->psw.mask & PSW_MASK_PSTATE)) { - /* - * VM presents pseudo page faults if the interrupted - * state was not disabled for interrupts. So we can - * get pseudo page fault interrupts while running - * in kernel mode. We simply access the page here - * while we are running disabled. VM will then swap - * in the page synchronously. - */ - if (check_user_space(regs, error_code) == 0) - /* dereference a virtual kernel address */ - __asm__ __volatile__ ( - " ic 0,0(%0)" - : : "a" (address) : "0"); - else - /* dereference a virtual user address */ - __asm__ __volatile__ ( - " la 2,0(%0)\n" - " sacf 512\n" - " ic 2,0(2)\n" - "0:sacf 0\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 0b,0b\n" - ".previous" - : : "a" (address) : "2" ); - - return; - } - /* initialize and add element to pseudo_lock_queue */ - init_waitqueue_head (&wait_struct.queue); - wait_struct.address = address; - wait_struct.resolved = 0; - spin_lock(&pseudo_wait_spinlock); - wait_struct.next = pseudo_lock_queue; - pseudo_lock_queue = &wait_struct; - spin_unlock(&pseudo_wait_spinlock); - /* - * The instruction that caused the program check will - * be repeated. Don't signal single step via SIGTRAP. - */ - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); - /* go to sleep */ - wait_event(wait_struct.queue, wait_struct.resolved); - } -} -#endif /* CONFIG_ARCH_S390X */ - #ifdef CONFIG_PFAULT /* * 'pfault' pseudo page faults routines. @@ -508,7 +399,7 @@ int pfault_init(void) " .quad 0b,1b\n" #endif /* CONFIG_ARCH_S390X */ ".previous" - : "=d" (rc) : "a" (&refbk) : "cc" ); + : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" ); __ctl_set_bit(0, 9); return rc; } @@ -532,7 +423,7 @@ void pfault_fini(void) " .quad 0b,0b\n" #endif /* CONFIG_ARCH_S390X */ ".previous" - : : "a" (&refbk) : "cc" ); + : : "a" (&refbk), "m" (refbk) : "cc" ); } asmlinkage void |