summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Schaefer <gerald.schaefer@de.ibm.com>2019-02-03 15:37:20 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2019-04-29 04:47:10 -0400
commita80313ff91abda67641dc33bed97f6bcc5e9f6a4 (patch)
treefce012f16f783ae75583b9f2ca3f0925abff7216
parent087c4d7423989b110c3312592db05acc009a5d58 (diff)
s390/kernel: introduce .dma sections
With a relocatable kernel that could reside at any place in memory, code and data that has to stay below 2 GB needs special handling. This patch introduces .dma sections for such text, data and ex_table. The sections will be part of the decompressor kernel, so they will not be relocated and stay below 2 GB. Their location is passed over to the decompressed / relocated kernel via the .boot.preserved.data section. The duald and aste for control register setup also need to stay below 2 GB, so move the setup code from arch/s390/kernel/head64.S to arch/s390/boot/head.S. The duct and linkage_stack could reside above 2 GB, but their content has to be preserved for the decompresed kernel, so they are also moved into the .dma section. The start and end address of the .dma sections is added to vmcoreinfo, for crash support, to help debugging in case the kernel crashed there. Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Reviewed-by: Philipp Rudo <prudo@linux.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-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}