]> git.dujemihanovic.xyz Git - linux.git/commitdiff
s390/kernel: introduce .dma sections
authorGerald Schaefer <gerald.schaefer@de.ibm.com>
Sun, 3 Feb 2019 20:37:20 +0000 (21:37 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 29 Apr 2019 08:47:10 +0000 (10:47 +0200)
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>
24 files changed:
arch/s390/boot/Makefile
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/boot/head.S
arch/s390/boot/startup.c
arch/s390/boot/text_dma.S [new file with mode: 0644]
arch/s390/hypfs/hypfs_diag0c.c
arch/s390/include/asm/diag.h
arch/s390/include/asm/extable.h
arch/s390/include/asm/ipl.h
arch/s390/include/asm/linkage.h
arch/s390/include/asm/sections.h
arch/s390/kernel/base.S
arch/s390/kernel/diag.c
arch/s390/kernel/early.c
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/swsusp.S
arch/s390/kernel/traps.c
arch/s390/mm/fault.c
arch/s390/mm/vmem.c

index 4df43e83363a51b190b1706c159ad59870c36776..88932c25ad26cc31003535c532ed60d3045171c0 100644 (file)
@@ -30,7 +30,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
 
 obj-y  := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
 obj-y  += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
-obj-y  += ctype.o
+obj-y  += ctype.o text_dma.o
 obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST)   += uv.o
 obj-$(CONFIG_RELOCATABLE)      += machine_kexec_reloc.o
 targets        := bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)
index 1c8ef393c6569a48bd190d6fe77ebd9fa7ad2f2b..112b8d9f1e4cd9752e70eff11d3a164f5ac72c31 100644 (file)
@@ -33,6 +33,27 @@ SECTIONS
                *(.data.*)
                _edata = . ;
        }
+       /*
+       * .dma section for code, data, ex_table that need to stay below 2 GB,
+       * even when the kernel is relocate: above 2 GB.
+       */
+       _sdma = .;
+       .dma.text : {
+               . = ALIGN(PAGE_SIZE);
+               _stext_dma = .;
+               *(.dma.text)
+               . = ALIGN(PAGE_SIZE);
+               _etext_dma = .;
+       }
+       . = ALIGN(16);
+       .dma.ex_table : {
+               _start_dma_ex_table = .;
+               KEEP(*(.dma.ex_table))
+               _stop_dma_ex_table = .;
+       }
+       .dma.data : { *(.dma.data) }
+       _edma = .;
+
        BOOT_DATA
        BOOT_DATA_PRESERVED
 
index c6b4b4c5dd5851e54c8c5c88d949fd646550bf02..028aab03a9e7782ceb5b9b5104091399c39d6e10 100644 (file)
@@ -305,7 +305,7 @@ ENTRY(startup_kdump)
        xc      0x300(256),0x300
        xc      0xe00(256),0xe00
        xc      0xf00(256),0xf00
-       lctlg   %c0,%c15,0x200(%r0)     # initialize control registers
+       lctlg   %c0,%c15,.Lctl-.LPG0(%r13)      # load control registers
        stcke   __LC_BOOT_CLOCK
        mvc     __LC_LAST_UPDATE_CLOCK(8),__LC_BOOT_CLOCK+1
        spt     6f-.LPG0(%r13)
@@ -319,6 +319,36 @@ ENTRY(startup_kdump)
        .align  8
 6:     .long   0x7fffffff,0xffffffff
 
+.Lctl: .quad   0x04040000              # cr0: AFP registers & secondary space
+       .quad   0                       # cr1: primary space segment table
+       .quad   .Lduct                  # cr2: dispatchable unit control table
+       .quad   0                       # cr3: instruction authorization
+       .quad   0xffff                  # cr4: instruction authorization
+       .quad   .Lduct                  # cr5: primary-aste origin
+       .quad   0                       # cr6:  I/O interrupts
+       .quad   0                       # cr7:  secondary space segment table
+       .quad   0                       # cr8:  access registers translation
+       .quad   0                       # cr9:  tracing off
+       .quad   0                       # cr10: tracing off
+       .quad   0                       # cr11: tracing off
+       .quad   0                       # cr12: tracing off
+       .quad   0                       # cr13: home space segment table
+       .quad   0xc0000000              # cr14: machine check handling off
+       .quad   .Llinkage_stack         # cr15: linkage stack operations
+
+       .section .dma.data,"aw",@progbits
+.Lduct: .long  0,.Laste,.Laste,0,.Lduald,0,0,0
+       .long   0,0,0,0,0,0,0,0
+.Llinkage_stack:
+       .long   0,0,0x89000000,0,0,0,0x8a000000,0
+       .align 64
+.Laste:        .quad   0,0xffffffffffffffff,0,0,0,0,0,0
+       .align  128
+.Lduald:.rept  8
+       .long   0x80000000,0,0,0        # invalid access-list entries
+       .endr
+       .previous
+
 #include "head_kdump.S"
 
 #
index b7d6a76cb5e97a51b488fc5668d85adeeaed05ed..e3f339d248cea705791ab6b862306fe7fa407b03 100644 (file)
@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/string.h>
 #include <linux/elf.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/kexec.h>
 #include <asm/sclp.h>
+#include <asm/diag.h>
 #include <asm/uv.h>
 #include "compressed/decompressor.h"
 #include "boot.h"
 extern char __boot_data_start[], __boot_data_end[];
 extern char __boot_data_preserved_start[], __boot_data_preserved_end[];
 
+/*
+ * Some code and data needs to stay below 2 GB, even when the kernel would be
+ * relocated above 2 GB, because it has to use 31 bit addresses.
+ * Such code and data is part of the .dma section, and its location is passed
+ * over to the decompressed / relocated kernel via the .boot.preserved.data
+ * section.
+ */
+extern char _sdma[], _edma[];
+extern char _stext_dma[], _etext_dma[];
+extern struct exception_table_entry _start_dma_ex_table[];
+extern struct exception_table_entry _stop_dma_ex_table[];
+unsigned long __bootdata_preserved(__sdma) = __pa(&_sdma);
+unsigned long __bootdata_preserved(__edma) = __pa(&_edma);
+unsigned long __bootdata_preserved(__stext_dma) = __pa(&_stext_dma);
+unsigned long __bootdata_preserved(__etext_dma) = __pa(&_etext_dma);
+struct exception_table_entry *
+       __bootdata_preserved(__start_dma_ex_table) = _start_dma_ex_table;
+struct exception_table_entry *
+       __bootdata_preserved(__stop_dma_ex_table) = _stop_dma_ex_table;
+
+int _diag210_dma(struct diag210 *addr);
+int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode);
+int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode);
+void _diag0c_dma(struct hypfs_diag0c_entry *entry);
+void _diag308_reset_dma(void);
+struct diag_ops __bootdata_preserved(diag_dma_ops) = {
+       .diag210 = _diag210_dma,
+       .diag26c = _diag26c_dma,
+       .diag14 = _diag14_dma,
+       .diag0c = _diag0c_dma,
+       .diag308_reset = _diag308_reset_dma
+};
+static struct diag210 _diag210_tmp_dma __section(".dma.data");
+struct diag210 *__bootdata_preserved(__diag210_tmp_dma) = &_diag210_tmp_dma;
+void _swsusp_reset_dma(void);
+unsigned long __bootdata_preserved(__swsusp_reset_dma) = __pa(_swsusp_reset_dma);
+
 void error(char *x)
 {
        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 (file)
index 0000000..2414360
--- /dev/null
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Code that needs to run below 2 GB.
+ *
+ * Copyright IBM Corp. 2019
+ */
+
+#include <linux/linkage.h>
+#include <asm/errno.h>
+#include <asm/sigp.h>
+
+       .section .dma.text,"ax"
+/*
+ * Simplified version of expoline thunk. The normal thunks can not be used here,
+ * because they might be more than 2 GB away, and not reachable by the relative
+ * branch. No comdat, exrl, etc. optimizations used here, because it only
+ * affects a few functions that are not performance-relevant.
+ */
+       .macro BR_EX_DMA_r14
+       larl    %r1,0f
+       ex      0,0(%r1)
+       j       .
+0:     br      %r14
+       .endm
+
+/*
+ * int _diag14_dma(unsigned long rx, unsigned long ry1, unsigned long subcode)
+ */
+ENTRY(_diag14_dma)
+       lgr     %r1,%r2
+       lgr     %r2,%r3
+       lgr     %r3,%r4
+       lhi     %r5,-EIO
+       sam31
+       diag    %r1,%r2,0x14
+.Ldiag14_ex:
+       ipm     %r5
+       srl     %r5,28
+.Ldiag14_fault:
+       sam64
+       lgfr    %r2,%r5
+       BR_EX_DMA_r14
+       EX_TABLE_DMA(.Ldiag14_ex, .Ldiag14_fault)
+
+/*
+ * int _diag210_dma(struct diag210 *addr)
+ */
+ENTRY(_diag210_dma)
+       lgr     %r1,%r2
+       lhi     %r2,-1
+       sam31
+       diag    %r1,%r0,0x210
+.Ldiag210_ex:
+       ipm     %r2
+       srl     %r2,28
+.Ldiag210_fault:
+       sam64
+       lgfr    %r2,%r2
+       BR_EX_DMA_r14
+       EX_TABLE_DMA(.Ldiag210_ex, .Ldiag210_fault)
+
+/*
+ * int _diag26c_dma(void *req, void *resp, enum diag26c_sc subcode)
+ */
+ENTRY(_diag26c_dma)
+       lghi    %r5,-EOPNOTSUPP
+       sam31
+       diag    %r2,%r4,0x26c
+.Ldiag26c_ex:
+       sam64
+       lgfr    %r2,%r5
+       BR_EX_DMA_r14
+       EX_TABLE_DMA(.Ldiag26c_ex, .Ldiag26c_ex)
+
+/*
+ * void _diag0c_dma(struct hypfs_diag0c_entry *entry)
+ */
+ENTRY(_diag0c_dma)
+       sam31
+       diag    %r2,%r2,0x0c
+       sam64
+       BR_EX_DMA_r14
+
+/*
+ * void _swsusp_reset_dma(void)
+ */
+ENTRY(_swsusp_reset_dma)
+       larl    %r1,restart_entry
+       larl    %r2,.Lrestart_diag308_psw
+       og      %r1,0(%r2)
+       stg     %r1,0(%r0)
+       lghi    %r0,0
+       diag    %r0,%r0,0x308
+restart_entry:
+       lhi     %r1,1
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE
+       sam64
+       BR_EX_DMA_r14
+
+/*
+ * void _diag308_reset_dma(void)
+ *
+ * Calls diag 308 subcode 1 and continues execution
+ */
+ENTRY(_diag308_reset_dma)
+       larl    %r4,.Lctlregs           # Save control registers
+       stctg   %c0,%c15,0(%r4)
+       lg      %r2,0(%r4)              # Disable lowcore protection
+       nilh    %r2,0xefff
+       larl    %r4,.Lctlreg0
+       stg     %r2,0(%r4)
+       lctlg   %c0,%c0,0(%r4)
+       larl    %r4,.Lfpctl             # Floating point control register
+       stfpc   0(%r4)
+       larl    %r4,.Lprefix            # Save prefix register
+       stpx    0(%r4)
+       larl    %r4,.Lprefix_zero       # Set prefix register to 0
+       spx     0(%r4)
+       larl    %r4,.Lcontinue_psw      # Save PSW flags
+       epsw    %r2,%r3
+       stm     %r2,%r3,0(%r4)
+       larl    %r4,restart_part2       # Setup restart PSW at absolute 0
+       larl    %r3,.Lrestart_diag308_psw
+       og      %r4,0(%r3)              # Save PSW
+       lghi    %r3,0
+       sturg   %r4,%r3                 # Use sturg, because of large pages
+       lghi    %r1,1
+       lghi    %r0,0
+       diag    %r0,%r1,0x308
+restart_part2:
+       lhi     %r0,0                   # Load r0 with zero
+       lhi     %r1,2                   # Use mode 2 = ESAME (dump)
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE   # Switch to ESAME mode
+       sam64                           # Switch to 64 bit addressing mode
+       larl    %r4,.Lctlregs           # Restore control registers
+       lctlg   %c0,%c15,0(%r4)
+       larl    %r4,.Lfpctl             # Restore floating point ctl register
+       lfpc    0(%r4)
+       larl    %r4,.Lprefix            # Restore prefix register
+       spx     0(%r4)
+       larl    %r4,.Lcontinue_psw      # Restore PSW flags
+       lpswe   0(%r4)
+.Lcontinue:
+       BR_EX_DMA_r14
+
+       .section .dma.data,"aw",@progbits
+.align 8
+.Lrestart_diag308_psw:
+       .long   0x00080000,0x80000000
+
+.align 8
+.Lcontinue_psw:
+       .quad   0,.Lcontinue
+
+.align 8
+.Lctlreg0:
+       .quad   0
+.Lctlregs:
+       .rept   16
+       .quad   0
+       .endr
+.Lfpctl:
+       .long   0
+.Lprefix:
+       .long   0
+.Lprefix_zero:
+       .long   0
index 72e3140fafb50a9b32d347a3b0e1a7807722f5e4..3235e4d82f2d550c209baaa6d94c5800e73c56c3 100644 (file)
 
 #define DBFS_D0C_HDR_VERSION 0
 
-/*
- * Execute diagnose 0c in 31 bit mode
- */
-static void diag0c(struct hypfs_diag0c_entry *entry)
-{
-       diag_stat_inc(DIAG_STAT_X00C);
-       asm volatile (
-               "       sam31\n"
-               "       diag    %0,%0,0x0c\n"
-               "       sam64\n"
-               : /* no output register */
-               : "a" (entry)
-               : "memory");
-}
-
 /*
  * Get hypfs_diag0c_entry from CPU vector and store diag0c data
  */
 static void diag0c_fn(void *data)
 {
-       diag0c(((void **) data)[smp_processor_id()]);
+       diag_stat_inc(DIAG_STAT_X00C);
+       diag_dma_ops.diag0c(((void **) data)[smp_processor_id()]);
 }
 
 /*
index 19562be22b7e30c12cfa8c78ada1fb39ebbecd14..0036eab14391d35854a9540c5a1d64033f3eab1c 100644 (file)
@@ -308,4 +308,17 @@ union diag318_info {
 int diag204(unsigned long subcode, unsigned long size, void *addr);
 int diag224(void *ptr);
 int diag26c(void *req, void *resp, enum diag26c_sc subcode);
+
+struct hypfs_diag0c_entry;
+
+struct diag_ops {
+       int (*diag210)(struct diag210 *addr);
+       int (*diag26c)(void *req, void *resp, enum diag26c_sc subcode);
+       int (*diag14)(unsigned long rx, unsigned long ry1, unsigned long subcode);
+       void (*diag0c)(struct hypfs_diag0c_entry *entry);
+       void (*diag308_reset)(void);
+};
+
+extern struct diag_ops diag_dma_ops;
+extern struct diag210 *__diag210_tmp_dma;
 #endif /* _ASM_S390_DIAG_H */
index 80a4e5a9cb46022352f956ebe04c8007564c8879..ae27f756b409f4adddcc8f00dea2629271c8cf7d 100644 (file)
@@ -19,6 +19,11 @@ struct exception_table_entry
        int insn, fixup;
 };
 
+extern struct exception_table_entry *__start_dma_ex_table;
+extern struct exception_table_entry *__stop_dma_ex_table;
+
+const struct exception_table_entry *s390_search_extables(unsigned long addr);
+
 static inline unsigned long extable_fixup(const struct exception_table_entry *x)
 {
        return (unsigned long)&x->fixup + x->fixup;
index 420d39ebdc46b5740ddcde6b58d49f0efbe658e9..084e71b7272afd421be5b6b4a9021ede7c9dc907 100644 (file)
@@ -127,7 +127,6 @@ enum diag308_rc {
 };
 
 extern int diag308(unsigned long subcode, void *addr);
-extern void diag308_reset(void);
 extern void store_status(void (*fn)(void *), void *data);
 extern void lgr_info_log(void);
 
index 1b95da3fdd64e0d40d4960f89dfb3768298b5cec..7f22262b0e46ca9c0a6a0a8b4d4ac2683b4862e4 100644 (file)
        .long   (_target) - . ;         \
        .previous
 
+#define EX_TABLE_DMA(_fault, _target)  \
+       .section .dma.ex_table, "a" ;   \
+       .align  4 ;                     \
+       .long   (_fault) - . ;          \
+       .long   (_target) - . ;         \
+       .previous
+
 #endif /* __ASSEMBLY__ */
 #endif
index 29e55739b516a75e4a8f332a8a2ec159dad4a890..af670fa4b12aa421a5770d2d482f9a25c205b051 100644 (file)
@@ -23,4 +23,7 @@
  */
 #define __bootdata_preserved(var) __section(.boot.preserved.data.var) var
 
+extern unsigned long __sdma, __edma;
+extern unsigned long __stext_dma, __etext_dma;
+
 #endif
index f268fca67e822a1e4b9d1547400aa1353c10af5e..d6ee5978e2731dea198470e3da3278d94fc9790d 100644 (file)
@@ -79,71 +79,3 @@ disabled_wait_psw:
 s390_base_pgm_handler_fn:
        .quad   0
        .previous
-
-#
-# Calls diag 308 subcode 1 and continues execution
-#
-ENTRY(diag308_reset)
-       larl    %r4,.Lctlregs           # Save control registers
-       stctg   %c0,%c15,0(%r4)
-       lg      %r2,0(%r4)              # Disable lowcore protection
-       nilh    %r2,0xefff
-       larl    %r4,.Lctlreg0
-       stg     %r2,0(%r4)
-       lctlg   %c0,%c0,0(%r4)
-       larl    %r4,.Lfpctl             # Floating point control register
-       stfpc   0(%r4)
-       larl    %r4,.Lprefix            # Save prefix register
-       stpx    0(%r4)
-       larl    %r4,.Lprefix_zero       # Set prefix register to 0
-       spx     0(%r4)
-       larl    %r4,.Lcontinue_psw      # Save PSW flags
-       epsw    %r2,%r3
-       stm     %r2,%r3,0(%r4)
-       larl    %r4,.Lrestart_psw       # Setup restart PSW at absolute 0
-       lghi    %r3,0
-       lg      %r4,0(%r4)              # Save PSW
-       sturg   %r4,%r3                 # Use sturg, because of large pages
-       lghi    %r1,1
-       lghi    %r0,0
-       diag    %r0,%r1,0x308
-.Lrestart_part2:
-       lhi     %r0,0                   # Load r0 with zero
-       lhi     %r1,2                   # Use mode 2 = ESAME (dump)
-       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE   # Switch to ESAME mode
-       sam64                           # Switch to 64 bit addressing mode
-       larl    %r4,.Lctlregs           # Restore control registers
-       lctlg   %c0,%c15,0(%r4)
-       larl    %r4,.Lfpctl             # Restore floating point ctl register
-       lfpc    0(%r4)
-       larl    %r4,.Lprefix            # Restore prefix register
-       spx     0(%r4)
-       larl    %r4,.Lcontinue_psw      # Restore PSW flags
-       lpswe   0(%r4)
-.Lcontinue:
-       BR_EX   %r14
-.align 16
-.Lrestart_psw:
-       .long   0x00080000,0x80000000 + .Lrestart_part2
-
-       .section .data..nosave,"aw",@progbits
-.align 8
-.Lcontinue_psw:
-       .quad   0,.Lcontinue
-       .previous
-
-       .section .bss
-.align 8
-.Lctlreg0:
-       .quad   0
-.Lctlregs:
-       .rept   16
-       .quad   0
-       .endr
-.Lfpctl:
-       .long   0
-.Lprefix:
-       .long   0
-.Lprefix_zero:
-       .long   0
-       .previous
index 7edaa733a77fdd9286382f745bdf103253fba26d..e9dac9a24d3fc06932397c0a2b0d21747748ea73 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/debugfs.h>
 #include <asm/diag.h>
 #include <asm/trace/diag.h>
+#include <asm/sections.h>
 
 struct diag_stat {
        unsigned int counter[NR_DIAG_STAT];
@@ -49,6 +50,9 @@ static const struct diag_desc diag_map[NR_DIAG_STAT] = {
        [DIAG_STAT_X500] = { .code = 0x500, .name = "Virtio Service" },
 };
 
+struct diag_ops __bootdata_preserved(diag_dma_ops);
+struct diag210 *__bootdata_preserved(__diag210_tmp_dma);
+
 static int show_diag_stat(struct seq_file *m, void *v)
 {
        struct diag_stat *stat;
@@ -139,30 +143,10 @@ EXPORT_SYMBOL(diag_stat_inc_norecursion);
 /*
  * Diagnose 14: Input spool file manipulation
  */
-static inline int __diag14(unsigned long rx, unsigned long ry1,
-                          unsigned long subcode)
-{
-       register unsigned long _ry1 asm("2") = ry1;
-       register unsigned long _ry2 asm("3") = subcode;
-       int rc = 0;
-
-       asm volatile(
-               "   sam31\n"
-               "   diag    %2,2,0x14\n"
-               "   sam64\n"
-               "   ipm     %0\n"
-               "   srl     %0,28\n"
-               : "=d" (rc), "+d" (_ry2)
-               : "d" (rx), "d" (_ry1)
-               : "cc");
-
-       return rc;
-}
-
 int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
 {
        diag_stat_inc(DIAG_STAT_X014);
-       return __diag14(rx, ry1, subcode);
+       return diag_dma_ops.diag14(rx, ry1, subcode);
 }
 EXPORT_SYMBOL(diag14);
 
@@ -195,30 +179,17 @@ EXPORT_SYMBOL(diag204);
  */
 int diag210(struct diag210 *addr)
 {
-       /*
-        * diag 210 needs its data below the 2GB border, so we
-        * use a static data area to be sure
-        */
-       static struct diag210 diag210_tmp;
        static DEFINE_SPINLOCK(diag210_lock);
        unsigned long flags;
        int ccode;
 
        spin_lock_irqsave(&diag210_lock, flags);
-       diag210_tmp = *addr;
+       *__diag210_tmp_dma = *addr;
 
        diag_stat_inc(DIAG_STAT_X210);
-       asm volatile(
-               "       lhi     %0,-1\n"
-               "       sam31\n"
-               "       diag    %1,0,0x210\n"
-               "0:     ipm     %0\n"
-               "       srl     %0,28\n"
-               "1:     sam64\n"
-               EX_TABLE(0b, 1b)
-               : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
-
-       *addr = diag210_tmp;
+       ccode = diag_dma_ops.diag210(__diag210_tmp_dma);
+
+       *addr = *__diag210_tmp_dma;
        spin_unlock_irqrestore(&diag210_lock, flags);
 
        return ccode;
@@ -243,27 +214,9 @@ EXPORT_SYMBOL(diag224);
 /*
  * Diagnose 26C: Access Certain System Information
  */
-static inline int __diag26c(void *req, void *resp, enum diag26c_sc subcode)
-{
-       register unsigned long _req asm("2") = (addr_t) req;
-       register unsigned long _resp asm("3") = (addr_t) resp;
-       register unsigned long _subcode asm("4") = subcode;
-       register unsigned long _rc asm("5") = -EOPNOTSUPP;
-
-       asm volatile(
-               "       sam31\n"
-               "       diag    %[rx],%[ry],0x26c\n"
-               "0:     sam64\n"
-               EX_TABLE(0b,0b)
-               : "+d" (_rc)
-               : [rx] "d" (_req), "d" (_resp), [ry] "d" (_subcode)
-               : "cc", "memory");
-       return _rc;
-}
-
 int diag26c(void *req, void *resp, enum diag26c_sc subcode)
 {
        diag_stat_inc(DIAG_STAT_X26C);
-       return __diag26c(req, resp, subcode);
+       return diag_dma_ops.diag26c(req, resp, subcode);
 }
 EXPORT_SYMBOL(diag26c);
index ab09ada0e930d48e2fe78f4e00d4427961b3c4a3..33f704c16bd333376df5609694188816c2fbff63 100644 (file)
@@ -139,7 +139,7 @@ static void early_pgm_check_handler(void)
        unsigned long addr;
 
        addr = S390_lowcore.program_old_psw.addr;
-       fixup = search_exception_tables(addr);
+       fixup = s390_search_extables(addr);
        if (!fixup)
                disabled_wait(0);
        /* Disable low address protection before storing into lowcore. */
index 56491e636eabc5da499de49f109ef4f0d3913f8e..5aea1a527443004f455f56637f017d023077ab19 100644 (file)
@@ -26,7 +26,6 @@ ENTRY(startup_continue)
 0:     larl    %r1,tod_clock_base
        mvc     0(16,%r1),__LC_BOOT_CLOCK
        larl    %r13,.LPG1              # get base
-       lctlg   %c0,%c15,.Lctl-.LPG1(%r13)      # load control registers
        larl    %r0,boot_vdso_data
        stg     %r0,__LC_VDSO_PER_CPU
 #
@@ -61,22 +60,6 @@ ENTRY(startup_continue)
 
        .align  16
 .LPG1:
-.Lctl: .quad   0x04040000              # cr0: AFP registers & secondary space
-       .quad   0                       # cr1: primary space segment table
-       .quad   .Lduct                  # cr2: dispatchable unit control table
-       .quad   0                       # cr3: instruction authorization
-       .quad   0xffff                  # cr4: instruction authorization
-       .quad   .Lduct                  # cr5: primary-aste origin
-       .quad   0                       # cr6:  I/O interrupts
-       .quad   0                       # cr7:  secondary space segment table
-       .quad   0                       # cr8:  access registers translation
-       .quad   0                       # cr9:  tracing off
-       .quad   0                       # cr10: tracing off
-       .quad   0                       # cr11: tracing off
-       .quad   0                       # cr12: tracing off
-       .quad   0                       # cr13: home space segment table
-       .quad   0xc0000000              # cr14: machine check handling off
-       .quad   .Llinkage_stack         # cr15: linkage stack operations
 .Lpcmsk:.quad  0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad 0x80000000 + 0x20000 - 8        # 2GB + 128K - 8
@@ -84,14 +67,5 @@ ENTRY(startup_continue)
 .Lparmaddr:
        .quad   PARMAREA
        .align  64
-.Lduct: .long  0,.Laste,.Laste,0,.Lduald,0,0,0
-       .long   0,0,0,0,0,0,0,0
-.Laste:        .quad   0,0xffffffffffffffff,0,0,0,0,0,0
-       .align  128
-.Lduald:.rept  8
-       .long   0x80000000,0,0,0        # invalid access-list entries
-       .endr
-.Llinkage_stack:
-       .long   0,0,0x89000000,0,0,0,0x8a000000,0
 .Ldw:  .quad   0x0002000180000000,0x0000000000000000
 .Laregs:.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
index e123c0df83f1c8c5345478bd5795675bbd4ea315..aa8fe768640e44aa34791bc9f6cd14bd991b9bf3 100644 (file)
@@ -1720,7 +1720,7 @@ void s390_reset_system(void)
 
        /* Disable lowcore protection */
        __ctl_clear_bit(0, 28);
-       diag308_reset();
+       diag_dma_ops.diag308_reset();
 }
 
 #ifdef CONFIG_KEXEC_FILE
index 263426dcf97ddff58a3391c4bf3dc36fe9afda50..6f1388391620afc84734e526c51ca8dc8319ee14 100644 (file)
@@ -573,7 +573,7 @@ static int kprobe_trap_handler(struct pt_regs *regs, int trapnr)
                 * In case the user-specified fault handler returned
                 * zero, try to fix up.
                 */
-               entry = search_exception_tables(regs->psw.addr);
+               entry = s390_search_extables(regs->psw.addr);
                if (entry) {
                        regs->psw.addr = extable_fixup(entry);
                        return 1;
index cb582649aba6b491a687c758a7460de90a23af3b..4b998d639c32ef888b855db4c3623e670b74d41e 100644 (file)
@@ -253,6 +253,8 @@ void arch_crash_save_vmcoreinfo(void)
        VMCOREINFO_SYMBOL(high_memory);
        VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
        mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
+       vmcoreinfo_append_str("SDMA=%lx\n", __sdma);
+       vmcoreinfo_append_str("EDMA=%lx\n", __edma);
 }
 
 void machine_shutdown(void)
index 94efb1eb34b6031bddb55683fd454fd227a19c2d..4ccaf5ed96ee9952ce7906856c645a000cb82f49 100644 (file)
@@ -101,6 +101,14 @@ unsigned long __bootdata(memory_end);
 unsigned long __bootdata(max_physmem_end);
 struct mem_detect_info __bootdata(mem_detect);
 
+struct exception_table_entry *__bootdata_preserved(__start_dma_ex_table);
+struct exception_table_entry *__bootdata_preserved(__stop_dma_ex_table);
+unsigned long __bootdata_preserved(__swsusp_reset_dma);
+unsigned long __bootdata_preserved(__stext_dma);
+unsigned long __bootdata_preserved(__etext_dma);
+unsigned long __bootdata_preserved(__sdma);
+unsigned long __bootdata_preserved(__edma);
+
 unsigned long VMALLOC_START;
 EXPORT_SYMBOL(VMALLOC_START);
 
@@ -832,6 +840,7 @@ static void __init reserve_kernel(void)
        memblock_reserve(0, HEAD_END);
        memblock_reserve((unsigned long)_stext, PFN_PHYS(start_pfn)
                         - (unsigned long)_stext);
+       memblock_reserve(__sdma, __edma - __sdma);
 }
 
 static void __init setup_memory(void)
index bd197baf1dc337f018af35eeb19635b1c95998b7..88634fb0cc50b7c90120f63877857c86832a8810 100644 (file)
@@ -689,7 +689,7 @@ void __init smp_save_dump_cpus(void)
                        smp_save_cpu_regs(sa, addr, is_boot_cpu, page);
        }
        memblock_free(page, PAGE_SIZE);
-       diag308_reset();
+       diag_dma_ops.diag308_reset();
        pcpu_set_smt(0);
 }
 #endif /* CONFIG_CRASH_DUMP */
index 993100c31d65541be4eacca268c623316bab49d4..f5219ce11cc5b5e6c741bffaaeec6a73df2cbe62 100644 (file)
@@ -154,20 +154,13 @@ ENTRY(swsusp_arch_resume)
        ptlb                            /* flush tlb */
 
        /* Reset System */
-       larl    %r1,restart_entry
-       larl    %r2,.Lrestart_diag308_psw
-       og      %r1,0(%r2)
-       stg     %r1,0(%r0)
        larl    %r1,.Lnew_pgm_check_psw
        epsw    %r2,%r3
        stm     %r2,%r3,0(%r1)
        mvc     __LC_PGM_NEW_PSW(16,%r0),0(%r1)
-       lghi    %r0,0
-       diag    %r0,%r0,0x308
-restart_entry:
-       lhi     %r1,1
-       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE
-       sam64
+       larl    %r1,__swsusp_reset_dma
+       lg      %r1,0(%r1)
+       BASR_EX %r14,%r1
 #ifdef CONFIG_SMP
        larl    %r1,smp_cpu_mt_shift
        icm     %r1,15,0(%r1)
@@ -275,8 +268,6 @@ restore_registers:
 .Lpanic_string:
        .asciz  "Resume not possible because suspend CPU is no longer available\n"
        .align  8
-.Lrestart_diag308_psw:
-       .long   0x00080000,0x80000000
 .Lrestart_suspend_psw:
        .quad   0x0000000180000000,restart_suspend
 .Lnew_pgm_check_psw:
index 8003b38c1688f00ba02656e3e7a37f75de9d59f4..82e81a9f711269177274a3beeee80ce6ba915da8 100644 (file)
@@ -49,7 +49,7 @@ void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
                report_user_fault(regs, si_signo, 0);
         } else {
                 const struct exception_table_entry *fixup;
-               fixup = search_exception_tables(regs->psw.addr);
+               fixup = s390_search_extables(regs->psw.addr);
                 if (fixup)
                        regs->psw.addr = extable_fixup(fixup);
                else {
@@ -263,5 +263,6 @@ NOKPROBE_SYMBOL(kernel_stack_overflow);
 
 void __init trap_init(void)
 {
+       sort_extable(__start_dma_ex_table, __stop_dma_ex_table);
        local_mcck_enable();
 }
index 11613362c4e75f9d3668a9618dfed7d7265d9d32..c220399ae196e07ab3d6cf5a2ef5a4931eaff025 100644 (file)
@@ -247,12 +247,24 @@ static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
                        current);
 }
 
+const struct exception_table_entry *s390_search_extables(unsigned long addr)
+{
+       const struct exception_table_entry *fixup;
+
+       fixup = search_extable(__start_dma_ex_table,
+                              __stop_dma_ex_table - __start_dma_ex_table,
+                              addr);
+       if (!fixup)
+               fixup = search_exception_tables(addr);
+       return fixup;
+}
+
 static noinline void do_no_context(struct pt_regs *regs)
 {
        const struct exception_table_entry *fixup;
 
        /* Are we prepared to handle this kernel fault?  */
-       fixup = search_exception_tables(regs->psw.addr);
+       fixup = s390_search_extables(regs->psw.addr);
        if (fixup) {
                regs->psw.addr = extable_fixup(fixup);
                return;
index 0472e27febdfaa620cf4cd5849690907486d1136..b403fa14847dce14c7150214fdceb624740d2592 100644 (file)
@@ -413,6 +413,8 @@ void __init vmem_map_init(void)
        __set_memory((unsigned long)_sinittext,
                     (unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT,
                     SET_MEMORY_RO | SET_MEMORY_X);
+       __set_memory(__stext_dma, (__etext_dma - __stext_dma) >> PAGE_SHIFT,
+                    SET_MEMORY_RO | SET_MEMORY_X);
        pr_info("Write protected kernel read-only data: %luk\n",
                (unsigned long)(__end_rodata - _stext) >> 10);
 }