summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/boot/Makefile2
-rw-r--r--arch/s390/boot/compressed/vmlinux.lds.S21
-rw-r--r--arch/s390/boot/head.S32
-rw-r--r--arch/s390/boot/startup.c39
-rw-r--r--arch/s390/boot/text_dma.S167
-rw-r--r--arch/s390/hypfs/hypfs_diag0c.c18
-rw-r--r--arch/s390/include/asm/diag.h13
-rw-r--r--arch/s390/include/asm/extable.h5
-rw-r--r--arch/s390/include/asm/ipl.h1
-rw-r--r--arch/s390/include/asm/linkage.h7
-rw-r--r--arch/s390/include/asm/sections.h3
-rw-r--r--arch/s390/kernel/base.S68
-rw-r--r--arch/s390/kernel/diag.c67
-rw-r--r--arch/s390/kernel/early.c2
-rw-r--r--arch/s390/kernel/head64.S26
-rw-r--r--arch/s390/kernel/ipl.c2
-rw-r--r--arch/s390/kernel/kprobes.c2
-rw-r--r--arch/s390/kernel/machine_kexec.c2
-rw-r--r--arch/s390/kernel/setup.c9
-rw-r--r--arch/s390/kernel/smp.c2
-rw-r--r--arch/s390/kernel/swsusp.S15
-rw-r--r--arch/s390/kernel/traps.c3
-rw-r--r--arch/s390/mm/fault.c14
-rw-r--r--arch/s390/mm/vmem.c2
24 files changed, 334 insertions, 188 deletions
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index 4df43e83363a..88932c25ad26 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -30,7 +30,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
30 30
31obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o 31obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
32obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o 32obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
33obj-y += ctype.o 33obj-y += ctype.o text_dma.o
34obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o 34obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o
35obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o 35obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o
36targets := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y) 36targets := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)
diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S
index 1c8ef393c656..112b8d9f1e4c 100644
--- a/arch/s390/boot/compressed/vmlinux.lds.S
+++ b/arch/s390/boot/compressed/vmlinux.lds.S
@@ -33,6 +33,27 @@ SECTIONS
33 *(.data.*) 33 *(.data.*)
34 _edata = . ; 34 _edata = . ;
35 } 35 }
36 /*
37 * .dma section for code, data, ex_table that need to stay below 2 GB,
38 * even when the kernel is relocate: above 2 GB.
39 */
40 _sdma = .;
41 .dma.text : {
42 . = ALIGN(PAGE_SIZE);
43 _stext_dma = .;
44 *(.dma.text)
45 . = ALIGN(PAGE_SIZE);
46 _etext_dma = .;
47 }
48 . = ALIGN(16);
49 .dma.ex_table : {
50 _start_dma_ex_table = .;
51 KEEP(*(.dma.ex_table))
52 _stop_dma_ex_table = .;
53 }
54 .dma.data : { *(.dma.data) }
55 _edma = .;
56
36 BOOT_DATA 57 BOOT_DATA
37 BOOT_DATA_PRESERVED 58 BOOT_DATA_PRESERVED
38 59
diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S
index c6b4b4c5dd58..028aab03a9e7 100644
--- a/arch/s390/boot/head.S
+++ b/arch/s390/boot/head.S
@@ -305,7 +305,7 @@ ENTRY(startup_kdump)
305 xc 0x300(256),0x300 305 xc 0x300(256),0x300
306 xc 0xe00(256),0xe00 306 xc 0xe00(256),0xe00
307 xc 0xf00(256),0xf00 307 xc 0xf00(256),0xf00
308 lctlg %c0,%c15,0x200(%r0) # initialize control registers 308 lctlg %c0,%c15,.Lctl-.LPG0(%r13) # load control registers
309 stcke __LC_BOOT_CLOCK 309 stcke __LC_BOOT_CLOCK
310 mvc __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1 310 mvc __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
311 spt 6f-.LPG0(%r13) 311 spt 6f-.LPG0(%r13)
@@ -319,6 +319,36 @@ ENTRY(startup_kdump)
319 .align 8 319 .align 8
3206: .long 0x7fffffff,0xffffffff 3206: .long 0x7fffffff,0xffffffff
321 321
322.Lctl: .quad 0x04040000 # cr0: AFP registers & secondary space
323 .quad 0 # cr1: primary space segment table
324 .quad .Lduct # cr2: dispatchable unit control table
325 .quad 0 # cr3: instruction authorization
326 .quad 0xffff # cr4: instruction authorization
327 .quad .Lduct # cr5: primary-aste origin
328 .quad 0 # cr6: I/O interrupts
329 .quad 0 # cr7: secondary space segment table
330 .quad 0 # cr8: access registers translation
331 .quad 0 # cr9: tracing off
332 .quad 0 # cr10: tracing off
333 .quad 0 # cr11: tracing off
334 .quad 0 # cr12: tracing off
335 .quad 0 # cr13: home space segment table
336 .quad 0xc0000000 # cr14: machine check handling off
337 .quad .Llinkage_stack # cr15: linkage stack operations
338
339 .section .dma.data,"aw",@progbits
340.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0
341 .long 0,0,0,0,0,0,0,0
342.Llinkage_stack:
343 .long 0,0,0x89000000,0,0,0,0x8a000000,0
344 .align 64
345.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0
346 .align 128
347.Lduald:.rept 8
348 .long 0x80000000,0,0,0 # invalid access-list entries
349 .endr
350 .previous
351
322#include "head_kdump.S" 352#include "head_kdump.S"
323 353
324# 354#
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index b7d6a76cb5e9..e3f339d248ce 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -1,9 +1,11 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/string.h> 2#include <linux/string.h>
3#include <linux/elf.h> 3#include <linux/elf.h>
4#include <asm/sections.h>
4#include <asm/setup.h> 5#include <asm/setup.h>
5#include <asm/kexec.h> 6#include <asm/kexec.h>
6#include <asm/sclp.h> 7#include <asm/sclp.h>
8#include <asm/diag.h>
7#include <asm/uv.h> 9#include <asm/uv.h>
8#include "compressed/decompressor.h" 10#include "compressed/decompressor.h"
9#include "boot.h" 11#include "boot.h"
@@ -11,6 +13,43 @@
11extern char __boot_data_start[], __boot_data_end[]; 13extern char __boot_data_start[], __boot_data_end[];
12extern char __boot_data_preserved_start[], __boot_data_preserved_end[]; 14extern char __boot_data_preserved_start[], __boot_data_preserved_end[];
13 15
16/*
17 * Some code and data needs to stay below 2 GB, even when the kernel would be
18 * relocated above 2 GB, because it has to use 31 bit addresses.
19 * Such code and data is part of the .dma section, and its location is passed
20 * over to the decompressed / relocated kernel via the .boot.preserved.data
21 * section.
22 */
23extern char _sdma[], _edma[];
24extern char _stext_dma[], _etext_dma[];
25extern struct exception_table_entry _start_dma_ex_table[];
26extern struct exception_table_entry _stop_dma_ex_table[];
27unsigned long __bootdata_preserved(__sdma) = __pa(&_sdma);
28unsigned long __bootdata_preserved(__edma) = __pa(&_edma);
29unsigned long __bootdata_preserved(__stext_dma) = __pa(&_stext_dma);
30unsigned long __bootdata_preserved(__etext_dma) = __pa(&_etext_dma);
31struct exception_table_entry *
32 __bootdata_preserved(__start_dma_ex_table) = _start_dma_ex_table;
33struct exception_table_entry *
34 __bootdata_preserved(__stop_dma_ex_table) = _stop_dma_ex_table;
35
36int _diag210_dma(struct diag210 *addr);
37int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode);
38int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode);
39void _diag0c_dma(struct hypfs_diag0c_entry *entry);
40void _diag308_reset_dma(void);
41struct diag_ops __bootdata_preserved(diag_dma_ops) = {
42 .diag210 = _diag210_dma,
43 .diag26c = _diag26c_dma,
44 .diag14 = _diag14_dma,
45 .diag0c = _diag0c_dma,
46 .diag308_reset = _diag308_reset_dma
47};
48static struct diag210 _diag210_tmp_dma __section(".dma.data");
49struct diag210 *__bootdata_preserved(__diag210_tmp_dma) = &_diag210_tmp_dma;
50void _swsusp_reset_dma(void);
51unsigned long __bootdata_preserved(__swsusp_reset_dma) = __pa(_swsusp_reset_dma);
52
14void error(char *x) 53void error(char *x)
15{ 54{
16 sclp_early_printk("\n\n"); 55 sclp_early_printk("\n\n");
diff --git a/arch/s390/boot/text_dma.S b/arch/s390/boot/text_dma.S
new file mode 100644
index 000000000000..2414360ff22d
--- /dev/null
+++ b/arch/s390/boot/text_dma.S
@@ -0,0 +1,167 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Code that needs to run below 2 GB.
4 *
5 * Copyright IBM Corp. 2019
6 */
7
8#include <linux/linkage.h>
9#include <asm/errno.h>
10#include <asm/sigp.h>
11
12 .section .dma.text,"ax"
13/*
14 * Simplified version of expoline thunk. The normal thunks can not be used here,
15 * because they might be more than 2 GB away, and not reachable by the relative
16 * branch. No comdat, exrl, etc. optimizations used here, because it only
17 * affects a few functions that are not performance-relevant.
18 */
19 .macro BR_EX_DMA_r14
20 larl %r1,0f
21 ex 0,0(%r1)
22 j .
230: br %r14
24 .endm
25
26/*
27 * int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode)
28 */
29ENTRY(_diag14_dma)
30 lgr %r1,%r2
31 lgr %r2,%r3
32 lgr %r3,%r4
33 lhi %r5,-EIO
34 sam31
35 diag %r1,%r2,0x14
36.Ldiag14_ex:
37 ipm %r5
38 srl %r5,28
39.Ldiag14_fault:
40 sam64
41 lgfr %r2,%r5
42 BR_EX_DMA_r14
43 EX_TABLE_DMA(.Ldiag14_ex, .Ldiag14_fault)
44
45/*
46 * int _diag210_dma(struct diag210 *addr)
47 */
48ENTRY(_diag210_dma)
49 lgr %r1,%r2
50 lhi %r2,-1
51 sam31
52 diag %r1,%r0,0x210
53.Ldiag210_ex:
54 ipm %r2
55 srl %r2,28
56.Ldiag210_fault:
57 sam64
58 lgfr %r2,%r2
59 BR_EX_DMA_r14
60 EX_TABLE_DMA(.Ldiag210_ex, .Ldiag210_fault)
61
62/*
63 * int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode)
64 */
65ENTRY(_diag26c_dma)
66 lghi %r5,-EOPNOTSUPP
67 sam31
68 diag %r2,%r4,0x26c
69.Ldiag26c_ex:
70 sam64
71 lgfr %r2,%r5
72 BR_EX_DMA_r14
73 EX_TABLE_DMA(.Ldiag26c_ex, .Ldiag26c_ex)
74
75/*
76 * void _diag0c_dma(struct hypfs_diag0c_entry *entry)
77 */
78ENTRY(_diag0c_dma)
79 sam31
80 diag %r2,%r2,0x0c
81 sam64
82 BR_EX_DMA_r14
83
84/*
85 * void _swsusp_reset_dma(void)
86 */
87ENTRY(_swsusp_reset_dma)
88 larl %r1,restart_entry
89 larl %r2,.Lrestart_diag308_psw
90 og %r1,0(%r2)
91 stg %r1,0(%r0)
92 lghi %r0,0
93 diag %r0,%r0,0x308
94restart_entry:
95 lhi %r1,1
96 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
97 sam64
98 BR_EX_DMA_r14
99
100/*
101 * void _diag308_reset_dma(void)
102 *
103 * Calls diag 308 subcode 1 and continues execution
104 */
105ENTRY(_diag308_reset_dma)
106 larl %r4,.Lctlregs # Save control registers
107 stctg %c0,%c15,0(%r4)
108 lg %r2,0(%r4) # Disable lowcore protection
109 nilh %r2,0xefff
110 larl %r4,.Lctlreg0
111 stg %r2,0(%r4)
112 lctlg %c0,%c0,0(%r4)
113 larl %r4,.Lfpctl # Floating point control register
114 stfpc 0(%r4)
115 larl %r4,.Lprefix # Save prefix register
116 stpx 0(%r4)
117 larl %r4,.Lprefix_zero # Set prefix register to 0
118 spx 0(%r4)
119 larl %r4,.Lcontinue_psw # Save PSW flags
120 epsw %r2,%r3
121 stm %r2,%r3,0(%r4)
122 larl %r4,restart_part2 # Setup restart PSW at absolute 0
123 larl %r3,.Lrestart_diag308_psw
124 og %r4,0(%r3) # Save PSW
125 lghi %r3,0
126 sturg %r4,%r3 # Use sturg, because of large pages
127 lghi %r1,1
128 lghi %r0,0
129 diag %r0,%r1,0x308
130restart_part2:
131 lhi %r0,0 # Load r0 with zero
132 lhi %r1,2 # Use mode 2 = ESAME (dump)
133 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode
134 sam64 # Switch to 64 bit addressing mode
135 larl %r4,.Lctlregs # Restore control registers
136 lctlg %c0,%c15,0(%r4)
137 larl %r4,.Lfpctl # Restore floating point ctl register
138 lfpc 0(%r4)
139 larl %r4,.Lprefix # Restore prefix register
140 spx 0(%r4)
141 larl %r4,.Lcontinue_psw # Restore PSW flags
142 lpswe 0(%r4)
143.Lcontinue:
144 BR_EX_DMA_r14
145
146 .section .dma.data,"aw",@progbits
147.align 8
148.Lrestart_diag308_psw:
149 .long 0x00080000,0x80000000
150
151.align 8
152.Lcontinue_psw:
153 .quad 0,.Lcontinue
154
155.align 8
156.Lctlreg0:
157 .quad 0
158.Lctlregs:
159 .rept 16
160 .quad 0
161 .endr
162.Lfpctl:
163 .long 0
164.Lprefix:
165 .long 0
166.Lprefix_zero:
167 .long 0
diff --git a/arch/s390/hypfs/hypfs_diag0c.c b/arch/s390/hypfs/hypfs_diag0c.c
index 72e3140fafb5..3235e4d82f2d 100644
--- a/arch/s390/hypfs/hypfs_diag0c.c
+++ b/arch/s390/hypfs/hypfs_diag0c.c
@@ -16,26 +16,12 @@
16#define DBFS_D0C_HDR_VERSION 0 16#define DBFS_D0C_HDR_VERSION 0
17 17
18/* 18/*
19 * Execute diagnose 0c in 31 bit mode
20 */
21static void diag0c(struct hypfs_diag0c_entry *entry)
22{
23 diag_stat_inc(DIAG_STAT_X00C);
24 asm volatile (
25 " sam31\n"
26 " diag %0,%0,0x0c\n"
27 " sam64\n"
28 : /* no output register */
29 : "a" (entry)
30 : "memory");
31}
32
33/*
34 * Get hypfs_diag0c_entry from CPU vector and store diag0c data 19 * Get hypfs_diag0c_entry from CPU vector and store diag0c data
35 */ 20 */
36static void diag0c_fn(void *data) 21static void diag0c_fn(void *data)
37{ 22{
38 diag0c(((void **) data)[smp_processor_id()]); 23 diag_stat_inc(DIAG_STAT_X00C);
24 diag_dma_ops.diag0c(((void **) data)[smp_processor_id()]);
39} 25}
40 26
41/* 27/*
diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h
index 19562be22b7e..0036eab14391 100644
--- a/arch/s390/include/asm/diag.h
+++ b/arch/s390/include/asm/diag.h
@@ -308,4 +308,17 @@ union diag318_info {
308int diag204(unsigned long subcode, unsigned long size, void *addr); 308int diag204(unsigned long subcode, unsigned long size, void *addr);
309int diag224(void *ptr); 309int diag224(void *ptr);
310int diag26c(void *req, void *resp, enum diag26c_sc subcode); 310int diag26c(void *req, void *resp, enum diag26c_sc subcode);
311
312struct hypfs_diag0c_entry;
313
314struct diag_ops {
315 int (*diag210)(struct diag210 *addr);
316 int (*diag26c)(void *req, void *resp, enum diag26c_sc subcode);
317 int (*diag14)(unsigned long rx, unsigned long ry1, unsigned long subcode);
318 void (*diag0c)(struct hypfs_diag0c_entry *entry);
319 void (*diag308_reset)(void);
320};
321
322extern struct diag_ops diag_dma_ops;
323extern struct diag210 *__diag210_tmp_dma;
311#endif /* _ASM_S390_DIAG_H */ 324#endif /* _ASM_S390_DIAG_H */
diff --git a/arch/s390/include/asm/extable.h b/arch/s390/include/asm/extable.h
index 80a4e5a9cb46..ae27f756b409 100644
--- a/arch/s390/include/asm/extable.h
+++ b/arch/s390/include/asm/extable.h
@@ -19,6 +19,11 @@ struct exception_table_entry
19 int insn, fixup; 19 int insn, fixup;
20}; 20};
21 21
22extern struct exception_table_entry *__start_dma_ex_table;
23extern struct exception_table_entry *__stop_dma_ex_table;
24
25const struct exception_table_entry *s390_search_extables(unsigned long addr);
26
22static inline unsigned long extable_fixup(const struct exception_table_entry *x) 27static inline unsigned long extable_fixup(const struct exception_table_entry *x)
23{ 28{
24 return (unsigned long)&x->fixup + x->fixup; 29 return (unsigned long)&x->fixup + x->fixup;
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index 420d39ebdc46..084e71b7272a 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -127,7 +127,6 @@ enum diag308_rc {
127}; 127};
128 128
129extern int diag308(unsigned long subcode, void *addr); 129extern int diag308(unsigned long subcode, void *addr);
130extern void diag308_reset(void);
131extern void store_status(void (*fn)(void *), void *data); 130extern void store_status(void (*fn)(void *), void *data);
132extern void lgr_info_log(void); 131extern void lgr_info_log(void);
133 132
diff --git a/arch/s390/include/asm/linkage.h b/arch/s390/include/asm/linkage.h
index 1b95da3fdd64..7f22262b0e46 100644
--- a/arch/s390/include/asm/linkage.h
+++ b/arch/s390/include/asm/linkage.h
@@ -28,5 +28,12 @@
28 .long (_target) - . ; \ 28 .long (_target) - . ; \
29 .previous 29 .previous
30 30
31#define EX_TABLE_DMA(_fault, _target) \
32 .section .dma.ex_table, "a" ; \
33 .align 4 ; \
34 .long (_fault) - . ; \
35 .long (_target) - . ; \
36 .previous
37
31#endif /* __ASSEMBLY__ */ 38#endif /* __ASSEMBLY__ */
32#endif 39#endif
diff --git a/arch/s390/include/asm/sections.h b/arch/s390/include/asm/sections.h
index 29e55739b516..af670fa4b12a 100644
--- a/arch/s390/include/asm/sections.h
+++ b/arch/s390/include/asm/sections.h
@@ -23,4 +23,7 @@
23 */ 23 */
24#define __bootdata_preserved(var) __section(.boot.preserved.data.var) var 24#define __bootdata_preserved(var) __section(.boot.preserved.data.var) var
25 25
26extern unsigned long __sdma, __edma;
27extern unsigned long __stext_dma, __etext_dma;
28
26#endif 29#endif
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index f268fca67e82..d6ee5978e273 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -79,71 +79,3 @@ disabled_wait_psw:
79s390_base_pgm_handler_fn: 79s390_base_pgm_handler_fn:
80 .quad 0 80 .quad 0
81 .previous 81 .previous
82
83#
84# Calls diag 308 subcode 1 and continues execution
85#
86ENTRY(diag308_reset)
87 larl %r4,.Lctlregs # Save control registers
88 stctg %c0,%c15,0(%r4)
89 lg %r2,0(%r4) # Disable lowcore protection
90 nilh %r2,0xefff
91 larl %r4,.Lctlreg0
92 stg %r2,0(%r4)
93 lctlg %c0,%c0,0(%r4)
94 larl %r4,.Lfpctl # Floating point control register
95 stfpc 0(%r4)
96 larl %r4,.Lprefix # Save prefix register
97 stpx 0(%r4)
98 larl %r4,.Lprefix_zero # Set prefix register to 0
99 spx 0(%r4)
100 larl %r4,.Lcontinue_psw # Save PSW flags
101 epsw %r2,%r3
102 stm %r2,%r3,0(%r4)
103 larl %r4,.Lrestart_psw # Setup restart PSW at absolute 0
104 lghi %r3,0
105 lg %r4,0(%r4) # Save PSW
106 sturg %r4,%r3 # Use sturg, because of large pages
107 lghi %r1,1
108 lghi %r0,0
109 diag %r0,%r1,0x308
110.Lrestart_part2:
111 lhi %r0,0 # Load r0 with zero
112 lhi %r1,2 # Use mode 2 = ESAME (dump)
113 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode
114 sam64 # Switch to 64 bit addressing mode
115 larl %r4,.Lctlregs # Restore control registers
116 lctlg %c0,%c15,0(%r4)
117 larl %r4,.Lfpctl # Restore floating point ctl register
118 lfpc 0(%r4)
119 larl %r4,.Lprefix # Restore prefix register
120 spx 0(%r4)
121 larl %r4,.Lcontinue_psw # Restore PSW flags
122 lpswe 0(%r4)
123.Lcontinue:
124 BR_EX %r14
125.align 16
126.Lrestart_psw:
127 .long 0x00080000,0x80000000 + .Lrestart_part2
128
129 .section .data..nosave,"aw",@progbits
130.align 8
131.Lcontinue_psw:
132 .quad 0,.Lcontinue
133 .previous
134
135 .section .bss
136.align 8
137.Lctlreg0:
138 .quad 0
139.Lctlregs:
140 .rept 16
141 .quad 0
142 .endr
143.Lfpctl:
144 .long 0
145.Lprefix:
146 .long 0
147.Lprefix_zero:
148 .long 0
149 .previous
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
index 7edaa733a77f..e9dac9a24d3f 100644
--- a/arch/s390/kernel/diag.c
+++ b/arch/s390/kernel/diag.c
@@ -13,6 +13,7 @@
13#include <linux/debugfs.h> 13#include <linux/debugfs.h>
14#include <asm/diag.h> 14#include <asm/diag.h>
15#include <asm/trace/diag.h> 15#include <asm/trace/diag.h>
16#include <asm/sections.h>
16 17
17struct diag_stat { 18struct diag_stat {
18 unsigned int counter[NR_DIAG_STAT]; 19 unsigned int counter[NR_DIAG_STAT];
@@ -49,6 +50,9 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = {
49 [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" }, 50 [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
50}; 51};
51 52
53struct diag_ops __bootdata_preserved(diag_dma_ops);
54struct diag210 *__bootdata_preserved(__diag210_tmp_dma);
55
52static int show_diag_stat(struct seq_file *m, void *v) 56static int show_diag_stat(struct seq_file *m, void *v)
53{ 57{
54 struct diag_stat *stat; 58 struct diag_stat *stat;
@@ -139,30 +143,10 @@ EXPORT_SYMBOL(diag_stat_inc_norecursion);
139/* 143/*
140 * Diagnose 14: Input spool file manipulation 144 * Diagnose 14: Input spool file manipulation
141 */ 145 */
142static inline int __diag14(unsigned long rx, unsigned long ry1,
143 unsigned long subcode)
144{
145 register unsigned long _ry1 asm("2") = ry1;
146 register unsigned long _ry2 asm("3") = subcode;
147 int rc = 0;
148
149 asm volatile(
150 " sam31\n"
151 " diag %2,2,0x14\n"
152 " sam64\n"
153 " ipm %0\n"
154 " srl %0,28\n"
155 : "=d" (rc), "+d" (_ry2)
156 : "d" (rx), "d" (_ry1)
157 : "cc");
158
159 return rc;
160}
161
162int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode) 146int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
163{ 147{
164 diag_stat_inc(DIAG_STAT_X014); 148 diag_stat_inc(DIAG_STAT_X014);
165 return __diag14(rx, ry1, subcode); 149 return diag_dma_ops.diag14(rx, ry1, subcode);
166} 150}
167EXPORT_SYMBOL(diag14); 151EXPORT_SYMBOL(diag14);
168 152
@@ -195,30 +179,17 @@ EXPORT_SYMBOL(diag204);
195 */ 179 */
196int diag210(struct diag210 *addr) 180int diag210(struct diag210 *addr)
197{ 181{
198 /*
199 * diag 210 needs its data below the 2GB border, so we
200 * use a static data area to be sure
201 */
202 static struct diag210 diag210_tmp;
203 static DEFINE_SPINLOCK(diag210_lock); 182 static DEFINE_SPINLOCK(diag210_lock);
204 unsigned long flags; 183 unsigned long flags;
205 int ccode; 184 int ccode;
206 185
207 spin_lock_irqsave(&diag210_lock, flags); 186 spin_lock_irqsave(&diag210_lock, flags);
208 diag210_tmp = *addr; 187 *__diag210_tmp_dma = *addr;
209 188
210 diag_stat_inc(DIAG_STAT_X210); 189 diag_stat_inc(DIAG_STAT_X210);
211 asm volatile( 190 ccode = diag_dma_ops.diag210(__diag210_tmp_dma);
212 " lhi %0,-1\n" 191
213 " sam31\n" 192 *addr = *__diag210_tmp_dma;
214 " diag %1,0,0x210\n"
215 "0: ipm %0\n"
216 " srl %0,28\n"
217 "1: sam64\n"
218 EX_TABLE(0b, 1b)
219 : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
220
221 *addr = diag210_tmp;
222 spin_unlock_irqrestore(&diag210_lock, flags); 193 spin_unlock_irqrestore(&diag210_lock, flags);
223 194
224 return ccode; 195 return ccode;
@@ -243,27 +214,9 @@ EXPORT_SYMBOL(diag224);
243/* 214/*
244 * Diagnose 26C: Access Certain System Information 215 * Diagnose 26C: Access Certain System Information
245 */ 216 */
246static inline int __diag26c(void *req, void *resp, enum diag26c_sc subcode)
247{
248 register unsigned long _req asm("2") = (addr_t) req;
249 register unsigned long _resp asm("3") = (addr_t) resp;
250 register unsigned long _subcode asm("4") = subcode;
251 register unsigned long _rc asm("5") = -EOPNOTSUPP;
252
253 asm volatile(
254 " sam31\n"
255 " diag %[rx],%[ry],0x26c\n"
256 "0: sam64\n"
257 EX_TABLE(0b,0b)
258 : "+d" (_rc)
259 : [rx] "d" (_req), "d" (_resp), [ry] "d" (_subcode)
260 : "cc", "memory");
261 return _rc;
262}
263
264int diag26c(void *req, void *resp, enum diag26c_sc subcode) 217int diag26c(void *req, void *resp, enum diag26c_sc subcode)
265{ 218{
266 diag_stat_inc(DIAG_STAT_X26C); 219 diag_stat_inc(DIAG_STAT_X26C);
267 return __diag26c(req, resp, subcode); 220 return diag_dma_ops.diag26c(req, resp, subcode);
268} 221}
269EXPORT_SYMBOL(diag26c); 222EXPORT_SYMBOL(diag26c);
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index ab09ada0e930..33f704c16bd3 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -139,7 +139,7 @@ static void early_pgm_check_handler(void)
139 unsigned long addr; 139 unsigned long addr;
140 140
141 addr = S390_lowcore.program_old_psw.addr; 141 addr = S390_lowcore.program_old_psw.addr;
142 fixup = search_exception_tables(addr); 142 fixup = s390_search_extables(addr);
143 if (!fixup) 143 if (!fixup)
144 disabled_wait(0); 144 disabled_wait(0);
145 /* Disable low address protection before storing into lowcore. */ 145 /* Disable low address protection before storing into lowcore. */
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 56491e636eab..5aea1a527443 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -26,7 +26,6 @@ ENTRY(startup_continue)
260: larl %r1,tod_clock_base 260: larl %r1,tod_clock_base
27 mvc 0(16,%r1),__LC_BOOT_CLOCK 27 mvc 0(16,%r1),__LC_BOOT_CLOCK
28 larl %r13,.LPG1 # get base 28 larl %r13,.LPG1 # get base
29 lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
30 larl %r0,boot_vdso_data 29 larl %r0,boot_vdso_data
31 stg %r0,__LC_VDSO_PER_CPU 30 stg %r0,__LC_VDSO_PER_CPU
32# 31#
@@ -61,22 +60,6 @@ ENTRY(startup_continue)
61 60
62 .align 16 61 .align 16
63.LPG1: 62.LPG1:
64.Lctl: .quad 0x04040000 # cr0: AFP registers & secondary space
65 .quad 0 # cr1: primary space segment table
66 .quad .Lduct # cr2: dispatchable unit control table
67 .quad 0 # cr3: instruction authorization
68 .quad 0xffff # cr4: instruction authorization
69 .quad .Lduct # cr5: primary-aste origin
70 .quad 0 # cr6: I/O interrupts
71 .quad 0 # cr7: secondary space segment table
72 .quad 0 # cr8: access registers translation
73 .quad 0 # cr9: tracing off
74 .quad 0 # cr10: tracing off
75 .quad 0 # cr11: tracing off
76 .quad 0 # cr12: tracing off
77 .quad 0 # cr13: home space segment table
78 .quad 0xc0000000 # cr14: machine check handling off
79 .quad .Llinkage_stack # cr15: linkage stack operations
80.Lpcmsk:.quad 0x0000000180000000 63.Lpcmsk:.quad 0x0000000180000000
81.L4malign:.quad 0xffffffffffc00000 64.L4malign:.quad 0xffffffffffc00000
82.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 65.Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
@@ -84,14 +67,5 @@ ENTRY(startup_continue)
84.Lparmaddr: 67.Lparmaddr:
85 .quad PARMAREA 68 .quad PARMAREA
86 .align 64 69 .align 64
87.Lduct: .long 0,.Laste,.Laste,0,.Lduald,0,0,0
88 .long 0,0,0,0,0,0,0,0
89.Laste: .quad 0,0xffffffffffffffff,0,0,0,0,0,0
90 .align 128
91.Lduald:.rept 8
92 .long 0x80000000,0,0,0 # invalid access-list entries
93 .endr
94.Llinkage_stack:
95 .long 0,0,0x89000000,0,0,0,0x8a000000,0
96.Ldw: .quad 0x0002000180000000,0x0000000000000000 70.Ldw: .quad 0x0002000180000000,0x0000000000000000
97.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 71.Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index e123c0df83f1..aa8fe768640e 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1720,7 +1720,7 @@ void s390_reset_system(void)
1720 1720
1721 /* Disable lowcore protection */ 1721 /* Disable lowcore protection */
1722 __ctl_clear_bit(0, 28); 1722 __ctl_clear_bit(0, 28);
1723 diag308_reset(); 1723 diag_dma_ops.diag308_reset();
1724} 1724}
1725 1725
1726#ifdef CONFIG_KEXEC_FILE 1726#ifdef CONFIG_KEXEC_FILE
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 263426dcf97d..6f1388391620 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -573,7 +573,7 @@ static int kprobe_trap_handler(struct pt_regs *regs, int trapnr)
573 * In case the user-specified fault handler returned 573 * In case the user-specified fault handler returned
574 * zero, try to fix up. 574 * zero, try to fix up.
575 */ 575 */
576 entry = search_exception_tables(regs->psw.addr); 576 entry = s390_search_extables(regs->psw.addr);
577 if (entry) { 577 if (entry) {
578 regs->psw.addr = extable_fixup(entry); 578 regs->psw.addr = extable_fixup(entry);
579 return 1; 579 return 1;
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index cb582649aba6..4b998d639c32 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -253,6 +253,8 @@ void arch_crash_save_vmcoreinfo(void)
253 VMCOREINFO_SYMBOL(high_memory); 253 VMCOREINFO_SYMBOL(high_memory);
254 VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS); 254 VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
255 mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); 255 mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
256 vmcoreinfo_append_str("SDMA=%lx\n", __sdma);
257 vmcoreinfo_append_str("EDMA=%lx\n", __edma);
256} 258}
257 259
258void machine_shutdown(void) 260void machine_shutdown(void)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 94efb1eb34b6..4ccaf5ed96ee 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -101,6 +101,14 @@ unsigned long __bootdata(memory_end);
101unsigned long __bootdata(max_physmem_end); 101unsigned long __bootdata(max_physmem_end);
102struct mem_detect_info __bootdata(mem_detect); 102struct mem_detect_info __bootdata(mem_detect);
103 103
104struct exception_table_entry *__bootdata_preserved(__start_dma_ex_table);
105struct exception_table_entry *__bootdata_preserved(__stop_dma_ex_table);
106unsigned long __bootdata_preserved(__swsusp_reset_dma);
107unsigned long __bootdata_preserved(__stext_dma);
108unsigned long __bootdata_preserved(__etext_dma);
109unsigned long __bootdata_preserved(__sdma);
110unsigned long __bootdata_preserved(__edma);
111
104unsigned long VMALLOC_START; 112unsigned long VMALLOC_START;
105EXPORT_SYMBOL(VMALLOC_START); 113EXPORT_SYMBOL(VMALLOC_START);
106 114
@@ -832,6 +840,7 @@ static void __init reserve_kernel(void)
832 memblock_reserve(0, HEAD_END); 840 memblock_reserve(0, HEAD_END);
833 memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn) 841 memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn)
834 - (unsigned long)_stext); 842 - (unsigned long)_stext);
843 memblock_reserve(__sdma, __edma - __sdma);
835} 844}
836 845
837static void __init setup_memory(void) 846static void __init setup_memory(void)
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index bd197baf1dc3..88634fb0cc50 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -689,7 +689,7 @@ void __init smp_save_dump_cpus(void)
689 smp_save_cpu_regs(sa, addr, is_boot_cpu, page); 689 smp_save_cpu_regs(sa, addr, is_boot_cpu, page);
690 } 690 }
691 memblock_free(page, PAGE_SIZE); 691 memblock_free(page, PAGE_SIZE);
692 diag308_reset(); 692 diag_dma_ops.diag308_reset();
693 pcpu_set_smt(0); 693 pcpu_set_smt(0);
694} 694}
695#endif /* CONFIG_CRASH_DUMP */ 695#endif /* CONFIG_CRASH_DUMP */
diff --git a/arch/s390/kernel/swsusp.S b/arch/s390/kernel/swsusp.S
index 993100c31d65..f5219ce11cc5 100644
--- a/arch/s390/kernel/swsusp.S
+++ b/arch/s390/kernel/swsusp.S
@@ -154,20 +154,13 @@ ENTRY(swsusp_arch_resume)
154 ptlb /* flush tlb */ 154 ptlb /* flush tlb */
155 155
156 /* Reset System */ 156 /* Reset System */
157 larl %r1,restart_entry
158 larl %r2,.Lrestart_diag308_psw
159 og %r1,0(%r2)
160 stg %r1,0(%r0)
161 larl %r1,.Lnew_pgm_check_psw 157 larl %r1,.Lnew_pgm_check_psw
162 epsw %r2,%r3 158 epsw %r2,%r3
163 stm %r2,%r3,0(%r1) 159 stm %r2,%r3,0(%r1)
164 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) 160 mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1)
165 lghi %r0,0 161 larl %r1,__swsusp_reset_dma
166 diag %r0,%r0,0x308 162 lg %r1,0(%r1)
167restart_entry: 163 BASR_EX %r14,%r1
168 lhi %r1,1
169 sigp %r1,%r0,SIGP_SET_ARCHITECTURE
170 sam64
171#ifdef CONFIG_SMP 164#ifdef CONFIG_SMP
172 larl %r1,smp_cpu_mt_shift 165 larl %r1,smp_cpu_mt_shift
173 icm %r1,15,0(%r1) 166 icm %r1,15,0(%r1)
@@ -275,8 +268,6 @@ restore_registers:
275.Lpanic_string: 268.Lpanic_string:
276 .asciz "Resume not possible because suspend CPU is no longer available\n" 269 .asciz "Resume not possible because suspend CPU is no longer available\n"
277 .align 8 270 .align 8
278.Lrestart_diag308_psw:
279 .long 0x00080000,0x80000000
280.Lrestart_suspend_psw: 271.Lrestart_suspend_psw:
281 .quad 0x0000000180000000,restart_suspend 272 .quad 0x0000000180000000,restart_suspend
282.Lnew_pgm_check_psw: 273.Lnew_pgm_check_psw:
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 8003b38c1688..82e81a9f7112 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -49,7 +49,7 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
49 report_user_fault(regs, si_signo, 0); 49 report_user_fault(regs, si_signo, 0);
50 } else { 50 } else {
51 const struct exception_table_entry *fixup; 51 const struct exception_table_entry *fixup;
52 fixup = search_exception_tables(regs->psw.addr); 52 fixup = s390_search_extables(regs->psw.addr);
53 if (fixup) 53 if (fixup)
54 regs->psw.addr = extable_fixup(fixup); 54 regs->psw.addr = extable_fixup(fixup);
55 else { 55 else {
@@ -263,5 +263,6 @@ NOKPROBE_SYMBOL(kernel_stack_overflow);
263 263
264void __init trap_init(void) 264void __init trap_init(void)
265{ 265{
266 sort_extable(__start_dma_ex_table, __stop_dma_ex_table);
266 local_mcck_enable(); 267 local_mcck_enable();
267} 268}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 11613362c4e7..c220399ae196 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -247,12 +247,24 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
247 current); 247 current);
248} 248}
249 249
250const struct exception_table_entry *s390_search_extables(unsigned long addr)
251{
252 const struct exception_table_entry *fixup;
253
254 fixup = search_extable(__start_dma_ex_table,
255 __stop_dma_ex_table - __start_dma_ex_table,
256 addr);
257 if (!fixup)
258 fixup = search_exception_tables(addr);
259 return fixup;
260}
261
250static noinline void do_no_context(struct pt_regs *regs) 262static noinline void do_no_context(struct pt_regs *regs)
251{ 263{
252 const struct exception_table_entry *fixup; 264 const struct exception_table_entry *fixup;
253 265
254 /* Are we prepared to handle this kernel fault? */ 266 /* Are we prepared to handle this kernel fault? */
255 fixup = search_exception_tables(regs->psw.addr); 267 fixup = s390_search_extables(regs->psw.addr);
256 if (fixup) { 268 if (fixup) {
257 regs->psw.addr = extable_fixup(fixup); 269 regs->psw.addr = extable_fixup(fixup);
258 return; 270 return;
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 0472e27febdf..b403fa14847d 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -413,6 +413,8 @@ void __init vmem_map_init(void)
413 __set_memory((unsigned long)_sinittext, 413 __set_memory((unsigned long)_sinittext,
414 (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT, 414 (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT,
415 SET_MEMORY_RO | SET_MEMORY_X); 415 SET_MEMORY_RO | SET_MEMORY_X);
416 __set_memory(__stext_dma, (__etext_dma - __stext_dma) >> PAGE_SHIFT,
417 SET_MEMORY_RO | SET_MEMORY_X);
416 pr_info("Write protected kernel read-only data: %luk\n", 418 pr_info("Write protected kernel read-only data: %luk\n",
417 (unsigned long)(__end_rodata - _stext) >> 10); 419 (unsigned long)(__end_rodata - _stext) >> 10);
418} 420}