aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/Kconfig.debug12
-rw-r--r--arch/s390/include/asm/chpid.h2
-rw-r--r--arch/s390/include/asm/css_chars.h3
-rw-r--r--arch/s390/include/asm/page.h14
-rw-r--r--arch/s390/include/asm/pgtable.h30
-rw-r--r--arch/s390/include/asm/setup.h14
-rw-r--r--arch/s390/include/uapi/asm/chsc.h10
-rw-r--r--arch/s390/kernel/early.c17
-rw-r--r--arch/s390/kernel/entry64.S2
-rw-r--r--arch/s390/kernel/head.S101
-rw-r--r--arch/s390/kernel/head31.S3
-rw-r--r--arch/s390/kernel/head64.S3
-rw-r--r--arch/s390/kernel/module.c11
-rw-r--r--arch/s390/kernel/setup.c51
-rw-r--r--arch/s390/mm/Makefile1
-rw-r--r--arch/s390/mm/dump_pagetables.c226
-rw-r--r--arch/s390/mm/pageattr.c40
-rw-r--r--arch/s390/mm/vmem.c45
-rw-r--r--drivers/s390/block/dcssblk.c52
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c1
20 files changed, 497 insertions, 141 deletions
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index d76cef3fef37..fc32a2df4974 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -31,6 +31,18 @@ config DEBUG_STRICT_USER_COPY_CHECKS
31 31
32 If unsure, or if you run an older (pre 4.4) gcc, say N. 32 If unsure, or if you run an older (pre 4.4) gcc, say N.
33 33
34config S390_PTDUMP
35 bool "Export kernel pagetable layout to userspace via debugfs"
36 depends on DEBUG_KERNEL
37 select DEBUG_FS
38 ---help---
39 Say Y here if you want to show the kernel pagetable layout in a
40 debugfs file. This information is only useful for kernel developers
41 who are working in architecture specific areas of the kernel.
42 It is probably not a good idea to enable this feature in a production
43 kernel.
44 If in doubt, say "N"
45
34config DEBUG_SET_MODULE_RONX 46config DEBUG_SET_MODULE_RONX
35 def_bool y 47 def_bool y
36 depends on MODULES 48 depends on MODULES
diff --git a/arch/s390/include/asm/chpid.h b/arch/s390/include/asm/chpid.h
index 64c76ddde3c1..38c405ef89ce 100644
--- a/arch/s390/include/asm/chpid.h
+++ b/arch/s390/include/asm/chpid.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright IBM Corp. 2007 2 * Copyright IBM Corp. 2007, 2012
3 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 3 * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
4 */ 4 */
5#ifndef _ASM_S390_CHPID_H 5#ifndef _ASM_S390_CHPID_H
diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h
index a06ebc2623fb..7e1c917bbba2 100644
--- a/arch/s390/include/asm/css_chars.h
+++ b/arch/s390/include/asm/css_chars.h
@@ -3,8 +3,6 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#ifdef __KERNEL__
7
8struct css_general_char { 6struct css_general_char {
9 u64 : 12; 7 u64 : 12;
10 u32 dynio : 1; /* bit 12 */ 8 u32 dynio : 1; /* bit 12 */
@@ -35,5 +33,4 @@ struct css_general_char {
35 33
36extern struct css_general_char css_general_characteristics; 34extern struct css_general_char css_general_characteristics;
37 35
38#endif /* __KERNEL__ */
39#endif 36#endif
diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h
index 27ab3c7c1e8b..6d5367060a56 100644
--- a/arch/s390/include/asm/page.h
+++ b/arch/s390/include/asm/page.h
@@ -30,12 +30,20 @@
30#include <asm/setup.h> 30#include <asm/setup.h>
31#ifndef __ASSEMBLY__ 31#ifndef __ASSEMBLY__
32 32
33static unsigned long pfmf(unsigned long function, unsigned long address)
34{
35 asm volatile(
36 " .insn rre,0xb9af0000,%[function],%[address]"
37 : [address] "+a" (address)
38 : [function] "d" (function)
39 : "memory");
40 return address;
41}
42
33static inline void clear_page(void *page) 43static inline void clear_page(void *page)
34{ 44{
35 if (MACHINE_HAS_PFMF) { 45 if (MACHINE_HAS_PFMF) {
36 asm volatile( 46 pfmf(0x10000, (unsigned long)page);
37 " .insn rre,0xb9af0000,%0,%1"
38 : : "d" (0x10000), "a" (page) : "memory", "cc");
39 } else { 47 } else {
40 register unsigned long reg1 asm ("1") = 0; 48 register unsigned long reg1 asm ("1") = 0;
41 register void *reg2 asm ("2") = page; 49 register void *reg2 asm ("2") = page;
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 979fe3dc0788..dd647c919a66 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -119,13 +119,12 @@ static inline int is_zero_pfn(unsigned long pfn)
119 119
120#ifndef __ASSEMBLY__ 120#ifndef __ASSEMBLY__
121/* 121/*
122 * The vmalloc area will always be on the topmost area of the kernel 122 * The vmalloc and module area will always be on the topmost area of the kernel
123 * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc, 123 * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules.
124 * which should be enough for any sane case. 124 * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where
125 * By putting vmalloc at the top, we maximise the gap between physical 125 * modules will reside. That makes sure that inter module branches always
126 * memory and vmalloc to catch misplaced memory accesses. As a side 126 * happen without trampolines and in addition the placement within a 2GB frame
127 * effect, this also makes sure that 64 bit module code cannot be used 127 * is branch prediction unit friendly.
128 * as system call address.
129 */ 128 */
130extern unsigned long VMALLOC_START; 129extern unsigned long VMALLOC_START;
131extern unsigned long VMALLOC_END; 130extern unsigned long VMALLOC_END;
@@ -133,6 +132,14 @@ extern struct page *vmemmap;
133 132
134#define VMEM_MAX_PHYS ((unsigned long) vmemmap) 133#define VMEM_MAX_PHYS ((unsigned long) vmemmap)
135 134
135#ifdef CONFIG_64BIT
136extern unsigned long MODULES_VADDR;
137extern unsigned long MODULES_END;
138#define MODULES_VADDR MODULES_VADDR
139#define MODULES_END MODULES_END
140#define MODULES_LEN (1UL << 31)
141#endif
142
136/* 143/*
137 * A 31 bit pagetable entry of S390 has following format: 144 * A 31 bit pagetable entry of S390 has following format:
138 * | PFRA | | OS | 145 * | PFRA | | OS |
@@ -507,6 +514,15 @@ static inline int pmd_none(pmd_t pmd)
507 return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; 514 return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
508} 515}
509 516
517static inline int pmd_large(pmd_t pmd)
518{
519#ifdef CONFIG_64BIT
520 return !!(pmd_val(pmd) & _SEGMENT_ENTRY_LARGE);
521#else
522 return 0;
523#endif
524}
525
510static inline int pmd_bad(pmd_t pmd) 526static inline int pmd_bad(pmd_t pmd)
511{ 527{
512 unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV; 528 unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV;
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 55ad134bcedf..f69f76b3447a 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -71,8 +71,8 @@ extern unsigned int s390_user_mode;
71#define MACHINE_FLAG_DIAG9C (1UL << 7) 71#define MACHINE_FLAG_DIAG9C (1UL << 7)
72#define MACHINE_FLAG_MVCOS (1UL << 8) 72#define MACHINE_FLAG_MVCOS (1UL << 8)
73#define MACHINE_FLAG_KVM (1UL << 9) 73#define MACHINE_FLAG_KVM (1UL << 9)
74#define MACHINE_FLAG_HPAGE (1UL << 10) 74#define MACHINE_FLAG_EDAT1 (1UL << 10)
75#define MACHINE_FLAG_PFMF (1UL << 11) 75#define MACHINE_FLAG_EDAT2 (1UL << 11)
76#define MACHINE_FLAG_LPAR (1UL << 12) 76#define MACHINE_FLAG_LPAR (1UL << 12)
77#define MACHINE_FLAG_SPP (1UL << 13) 77#define MACHINE_FLAG_SPP (1UL << 13)
78#define MACHINE_FLAG_TOPOLOGY (1UL << 14) 78#define MACHINE_FLAG_TOPOLOGY (1UL << 14)
@@ -84,6 +84,8 @@ extern unsigned int s390_user_mode;
84#define MACHINE_IS_LPAR (S390_lowcore.machine_flags & MACHINE_FLAG_LPAR) 84#define MACHINE_IS_LPAR (S390_lowcore.machine_flags & MACHINE_FLAG_LPAR)
85 85
86#define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C) 86#define MACHINE_HAS_DIAG9C (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
87#define MACHINE_HAS_PFMF MACHINE_HAS_EDAT1
88#define MACHINE_HAS_HPAGE MACHINE_HAS_EDAT1
87 89
88#ifndef CONFIG_64BIT 90#ifndef CONFIG_64BIT
89#define MACHINE_HAS_IEEE (S390_lowcore.machine_flags & MACHINE_FLAG_IEEE) 91#define MACHINE_HAS_IEEE (S390_lowcore.machine_flags & MACHINE_FLAG_IEEE)
@@ -92,8 +94,8 @@ extern unsigned int s390_user_mode;
92#define MACHINE_HAS_DIAG44 (1) 94#define MACHINE_HAS_DIAG44 (1)
93#define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG) 95#define MACHINE_HAS_MVPG (S390_lowcore.machine_flags & MACHINE_FLAG_MVPG)
94#define MACHINE_HAS_MVCOS (0) 96#define MACHINE_HAS_MVCOS (0)
95#define MACHINE_HAS_HPAGE (0) 97#define MACHINE_HAS_EDAT1 (0)
96#define MACHINE_HAS_PFMF (0) 98#define MACHINE_HAS_EDAT2 (0)
97#define MACHINE_HAS_SPP (0) 99#define MACHINE_HAS_SPP (0)
98#define MACHINE_HAS_TOPOLOGY (0) 100#define MACHINE_HAS_TOPOLOGY (0)
99#define MACHINE_HAS_TE (0) 101#define MACHINE_HAS_TE (0)
@@ -105,8 +107,8 @@ extern unsigned int s390_user_mode;
105#define MACHINE_HAS_DIAG44 (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44) 107#define MACHINE_HAS_DIAG44 (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
106#define MACHINE_HAS_MVPG (1) 108#define MACHINE_HAS_MVPG (1)
107#define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) 109#define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS)
108#define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) 110#define MACHINE_HAS_EDAT1 (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
109#define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) 111#define MACHINE_HAS_EDAT2 (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
110#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) 112#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
111#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) 113#define MACHINE_HAS_TOPOLOGY (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
112#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE) 114#define MACHINE_HAS_TE (S390_lowcore.machine_flags & MACHINE_FLAG_TE)
diff --git a/arch/s390/include/uapi/asm/chsc.h b/arch/s390/include/uapi/asm/chsc.h
index aea451fd182e..1c6a7f85a581 100644
--- a/arch/s390/include/uapi/asm/chsc.h
+++ b/arch/s390/include/uapi/asm/chsc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * ioctl interface for /dev/chsc 2 * ioctl interface for /dev/chsc
3 * 3 *
4 * Copyright IBM Corp. 2008 4 * Copyright IBM Corp. 2008, 2012
5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> 5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
6 */ 6 */
7 7
@@ -9,9 +9,12 @@
9#define _ASM_CHSC_H 9#define _ASM_CHSC_H
10 10
11#include <linux/types.h> 11#include <linux/types.h>
12#include <linux/ioctl.h>
12#include <asm/chpid.h> 13#include <asm/chpid.h>
13#include <asm/schid.h> 14#include <asm/schid.h>
14 15
16#define CHSC_SIZE 0x1000
17
15struct chsc_async_header { 18struct chsc_async_header {
16 __u16 length; 19 __u16 length;
17 __u16 code; 20 __u16 code;
@@ -23,15 +26,14 @@ struct chsc_async_header {
23 26
24struct chsc_async_area { 27struct chsc_async_area {
25 struct chsc_async_header header; 28 struct chsc_async_header header;
26 __u8 data[PAGE_SIZE - 16 /* size of chsc_async_header */]; 29 __u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)];
27} __attribute__ ((packed)); 30} __attribute__ ((packed));
28 31
29
30struct chsc_response_struct { 32struct chsc_response_struct {
31 __u16 length; 33 __u16 length;
32 __u16 code; 34 __u16 code;
33 __u32 parms; 35 __u32 parms;
34 __u8 data[PAGE_SIZE - 8]; 36 __u8 data[CHSC_SIZE - 2 * sizeof(__u16) - sizeof(__u32)];
35} __attribute__ ((packed)); 37} __attribute__ ((packed));
36 38
37struct chsc_chp_cd { 39struct chsc_chp_cd {
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 00d114445068..1f0eee9e7daa 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -283,14 +283,6 @@ static noinline __init void setup_facility_list(void)
283 ARRAY_SIZE(S390_lowcore.stfle_fac_list)); 283 ARRAY_SIZE(S390_lowcore.stfle_fac_list));
284} 284}
285 285
286static noinline __init void setup_hpage(void)
287{
288 if (!test_facility(2) || !test_facility(8))
289 return;
290 S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE;
291 __ctl_set_bit(0, 23);
292}
293
294static __init void detect_mvpg(void) 286static __init void detect_mvpg(void)
295{ 287{
296#ifndef CONFIG_64BIT 288#ifndef CONFIG_64BIT
@@ -378,10 +370,14 @@ static __init void detect_diag44(void)
378static __init void detect_machine_facilities(void) 370static __init void detect_machine_facilities(void)
379{ 371{
380#ifdef CONFIG_64BIT 372#ifdef CONFIG_64BIT
373 if (test_facility(8)) {
374 S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1;
375 __ctl_set_bit(0, 23);
376 }
377 if (test_facility(78))
378 S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2;
381 if (test_facility(3)) 379 if (test_facility(3))
382 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; 380 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
383 if (test_facility(8))
384 S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF;
385 if (test_facility(27)) 381 if (test_facility(27))
386 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; 382 S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
387 if (test_facility(40)) 383 if (test_facility(40))
@@ -484,7 +480,6 @@ void __init startup_init(void)
484 detect_diag9c(); 480 detect_diag9c();
485 detect_diag44(); 481 detect_diag44();
486 detect_machine_facilities(); 482 detect_machine_facilities();
487 setup_hpage();
488 setup_topology(); 483 setup_topology();
489 sclp_facilities_detect(); 484 sclp_facilities_detect();
490 detect_memory_layout(memory_chunk); 485 detect_memory_layout(memory_chunk);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 7549985402f7..8f211ad1c695 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -295,7 +295,7 @@ sysc_sigpending:
295 jno sysc_return 295 jno sysc_return
296 lmg %r2,%r7,__PT_R2(%r11) # load svc arguments 296 lmg %r2,%r7,__PT_R2(%r11) # load svc arguments
297 lghi %r8,0 # svc 0 returns -ENOSYS 297 lghi %r8,0 # svc 0 returns -ENOSYS
298 lh %r1,__PT_INT_CODE+2(%r11) # load new svc number 298 llgh %r1,__PT_INT_CODE+2(%r11) # load new svc number
299 cghi %r1,NR_syscalls 299 cghi %r1,NR_syscalls
300 jnl sysc_nr_ok # invalid svc number -> do svc 0 300 jnl sysc_nr_ok # invalid svc number -> do svc 0
301 slag %r8,%r1,2 301 slag %r8,%r1,2
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 805b6686b641..984726cbce16 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -52,7 +52,7 @@ __HEAD
52 .long 0x02000370,0x60000050 # the channel program the PSW 52 .long 0x02000370,0x60000050 # the channel program the PSW
53 .long 0x020003c0,0x60000050 # at location 0 is loaded. 53 .long 0x020003c0,0x60000050 # at location 0 is loaded.
54 .long 0x02000410,0x60000050 # Initial processing starts 54 .long 0x02000410,0x60000050 # Initial processing starts
55 .long 0x02000460,0x60000050 # at 0xf0 = iplstart. 55 .long 0x02000460,0x60000050 # at 0x200 = iplstart.
56 .long 0x020004b0,0x60000050 56 .long 0x020004b0,0x60000050
57 .long 0x02000500,0x60000050 57 .long 0x02000500,0x60000050
58 .long 0x02000550,0x60000050 58 .long 0x02000550,0x60000050
@@ -62,11 +62,54 @@ __HEAD
62 .long 0x02000690,0x60000050 62 .long 0x02000690,0x60000050
63 .long 0x020006e0,0x20000050 63 .long 0x020006e0,0x20000050
64 64
65 .org 0xf0 65 .org 0x200
66#
67# subroutine to set architecture mode
68#
69.Lsetmode:
70#ifdef CONFIG_64BIT
71 mvi __LC_AR_MODE_ID,1 # set esame flag
72 slr %r0,%r0 # set cpuid to zero
73 lhi %r1,2 # mode 2 = esame (dump)
74 sigp %r1,%r0,0x12 # switch to esame mode
75 bras %r13,0f
76 .fill 16,4,0x0
770: lmh %r0,%r15,0(%r13) # clear high-order half of gprs
78 sam31 # switch to 31 bit addressing mode
79#else
80 mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
81#endif
82 br %r14
83
84#
85# subroutine to wait for end I/O
86#
87.Lirqwait:
88#ifdef CONFIG_64BIT
89 mvc 0x1f0(16),.Lnewpsw # set up IO interrupt psw
90 lpsw .Lwaitpsw
91.Lioint:
92 br %r14
93 .align 8
94.Lnewpsw:
95 .quad 0x0000000080000000,.Lioint
96#else
97 mvc 0x78(8),.Lnewpsw # set up IO interrupt psw
98 lpsw .Lwaitpsw
99.Lioint:
100 br %r14
101 .align 8
102.Lnewpsw:
103 .long 0x00080000,0x80000000+.Lioint
104#endif
105.Lwaitpsw:
106 .long 0x020a0000,0x80000000+.Lioint
107
66# 108#
67# subroutine for loading cards from the reader 109# subroutine for loading cards from the reader
68# 110#
69.Lloader: 111.Lloader:
112 la %r4,0(%r14)
70 la %r3,.Lorb # r2 = address of orb into r2 113 la %r3,.Lorb # r2 = address of orb into r2
71 la %r5,.Lirb # r4 = address of irb 114 la %r5,.Lirb # r4 = address of irb
72 la %r6,.Lccws 115 la %r6,.Lccws
@@ -83,9 +126,7 @@ __HEAD
83 ssch 0(%r3) # load chunk of 1600 bytes 126 ssch 0(%r3) # load chunk of 1600 bytes
84 bnz .Llderr 127 bnz .Llderr
85.Lwait4irq: 128.Lwait4irq:
86 mvc 0x78(8),.Lnewpsw # set up IO interrupt psw 129 bas %r14,.Lirqwait
87 lpsw .Lwaitpsw
88.Lioint:
89 c %r1,0xb8 # compare subchannel number 130 c %r1,0xb8 # compare subchannel number
90 bne .Lwait4irq 131 bne .Lwait4irq
91 tsch 0(%r5) 132 tsch 0(%r5)
@@ -104,7 +145,7 @@ __HEAD
104 sr %r0,%r3 # #ccws*80-residual=#bytes read 145 sr %r0,%r3 # #ccws*80-residual=#bytes read
105 ar %r2,%r0 146 ar %r2,%r0
106 147
107 br %r14 # r2 contains the total size 148 br %r4 # r2 contains the total size
108 149
109.Lcont: 150.Lcont:
110 ahi %r2,0x640 # add 0x640 to total size 151 ahi %r2,0x640 # add 0x640 to total size
@@ -128,10 +169,6 @@ __HEAD
128.Lloadp:.long 0,0 169.Lloadp:.long 0,0
129 .align 8 170 .align 8
130.Lcrash:.long 0x000a0000,0x00000000 171.Lcrash:.long 0x000a0000,0x00000000
131.Lnewpsw:
132 .long 0x00080000,0x80000000+.Lioint
133.Lwaitpsw:
134 .long 0x020a0000,0x80000000+.Lioint
135 172
136 .align 8 173 .align 8
137.Lccws: .rept 19 174.Lccws: .rept 19
@@ -140,6 +177,7 @@ __HEAD
140 .long 0x02200050,0x00000000 177 .long 0x02200050,0x00000000
141 178
142iplstart: 179iplstart:
180 bas %r14,.Lsetmode # Immediately switch to 64 bit mode
143 lh %r1,0xb8 # test if subchannel number 181 lh %r1,0xb8 # test if subchannel number
144 bct %r1,.Lnoload # is valid 182 bct %r1,.Lnoload # is valid
145 l %r1,0xb8 # load ipl subchannel number 183 l %r1,0xb8 # load ipl subchannel number
@@ -209,8 +247,8 @@ iplstart:
209# 247#
210# reset files in VM reader 248# reset files in VM reader
211# 249#
212 stidp __LC_SAVE_AREA_SYNC # store cpuid 250 stidp .Lcpuid # store cpuid
213 tm __LC_SAVE_AREA_SYNC,0xff# running VM ? 251 tm .Lcpuid,0xff # running VM ?
214 bno .Lnoreset 252 bno .Lnoreset
215 la %r2,.Lreset 253 la %r2,.Lreset
216 lhi %r3,26 254 lhi %r3,26
@@ -222,23 +260,14 @@ iplstart:
222 tm 31(%r5),0xff # bits is set in the schib 260 tm 31(%r5),0xff # bits is set in the schib
223 bz .Lnoreset 261 bz .Lnoreset
224.Lwaitforirq: 262.Lwaitforirq:
225 mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw 263 bas %r14,.Lirqwait # wait for IO interrupt
226.Lwaitrdrirq:
227 lpsw .Lrdrwaitpsw
228.Lrdrint:
229 c %r1,0xb8 # compare subchannel number 264 c %r1,0xb8 # compare subchannel number
230 bne .Lwaitrdrirq 265 bne .Lwaitforirq
231 la %r5,.Lirb 266 la %r5,.Lirb
232 tsch 0(%r5) 267 tsch 0(%r5)
233.Lnoreset: 268.Lnoreset:
234 b .Lnoload 269 b .Lnoload
235 270
236 .align 8
237.Lrdrnewpsw:
238 .long 0x00080000,0x80000000+.Lrdrint
239.Lrdrwaitpsw:
240 .long 0x020a0000,0x80000000+.Lrdrint
241
242# 271#
243# everything loaded, go for it 272# everything loaded, go for it
244# 273#
@@ -254,6 +283,8 @@ iplstart:
254 .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold" 283 .byte 0xc8,0xd6,0xd3,0xc4 # "change rdr all keep nohold"
255.L_eof: .long 0xc5d6c600 /* C'EOF' */ 284.L_eof: .long 0xc5d6c600 /* C'EOF' */
256.L_hdr: .long 0xc8c4d900 /* C'HDR' */ 285.L_hdr: .long 0xc8c4d900 /* C'HDR' */
286 .align 8
287.Lcpuid:.fill 8,1,0
257 288
258# 289#
259# SALIPL loader support. Based on a patch by Rob van der Heij. 290# SALIPL loader support. Based on a patch by Rob van der Heij.
@@ -263,6 +294,7 @@ iplstart:
263 .org 0x800 294 .org 0x800
264ENTRY(start) 295ENTRY(start)
265 stm %r0,%r15,0x07b0 # store registers 296 stm %r0,%r15,0x07b0 # store registers
297 bas %r14,.Lsetmode # Immediately switch to 64 bit mode
266 basr %r12,%r0 298 basr %r12,%r0
267.base: 299.base:
268 l %r11,.parm 300 l %r11,.parm
@@ -343,6 +375,18 @@ ENTRY(startup)
343ENTRY(startup_kdump) 375ENTRY(startup_kdump)
344 j .Lep_startup_kdump 376 j .Lep_startup_kdump
345.Lep_startup_normal: 377.Lep_startup_normal:
378#ifdef CONFIG_64BIT
379 mvi __LC_AR_MODE_ID,1 # set esame flag
380 slr %r0,%r0 # set cpuid to zero
381 lhi %r1,2 # mode 2 = esame (dump)
382 sigp %r1,%r0,0x12 # switch to esame mode
383 bras %r13,0f
384 .fill 16,4,0x0
3850: lmh %r0,%r15,0(%r13) # clear high-order half of gprs
386 sam31 # switch to 31 bit addressing mode
387#else
388 mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0)
389#endif
346 basr %r13,0 # get base 390 basr %r13,0 # get base
347.LPG0: 391.LPG0:
348 xc 0x200(256),0x200 # partially clear lowcore 392 xc 0x200(256),0x200 # partially clear lowcore
@@ -410,22 +454,17 @@ ENTRY(startup_kdump)
410#endif 454#endif
411 455
412#ifdef CONFIG_64BIT 456#ifdef CONFIG_64BIT
413 mvi __LC_AR_MODE_ID,1 # set esame flag 457 /* Continue with 64bit startup code in head64.S */
414 slr %r0,%r0 # set cpuid to zero
415 lhi %r1,2 # mode 2 = esame (dump)
416 sigp %r1,%r0,0x12 # switch to esame mode
417 sam64 # switch to 64 bit mode 458 sam64 # switch to 64 bit mode
418 larl %r13,4f
419 lmh %r0,%r15,0(%r13) # clear high-order half
420 jg startup_continue 459 jg startup_continue
4214: .fill 16,4,0x0
422#else 460#else
423 mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) 461 /* Continue with 31bit startup code in head31.S */
424 l %r13,4f-.LPG0(%r13) 462 l %r13,4f-.LPG0(%r13)
425 b 0(%r13) 463 b 0(%r13)
426 .align 8 464 .align 8
4274: .long startup_continue 4654: .long startup_continue
428#endif 466#endif
467
429 .align 8 468 .align 8
4305: .long 0x7fffffff,0xffffffff 4695: .long 0x7fffffff,0xffffffff
431 470
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S
index a1372ae24ae1..9a99856df1c9 100644
--- a/arch/s390/kernel/head31.S
+++ b/arch/s390/kernel/head31.S
@@ -78,10 +78,7 @@ ENTRY(startup_continue)
78 78
79ENTRY(_ehead) 79ENTRY(_ehead)
80 80
81#ifdef CONFIG_SHARED_KERNEL
82 .org 0x100000 - 0x11000 # head.o ends at 0x11000 81 .org 0x100000 - 0x11000 # head.o ends at 0x11000
83#endif
84
85# 82#
86# startup-code, running in absolute addressing mode 83# startup-code, running in absolute addressing mode
87# 84#
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index c108af28bbe8..b9e25ae2579c 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -76,10 +76,7 @@ ENTRY(startup_continue)
76 76
77ENTRY(_ehead) 77ENTRY(_ehead)
78 78
79#ifdef CONFIG_SHARED_KERNEL
80 .org 0x100000 - 0x11000 # head.o ends at 0x11000 79 .org 0x100000 - 0x11000 # head.o ends at 0x11000
81#endif
82
83# 80#
84# startup-code, running in absolute addressing mode 81# startup-code, running in absolute addressing mode
85# 82#
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 46412b1d7e1e..4610deafd953 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -44,6 +44,17 @@
44#define PLT_ENTRY_SIZE 20 44#define PLT_ENTRY_SIZE 20
45#endif /* CONFIG_64BIT */ 45#endif /* CONFIG_64BIT */
46 46
47#ifdef CONFIG_64BIT
48void *module_alloc(unsigned long size)
49{
50 if (PAGE_ALIGN(size) > MODULES_LEN)
51 return NULL;
52 return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
53 GFP_KERNEL, PAGE_KERNEL, -1,
54 __builtin_return_address(0));
55}
56#endif
57
47/* Free memory returned from module_alloc */ 58/* Free memory returned from module_alloc */
48void module_free(struct module *mod, void *module_region) 59void module_free(struct module *mod, void *module_region)
49{ 60{
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index afa9fdba200e..b1f2be9aaaad 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -105,6 +105,11 @@ EXPORT_SYMBOL(VMALLOC_END);
105struct page *vmemmap; 105struct page *vmemmap;
106EXPORT_SYMBOL(vmemmap); 106EXPORT_SYMBOL(vmemmap);
107 107
108#ifdef CONFIG_64BIT
109unsigned long MODULES_VADDR;
110unsigned long MODULES_END;
111#endif
112
108/* An array with a pointer to the lowcore of every CPU. */ 113/* An array with a pointer to the lowcore of every CPU. */
109struct _lowcore *lowcore_ptr[NR_CPUS]; 114struct _lowcore *lowcore_ptr[NR_CPUS];
110EXPORT_SYMBOL(lowcore_ptr); 115EXPORT_SYMBOL(lowcore_ptr);
@@ -544,19 +549,23 @@ static void __init setup_memory_end(void)
544 549
545 /* Choose kernel address space layout: 2, 3, or 4 levels. */ 550 /* Choose kernel address space layout: 2, 3, or 4 levels. */
546#ifdef CONFIG_64BIT 551#ifdef CONFIG_64BIT
547 vmalloc_size = VMALLOC_END ?: 128UL << 30; 552 vmalloc_size = VMALLOC_END ?: (128UL << 30) - MODULES_LEN;
548 tmp = (memory_end ?: real_memory_size) / PAGE_SIZE; 553 tmp = (memory_end ?: real_memory_size) / PAGE_SIZE;
549 tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size; 554 tmp = tmp * (sizeof(struct page) + PAGE_SIZE) + vmalloc_size;
550 if (tmp <= (1UL << 42)) 555 if (tmp <= (1UL << 42))
551 vmax = 1UL << 42; /* 3-level kernel page table */ 556 vmax = 1UL << 42; /* 3-level kernel page table */
552 else 557 else
553 vmax = 1UL << 53; /* 4-level kernel page table */ 558 vmax = 1UL << 53; /* 4-level kernel page table */
559 /* module area is at the end of the kernel address space. */
560 MODULES_END = vmax;
561 MODULES_VADDR = MODULES_END - MODULES_LEN;
562 VMALLOC_END = MODULES_VADDR;
554#else 563#else
555 vmalloc_size = VMALLOC_END ?: 96UL << 20; 564 vmalloc_size = VMALLOC_END ?: 96UL << 20;
556 vmax = 1UL << 31; /* 2-level kernel page table */ 565 vmax = 1UL << 31; /* 2-level kernel page table */
557#endif
558 /* vmalloc area is at the end of the kernel address space. */ 566 /* vmalloc area is at the end of the kernel address space. */
559 VMALLOC_END = vmax; 567 VMALLOC_END = vmax;
568#endif
560 VMALLOC_START = vmax - vmalloc_size; 569 VMALLOC_START = vmax - vmalloc_size;
561 570
562 /* Split remaining virtual space between 1:1 mapping & vmemmap array */ 571 /* Split remaining virtual space between 1:1 mapping & vmemmap array */
@@ -768,6 +777,40 @@ static void __init reserve_crashkernel(void)
768#endif 777#endif
769} 778}
770 779
780static void __init init_storage_keys(unsigned long start, unsigned long end)
781{
782 unsigned long boundary, function, size;
783
784 while (start < end) {
785 if (MACHINE_HAS_EDAT2) {
786 /* set storage keys for a 2GB frame */
787 function = 0x22000 | PAGE_DEFAULT_KEY;
788 size = 1UL << 31;
789 boundary = (start + size) & ~(size - 1);
790 if (boundary <= end) {
791 do {
792 start = pfmf(function, start);
793 } while (start < boundary);
794 continue;
795 }
796 }
797 if (MACHINE_HAS_EDAT1) {
798 /* set storage keys for a 1MB frame */
799 function = 0x21000 | PAGE_DEFAULT_KEY;
800 size = 1UL << 20;
801 boundary = (start + size) & ~(size - 1);
802 if (boundary <= end) {
803 do {
804 start = pfmf(function, start);
805 } while (start < boundary);
806 continue;
807 }
808 }
809 page_set_storage_key(start, PAGE_DEFAULT_KEY, 0);
810 start += PAGE_SIZE;
811 }
812}
813
771static void __init setup_memory(void) 814static void __init setup_memory(void)
772{ 815{
773 unsigned long bootmap_size; 816 unsigned long bootmap_size;
@@ -846,9 +889,7 @@ static void __init setup_memory(void)
846 memblock_add_node(PFN_PHYS(start_chunk), 889 memblock_add_node(PFN_PHYS(start_chunk),
847 PFN_PHYS(end_chunk - start_chunk), 0); 890 PFN_PHYS(end_chunk - start_chunk), 0);
848 pfn = max(start_chunk, start_pfn); 891 pfn = max(start_chunk, start_pfn);
849 for (; pfn < end_chunk; pfn++) 892 init_storage_keys(PFN_PHYS(pfn), PFN_PHYS(end_chunk));
850 page_set_storage_key(PFN_PHYS(pfn),
851 PAGE_DEFAULT_KEY, 0);
852 } 893 }
853 894
854 psw_set_key(PAGE_DEFAULT_KEY); 895 psw_set_key(PAGE_DEFAULT_KEY);
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 0f5536b0c1a1..1bea6d1f55ab 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -7,3 +7,4 @@ obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
7obj-$(CONFIG_CMM) += cmm.o 7obj-$(CONFIG_CMM) += cmm.o
8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 8obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
9obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o 9obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
10obj-$(CONFIG_S390_PTDUMP) += dump_pagetables.o
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
new file mode 100644
index 000000000000..cbc6668acb85
--- /dev/null
+++ b/arch/s390/mm/dump_pagetables.c
@@ -0,0 +1,226 @@
1#include <linux/seq_file.h>
2#include <linux/debugfs.h>
3#include <linux/module.h>
4#include <linux/mm.h>
5#include <asm/sections.h>
6#include <asm/pgtable.h>
7
8static unsigned long max_addr;
9
10struct addr_marker {
11 unsigned long start_address;
12 const char *name;
13};
14
15enum address_markers_idx {
16 IDENTITY_NR = 0,
17 KERNEL_START_NR,
18 KERNEL_END_NR,
19 VMEMMAP_NR,
20 VMALLOC_NR,
21#ifdef CONFIG_64BIT
22 MODULES_NR,
23#endif
24};
25
26static struct addr_marker address_markers[] = {
27 [IDENTITY_NR] = {0, "Identity Mapping"},
28 [KERNEL_START_NR] = {(unsigned long)&_stext, "Kernel Image Start"},
29 [KERNEL_END_NR] = {(unsigned long)&_end, "Kernel Image End"},
30 [VMEMMAP_NR] = {0, "vmemmap Area"},
31 [VMALLOC_NR] = {0, "vmalloc Area"},
32#ifdef CONFIG_64BIT
33 [MODULES_NR] = {0, "Modules Area"},
34#endif
35 { -1, NULL }
36};
37
38struct pg_state {
39 int level;
40 unsigned int current_prot;
41 unsigned long start_address;
42 unsigned long current_address;
43 const struct addr_marker *marker;
44};
45
46static void print_prot(struct seq_file *m, unsigned int pr, int level)
47{
48 static const char * const level_name[] =
49 { "ASCE", "PGD", "PUD", "PMD", "PTE" };
50
51 seq_printf(m, "%s ", level_name[level]);
52 if (pr & _PAGE_INVALID)
53 seq_printf(m, "I\n");
54 else
55 seq_printf(m, "%s\n", pr & _PAGE_RO ? "RO" : "RW");
56}
57
58static void note_page(struct seq_file *m, struct pg_state *st,
59 unsigned int new_prot, int level)
60{
61 static const char units[] = "KMGTPE";
62 int width = sizeof(unsigned long) * 2;
63 const char *unit = units;
64 unsigned int prot, cur;
65 unsigned long delta;
66
67 /*
68 * If we have a "break" in the series, we need to flush the state
69 * that we have now. "break" is either changing perms, levels or
70 * address space marker.
71 */
72 prot = new_prot;
73 cur = st->current_prot;
74
75 if (!st->level) {
76 /* First entry */
77 st->current_prot = new_prot;
78 st->level = level;
79 st->marker = address_markers;
80 seq_printf(m, "---[ %s ]---\n", st->marker->name);
81 } else if (prot != cur || level != st->level ||
82 st->current_address >= st->marker[1].start_address) {
83 /* Print the actual finished series */
84 seq_printf(m, "0x%0*lx-0x%0*lx",
85 width, st->start_address,
86 width, st->current_address);
87 delta = (st->current_address - st->start_address) >> 10;
88 while (!(delta & 0x3ff) && unit[1]) {
89 delta >>= 10;
90 unit++;
91 }
92 seq_printf(m, "%9lu%c ", delta, *unit);
93 print_prot(m, st->current_prot, st->level);
94 if (st->current_address >= st->marker[1].start_address) {
95 st->marker++;
96 seq_printf(m, "---[ %s ]---\n", st->marker->name);
97 }
98 st->start_address = st->current_address;
99 st->current_prot = new_prot;
100 st->level = level;
101 }
102}
103
104/*
105 * The actual page table walker functions. In order to keep the implementation
106 * of print_prot() short, we only check and pass _PAGE_INVALID and _PAGE_RO
107 * flags to note_page() if a region, segment or page table entry is invalid or
108 * read-only.
109 * After all it's just a hint that the current level being walked contains an
110 * invalid or read-only entry.
111 */
112static void walk_pte_level(struct seq_file *m, struct pg_state *st,
113 pmd_t *pmd, unsigned long addr)
114{
115 unsigned int prot;
116 pte_t *pte;
117 int i;
118
119 for (i = 0; i < PTRS_PER_PTE && addr < max_addr; i++) {
120 st->current_address = addr;
121 pte = pte_offset_kernel(pmd, addr);
122 prot = pte_val(*pte) & (_PAGE_RO | _PAGE_INVALID);
123 note_page(m, st, prot, 4);
124 addr += PAGE_SIZE;
125 }
126}
127
128static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
129 pud_t *pud, unsigned long addr)
130{
131 unsigned int prot;
132 pmd_t *pmd;
133 int i;
134
135 for (i = 0; i < PTRS_PER_PMD && addr < max_addr; i++) {
136 st->current_address = addr;
137 pmd = pmd_offset(pud, addr);
138 if (!pmd_none(*pmd)) {
139 if (pmd_large(*pmd)) {
140 prot = pmd_val(*pmd) & _SEGMENT_ENTRY_RO;
141 note_page(m, st, prot, 3);
142 } else
143 walk_pte_level(m, st, pmd, addr);
144 } else
145 note_page(m, st, _PAGE_INVALID, 3);
146 addr += PMD_SIZE;
147 }
148}
149
150static void walk_pud_level(struct seq_file *m, struct pg_state *st,
151 pgd_t *pgd, unsigned long addr)
152{
153 pud_t *pud;
154 int i;
155
156 for (i = 0; i < PTRS_PER_PUD && addr < max_addr; i++) {
157 st->current_address = addr;
158 pud = pud_offset(pgd, addr);
159 if (!pud_none(*pud))
160 walk_pmd_level(m, st, pud, addr);
161 else
162 note_page(m, st, _PAGE_INVALID, 2);
163 addr += PUD_SIZE;
164 }
165}
166
167static void walk_pgd_level(struct seq_file *m)
168{
169 unsigned long addr = 0;
170 struct pg_state st;
171 pgd_t *pgd;
172 int i;
173
174 memset(&st, 0, sizeof(st));
175 for (i = 0; i < PTRS_PER_PGD && addr < max_addr; i++) {
176 st.current_address = addr;
177 pgd = pgd_offset_k(addr);
178 if (!pgd_none(*pgd))
179 walk_pud_level(m, &st, pgd, addr);
180 else
181 note_page(m, &st, _PAGE_INVALID, 1);
182 addr += PGDIR_SIZE;
183 }
184 /* Flush out the last page */
185 st.current_address = max_addr;
186 note_page(m, &st, 0, 0);
187}
188
189static int ptdump_show(struct seq_file *m, void *v)
190{
191 walk_pgd_level(m);
192 return 0;
193}
194
195static int ptdump_open(struct inode *inode, struct file *filp)
196{
197 return single_open(filp, ptdump_show, NULL);
198}
199
200static const struct file_operations ptdump_fops = {
201 .open = ptdump_open,
202 .read = seq_read,
203 .llseek = seq_lseek,
204 .release = single_release,
205};
206
207static int pt_dump_init(void)
208{
209 /*
210 * Figure out the maximum virtual address being accessible with the
211 * kernel ASCE. We need this to keep the page table walker functions
212 * from accessing non-existent entries.
213 */
214#ifdef CONFIG_32BIT
215 max_addr = 1UL << 31;
216#else
217 max_addr = (S390_lowcore.kernel_asce & _REGION_ENTRY_TYPE_MASK) >> 2;
218 max_addr = 1UL << (max_addr * 11 + 31);
219 address_markers[MODULES_NR].start_address = MODULES_VADDR;
220#endif
221 address_markers[VMEMMAP_NR].start_address = (unsigned long) vmemmap;
222 address_markers[VMALLOC_NR].start_address = VMALLOC_START;
223 debugfs_create_file("kernel_page_tables", 0400, NULL, NULL, &ptdump_fops);
224 return 0;
225}
226device_initcall(pt_dump_init);
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index b36537a5f43e..00be01c4b4f3 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -8,25 +8,38 @@
8#include <asm/cacheflush.h> 8#include <asm/cacheflush.h>
9#include <asm/pgtable.h> 9#include <asm/pgtable.h>
10 10
11static pte_t *walk_page_table(unsigned long addr)
12{
13 pgd_t *pgdp;
14 pud_t *pudp;
15 pmd_t *pmdp;
16 pte_t *ptep;
17
18 pgdp = pgd_offset_k(addr);
19 if (pgd_none(*pgdp))
20 return NULL;
21 pudp = pud_offset(pgdp, addr);
22 if (pud_none(*pudp))
23 return NULL;
24 pmdp = pmd_offset(pudp, addr);
25 if (pmd_none(*pmdp) || pmd_large(*pmdp))
26 return NULL;
27 ptep = pte_offset_kernel(pmdp, addr);
28 if (pte_none(*ptep))
29 return NULL;
30 return ptep;
31}
32
11static void change_page_attr(unsigned long addr, int numpages, 33static void change_page_attr(unsigned long addr, int numpages,
12 pte_t (*set) (pte_t)) 34 pte_t (*set) (pte_t))
13{ 35{
14 pte_t *ptep, pte; 36 pte_t *ptep, pte;
15 pmd_t *pmdp;
16 pud_t *pudp;
17 pgd_t *pgdp;
18 int i; 37 int i;
19 38
20 for (i = 0; i < numpages; i++) { 39 for (i = 0; i < numpages; i++) {
21 pgdp = pgd_offset(&init_mm, addr); 40 ptep = walk_page_table(addr);
22 pudp = pud_offset(pgdp, addr); 41 if (WARN_ON_ONCE(!ptep))
23 pmdp = pmd_offset(pudp, addr); 42 break;
24 if (pmd_huge(*pmdp)) {
25 WARN_ON_ONCE(1);
26 continue;
27 }
28 ptep = pte_offset_kernel(pmdp, addr);
29
30 pte = *ptep; 43 pte = *ptep;
31 pte = set(pte); 44 pte = set(pte);
32 __ptep_ipte(addr, ptep); 45 __ptep_ipte(addr, ptep);
@@ -40,21 +53,18 @@ int set_memory_ro(unsigned long addr, int numpages)
40 change_page_attr(addr, numpages, pte_wrprotect); 53 change_page_attr(addr, numpages, pte_wrprotect);
41 return 0; 54 return 0;
42} 55}
43EXPORT_SYMBOL_GPL(set_memory_ro);
44 56
45int set_memory_rw(unsigned long addr, int numpages) 57int set_memory_rw(unsigned long addr, int numpages)
46{ 58{
47 change_page_attr(addr, numpages, pte_mkwrite); 59 change_page_attr(addr, numpages, pte_mkwrite);
48 return 0; 60 return 0;
49} 61}
50EXPORT_SYMBOL_GPL(set_memory_rw);
51 62
52/* not possible */ 63/* not possible */
53int set_memory_nx(unsigned long addr, int numpages) 64int set_memory_nx(unsigned long addr, int numpages)
54{ 65{
55 return 0; 66 return 0;
56} 67}
57EXPORT_SYMBOL_GPL(set_memory_nx);
58 68
59int set_memory_x(unsigned long addr, int numpages) 69int set_memory_x(unsigned long addr, int numpages)
60{ 70{
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index c22abf900c9e..387c7c60b5b8 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -79,7 +79,8 @@ static pte_t __ref *vmem_pte_alloc(unsigned long address)
79 */ 79 */
80static int vmem_add_mem(unsigned long start, unsigned long size, int ro) 80static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
81{ 81{
82 unsigned long address; 82 unsigned long end = start + size;
83 unsigned long address = start;
83 pgd_t *pg_dir; 84 pgd_t *pg_dir;
84 pud_t *pu_dir; 85 pud_t *pu_dir;
85 pmd_t *pm_dir; 86 pmd_t *pm_dir;
@@ -87,7 +88,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
87 pte_t pte; 88 pte_t pte;
88 int ret = -ENOMEM; 89 int ret = -ENOMEM;
89 90
90 for (address = start; address < start + size; address += PAGE_SIZE) { 91 while (address < end) {
91 pg_dir = pgd_offset_k(address); 92 pg_dir = pgd_offset_k(address);
92 if (pgd_none(*pg_dir)) { 93 if (pgd_none(*pg_dir)) {
93 pu_dir = vmem_pud_alloc(); 94 pu_dir = vmem_pud_alloc();
@@ -108,12 +109,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
108 pm_dir = pmd_offset(pu_dir, address); 109 pm_dir = pmd_offset(pu_dir, address);
109 110
110#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC) 111#if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
111 if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && 112 if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
112 (address + HPAGE_SIZE <= start + size) && 113 !(address & ~PMD_MASK) && (address + PMD_SIZE <= end)) {
113 (address >= HPAGE_SIZE)) {
114 pte_val(pte) |= _SEGMENT_ENTRY_LARGE; 114 pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
115 pmd_val(*pm_dir) = pte_val(pte); 115 pmd_val(*pm_dir) = pte_val(pte);
116 address += HPAGE_SIZE - PAGE_SIZE; 116 address += PMD_SIZE;
117 continue; 117 continue;
118 } 118 }
119#endif 119#endif
@@ -126,10 +126,11 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
126 126
127 pt_dir = pte_offset_kernel(pm_dir, address); 127 pt_dir = pte_offset_kernel(pm_dir, address);
128 *pt_dir = pte; 128 *pt_dir = pte;
129 address += PAGE_SIZE;
129 } 130 }
130 ret = 0; 131 ret = 0;
131out: 132out:
132 flush_tlb_kernel_range(start, start + size); 133 flush_tlb_kernel_range(start, end);
133 return ret; 134 return ret;
134} 135}
135 136
@@ -139,7 +140,8 @@ out:
139 */ 140 */
140static void vmem_remove_range(unsigned long start, unsigned long size) 141static void vmem_remove_range(unsigned long start, unsigned long size)
141{ 142{
142 unsigned long address; 143 unsigned long end = start + size;
144 unsigned long address = start;
143 pgd_t *pg_dir; 145 pgd_t *pg_dir;
144 pud_t *pu_dir; 146 pud_t *pu_dir;
145 pmd_t *pm_dir; 147 pmd_t *pm_dir;
@@ -147,25 +149,32 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
147 pte_t pte; 149 pte_t pte;
148 150
149 pte_val(pte) = _PAGE_TYPE_EMPTY; 151 pte_val(pte) = _PAGE_TYPE_EMPTY;
150 for (address = start; address < start + size; address += PAGE_SIZE) { 152 while (address < end) {
151 pg_dir = pgd_offset_k(address); 153 pg_dir = pgd_offset_k(address);
154 if (pgd_none(*pg_dir)) {
155 address += PGDIR_SIZE;
156 continue;
157 }
152 pu_dir = pud_offset(pg_dir, address); 158 pu_dir = pud_offset(pg_dir, address);
153 if (pud_none(*pu_dir)) 159 if (pud_none(*pu_dir)) {
160 address += PUD_SIZE;
154 continue; 161 continue;
162 }
155 pm_dir = pmd_offset(pu_dir, address); 163 pm_dir = pmd_offset(pu_dir, address);
156 if (pmd_none(*pm_dir)) 164 if (pmd_none(*pm_dir)) {
165 address += PMD_SIZE;
157 continue; 166 continue;
158 167 }
159 if (pmd_huge(*pm_dir)) { 168 if (pmd_large(*pm_dir)) {
160 pmd_clear(pm_dir); 169 pmd_clear(pm_dir);
161 address += HPAGE_SIZE - PAGE_SIZE; 170 address += PMD_SIZE;
162 continue; 171 continue;
163 } 172 }
164
165 pt_dir = pte_offset_kernel(pm_dir, address); 173 pt_dir = pte_offset_kernel(pm_dir, address);
166 *pt_dir = pte; 174 *pt_dir = pte;
175 address += PAGE_SIZE;
167 } 176 }
168 flush_tlb_kernel_range(start, start + size); 177 flush_tlb_kernel_range(start, end);
169} 178}
170 179
171/* 180/*
@@ -330,8 +339,8 @@ void __init vmem_map_init(void)
330 unsigned long start, end; 339 unsigned long start, end;
331 int i; 340 int i;
332 341
333 ro_start = ((unsigned long)&_stext) & PAGE_MASK; 342 ro_start = PFN_ALIGN((unsigned long)&_stext);
334 ro_end = PFN_ALIGN((unsigned long)&_eshared); 343 ro_end = (unsigned long)&_eshared & PAGE_MASK;
335 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { 344 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
336 if (memory_chunk[i].type == CHUNK_CRASHK || 345 if (memory_chunk[i].type == CHUNK_CRASHK ||
337 memory_chunk[i].type == CHUNK_OLDMEM) 346 memory_chunk[i].type == CHUNK_OLDMEM)
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index a5a55da2a1ac..b6ad0de07930 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -69,23 +69,9 @@ static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *a
69 size_t count); 69 size_t count);
70static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf, 70static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
71 size_t count); 71 size_t count);
72static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
73 size_t count);
74static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
75static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
76 size_t count);
77static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
78static ssize_t dcssblk_seglist_show(struct device *dev,
79 struct device_attribute *attr,
80 char *buf);
81 72
82static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store); 73static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
83static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store); 74static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
84static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
85 dcssblk_save_store);
86static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
87 dcssblk_shared_store);
88static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
89 75
90static struct device *dcssblk_root_dev; 76static struct device *dcssblk_root_dev;
91 77
@@ -416,6 +402,8 @@ out:
416 up_write(&dcssblk_devices_sem); 402 up_write(&dcssblk_devices_sem);
417 return rc; 403 return rc;
418} 404}
405static DEVICE_ATTR(shared, S_IWUSR | S_IRUSR, dcssblk_shared_show,
406 dcssblk_shared_store);
419 407
420/* 408/*
421 * device attribute for save operation on current copy 409 * device attribute for save operation on current copy
@@ -476,6 +464,8 @@ dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char
476 up_write(&dcssblk_devices_sem); 464 up_write(&dcssblk_devices_sem);
477 return count; 465 return count;
478} 466}
467static DEVICE_ATTR(save, S_IWUSR | S_IRUSR, dcssblk_save_show,
468 dcssblk_save_store);
479 469
480/* 470/*
481 * device attribute for showing all segments in a device 471 * device attribute for showing all segments in a device
@@ -502,6 +492,21 @@ dcssblk_seglist_show(struct device *dev, struct device_attribute *attr,
502 up_read(&dcssblk_devices_sem); 492 up_read(&dcssblk_devices_sem);
503 return i; 493 return i;
504} 494}
495static DEVICE_ATTR(seglist, S_IRUSR, dcssblk_seglist_show, NULL);
496
497static struct attribute *dcssblk_dev_attrs[] = {
498 &dev_attr_shared.attr,
499 &dev_attr_save.attr,
500 &dev_attr_seglist.attr,
501 NULL,
502};
503static struct attribute_group dcssblk_dev_attr_group = {
504 .attrs = dcssblk_dev_attrs,
505};
506static const struct attribute_group *dcssblk_dev_attr_groups[] = {
507 &dcssblk_dev_attr_group,
508 NULL,
509};
505 510
506/* 511/*
507 * device attribute for adding devices 512 * device attribute for adding devices
@@ -590,6 +595,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
590 595
591 dev_set_name(&dev_info->dev, dev_info->segment_name); 596 dev_set_name(&dev_info->dev, dev_info->segment_name);
592 dev_info->dev.release = dcssblk_release_segment; 597 dev_info->dev.release = dcssblk_release_segment;
598 dev_info->dev.groups = dcssblk_dev_attr_groups;
593 INIT_LIST_HEAD(&dev_info->lh); 599 INIT_LIST_HEAD(&dev_info->lh);
594 dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK); 600 dev_info->gd = alloc_disk(DCSSBLK_MINORS_PER_DISK);
595 if (dev_info->gd == NULL) { 601 if (dev_info->gd == NULL) {
@@ -637,21 +643,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
637 * register the device 643 * register the device
638 */ 644 */
639 rc = device_register(&dev_info->dev); 645 rc = device_register(&dev_info->dev);
640 if (rc) {
641 module_put(THIS_MODULE);
642 goto dev_list_del;
643 }
644 get_device(&dev_info->dev);
645 rc = device_create_file(&dev_info->dev, &dev_attr_shared);
646 if (rc)
647 goto unregister_dev;
648 rc = device_create_file(&dev_info->dev, &dev_attr_save);
649 if (rc)
650 goto unregister_dev;
651 rc = device_create_file(&dev_info->dev, &dev_attr_seglist);
652 if (rc) 646 if (rc)
653 goto unregister_dev; 647 goto put_dev;
654 648
649 get_device(&dev_info->dev);
655 add_disk(dev_info->gd); 650 add_disk(dev_info->gd);
656 651
657 switch (dev_info->segment_type) { 652 switch (dev_info->segment_type) {
@@ -668,12 +663,11 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
668 rc = count; 663 rc = count;
669 goto out; 664 goto out;
670 665
671unregister_dev: 666put_dev:
672 list_del(&dev_info->lh); 667 list_del(&dev_info->lh);
673 blk_cleanup_queue(dev_info->dcssblk_queue); 668 blk_cleanup_queue(dev_info->dcssblk_queue);
674 dev_info->gd->queue = NULL; 669 dev_info->gd->queue = NULL;
675 put_disk(dev_info->gd); 670 put_disk(dev_info->gd);
676 device_unregister(&dev_info->dev);
677 list_for_each_entry(seg_info, &dev_info->seg_list, lh) { 671 list_for_each_entry(seg_info, &dev_info->seg_list, lh) {
678 segment_unload(seg_info->segment_name); 672 segment_unload(seg_info->segment_name);
679 } 673 }
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index c7275e303a0d..899ffa19f5ec 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -39,7 +39,6 @@
39#include "zcrypt_msgtype6.h" 39#include "zcrypt_msgtype6.h"
40#include "zcrypt_pcixcc.h" 40#include "zcrypt_pcixcc.h"
41#include "zcrypt_cca_key.h" 41#include "zcrypt_cca_key.h"
42#include "zcrypt_msgtype6.h"
43 42
44#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */ 43#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
45#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ 44#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */