diff options
| -rw-r--r-- | arch/s390/defconfig | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/base.S | 150 | ||||
| -rw-r--r-- | arch/s390/kernel/early.c | 307 | ||||
| -rw-r--r-- | arch/s390/kernel/head31.S | 164 | ||||
| -rw-r--r-- | arch/s390/kernel/head64.S | 175 | ||||
| -rw-r--r-- | arch/s390/kernel/ipl.c | 15 | ||||
| -rw-r--r-- | arch/s390/kernel/reset.S | 90 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 134 | ||||
| -rw-r--r-- | drivers/s390/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/s390/char/Makefile | 4 | ||||
| -rw-r--r-- | drivers/s390/char/sclp.c | 12 | ||||
| -rw-r--r-- | drivers/s390/char/sclp.h | 18 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_cpi.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_info.c | 57 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_rw.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_vt220.c | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/cio.c | 10 | ||||
| -rw-r--r-- | include/asm-s390/processor.h | 12 | ||||
| -rw-r--r-- | include/asm-s390/reset.h | 3 | ||||
| -rw-r--r-- | include/asm-s390/sclp.h | 39 |
21 files changed, 598 insertions, 609 deletions
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index dbe3df4b0dab..7c621b8ef683 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
| @@ -433,7 +433,6 @@ CONFIG_TN3270_CONSOLE=y | |||
| 433 | CONFIG_TN3215=y | 433 | CONFIG_TN3215=y |
| 434 | CONFIG_TN3215_CONSOLE=y | 434 | CONFIG_TN3215_CONSOLE=y |
| 435 | CONFIG_CCW_CONSOLE=y | 435 | CONFIG_CCW_CONSOLE=y |
| 436 | CONFIG_SCLP=y | ||
| 437 | CONFIG_SCLP_TTY=y | 436 | CONFIG_SCLP_TTY=y |
| 438 | CONFIG_SCLP_CONSOLE=y | 437 | CONFIG_SCLP_CONSOLE=y |
| 439 | CONFIG_SCLP_VT220_TTY=y | 438 | CONFIG_SCLP_VT220_TTY=y |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 2de811a71a39..5492d25d7d69 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | EXTRA_AFLAGS := -traditional | 5 | EXTRA_AFLAGS := -traditional |
| 6 | 6 | ||
| 7 | obj-y := bitmap.o traps.o time.o process.o reset.o \ | 7 | obj-y := bitmap.o traps.o time.o process.o base.o early.o \ |
| 8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
| 9 | semaphore.o s390_ext.o debug.o irq.o ipl.o | 9 | semaphore.o s390_ext.o debug.o irq.o ipl.o |
| 10 | 10 | ||
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S new file mode 100644 index 000000000000..dc7e5259770f --- /dev/null +++ b/arch/s390/kernel/base.S | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * arch/s390/kernel/base.S | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2006,2007 | ||
| 5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 6 | * Michael Holzheu <holzheu@de.ibm.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <asm/ptrace.h> | ||
| 10 | #include <asm/lowcore.h> | ||
| 11 | |||
| 12 | #ifdef CONFIG_64BIT | ||
| 13 | |||
| 14 | .globl s390_base_mcck_handler | ||
| 15 | s390_base_mcck_handler: | ||
| 16 | basr %r13,0 | ||
| 17 | 0: lg %r15,__LC_PANIC_STACK # load panic stack | ||
| 18 | aghi %r15,-STACK_FRAME_OVERHEAD | ||
| 19 | larl %r1,s390_base_mcck_handler_fn | ||
| 20 | lg %r1,0(%r1) | ||
| 21 | ltgr %r1,%r1 | ||
| 22 | jz 1f | ||
| 23 | basr %r14,%r1 | ||
| 24 | 1: la %r1,4095 | ||
| 25 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) | ||
| 26 | lpswe __LC_MCK_OLD_PSW | ||
| 27 | |||
| 28 | .section .bss | ||
| 29 | .globl s390_base_mcck_handler_fn | ||
| 30 | s390_base_mcck_handler_fn: | ||
| 31 | .quad 0 | ||
| 32 | .previous | ||
| 33 | |||
| 34 | .globl s390_base_ext_handler | ||
| 35 | s390_base_ext_handler: | ||
| 36 | stmg %r0,%r15,__LC_SAVE_AREA | ||
| 37 | basr %r13,0 | ||
| 38 | 0: aghi %r15,-STACK_FRAME_OVERHEAD | ||
| 39 | larl %r1,s390_base_ext_handler_fn | ||
| 40 | lg %r1,0(%r1) | ||
| 41 | ltgr %r1,%r1 | ||
| 42 | jz 1f | ||
| 43 | basr %r14,%r1 | ||
| 44 | 1: lmg %r0,%r15,__LC_SAVE_AREA | ||
| 45 | ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit | ||
| 46 | lpswe __LC_EXT_OLD_PSW | ||
| 47 | |||
| 48 | .section .bss | ||
| 49 | .globl s390_base_ext_handler_fn | ||
| 50 | s390_base_ext_handler_fn: | ||
| 51 | .quad 0 | ||
| 52 | .previous | ||
| 53 | |||
| 54 | .globl s390_base_pgm_handler | ||
| 55 | s390_base_pgm_handler: | ||
| 56 | stmg %r0,%r15,__LC_SAVE_AREA | ||
| 57 | basr %r13,0 | ||
| 58 | 0: aghi %r15,-STACK_FRAME_OVERHEAD | ||
| 59 | larl %r1,s390_base_pgm_handler_fn | ||
| 60 | lg %r1,0(%r1) | ||
| 61 | ltgr %r1,%r1 | ||
| 62 | jz 1f | ||
| 63 | basr %r14,%r1 | ||
| 64 | lmg %r0,%r15,__LC_SAVE_AREA | ||
| 65 | lpswe __LC_PGM_OLD_PSW | ||
| 66 | 1: lpswe disabled_wait_psw-0b(%r13) | ||
| 67 | |||
| 68 | .align 8 | ||
| 69 | disabled_wait_psw: | ||
| 70 | .quad 0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler | ||
| 71 | |||
| 72 | .section .bss | ||
| 73 | .globl s390_base_pgm_handler_fn | ||
| 74 | s390_base_pgm_handler_fn: | ||
| 75 | .quad 0 | ||
| 76 | .previous | ||
| 77 | |||
| 78 | #else /* CONFIG_64BIT */ | ||
| 79 | |||
| 80 | .globl s390_base_mcck_handler | ||
| 81 | s390_base_mcck_handler: | ||
| 82 | basr %r13,0 | ||
| 83 | 0: l %r15,__LC_PANIC_STACK # load panic stack | ||
| 84 | ahi %r15,-STACK_FRAME_OVERHEAD | ||
| 85 | l %r1,2f-0b(%r13) | ||
| 86 | l %r1,0(%r1) | ||
| 87 | ltr %r1,%r1 | ||
| 88 | jz 1f | ||
| 89 | basr %r14,%r1 | ||
| 90 | 1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA | ||
| 91 | lpsw __LC_MCK_OLD_PSW | ||
| 92 | |||
| 93 | 2: .long s390_base_mcck_handler_fn | ||
| 94 | |||
| 95 | .section .bss | ||
| 96 | .globl s390_base_mcck_handler_fn | ||
| 97 | s390_base_mcck_handler_fn: | ||
| 98 | .long 0 | ||
| 99 | .previous | ||
| 100 | |||
| 101 | .globl s390_base_ext_handler | ||
| 102 | s390_base_ext_handler: | ||
| 103 | stm %r0,%r15,__LC_SAVE_AREA | ||
| 104 | basr %r13,0 | ||
| 105 | 0: ahi %r15,-STACK_FRAME_OVERHEAD | ||
| 106 | l %r1,2f-0b(%r13) | ||
| 107 | l %r1,0(%r1) | ||
| 108 | ltr %r1,%r1 | ||
| 109 | jz 1f | ||
| 110 | basr %r14,%r1 | ||
| 111 | 1: lm %r0,%r15,__LC_SAVE_AREA | ||
| 112 | ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit | ||
| 113 | lpsw __LC_EXT_OLD_PSW | ||
| 114 | |||
| 115 | 2: .long s390_base_ext_handler_fn | ||
| 116 | |||
| 117 | .section .bss | ||
| 118 | .globl s390_base_ext_handler_fn | ||
| 119 | s390_base_ext_handler_fn: | ||
| 120 | .long 0 | ||
| 121 | .previous | ||
| 122 | |||
| 123 | .globl s390_base_pgm_handler | ||
| 124 | s390_base_pgm_handler: | ||
| 125 | stm %r0,%r15,__LC_SAVE_AREA | ||
| 126 | basr %r13,0 | ||
| 127 | 0: ahi %r15,-STACK_FRAME_OVERHEAD | ||
| 128 | l %r1,2f-0b(%r13) | ||
| 129 | l %r1,0(%r1) | ||
| 130 | ltr %r1,%r1 | ||
| 131 | jz 1f | ||
| 132 | basr %r14,%r1 | ||
| 133 | lm %r0,%r15,__LC_SAVE_AREA | ||
| 134 | lpsw __LC_PGM_OLD_PSW | ||
| 135 | |||
| 136 | 1: lpsw disabled_wait_psw-0b(%r13) | ||
| 137 | |||
| 138 | 2: .long s390_base_pgm_handler_fn | ||
| 139 | |||
| 140 | disabled_wait_psw: | ||
| 141 | .align 8 | ||
| 142 | .long 0x000a0000,0x00000000 + s390_base_pgm_handler | ||
| 143 | |||
| 144 | .section .bss | ||
| 145 | .globl s390_base_pgm_handler_fn | ||
| 146 | s390_base_pgm_handler_fn: | ||
| 147 | .long 0 | ||
| 148 | .previous | ||
| 149 | |||
| 150 | #endif /* CONFIG_64BIT */ | ||
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c new file mode 100644 index 000000000000..40dd47970a33 --- /dev/null +++ b/arch/s390/kernel/early.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | /* | ||
| 2 | * arch/s390/kernel/early.c | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2007 | ||
| 5 | * Author(s): Hongjie Yang <hongjie@us.ibm.com>, | ||
| 6 | * Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/errno.h> | ||
| 11 | #include <linux/string.h> | ||
| 12 | #include <linux/ctype.h> | ||
| 13 | #include <linux/lockdep.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/pfn.h> | ||
| 16 | #include <linux/uaccess.h> | ||
| 17 | #include <asm/lowcore.h> | ||
| 18 | #include <asm/processor.h> | ||
| 19 | #include <asm/sections.h> | ||
| 20 | #include <asm/setup.h> | ||
| 21 | #include <asm/cpcmd.h> | ||
| 22 | #include <asm/sclp.h> | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Create a Kernel NSS if the SAVESYS= parameter is defined | ||
| 26 | */ | ||
| 27 | #define DEFSYS_CMD_SIZE 96 | ||
| 28 | #define SAVESYS_CMD_SIZE 32 | ||
| 29 | |||
| 30 | extern int _eshared; | ||
| 31 | char kernel_nss_name[NSS_NAME_SIZE + 1]; | ||
| 32 | |||
| 33 | #ifdef CONFIG_SHARED_KERNEL | ||
| 34 | static noinline __init void create_kernel_nss(void) | ||
| 35 | { | ||
| 36 | unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; | ||
| 37 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 38 | unsigned int sinitrd_pfn, einitrd_pfn; | ||
| 39 | #endif | ||
| 40 | int response; | ||
| 41 | char *savesys_ptr; | ||
| 42 | char upper_command_line[COMMAND_LINE_SIZE]; | ||
| 43 | char defsys_cmd[DEFSYS_CMD_SIZE]; | ||
| 44 | char savesys_cmd[SAVESYS_CMD_SIZE]; | ||
| 45 | |||
| 46 | /* Do nothing if we are not running under VM */ | ||
| 47 | if (!MACHINE_IS_VM) | ||
| 48 | return; | ||
| 49 | |||
| 50 | /* Convert COMMAND_LINE to upper case */ | ||
| 51 | for (i = 0; i < strlen(COMMAND_LINE); i++) | ||
| 52 | upper_command_line[i] = toupper(COMMAND_LINE[i]); | ||
| 53 | |||
| 54 | savesys_ptr = strstr(upper_command_line, "SAVESYS="); | ||
| 55 | |||
| 56 | if (!savesys_ptr) | ||
| 57 | return; | ||
| 58 | |||
| 59 | savesys_ptr += 8; /* Point to the beginning of the NSS name */ | ||
| 60 | for (i = 0; i < NSS_NAME_SIZE; i++) { | ||
| 61 | if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0') | ||
| 62 | break; | ||
| 63 | kernel_nss_name[i] = savesys_ptr[i]; | ||
| 64 | } | ||
| 65 | |||
| 66 | stext_pfn = PFN_DOWN(__pa(&_stext)); | ||
| 67 | eshared_pfn = PFN_DOWN(__pa(&_eshared)); | ||
| 68 | end_pfn = PFN_UP(__pa(&_end)); | ||
| 69 | min_size = end_pfn << 2; | ||
| 70 | |||
| 71 | sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", | ||
| 72 | kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, | ||
| 73 | eshared_pfn, end_pfn); | ||
| 74 | |||
| 75 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 76 | if (INITRD_START && INITRD_SIZE) { | ||
| 77 | sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); | ||
| 78 | einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); | ||
| 79 | min_size = einitrd_pfn << 2; | ||
| 80 | sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, | ||
| 81 | sinitrd_pfn, einitrd_pfn); | ||
| 82 | } | ||
| 83 | #endif | ||
| 84 | |||
| 85 | sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); | ||
| 86 | sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", | ||
| 87 | kernel_nss_name, kernel_nss_name); | ||
| 88 | |||
| 89 | __cpcmd(defsys_cmd, NULL, 0, &response); | ||
| 90 | |||
| 91 | if (response != 0) | ||
| 92 | return; | ||
| 93 | |||
| 94 | __cpcmd(savesys_cmd, NULL, 0, &response); | ||
| 95 | |||
| 96 | if (response != strlen(savesys_cmd)) | ||
| 97 | return; | ||
| 98 | |||
| 99 | ipl_flags = IPL_NSS_VALID; | ||
| 100 | } | ||
| 101 | |||
| 102 | #else /* CONFIG_SHARED_KERNEL */ | ||
| 103 | |||
| 104 | static inline void create_kernel_nss(void) { } | ||
| 105 | |||
| 106 | #endif /* CONFIG_SHARED_KERNEL */ | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Clear bss memory | ||
| 110 | */ | ||
| 111 | static noinline __init void clear_bss_section(void) | ||
| 112 | { | ||
| 113 | memset(__bss_start, 0, _end - __bss_start); | ||
| 114 | } | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Initialize storage key for kernel pages | ||
| 118 | */ | ||
| 119 | static noinline __init void init_kernel_storage_key(void) | ||
| 120 | { | ||
| 121 | unsigned long end_pfn, init_pfn; | ||
| 122 | |||
| 123 | end_pfn = PFN_UP(__pa(&_end)); | ||
| 124 | |||
| 125 | for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) | ||
| 126 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); | ||
| 127 | } | ||
| 128 | |||
| 129 | static noinline __init void detect_machine_type(void) | ||
| 130 | { | ||
| 131 | struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; | ||
| 132 | |||
| 133 | asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id)); | ||
| 134 | |||
| 135 | /* Running under z/VM ? */ | ||
| 136 | if (cpuinfo->cpu_id.version == 0xff) | ||
| 137 | machine_flags |= 1; | ||
| 138 | |||
| 139 | /* Running on a P/390 ? */ | ||
| 140 | if (cpuinfo->cpu_id.machine == 0x7490) | ||
| 141 | machine_flags |= 4; | ||
| 142 | } | ||
| 143 | |||
| 144 | static noinline __init int memory_fast_detect(void) | ||
| 145 | { | ||
| 146 | |||
| 147 | unsigned long val0 = 0; | ||
| 148 | unsigned long val1 = 0xc; | ||
| 149 | int ret = -ENOSYS; | ||
| 150 | |||
| 151 | if (ipl_flags & IPL_NSS_VALID) | ||
| 152 | return -ENOSYS; | ||
| 153 | |||
| 154 | asm volatile( | ||
| 155 | " diag %1,%2,0x260\n" | ||
| 156 | "0: lhi %0,0\n" | ||
| 157 | "1:\n" | ||
| 158 | EX_TABLE(0b,1b) | ||
| 159 | : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc"); | ||
| 160 | |||
| 161 | if (ret || val0 != val1) | ||
| 162 | return -ENOSYS; | ||
| 163 | |||
| 164 | memory_chunk[0].size = val0; | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | #define ADDR2G (1UL << 31) | ||
| 169 | |||
| 170 | static noinline __init unsigned long sclp_memory_detect(void) | ||
| 171 | { | ||
| 172 | struct sclp_readinfo_sccb *sccb; | ||
| 173 | unsigned long long memsize; | ||
| 174 | |||
| 175 | sccb = &s390_readinfo_sccb; | ||
| 176 | |||
| 177 | if (sccb->header.response_code != 0x10) | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | if (sccb->rnsize) | ||
| 181 | memsize = sccb->rnsize << 20; | ||
| 182 | else | ||
| 183 | memsize = sccb->rnsize2 << 20; | ||
| 184 | if (sccb->rnmax) | ||
| 185 | memsize *= sccb->rnmax; | ||
| 186 | else | ||
| 187 | memsize *= sccb->rnmax2; | ||
| 188 | #ifndef CONFIG_64BIT | ||
| 189 | /* | ||
| 190 | * Can't deal with more than 2G in 31 bit addressing mode, so | ||
| 191 | * limit the value in order to avoid strange side effects. | ||
| 192 | */ | ||
| 193 | if (memsize > ADDR2G) | ||
| 194 | memsize = ADDR2G; | ||
| 195 | #endif | ||
| 196 | return (unsigned long) memsize; | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline __init unsigned long __tprot(unsigned long addr) | ||
| 200 | { | ||
| 201 | int cc = -1; | ||
| 202 | |||
| 203 | asm volatile( | ||
| 204 | " tprot 0(%1),0\n" | ||
| 205 | "0: ipm %0\n" | ||
| 206 | " srl %0,28\n" | ||
| 207 | "1:\n" | ||
| 208 | EX_TABLE(0b,1b) | ||
| 209 | : "+d" (cc) : "a" (addr) : "cc"); | ||
| 210 | return (unsigned long)cc; | ||
| 211 | } | ||
| 212 | |||
| 213 | /* Checking memory in 128KB increments. */ | ||
| 214 | #define CHUNK_INCR (1UL << 17) | ||
| 215 | |||
| 216 | static noinline __init void find_memory_chunks(unsigned long memsize) | ||
| 217 | { | ||
| 218 | unsigned long addr = 0, old_addr = 0; | ||
| 219 | unsigned long old_cc = CHUNK_READ_WRITE; | ||
| 220 | unsigned long cc; | ||
| 221 | int chunk = 0; | ||
| 222 | |||
| 223 | while (chunk < MEMORY_CHUNKS) { | ||
| 224 | cc = __tprot(addr); | ||
| 225 | while (cc == old_cc) { | ||
| 226 | addr += CHUNK_INCR; | ||
| 227 | cc = __tprot(addr); | ||
| 228 | #ifndef CONFIG_64BIT | ||
| 229 | if (addr == ADDR2G) | ||
| 230 | break; | ||
| 231 | #endif | ||
| 232 | } | ||
| 233 | |||
| 234 | if (old_addr != addr && | ||
| 235 | (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) { | ||
| 236 | memory_chunk[chunk].addr = old_addr; | ||
| 237 | memory_chunk[chunk].size = addr - old_addr; | ||
| 238 | memory_chunk[chunk].type = old_cc; | ||
| 239 | chunk++; | ||
| 240 | } | ||
| 241 | |||
| 242 | old_addr = addr; | ||
| 243 | old_cc = cc; | ||
| 244 | |||
| 245 | #ifndef CONFIG_64BIT | ||
| 246 | if (addr == ADDR2G) | ||
| 247 | break; | ||
| 248 | #endif | ||
| 249 | /* | ||
| 250 | * Finish memory detection at the first hole, unless | ||
| 251 | * - we reached the hsa -> skip it. | ||
| 252 | * - we know there must be more. | ||
| 253 | */ | ||
| 254 | if (cc == -1UL && !memsize && old_addr != ADDR2G) | ||
| 255 | break; | ||
| 256 | if (memsize && addr >= memsize) | ||
| 257 | break; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | static __init void early_pgm_check_handler(void) | ||
| 262 | { | ||
| 263 | unsigned long addr; | ||
| 264 | const struct exception_table_entry *fixup; | ||
| 265 | |||
| 266 | addr = S390_lowcore.program_old_psw.addr; | ||
| 267 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); | ||
| 268 | if (!fixup) | ||
| 269 | disabled_wait(0); | ||
| 270 | S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; | ||
| 271 | } | ||
| 272 | |||
| 273 | static noinline __init void setup_lowcore_early(void) | ||
| 274 | { | ||
| 275 | psw_t psw; | ||
| 276 | |||
| 277 | psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; | ||
| 278 | psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler; | ||
| 279 | S390_lowcore.external_new_psw = psw; | ||
| 280 | psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; | ||
| 281 | S390_lowcore.program_new_psw = psw; | ||
| 282 | s390_base_pgm_handler_fn = early_pgm_check_handler; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* | ||
| 286 | * Save ipl parameters, clear bss memory, initialize storage keys | ||
| 287 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | ||
| 288 | */ | ||
| 289 | void __init startup_init(void) | ||
| 290 | { | ||
| 291 | unsigned long memsize; | ||
| 292 | |||
| 293 | ipl_save_parameters(); | ||
| 294 | clear_bss_section(); | ||
| 295 | init_kernel_storage_key(); | ||
| 296 | lockdep_init(); | ||
| 297 | lockdep_off(); | ||
| 298 | detect_machine_type(); | ||
| 299 | create_kernel_nss(); | ||
| 300 | sort_main_extable(); | ||
| 301 | setup_lowcore_early(); | ||
| 302 | sclp_readinfo_early(); | ||
| 303 | memsize = sclp_memory_detect(); | ||
| 304 | if (memory_fast_detect() < 0) | ||
| 305 | find_memory_chunks(memsize); | ||
| 306 | lockdep_on(); | ||
| 307 | } | ||
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index b3dcdcdc80c0..453fd3b4edea 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S | |||
| @@ -58,145 +58,6 @@ startup_continue: | |||
| 58 | l %r14,.Lstartup_init-.LPG1(%r13) | 58 | l %r14,.Lstartup_init-.LPG1(%r13) |
| 59 | basr %r14,%r14 | 59 | basr %r14,%r14 |
| 60 | 60 | ||
| 61 | l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word | ||
| 62 | .Lservicecall: | ||
| 63 | stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts | ||
| 64 | |||
| 65 | stctl %r0, %r0,.Lcr-.LPG1(%r13) # get cr0 | ||
| 66 | la %r1,0x200 # set bit 22 | ||
| 67 | o %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 | ||
| 68 | st %r1,.Lcr-.LPG1(%r13) | ||
| 69 | lctl %r0, %r0,.Lcr-.LPG1(%r13) # load modified cr0 | ||
| 70 | |||
| 71 | mvc __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw | ||
| 72 | la %r1, .Lsclph-.LPG1(%r13) | ||
| 73 | a %r1,__LC_EXT_NEW_PSW+4 # set handler | ||
| 74 | st %r1,__LC_EXT_NEW_PSW+4 | ||
| 75 | |||
| 76 | l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff | ||
| 77 | lr %r1,%r4 # our sccb | ||
| 78 | .insn rre,0xb2200000,%r2,%r1 # service call | ||
| 79 | ipm %r1 | ||
| 80 | srl %r1,28 # get cc code | ||
| 81 | xr %r3, %r3 | ||
| 82 | chi %r1,3 | ||
| 83 | be .Lfchunk-.LPG1(%r13) # leave | ||
| 84 | chi %r1,2 | ||
| 85 | be .Lservicecall-.LPG1(%r13) | ||
| 86 | lpsw .Lwaitsclp-.LPG1(%r13) | ||
| 87 | .Lsclph: | ||
| 88 | lh %r1,.Lsccbr-.Lsccb(%r4) | ||
| 89 | chi %r1,0x10 # 0x0010 is the sucess code | ||
| 90 | je .Lprocsccb # let's process the sccb | ||
| 91 | chi %r1,0x1f0 | ||
| 92 | bne .Lfchunk-.LPG1(%r13) # unhandled error code | ||
| 93 | c %r2, .Lrcp-.LPG1(%r13) # Did we try Read SCP forced | ||
| 94 | bne .Lfchunk-.LPG1(%r13) # if no, give up | ||
| 95 | l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP | ||
| 96 | b .Lservicecall-.LPG1(%r13) | ||
| 97 | .Lprocsccb: | ||
| 98 | lhi %r1,0 | ||
| 99 | icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 | ||
| 100 | jnz .Lscnd | ||
| 101 | lhi %r1,0x800 # otherwise report 2GB | ||
| 102 | .Lscnd: | ||
| 103 | lhi %r3,0x800 # limit reported memory size to 2GB | ||
| 104 | cr %r1,%r3 | ||
| 105 | jl .Lno2gb | ||
| 106 | lr %r1,%r3 | ||
| 107 | .Lno2gb: | ||
| 108 | xr %r3,%r3 # same logic | ||
| 109 | ic %r3,.Lscpa1-.Lsccb(%r4) | ||
| 110 | chi %r3,0x00 | ||
| 111 | jne .Lcompmem | ||
| 112 | l %r3,.Lscpa2-.Lsccb(%r4) | ||
| 113 | .Lcompmem: | ||
| 114 | mr %r2,%r1 # mem in MB on 128-bit | ||
| 115 | l %r1,.Lonemb-.LPG1(%r13) | ||
| 116 | mr %r2,%r1 # mem size in bytes in %r3 | ||
| 117 | b .Lfchunk-.LPG1(%r13) | ||
| 118 | |||
| 119 | .align 4 | ||
| 120 | .Linittu: | ||
| 121 | .long init_thread_union | ||
| 122 | .Lstartup_init: | ||
| 123 | .long startup_init | ||
| 124 | .Lpmask: | ||
| 125 | .byte 0 | ||
| 126 | .align 8 | ||
| 127 | .Lpcext:.long 0x00080000,0x80000000 | ||
| 128 | .Lcr: | ||
| 129 | .long 0x00 # place holder for cr0 | ||
| 130 | .align 8 | ||
| 131 | .Lwaitsclp: | ||
| 132 | .long 0x010a0000,0x80000000 + .Lsclph | ||
| 133 | .Lrcp: | ||
| 134 | .int 0x00120001 # Read SCP forced code | ||
| 135 | .Lrcp2: | ||
| 136 | .int 0x00020001 # Read SCP code | ||
| 137 | .Lonemb: | ||
| 138 | .int 0x100000 | ||
| 139 | .Lfchunk: | ||
| 140 | |||
| 141 | # | ||
| 142 | # find memory chunks. | ||
| 143 | # | ||
| 144 | lr %r9,%r3 # end of mem | ||
| 145 | mvc __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13) | ||
| 146 | la %r1,1 # test in increments of 128KB | ||
| 147 | sll %r1,17 | ||
| 148 | l %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array | ||
| 149 | slr %r4,%r4 # set start of chunk to zero | ||
| 150 | slr %r5,%r5 # set end of chunk to zero | ||
| 151 | slr %r6,%r6 # set access code to zero | ||
| 152 | la %r10,MEMORY_CHUNKS # number of chunks | ||
| 153 | .Lloop: | ||
| 154 | tprot 0(%r5),0 # test protection of first byte | ||
| 155 | ipm %r7 | ||
| 156 | srl %r7,28 | ||
| 157 | clr %r6,%r7 # compare cc with last access code | ||
| 158 | be .Lsame-.LPG1(%r13) | ||
| 159 | lhi %r8,0 # no program checks | ||
| 160 | b .Lsavchk-.LPG1(%r13) | ||
| 161 | .Lsame: | ||
| 162 | ar %r5,%r1 # add 128KB to end of chunk | ||
| 163 | bno .Lloop-.LPG1(%r13) # r1 < 0x80000000 -> loop | ||
| 164 | .Lchkmem: # > 2GB or tprot got a program check | ||
| 165 | lhi %r8,1 # set program check flag | ||
| 166 | .Lsavchk: | ||
| 167 | clr %r4,%r5 # chunk size > 0? | ||
| 168 | be .Lchkloop-.LPG1(%r13) | ||
| 169 | st %r4,0(%r3) # store start address of chunk | ||
| 170 | lr %r0,%r5 | ||
| 171 | slr %r0,%r4 | ||
| 172 | st %r0,4(%r3) # store size of chunk | ||
| 173 | st %r6,8(%r3) # store type of chunk | ||
| 174 | la %r3,12(%r3) | ||
| 175 | ahi %r10,-1 # update chunk number | ||
| 176 | .Lchkloop: | ||
| 177 | lr %r6,%r7 # set access code to last cc | ||
| 178 | # we got an exception or we're starting a new | ||
| 179 | # chunk , we must check if we should | ||
| 180 | # still try to find valid memory (if we detected | ||
| 181 | # the amount of available storage), and if we | ||
| 182 | # have chunks left | ||
| 183 | xr %r0,%r0 | ||
| 184 | clr %r0,%r9 # did we detect memory? | ||
| 185 | je .Ldonemem # if not, leave | ||
| 186 | chi %r10,0 # do we have chunks left? | ||
| 187 | je .Ldonemem | ||
| 188 | chi %r8,1 # program check ? | ||
| 189 | je .Lpgmchk | ||
| 190 | lr %r4,%r5 # potential new chunk | ||
| 191 | alr %r5,%r1 # add 128KB to end of chunk | ||
| 192 | j .Llpcnt | ||
| 193 | .Lpgmchk: | ||
| 194 | alr %r5,%r1 # add 128KB to end of chunk | ||
| 195 | lr %r4,%r5 # potential new chunk | ||
| 196 | .Llpcnt: | ||
| 197 | clr %r5,%r9 # should we go on? | ||
| 198 | jl .Lloop | ||
| 199 | .Ldonemem: | ||
| 200 | l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags | 61 | l %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags |
| 201 | # | 62 | # |
| 202 | # find out if we have an IEEE fpu | 63 | # find out if we have an IEEE fpu |
| @@ -273,7 +134,6 @@ startup_continue: | |||
| 273 | .long 0 # cr15: linkage stack operations | 134 | .long 0 # cr15: linkage stack operations |
| 274 | .Lduct: .long 0,0,0,0,0,0,0,0 | 135 | .Lduct: .long 0,0,0,0,0,0,0,0 |
| 275 | .long 0,0,0,0,0,0,0,0 | 136 | .long 0,0,0,0,0,0,0,0 |
| 276 | .Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem | ||
| 277 | .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu | 137 | .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu |
| 278 | .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp | 138 | .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp |
| 279 | .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg | 139 | .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg |
| @@ -284,7 +144,9 @@ startup_continue: | |||
| 284 | .Lbss_bgn: .long __bss_start | 144 | .Lbss_bgn: .long __bss_start |
| 285 | .Lbss_end: .long _end | 145 | .Lbss_end: .long _end |
| 286 | .Lparmaddr: .long PARMAREA | 146 | .Lparmaddr: .long PARMAREA |
| 287 | .Lsccbaddr: .long .Lsccb | 147 | .Linittu: .long init_thread_union |
| 148 | .Lstartup_init: | ||
| 149 | .long startup_init | ||
| 288 | 150 | ||
| 289 | .globl ipl_schib | 151 | .globl ipl_schib |
| 290 | ipl_schib: | 152 | ipl_schib: |
| @@ -300,26 +162,6 @@ ipl_devno: | |||
| 300 | .word 0 | 162 | .word 0 |
| 301 | 163 | ||
| 302 | .org 0x12000 | 164 | .org 0x12000 |
| 303 | .globl s390_readinfo_sccb | ||
| 304 | s390_readinfo_sccb: | ||
| 305 | .Lsccb: | ||
| 306 | .hword 0x1000 # length, one page | ||
| 307 | .byte 0x00,0x00,0x00 | ||
| 308 | .byte 0x80 # variable response bit set | ||
| 309 | .Lsccbr: | ||
| 310 | .hword 0x00 # response code | ||
| 311 | .Lscpincr1: | ||
| 312 | .hword 0x00 | ||
| 313 | .Lscpa1: | ||
| 314 | .byte 0x00 | ||
| 315 | .fill 89,1,0 | ||
| 316 | .Lscpa2: | ||
| 317 | .int 0x00 | ||
| 318 | .Lscpincr2: | ||
| 319 | .quad 0x00 | ||
| 320 | .fill 3984,1,0 | ||
| 321 | .org 0x13000 | ||
| 322 | |||
| 323 | #ifdef CONFIG_SHARED_KERNEL | 165 | #ifdef CONFIG_SHARED_KERNEL |
| 324 | .org 0x100000 | 166 | .org 0x100000 |
| 325 | #endif | 167 | #endif |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 030a1c95f47c..b8fec4e5c5d4 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
| @@ -65,162 +65,6 @@ startup_continue: | |||
| 65 | brasl %r14,startup_init | 65 | brasl %r14,startup_init |
| 66 | # set program check new psw mask | 66 | # set program check new psw mask |
| 67 | mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) | 67 | mvc __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) |
| 68 | larl %r1,.Lslowmemdetect # set program check address | ||
| 69 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
| 70 | lghi %r1,0xc | ||
| 71 | diag %r0,%r1,0x260 # get memory size of virtual machine | ||
| 72 | cgr %r0,%r1 # different? -> old detection routine | ||
| 73 | jne .Lslowmemdetect | ||
| 74 | larl %r3,ipl_flags | ||
| 75 | llgt %r3,0(%r3) | ||
| 76 | chi %r3,4 # ipled from an kernel NSS | ||
| 77 | je .Lslowmemdetect | ||
| 78 | aghi %r1,1 # size is one more than end | ||
| 79 | larl %r2,memory_chunk | ||
| 80 | stg %r1,8(%r2) # store size of chunk | ||
| 81 | |||
| 82 | .Lslowmemdetect: | ||
| 83 | l %r2,.Lrcp-.LPG1(%r13) # Read SCP forced command word | ||
| 84 | .Lservicecall: | ||
| 85 | stosm .Lpmask-.LPG1(%r13),0x01 # authorize ext interrupts | ||
| 86 | |||
| 87 | stctg %r0,%r0,.Lcr-.LPG1(%r13) # get cr0 | ||
| 88 | la %r1,0x200 # set bit 22 | ||
| 89 | og %r1,.Lcr-.LPG1(%r13) # or old cr0 with r1 | ||
| 90 | stg %r1,.Lcr-.LPG1(%r13) | ||
| 91 | lctlg %r0,%r0,.Lcr-.LPG1(%r13) # load modified cr0 | ||
| 92 | |||
| 93 | mvc __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw | ||
| 94 | larl %r1,.Lsclph | ||
| 95 | stg %r1,__LC_EXT_NEW_PSW+8 # set handler | ||
| 96 | |||
| 97 | larl %r4,.Lsccb # %r4 is our index for sccb stuff | ||
| 98 | lgr %r1,%r4 # our sccb | ||
| 99 | .insn rre,0xb2200000,%r2,%r1 # service call | ||
| 100 | ipm %r1 | ||
| 101 | srl %r1,28 # get cc code | ||
| 102 | xr %r3,%r3 | ||
| 103 | chi %r1,3 | ||
| 104 | be .Lfchunk-.LPG1(%r13) # leave | ||
| 105 | chi %r1,2 | ||
| 106 | be .Lservicecall-.LPG1(%r13) | ||
| 107 | lpswe .Lwaitsclp-.LPG1(%r13) | ||
| 108 | .Lsclph: | ||
| 109 | lh %r1,.Lsccbr-.Lsccb(%r4) | ||
| 110 | chi %r1,0x10 # 0x0010 is the sucess code | ||
| 111 | je .Lprocsccb # let's process the sccb | ||
| 112 | chi %r1,0x1f0 | ||
| 113 | bne .Lfchunk-.LPG1(%r13) # unhandled error code | ||
| 114 | c %r2,.Lrcp-.LPG1(%r13) # Did we try Read SCP forced | ||
| 115 | bne .Lfchunk-.LPG1(%r13) # if no, give up | ||
| 116 | l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP | ||
| 117 | b .Lservicecall-.LPG1(%r13) | ||
| 118 | .Lprocsccb: | ||
| 119 | lghi %r1,0 | ||
| 120 | icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 | ||
| 121 | jnz .Lscnd | ||
| 122 | lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one | ||
| 123 | .Lscnd: | ||
| 124 | xr %r3,%r3 # same logic | ||
| 125 | ic %r3,.Lscpa1-.Lsccb(%r4) | ||
| 126 | chi %r3,0x00 | ||
| 127 | jne .Lcompmem | ||
| 128 | l %r3,.Lscpa2-.Lsccb(%r4) | ||
| 129 | .Lcompmem: | ||
| 130 | mlgr %r2,%r1 # mem in MB on 128-bit | ||
| 131 | l %r1,.Lonemb-.LPG1(%r13) | ||
| 132 | mlgr %r2,%r1 # mem size in bytes in %r3 | ||
| 133 | b .Lfchunk-.LPG1(%r13) | ||
| 134 | |||
| 135 | .align 4 | ||
| 136 | .Lpmask: | ||
| 137 | .byte 0 | ||
| 138 | .align 8 | ||
| 139 | .Lcr: | ||
| 140 | .quad 0x00 # place holder for cr0 | ||
| 141 | .Lwaitsclp: | ||
| 142 | .quad 0x0102000180000000,.Lsclph | ||
| 143 | .Lrcp: | ||
| 144 | .int 0x00120001 # Read SCP forced code | ||
| 145 | .Lrcp2: | ||
| 146 | .int 0x00020001 # Read SCP code | ||
| 147 | .Lonemb: | ||
| 148 | .int 0x100000 | ||
| 149 | |||
| 150 | .Lfchunk: | ||
| 151 | |||
| 152 | # | ||
| 153 | # find memory chunks. | ||
| 154 | # | ||
| 155 | larl %r9,memory_chunk # skip tprot loop if diag260 | ||
| 156 | lg %r9,8(%r9) # memory detection was successful | ||
| 157 | ltgr %r9,%r9 | ||
| 158 | jne .Ldonemem | ||
| 159 | |||
| 160 | lgr %r9,%r3 # end of mem | ||
| 161 | larl %r1,.Lchkmem # set program check address | ||
| 162 | stg %r1,__LC_PGM_NEW_PSW+8 | ||
| 163 | la %r1,1 # test in increments of 128KB | ||
| 164 | sllg %r1,%r1,17 | ||
| 165 | larl %r3,memory_chunk | ||
| 166 | slgr %r4,%r4 # set start of chunk to zero | ||
| 167 | slgr %r5,%r5 # set end of chunk to zero | ||
| 168 | slr %r6,%r6 # set access code to zero | ||
| 169 | la %r10,MEMORY_CHUNKS # number of chunks | ||
| 170 | .Lloop: | ||
| 171 | tprot 0(%r5),0 # test protection of first byte | ||
| 172 | ipm %r7 | ||
| 173 | srl %r7,28 | ||
| 174 | clr %r6,%r7 # compare cc with last access code | ||
| 175 | je .Lsame | ||
| 176 | lghi %r8,0 # no program checks | ||
| 177 | j .Lsavchk | ||
| 178 | .Lsame: | ||
| 179 | algr %r5,%r1 # add 128KB to end of chunk | ||
| 180 | # no need to check here, | ||
| 181 | brc 12,.Lloop # this is the same chunk | ||
| 182 | .Lchkmem: # > 16EB or tprot got a program check | ||
| 183 | lghi %r8,1 # set program check flag | ||
| 184 | .Lsavchk: | ||
| 185 | clgr %r4,%r5 # chunk size > 0? | ||
| 186 | je .Lchkloop | ||
| 187 | stg %r4,0(%r3) # store start address of chunk | ||
| 188 | lgr %r0,%r5 | ||
| 189 | slgr %r0,%r4 | ||
| 190 | stg %r0,8(%r3) # store size of chunk | ||
| 191 | st %r6,20(%r3) # store type of chunk | ||
| 192 | la %r3,24(%r3) | ||
| 193 | ahi %r10,-1 # update chunk number | ||
| 194 | .Lchkloop: | ||
| 195 | lr %r6,%r7 # set access code to last cc | ||
| 196 | # we got an exception or we're starting a new | ||
| 197 | # chunk , we must check if we should | ||
| 198 | # still try to find valid memory (if we detected | ||
| 199 | # the amount of available storage), and if we | ||
| 200 | # have chunks left | ||
| 201 | lghi %r4,1 | ||
| 202 | sllg %r4,%r4,31 | ||
| 203 | clgr %r5,%r4 | ||
| 204 | je .Lhsaskip | ||
| 205 | xr %r0, %r0 | ||
| 206 | clgr %r0, %r9 # did we detect memory? | ||
| 207 | je .Ldonemem # if not, leave | ||
| 208 | chi %r10, 0 # do we have chunks left? | ||
| 209 | je .Ldonemem | ||
| 210 | .Lhsaskip: | ||
| 211 | chi %r8,1 # program check ? | ||
| 212 | je .Lpgmchk | ||
| 213 | lgr %r4,%r5 # potential new chunk | ||
| 214 | algr %r5,%r1 # add 128KB to end of chunk | ||
| 215 | j .Llpcnt | ||
| 216 | .Lpgmchk: | ||
| 217 | algr %r5,%r1 # add 128KB to end of chunk | ||
| 218 | lgr %r4,%r5 # potential new chunk | ||
| 219 | .Llpcnt: | ||
| 220 | clgr %r5,%r9 # should we go on? | ||
| 221 | jl .Lloop | ||
| 222 | .Ldonemem: | ||
| 223 | |||
| 224 | larl %r12,machine_flags | 68 | larl %r12,machine_flags |
| 225 | # | 69 | # |
| 226 | # find out if we have the MVPG instruction | 70 | # find out if we have the MVPG instruction |
| @@ -324,25 +168,6 @@ ipl_devno: | |||
| 324 | .word 0 | 168 | .word 0 |
| 325 | 169 | ||
| 326 | .org 0x12000 | 170 | .org 0x12000 |
| 327 | .globl s390_readinfo_sccb | ||
| 328 | s390_readinfo_sccb: | ||
| 329 | .Lsccb: | ||
| 330 | .hword 0x1000 # length, one page | ||
| 331 | .byte 0x00,0x00,0x00 | ||
| 332 | .byte 0x80 # variable response bit set | ||
| 333 | .Lsccbr: | ||
| 334 | .hword 0x00 # response code | ||
| 335 | .Lscpincr1: | ||
| 336 | .hword 0x00 | ||
| 337 | .Lscpa1: | ||
| 338 | .byte 0x00 | ||
| 339 | .fill 89,1,0 | ||
| 340 | .Lscpa2: | ||
| 341 | .int 0x00 | ||
| 342 | .Lscpincr2: | ||
| 343 | .quad 0x00 | ||
| 344 | .fill 3984,1,0 | ||
| 345 | .org 0x13000 | ||
| 346 | 171 | ||
| 347 | #ifdef CONFIG_SHARED_KERNEL | 172 | #ifdef CONFIG_SHARED_KERNEL |
| 348 | .org 0x100000 | 173 | .org 0x100000 |
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 13eacce62011..052259530651 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
| @@ -20,14 +20,13 @@ | |||
| 20 | #include <asm/cio.h> | 20 | #include <asm/cio.h> |
| 21 | #include <asm/ebcdic.h> | 21 | #include <asm/ebcdic.h> |
| 22 | #include <asm/reset.h> | 22 | #include <asm/reset.h> |
| 23 | #include <asm/sclp.h> | ||
| 23 | 24 | ||
| 24 | #define IPL_PARM_BLOCK_VERSION 0 | 25 | #define IPL_PARM_BLOCK_VERSION 0 |
| 25 | #define LOADPARM_LEN 8 | ||
| 26 | 26 | ||
| 27 | extern char s390_readinfo_sccb[]; | 27 | #define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10) |
| 28 | #define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010) | 28 | #define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm) |
| 29 | #define SCCB_LOADPARM (&s390_readinfo_sccb[24]) | 29 | #define SCCB_FLAG (s390_readinfo_sccb.flags) |
| 30 | #define SCCB_FLAG (s390_readinfo_sccb[91]) | ||
| 31 | 30 | ||
| 32 | enum ipl_type { | 31 | enum ipl_type { |
| 33 | IPL_TYPE_NONE = 1, | 32 | IPL_TYPE_NONE = 1, |
| @@ -1080,8 +1079,6 @@ static void do_reset_calls(void) | |||
| 1080 | reset->fn(); | 1079 | reset->fn(); |
| 1081 | } | 1080 | } |
| 1082 | 1081 | ||
| 1083 | extern void reset_mcck_handler(void); | ||
| 1084 | extern void reset_pgm_handler(void); | ||
| 1085 | extern __u32 dump_prefix_page; | 1082 | extern __u32 dump_prefix_page; |
| 1086 | 1083 | ||
| 1087 | void s390_reset_system(void) | 1084 | void s390_reset_system(void) |
| @@ -1105,12 +1102,12 @@ void s390_reset_system(void) | |||
| 1105 | /* Set new machine check handler */ | 1102 | /* Set new machine check handler */ |
| 1106 | S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; | 1103 | S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; |
| 1107 | S390_lowcore.mcck_new_psw.addr = | 1104 | S390_lowcore.mcck_new_psw.addr = |
| 1108 | PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; | 1105 | PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler; |
| 1109 | 1106 | ||
| 1110 | /* Set new program check handler */ | 1107 | /* Set new program check handler */ |
| 1111 | S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; | 1108 | S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; |
| 1112 | S390_lowcore.program_new_psw.addr = | 1109 | S390_lowcore.program_new_psw.addr = |
| 1113 | PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler; | 1110 | PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; |
| 1114 | 1111 | ||
| 1115 | do_reset_calls(); | 1112 | do_reset_calls(); |
| 1116 | } | 1113 | } |
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S deleted file mode 100644 index 8a87355161fa..000000000000 --- a/arch/s390/kernel/reset.S +++ /dev/null | |||
| @@ -1,90 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * arch/s390/kernel/reset.S | ||
| 3 | * | ||
| 4 | * Copyright (C) IBM Corp. 2006 | ||
| 5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 6 | * Michael Holzheu <holzheu@de.ibm.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <asm/ptrace.h> | ||
| 10 | #include <asm/lowcore.h> | ||
| 11 | |||
| 12 | #ifdef CONFIG_64BIT | ||
| 13 | |||
| 14 | .globl reset_mcck_handler | ||
| 15 | reset_mcck_handler: | ||
| 16 | basr %r13,0 | ||
| 17 | 0: lg %r15,__LC_PANIC_STACK # load panic stack | ||
| 18 | aghi %r15,-STACK_FRAME_OVERHEAD | ||
| 19 | lg %r1,s390_reset_mcck_handler-0b(%r13) | ||
| 20 | ltgr %r1,%r1 | ||
| 21 | jz 1f | ||
| 22 | basr %r14,%r1 | ||
| 23 | 1: la %r1,4095 | ||
| 24 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) | ||
| 25 | lpswe __LC_MCK_OLD_PSW | ||
| 26 | |||
| 27 | .globl s390_reset_mcck_handler | ||
| 28 | s390_reset_mcck_handler: | ||
| 29 | .quad 0 | ||
| 30 | |||
| 31 | .globl reset_pgm_handler | ||
| 32 | reset_pgm_handler: | ||
| 33 | stmg %r0,%r15,__LC_SAVE_AREA | ||
| 34 | basr %r13,0 | ||
| 35 | 0: lg %r15,__LC_PANIC_STACK # load panic stack | ||
| 36 | aghi %r15,-STACK_FRAME_OVERHEAD | ||
| 37 | lg %r1,s390_reset_pgm_handler-0b(%r13) | ||
| 38 | ltgr %r1,%r1 | ||
| 39 | jz 1f | ||
| 40 | basr %r14,%r1 | ||
| 41 | lmg %r0,%r15,__LC_SAVE_AREA | ||
| 42 | lpswe __LC_PGM_OLD_PSW | ||
| 43 | 1: lpswe disabled_wait_psw-0b(%r13) | ||
| 44 | .globl s390_reset_pgm_handler | ||
| 45 | s390_reset_pgm_handler: | ||
| 46 | .quad 0 | ||
| 47 | .align 8 | ||
| 48 | disabled_wait_psw: | ||
| 49 | .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler | ||
| 50 | |||
| 51 | #else /* CONFIG_64BIT */ | ||
| 52 | |||
| 53 | .globl reset_mcck_handler | ||
| 54 | reset_mcck_handler: | ||
| 55 | basr %r13,0 | ||
| 56 | 0: l %r15,__LC_PANIC_STACK # load panic stack | ||
| 57 | ahi %r15,-STACK_FRAME_OVERHEAD | ||
| 58 | l %r1,s390_reset_mcck_handler-0b(%r13) | ||
| 59 | ltr %r1,%r1 | ||
| 60 | jz 1f | ||
| 61 | basr %r14,%r1 | ||
| 62 | 1: lm %r0,%r15,__LC_GPREGS_SAVE_AREA | ||
| 63 | lpsw __LC_MCK_OLD_PSW | ||
| 64 | |||
| 65 | .globl s390_reset_mcck_handler | ||
| 66 | s390_reset_mcck_handler: | ||
| 67 | .long 0 | ||
| 68 | |||
| 69 | .globl reset_pgm_handler | ||
| 70 | reset_pgm_handler: | ||
| 71 | stm %r0,%r15,__LC_SAVE_AREA | ||
| 72 | basr %r13,0 | ||
| 73 | 0: l %r15,__LC_PANIC_STACK # load panic stack | ||
| 74 | ahi %r15,-STACK_FRAME_OVERHEAD | ||
| 75 | l %r1,s390_reset_pgm_handler-0b(%r13) | ||
| 76 | ltr %r1,%r1 | ||
| 77 | jz 1f | ||
| 78 | basr %r14,%r1 | ||
| 79 | lm %r0,%r15,__LC_SAVE_AREA | ||
| 80 | lpsw __LC_PGM_OLD_PSW | ||
| 81 | |||
| 82 | 1: lpsw disabled_wait_psw-0b(%r13) | ||
| 83 | .globl s390_reset_pgm_handler | ||
| 84 | s390_reset_pgm_handler: | ||
| 85 | .long 0 | ||
| 86 | disabled_wait_psw: | ||
| 87 | .align 8 | ||
| 88 | .long 0x000a0000,0x00000000 + reset_pgm_handler | ||
| 89 | |||
| 90 | #endif /* CONFIG_64BIT */ | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2fa866f6f711..f73a11528217 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -284,140 +284,6 @@ static void __init conmode_default(void) | |||
| 284 | } | 284 | } |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | /* | ||
| 288 | * Create a Kernel NSS if the SAVESYS= parameter is defined | ||
| 289 | */ | ||
| 290 | #define DEFSYS_CMD_SIZE 96 | ||
| 291 | #define SAVESYS_CMD_SIZE 32 | ||
| 292 | |||
| 293 | extern int _eshared; | ||
| 294 | char kernel_nss_name[NSS_NAME_SIZE + 1]; | ||
| 295 | |||
| 296 | #ifdef CONFIG_SHARED_KERNEL | ||
| 297 | static __init void create_kernel_nss(void) | ||
| 298 | { | ||
| 299 | unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; | ||
| 300 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 301 | unsigned int sinitrd_pfn, einitrd_pfn; | ||
| 302 | #endif | ||
| 303 | int response; | ||
| 304 | char *savesys_ptr; | ||
| 305 | char upper_command_line[COMMAND_LINE_SIZE]; | ||
| 306 | char defsys_cmd[DEFSYS_CMD_SIZE]; | ||
| 307 | char savesys_cmd[SAVESYS_CMD_SIZE]; | ||
| 308 | |||
| 309 | /* Do nothing if we are not running under VM */ | ||
| 310 | if (!MACHINE_IS_VM) | ||
| 311 | return; | ||
| 312 | |||
| 313 | /* Convert COMMAND_LINE to upper case */ | ||
| 314 | for (i = 0; i < strlen(COMMAND_LINE); i++) | ||
| 315 | upper_command_line[i] = toupper(COMMAND_LINE[i]); | ||
| 316 | |||
| 317 | savesys_ptr = strstr(upper_command_line, "SAVESYS="); | ||
| 318 | |||
| 319 | if (!savesys_ptr) | ||
| 320 | return; | ||
| 321 | |||
| 322 | savesys_ptr += 8; /* Point to the beginning of the NSS name */ | ||
| 323 | for (i = 0; i < NSS_NAME_SIZE; i++) { | ||
| 324 | if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0') | ||
| 325 | break; | ||
| 326 | kernel_nss_name[i] = savesys_ptr[i]; | ||
| 327 | } | ||
| 328 | |||
| 329 | stext_pfn = PFN_DOWN(__pa(&_stext)); | ||
| 330 | eshared_pfn = PFN_DOWN(__pa(&_eshared)); | ||
| 331 | end_pfn = PFN_UP(__pa(&_end)); | ||
| 332 | min_size = end_pfn << 2; | ||
| 333 | |||
| 334 | sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X", | ||
| 335 | kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1, | ||
| 336 | eshared_pfn, end_pfn); | ||
| 337 | |||
| 338 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 339 | if (INITRD_START && INITRD_SIZE) { | ||
| 340 | sinitrd_pfn = PFN_DOWN(__pa(INITRD_START)); | ||
| 341 | einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE)); | ||
| 342 | min_size = einitrd_pfn << 2; | ||
| 343 | sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd, | ||
| 344 | sinitrd_pfn, einitrd_pfn); | ||
| 345 | } | ||
| 346 | #endif | ||
| 347 | |||
| 348 | sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); | ||
| 349 | sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", | ||
| 350 | kernel_nss_name, kernel_nss_name); | ||
| 351 | |||
| 352 | __cpcmd(defsys_cmd, NULL, 0, &response); | ||
| 353 | |||
| 354 | if (response != 0) | ||
| 355 | return; | ||
| 356 | |||
| 357 | __cpcmd(savesys_cmd, NULL, 0, &response); | ||
| 358 | |||
| 359 | if (response != strlen(savesys_cmd)) | ||
| 360 | return; | ||
| 361 | |||
| 362 | ipl_flags = IPL_NSS_VALID; | ||
| 363 | } | ||
| 364 | |||
| 365 | #else /* CONFIG_SHARED_KERNEL */ | ||
| 366 | |||
| 367 | static inline void create_kernel_nss(void) { } | ||
| 368 | |||
| 369 | #endif /* CONFIG_SHARED_KERNEL */ | ||
| 370 | |||
| 371 | /* | ||
| 372 | * Clear bss memory | ||
| 373 | */ | ||
| 374 | static __init void clear_bss_section(void) | ||
| 375 | { | ||
| 376 | memset(__bss_start, 0, _end - __bss_start); | ||
| 377 | } | ||
| 378 | |||
| 379 | /* | ||
| 380 | * Initialize storage key for kernel pages | ||
| 381 | */ | ||
| 382 | static __init void init_kernel_storage_key(void) | ||
| 383 | { | ||
| 384 | unsigned long end_pfn, init_pfn; | ||
| 385 | |||
| 386 | end_pfn = PFN_UP(__pa(&_end)); | ||
| 387 | |||
| 388 | for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) | ||
| 389 | page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); | ||
| 390 | } | ||
| 391 | |||
| 392 | static __init void detect_machine_type(void) | ||
| 393 | { | ||
| 394 | struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data; | ||
| 395 | |||
| 396 | asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id)); | ||
| 397 | |||
| 398 | /* Running under z/VM ? */ | ||
| 399 | if (cpuinfo->cpu_id.version == 0xff) | ||
| 400 | machine_flags |= 1; | ||
| 401 | |||
| 402 | /* Running on a P/390 ? */ | ||
| 403 | if (cpuinfo->cpu_id.machine == 0x7490) | ||
| 404 | machine_flags |= 4; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* | ||
| 408 | * Save ipl parameters, clear bss memory, initialize storage keys | ||
| 409 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | ||
| 410 | */ | ||
| 411 | void __init startup_init(void) | ||
| 412 | { | ||
| 413 | ipl_save_parameters(); | ||
| 414 | clear_bss_section(); | ||
| 415 | init_kernel_storage_key(); | ||
| 416 | lockdep_init(); | ||
| 417 | detect_machine_type(); | ||
| 418 | create_kernel_nss(); | ||
| 419 | } | ||
| 420 | |||
| 421 | #ifdef CONFIG_SMP | 287 | #ifdef CONFIG_SMP |
| 422 | void (*_machine_restart)(char *command) = machine_restart_smp; | 288 | void (*_machine_restart)(char *command) = machine_restart_smp; |
| 423 | void (*_machine_halt)(void) = machine_halt_smp; | 289 | void (*_machine_halt)(void) = machine_halt_smp; |
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index ae89b9b88743..165af398fdea 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig | |||
| @@ -103,14 +103,8 @@ config CCW_CONSOLE | |||
| 103 | depends on TN3215_CONSOLE || TN3270_CONSOLE | 103 | depends on TN3215_CONSOLE || TN3270_CONSOLE |
| 104 | default y | 104 | default y |
| 105 | 105 | ||
| 106 | config SCLP | ||
| 107 | bool "Support for SCLP" | ||
| 108 | help | ||
| 109 | Include support for the SCLP interface to the service element. | ||
| 110 | |||
| 111 | config SCLP_TTY | 106 | config SCLP_TTY |
| 112 | bool "Support for SCLP line mode terminal" | 107 | bool "Support for SCLP line mode terminal" |
| 113 | depends on SCLP | ||
| 114 | help | 108 | help |
| 115 | Include support for IBM SCLP line-mode terminals. | 109 | Include support for IBM SCLP line-mode terminals. |
| 116 | 110 | ||
| @@ -123,7 +117,6 @@ config SCLP_CONSOLE | |||
| 123 | 117 | ||
| 124 | config SCLP_VT220_TTY | 118 | config SCLP_VT220_TTY |
| 125 | bool "Support for SCLP VT220-compatible terminal" | 119 | bool "Support for SCLP VT220-compatible terminal" |
| 126 | depends on SCLP | ||
| 127 | help | 120 | help |
| 128 | Include support for an IBM SCLP VT220-compatible terminal. | 121 | Include support for an IBM SCLP VT220-compatible terminal. |
| 129 | 122 | ||
| @@ -136,7 +129,6 @@ config SCLP_VT220_CONSOLE | |||
| 136 | 129 | ||
| 137 | config SCLP_CPI | 130 | config SCLP_CPI |
| 138 | tristate "Control-Program Identification" | 131 | tristate "Control-Program Identification" |
| 139 | depends on SCLP | ||
| 140 | help | 132 | help |
| 141 | This option enables the hardware console interface for system | 133 | This option enables the hardware console interface for system |
| 142 | identification. This is commonly used for workload management and | 134 | identification. This is commonly used for workload management and |
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index c3e97b4fc186..293e667b50f2 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | # S/390 character devices | 2 | # S/390 character devices |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o | 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
| 6 | sclp_info.o | ||
| 6 | 7 | ||
| 7 | obj-$(CONFIG_TN3270) += raw3270.o | 8 | obj-$(CONFIG_TN3270) += raw3270.o |
| 8 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
| @@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o | |||
| 11 | 12 | ||
| 12 | obj-$(CONFIG_TN3215) += con3215.o | 13 | obj-$(CONFIG_TN3215) += con3215.o |
| 13 | 14 | ||
| 14 | obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o | ||
| 15 | obj-$(CONFIG_SCLP_TTY) += sclp_tty.o | 15 | obj-$(CONFIG_SCLP_TTY) += sclp_tty.o |
| 16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o | 16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o |
| 17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o | 17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index c1dd19bb7bf8..6a83e2d722a8 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
| @@ -96,8 +96,8 @@ static int sclp_init_mask(int calculate); | |||
| 96 | static int sclp_init(void); | 96 | static int sclp_init(void); |
| 97 | 97 | ||
| 98 | /* Perform service call. Return 0 on success, non-zero otherwise. */ | 98 | /* Perform service call. Return 0 on success, non-zero otherwise. */ |
| 99 | static int | 99 | int |
| 100 | service_call(sclp_cmdw_t command, void *sccb) | 100 | sclp_service_call(sclp_cmdw_t command, void *sccb) |
| 101 | { | 101 | { |
| 102 | int cc; | 102 | int cc; |
| 103 | 103 | ||
| @@ -173,7 +173,7 @@ __sclp_start_request(struct sclp_req *req) | |||
| 173 | if (sclp_running_state != sclp_running_state_idle) | 173 | if (sclp_running_state != sclp_running_state_idle) |
| 174 | return 0; | 174 | return 0; |
| 175 | del_timer(&sclp_request_timer); | 175 | del_timer(&sclp_request_timer); |
| 176 | rc = service_call(req->command, req->sccb); | 176 | rc = sclp_service_call(req->command, req->sccb); |
| 177 | req->start_count++; | 177 | req->start_count++; |
| 178 | 178 | ||
| 179 | if (rc == 0) { | 179 | if (rc == 0) { |
| @@ -325,7 +325,7 @@ __sclp_make_read_req(void) | |||
| 325 | sccb = (struct sccb_header *) sclp_read_sccb; | 325 | sccb = (struct sccb_header *) sclp_read_sccb; |
| 326 | clear_page(sccb); | 326 | clear_page(sccb); |
| 327 | memset(&sclp_read_req, 0, sizeof(struct sclp_req)); | 327 | memset(&sclp_read_req, 0, sizeof(struct sclp_req)); |
| 328 | sclp_read_req.command = SCLP_CMDW_READDATA; | 328 | sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA; |
| 329 | sclp_read_req.status = SCLP_REQ_QUEUED; | 329 | sclp_read_req.status = SCLP_REQ_QUEUED; |
| 330 | sclp_read_req.start_count = 0; | 330 | sclp_read_req.start_count = 0; |
| 331 | sclp_read_req.callback = sclp_read_cb; | 331 | sclp_read_req.callback = sclp_read_cb; |
| @@ -628,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask) | |||
| 628 | sccb = (struct init_sccb *) sclp_init_sccb; | 628 | sccb = (struct init_sccb *) sclp_init_sccb; |
| 629 | clear_page(sccb); | 629 | clear_page(sccb); |
| 630 | memset(&sclp_init_req, 0, sizeof(struct sclp_req)); | 630 | memset(&sclp_init_req, 0, sizeof(struct sclp_req)); |
| 631 | sclp_init_req.command = SCLP_CMDW_WRITEMASK; | 631 | sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK; |
| 632 | sclp_init_req.status = SCLP_REQ_FILLED; | 632 | sclp_init_req.status = SCLP_REQ_FILLED; |
| 633 | sclp_init_req.start_count = 0; | 633 | sclp_init_req.start_count = 0; |
| 634 | sclp_init_req.callback = NULL; | 634 | sclp_init_req.callback = NULL; |
| @@ -831,7 +831,7 @@ sclp_check_interface(void) | |||
| 831 | for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { | 831 | for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { |
| 832 | __sclp_make_init_req(0, 0); | 832 | __sclp_make_init_req(0, 0); |
| 833 | sccb = (struct init_sccb *) sclp_init_req.sccb; | 833 | sccb = (struct init_sccb *) sclp_init_req.sccb; |
| 834 | rc = service_call(sclp_init_req.command, sccb); | 834 | rc = sclp_service_call(sclp_init_req.command, sccb); |
| 835 | if (rc == -EIO) | 835 | if (rc == -EIO) |
| 836 | break; | 836 | break; |
| 837 | sclp_init_req.status = SCLP_REQ_RUNNING; | 837 | sclp_init_req.status = SCLP_REQ_RUNNING; |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 2c71d6ee7b5b..7d29ab45a6ed 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
| 15 | 15 | #include <asm/sclp.h> | |
| 16 | #include <asm/ebcdic.h> | 16 | #include <asm/ebcdic.h> |
| 17 | 17 | ||
| 18 | /* maximum number of pages concerning our own memory management */ | 18 | /* maximum number of pages concerning our own memory management */ |
| @@ -49,9 +49,11 @@ | |||
| 49 | 49 | ||
| 50 | typedef unsigned int sclp_cmdw_t; | 50 | typedef unsigned int sclp_cmdw_t; |
| 51 | 51 | ||
| 52 | #define SCLP_CMDW_READDATA 0x00770005 | 52 | #define SCLP_CMDW_READ_EVENT_DATA 0x00770005 |
| 53 | #define SCLP_CMDW_WRITEDATA 0x00760005 | 53 | #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005 |
| 54 | #define SCLP_CMDW_WRITEMASK 0x00780005 | 54 | #define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005 |
| 55 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
| 56 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
| 55 | 57 | ||
| 56 | #define GDS_ID_MDSMU 0x1310 | 58 | #define GDS_ID_MDSMU 0x1310 |
| 57 | #define GDS_ID_MDSRouteInfo 0x1311 | 59 | #define GDS_ID_MDSRouteInfo 0x1311 |
| @@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t; | |||
| 66 | 68 | ||
| 67 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ | 69 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ |
| 68 | 70 | ||
| 69 | struct sccb_header { | ||
| 70 | u16 length; | ||
| 71 | u8 function_code; | ||
| 72 | u8 control_mask[3]; | ||
| 73 | u16 response_code; | ||
| 74 | } __attribute__((packed)); | ||
| 75 | |||
| 76 | struct gds_subvector { | 71 | struct gds_subvector { |
| 77 | u8 length; | 72 | u8 length; |
| 78 | u8 key; | 73 | u8 key; |
| @@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg); | |||
| 131 | int sclp_remove_processed(struct sccb_header *sccb); | 126 | int sclp_remove_processed(struct sccb_header *sccb); |
| 132 | int sclp_deactivate(void); | 127 | int sclp_deactivate(void); |
| 133 | int sclp_reactivate(void); | 128 | int sclp_reactivate(void); |
| 129 | int sclp_service_call(sclp_cmdw_t command, void *sccb); | ||
| 134 | 130 | ||
| 135 | /* useful inlines */ | 131 | /* useful inlines */ |
| 136 | 132 | ||
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c index 4f873ae148b7..65aa2c85737f 100644 --- a/drivers/s390/char/sclp_cpi.c +++ b/drivers/s390/char/sclp_cpi.c | |||
| @@ -169,7 +169,7 @@ cpi_prepare_req(void) | |||
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | /* prepare request data structure presented to SCLP driver */ | 171 | /* prepare request data structure presented to SCLP driver */ |
| 172 | req->command = SCLP_CMDW_WRITEDATA; | 172 | req->command = SCLP_CMDW_WRITE_EVENT_DATA; |
| 173 | req->sccb = sccb; | 173 | req->sccb = sccb; |
| 174 | req->status = SCLP_REQ_FILLED; | 174 | req->status = SCLP_REQ_FILLED; |
| 175 | req->callback = cpi_callback; | 175 | req->callback = cpi_callback; |
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c new file mode 100644 index 000000000000..7bcbe643b087 --- /dev/null +++ b/drivers/s390/char/sclp_info.c | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * drivers/s390/char/sclp_info.c | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2007 | ||
| 5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/errno.h> | ||
| 10 | #include <linux/string.h> | ||
| 11 | #include <asm/sclp.h> | ||
| 12 | #include "sclp.h" | ||
| 13 | |||
| 14 | struct sclp_readinfo_sccb s390_readinfo_sccb; | ||
| 15 | |||
| 16 | void __init sclp_readinfo_early(void) | ||
| 17 | { | ||
| 18 | sclp_cmdw_t command; | ||
| 19 | struct sccb_header *sccb; | ||
| 20 | int ret; | ||
| 21 | |||
| 22 | __ctl_set_bit(0, 9); /* enable service signal subclass mask */ | ||
| 23 | |||
| 24 | sccb = &s390_readinfo_sccb.header; | ||
| 25 | command = SCLP_CMDW_READ_SCP_INFO_FORCED; | ||
| 26 | while (1) { | ||
| 27 | u16 response; | ||
| 28 | |||
| 29 | memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); | ||
| 30 | sccb->length = sizeof(s390_readinfo_sccb); | ||
| 31 | sccb->control_mask[2] = 0x80; | ||
| 32 | |||
| 33 | ret = sclp_service_call(command, &s390_readinfo_sccb); | ||
| 34 | |||
| 35 | if (ret == -EIO) | ||
| 36 | goto out; | ||
| 37 | if (ret == -EBUSY) | ||
| 38 | continue; | ||
| 39 | |||
| 40 | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | | ||
| 41 | PSW_MASK_WAIT | PSW_DEFAULT_KEY); | ||
| 42 | local_irq_disable(); | ||
| 43 | barrier(); | ||
| 44 | |||
| 45 | response = sccb->response_code; | ||
| 46 | |||
| 47 | if (response == 0x10) | ||
| 48 | break; | ||
| 49 | |||
| 50 | if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) | ||
| 51 | break; | ||
| 52 | |||
| 53 | command = SCLP_CMDW_READ_SCP_INFO; | ||
| 54 | } | ||
| 55 | out: | ||
| 56 | __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ | ||
| 57 | } | ||
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index 0c92d3909cca..2486783ea58e 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c | |||
| @@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer, | |||
| 460 | sccb->msg_buf.header.type = EvTyp_PMsgCmd; | 460 | sccb->msg_buf.header.type = EvTyp_PMsgCmd; |
| 461 | else | 461 | else |
| 462 | return -ENOSYS; | 462 | return -ENOSYS; |
| 463 | buffer->request.command = SCLP_CMDW_WRITEDATA; | 463 | buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; |
| 464 | buffer->request.status = SCLP_REQ_FILLED; | 464 | buffer->request.status = SCLP_REQ_FILLED; |
| 465 | buffer->request.callback = sclp_writedata_callback; | 465 | buffer->request.callback = sclp_writedata_callback; |
| 466 | buffer->request.callback_data = buffer; | 466 | buffer->request.callback_data = buffer; |
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index d8135cd4d7ab..544f137d70d7 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
| @@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request) | |||
| 207 | request->sclp_req.status = SCLP_REQ_FAILED; | 207 | request->sclp_req.status = SCLP_REQ_FAILED; |
| 208 | return -EIO; | 208 | return -EIO; |
| 209 | } | 209 | } |
| 210 | request->sclp_req.command = SCLP_CMDW_WRITEDATA; | 210 | request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA; |
| 211 | request->sclp_req.status = SCLP_REQ_FILLED; | 211 | request->sclp_req.status = SCLP_REQ_FILLED; |
| 212 | request->sclp_req.callback = sclp_vt220_callback; | 212 | request->sclp_req.callback = sclp_vt220_callback; |
| 213 | request->sclp_req.callback_data = (void *) request; | 213 | request->sclp_req.callback_data = (void *) request; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index ad2b37929848..23e71a76cdab 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
| @@ -895,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) | |||
| 895 | int rc; | 895 | int rc; |
| 896 | 896 | ||
| 897 | pgm_check_occured = 0; | 897 | pgm_check_occured = 0; |
| 898 | s390_reset_pgm_handler = cio_reset_pgm_check_handler; | 898 | s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; |
| 899 | rc = stsch(schid, addr); | 899 | rc = stsch(schid, addr); |
| 900 | s390_reset_pgm_handler = NULL; | 900 | s390_base_pgm_handler_fn = NULL; |
| 901 | 901 | ||
| 902 | /* The program check handler could have changed pgm_check_occured */ | 902 | /* The program check handler could have changed pgm_check_occured. */ |
| 903 | barrier(); | 903 | barrier(); |
| 904 | 904 | ||
| 905 | if (pgm_check_occured) | 905 | if (pgm_check_occured) |
| @@ -957,7 +957,7 @@ static void css_reset(void) | |||
| 957 | /* Reset subchannels. */ | 957 | /* Reset subchannels. */ |
| 958 | for_each_subchannel(__shutdown_subchannel_easy, NULL); | 958 | for_each_subchannel(__shutdown_subchannel_easy, NULL); |
| 959 | /* Reset channel paths. */ | 959 | /* Reset channel paths. */ |
| 960 | s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; | 960 | s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; |
| 961 | /* Enable channel report machine checks. */ | 961 | /* Enable channel report machine checks. */ |
| 962 | __ctl_set_bit(14, 28); | 962 | __ctl_set_bit(14, 28); |
| 963 | /* Temporarily reenable machine checks. */ | 963 | /* Temporarily reenable machine checks. */ |
| @@ -982,7 +982,7 @@ static void css_reset(void) | |||
| 982 | local_mcck_disable(); | 982 | local_mcck_disable(); |
| 983 | /* Disable channel report machine checks. */ | 983 | /* Disable channel report machine checks. */ |
| 984 | __ctl_clear_bit(14, 28); | 984 | __ctl_clear_bit(14, 28); |
| 985 | s390_reset_mcck_handler = NULL; | 985 | s390_base_mcck_handler_fn = NULL; |
| 986 | } | 986 | } |
| 987 | 987 | ||
| 988 | static struct reset_call css_reset_call = { | 988 | static struct reset_call css_reset_call = { |
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h index cf71c5449240..4c1b73940351 100644 --- a/include/asm-s390/processor.h +++ b/include/asm-s390/processor.h | |||
| @@ -331,6 +331,18 @@ static inline void disabled_wait(unsigned long code) | |||
| 331 | } | 331 | } |
| 332 | 332 | ||
| 333 | /* | 333 | /* |
| 334 | * Basic Machine Check/Program Check Handler. | ||
| 335 | */ | ||
| 336 | |||
| 337 | extern void s390_base_mcck_handler(void); | ||
| 338 | extern void s390_base_pgm_handler(void); | ||
| 339 | extern void s390_base_ext_handler(void); | ||
| 340 | |||
| 341 | extern void (*s390_base_mcck_handler_fn)(void); | ||
| 342 | extern void (*s390_base_pgm_handler_fn)(void); | ||
| 343 | extern void (*s390_base_ext_handler_fn)(void); | ||
| 344 | |||
| 345 | /* | ||
| 334 | * CPU idle notifier chain. | 346 | * CPU idle notifier chain. |
| 335 | */ | 347 | */ |
| 336 | #define CPU_IDLE 0 | 348 | #define CPU_IDLE 0 |
diff --git a/include/asm-s390/reset.h b/include/asm-s390/reset.h index 532e65a2aafc..f584f4a52581 100644 --- a/include/asm-s390/reset.h +++ b/include/asm-s390/reset.h | |||
| @@ -18,7 +18,4 @@ struct reset_call { | |||
| 18 | extern void register_reset_call(struct reset_call *reset); | 18 | extern void register_reset_call(struct reset_call *reset); |
| 19 | extern void unregister_reset_call(struct reset_call *reset); | 19 | extern void unregister_reset_call(struct reset_call *reset); |
| 20 | extern void s390_reset_system(void); | 20 | extern void s390_reset_system(void); |
| 21 | extern void (*s390_reset_mcck_handler)(void); | ||
| 22 | extern void (*s390_reset_pgm_handler)(void); | ||
| 23 | |||
| 24 | #endif /* _ASM_S390_RESET_H */ | 21 | #endif /* _ASM_S390_RESET_H */ |
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h new file mode 100644 index 000000000000..468b97018405 --- /dev/null +++ b/include/asm-s390/sclp.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-s390/sclp.h | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2007 | ||
| 5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef _ASM_S390_SCLP_H | ||
| 9 | #define _ASM_S390_SCLP_H | ||
| 10 | |||
| 11 | #include <linux/types.h> | ||
| 12 | |||
| 13 | struct sccb_header { | ||
| 14 | u16 length; | ||
| 15 | u8 function_code; | ||
| 16 | u8 control_mask[3]; | ||
| 17 | u16 response_code; | ||
| 18 | } __attribute__((packed)); | ||
| 19 | |||
| 20 | #define LOADPARM_LEN 8 | ||
| 21 | |||
| 22 | struct sclp_readinfo_sccb { | ||
| 23 | struct sccb_header header; /* 0-7 */ | ||
| 24 | u16 rnmax; /* 8-9 */ | ||
| 25 | u8 rnsize; /* 10 */ | ||
| 26 | u8 _reserved0[24 - 11]; /* 11-23 */ | ||
| 27 | u8 loadparm[LOADPARM_LEN]; /* 24-31 */ | ||
| 28 | u8 _reserved1[91 - 32]; /* 32-90 */ | ||
| 29 | u8 flags; /* 91 */ | ||
| 30 | u8 _reserved2[100 - 92]; /* 92-99 */ | ||
| 31 | u32 rnsize2; /* 100-103 */ | ||
| 32 | u64 rnmax2; /* 104-111 */ | ||
| 33 | u8 _reserved3[4096 - 112]; /* 112-4095 */ | ||
| 34 | } __attribute__((packed, aligned(4096))); | ||
| 35 | |||
| 36 | extern struct sclp_readinfo_sccb s390_readinfo_sccb; | ||
| 37 | extern void sclp_readinfo_early(void); | ||
| 38 | |||
| 39 | #endif /* _ASM_S390_SCLP_H */ | ||
