aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/s390/CommonIO12
-rw-r--r--arch/s390/include/asm/pgtable.h66
-rw-r--r--arch/s390/include/asm/setup.h9
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/crash_dump.c6
-rw-r--r--arch/s390/kernel/early.c1
-rw-r--r--arch/s390/kernel/mem_detect.c145
-rw-r--r--arch/s390/kernel/setup.c65
-rw-r--r--arch/s390/lib/uaccess_pt.c3
-rw-r--r--arch/s390/mm/Makefile2
-rw-r--r--arch/s390/mm/init.c11
-rw-r--r--arch/s390/mm/mem_detect.c134
-rw-r--r--arch/s390/mm/pgtable.c121
-rw-r--r--arch/s390/mm/vmem.c8
-rw-r--r--drivers/s390/char/sclp_cmd.c20
-rw-r--r--drivers/s390/char/zcore.c34
-rw-r--r--drivers/s390/cio/blacklist.c28
-rw-r--r--drivers/s390/crypto/ap_bus.c17
18 files changed, 415 insertions, 269 deletions
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO
index d378cba66456..6e0f63f343b4 100644
--- a/Documentation/s390/CommonIO
+++ b/Documentation/s390/CommonIO
@@ -8,9 +8,9 @@ Command line parameters
8 8
9 Enable logging of debug information in case of ccw device timeouts. 9 Enable logging of debug information in case of ccw device timeouts.
10 10
11* cio_ignore = {all} | 11* cio_ignore = device[,device[,..]]
12 {<device> | <range of devices>} | 12
13 {!<device> | !<range of devices>} 13 device := {all | [!]ipldev | [!]condev | [!]<devno> | [!]<devno>-<devno>}
14 14
15 The given devices will be ignored by the common I/O-layer; no detection 15 The given devices will be ignored by the common I/O-layer; no detection
16 and device sensing will be done on any of those devices. The subchannel to 16 and device sensing will be done on any of those devices. The subchannel to
@@ -24,8 +24,10 @@ Command line parameters
24 device numbers (0xabcd or abcd, for 2.4 backward compatibility). If you 24 device numbers (0xabcd or abcd, for 2.4 backward compatibility). If you
25 give a device number 0xabcd, it will be interpreted as 0.0.abcd. 25 give a device number 0xabcd, it will be interpreted as 0.0.abcd.
26 26
27 You can use the 'all' keyword to ignore all devices. 27 You can use the 'all' keyword to ignore all devices. The 'ipldev' and 'condev'
28 The '!' operator will cause the I/O-layer to _not_ ignore a device. 28 keywords can be used to refer to the CCW based boot device and CCW console
29 device respectively (these are probably useful only when combined with the '!'
30 operator). The '!' operator will cause the I/O-layer to _not_ ignore a device.
29 The command line is parsed from left to right. 31 The command line is parsed from left to right.
30 32
31 For example, 33 For example,
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index b4622915bd15..4105b8221fdd 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -306,6 +306,7 @@ extern unsigned long MODULES_END;
306#define RCP_HC_BIT 0x00200000UL 306#define RCP_HC_BIT 0x00200000UL
307#define RCP_GR_BIT 0x00040000UL 307#define RCP_GR_BIT 0x00040000UL
308#define RCP_GC_BIT 0x00020000UL 308#define RCP_GC_BIT 0x00020000UL
309#define RCP_IN_BIT 0x00008000UL /* IPTE notify bit */
309 310
310/* User dirty / referenced bit for KVM's migration feature */ 311/* User dirty / referenced bit for KVM's migration feature */
311#define KVM_UR_BIT 0x00008000UL 312#define KVM_UR_BIT 0x00008000UL
@@ -373,6 +374,7 @@ extern unsigned long MODULES_END;
373#define RCP_HC_BIT 0x0020000000000000UL 374#define RCP_HC_BIT 0x0020000000000000UL
374#define RCP_GR_BIT 0x0004000000000000UL 375#define RCP_GR_BIT 0x0004000000000000UL
375#define RCP_GC_BIT 0x0002000000000000UL 376#define RCP_GC_BIT 0x0002000000000000UL
377#define RCP_IN_BIT 0x0000800000000000UL /* IPTE notify bit */
376 378
377/* User dirty / referenced bit for KVM's migration feature */ 379/* User dirty / referenced bit for KVM's migration feature */
378#define KVM_UR_BIT 0x0000800000000000UL 380#define KVM_UR_BIT 0x0000800000000000UL
@@ -746,30 +748,42 @@ struct gmap {
746 748
747/** 749/**
748 * struct gmap_rmap - reverse mapping for segment table entries 750 * struct gmap_rmap - reverse mapping for segment table entries
749 * @next: pointer to the next gmap_rmap structure in the list 751 * @gmap: pointer to the gmap_struct
750 * @entry: pointer to a segment table entry 752 * @entry: pointer to a segment table entry
753 * @vmaddr: virtual address in the guest address space
751 */ 754 */
752struct gmap_rmap { 755struct gmap_rmap {
753 struct list_head list; 756 struct list_head list;
757 struct gmap *gmap;
754 unsigned long *entry; 758 unsigned long *entry;
759 unsigned long vmaddr;
755}; 760};
756 761
757/** 762/**
758 * struct gmap_pgtable - gmap information attached to a page table 763 * struct gmap_pgtable - gmap information attached to a page table
759 * @vmaddr: address of the 1MB segment in the process virtual memory 764 * @vmaddr: address of the 1MB segment in the process virtual memory
760 * @mapper: list of segment table entries maping a page table 765 * @mapper: list of segment table entries mapping a page table
761 */ 766 */
762struct gmap_pgtable { 767struct gmap_pgtable {
763 unsigned long vmaddr; 768 unsigned long vmaddr;
764 struct list_head mapper; 769 struct list_head mapper;
765}; 770};
766 771
772/**
773 * struct gmap_notifier - notify function block for page invalidation
774 * @notifier_call: address of callback function
775 */
776struct gmap_notifier {
777 struct list_head list;
778 void (*notifier_call)(struct gmap *gmap, unsigned long address);
779};
780
767struct gmap *gmap_alloc(struct mm_struct *mm); 781struct gmap *gmap_alloc(struct mm_struct *mm);
768void gmap_free(struct gmap *gmap); 782void gmap_free(struct gmap *gmap);
769void gmap_enable(struct gmap *gmap); 783void gmap_enable(struct gmap *gmap);
770void gmap_disable(struct gmap *gmap); 784void gmap_disable(struct gmap *gmap);
771int gmap_map_segment(struct gmap *gmap, unsigned long from, 785int gmap_map_segment(struct gmap *gmap, unsigned long from,
772 unsigned long to, unsigned long length); 786 unsigned long to, unsigned long len);
773int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); 787int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
774unsigned long __gmap_translate(unsigned long address, struct gmap *); 788unsigned long __gmap_translate(unsigned long address, struct gmap *);
775unsigned long gmap_translate(unsigned long address, struct gmap *); 789unsigned long gmap_translate(unsigned long address, struct gmap *);
@@ -777,6 +791,24 @@ unsigned long __gmap_fault(unsigned long address, struct gmap *);
777unsigned long gmap_fault(unsigned long address, struct gmap *); 791unsigned long gmap_fault(unsigned long address, struct gmap *);
778void gmap_discard(unsigned long from, unsigned long to, struct gmap *); 792void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
779 793
794void gmap_register_ipte_notifier(struct gmap_notifier *);
795void gmap_unregister_ipte_notifier(struct gmap_notifier *);
796int gmap_ipte_notify(struct gmap *, unsigned long start, unsigned long len);
797void gmap_do_ipte_notify(struct mm_struct *, unsigned long addr, pte_t *);
798
799static inline pgste_t pgste_ipte_notify(struct mm_struct *mm,
800 unsigned long addr,
801 pte_t *ptep, pgste_t pgste)
802{
803#ifdef CONFIG_PGSTE
804 if (pgste_val(pgste) & RCP_IN_BIT) {
805 pgste_val(pgste) &= ~RCP_IN_BIT;
806 gmap_do_ipte_notify(mm, addr, ptep);
807 }
808#endif
809 return pgste;
810}
811
780/* 812/*
781 * Certain architectures need to do special things when PTEs 813 * Certain architectures need to do special things when PTEs
782 * within a page table are directly modified. Thus, the following 814 * within a page table are directly modified. Thus, the following
@@ -1032,8 +1064,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
1032 pte_t pte; 1064 pte_t pte;
1033 1065
1034 mm->context.flush_mm = 1; 1066 mm->context.flush_mm = 1;
1035 if (mm_has_pgste(mm)) 1067 if (mm_has_pgste(mm)) {
1036 pgste = pgste_get_lock(ptep); 1068 pgste = pgste_get_lock(ptep);
1069 pgste = pgste_ipte_notify(mm, address, ptep, pgste);
1070 }
1037 1071
1038 pte = *ptep; 1072 pte = *ptep;
1039 if (!mm_exclusive(mm)) 1073 if (!mm_exclusive(mm))
@@ -1052,11 +1086,14 @@ static inline pte_t ptep_modify_prot_start(struct mm_struct *mm,
1052 unsigned long address, 1086 unsigned long address,
1053 pte_t *ptep) 1087 pte_t *ptep)
1054{ 1088{
1089 pgste_t pgste;
1055 pte_t pte; 1090 pte_t pte;
1056 1091
1057 mm->context.flush_mm = 1; 1092 mm->context.flush_mm = 1;
1058 if (mm_has_pgste(mm)) 1093 if (mm_has_pgste(mm)) {
1059 pgste_get_lock(ptep); 1094 pgste = pgste_get_lock(ptep);
1095 pgste_ipte_notify(mm, address, ptep, pgste);
1096 }
1060 1097
1061 pte = *ptep; 1098 pte = *ptep;
1062 if (!mm_exclusive(mm)) 1099 if (!mm_exclusive(mm))
@@ -1082,8 +1119,10 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
1082 pgste_t pgste; 1119 pgste_t pgste;
1083 pte_t pte; 1120 pte_t pte;
1084 1121
1085 if (mm_has_pgste(vma->vm_mm)) 1122 if (mm_has_pgste(vma->vm_mm)) {
1086 pgste = pgste_get_lock(ptep); 1123 pgste = pgste_get_lock(ptep);
1124 pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
1125 }
1087 1126
1088 pte = *ptep; 1127 pte = *ptep;
1089 __ptep_ipte(address, ptep); 1128 __ptep_ipte(address, ptep);
@@ -1111,8 +1150,11 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
1111 pgste_t pgste; 1150 pgste_t pgste;
1112 pte_t pte; 1151 pte_t pte;
1113 1152
1114 if (mm_has_pgste(mm)) 1153 if (mm_has_pgste(mm)) {
1115 pgste = pgste_get_lock(ptep); 1154 pgste = pgste_get_lock(ptep);
1155 if (!full)
1156 pgste = pgste_ipte_notify(mm, address, ptep, pgste);
1157 }
1116 1158
1117 pte = *ptep; 1159 pte = *ptep;
1118 if (!full) 1160 if (!full)
@@ -1135,8 +1177,10 @@ static inline pte_t ptep_set_wrprotect(struct mm_struct *mm,
1135 1177
1136 if (pte_write(pte)) { 1178 if (pte_write(pte)) {
1137 mm->context.flush_mm = 1; 1179 mm->context.flush_mm = 1;
1138 if (mm_has_pgste(mm)) 1180 if (mm_has_pgste(mm)) {
1139 pgste = pgste_get_lock(ptep); 1181 pgste = pgste_get_lock(ptep);
1182 pgste = pgste_ipte_notify(mm, address, ptep, pgste);
1183 }
1140 1184
1141 if (!mm_exclusive(mm)) 1185 if (!mm_exclusive(mm))
1142 __ptep_ipte(address, ptep); 1186 __ptep_ipte(address, ptep);
@@ -1160,8 +1204,10 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
1160 1204
1161 if (pte_same(*ptep, entry)) 1205 if (pte_same(*ptep, entry))
1162 return 0; 1206 return 0;
1163 if (mm_has_pgste(vma->vm_mm)) 1207 if (mm_has_pgste(vma->vm_mm)) {
1164 pgste = pgste_get_lock(ptep); 1208 pgste = pgste_get_lock(ptep);
1209 pgste = pgste_ipte_notify(vma->vm_mm, address, ptep, pgste);
1210 }
1165 1211
1166 __ptep_ipte(address, ptep); 1212 __ptep_ipte(address, ptep);
1167 1213
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index ff67d730c00c..59880dbaf360 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -33,8 +33,6 @@
33 33
34#define CHUNK_READ_WRITE 0 34#define CHUNK_READ_WRITE 0
35#define CHUNK_READ_ONLY 1 35#define CHUNK_READ_ONLY 1
36#define CHUNK_OLDMEM 4
37#define CHUNK_CRASHK 5
38 36
39struct mem_chunk { 37struct mem_chunk {
40 unsigned long addr; 38 unsigned long addr;
@@ -43,13 +41,12 @@ struct mem_chunk {
43}; 41};
44 42
45extern struct mem_chunk memory_chunk[]; 43extern struct mem_chunk memory_chunk[];
46extern unsigned long real_memory_size;
47extern int memory_end_set; 44extern int memory_end_set;
48extern unsigned long memory_end; 45extern unsigned long memory_end;
49 46
50void detect_memory_layout(struct mem_chunk chunk[]); 47void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize);
51void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr, 48void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
52 unsigned long size, int type); 49 unsigned long size);
53 50
54#define PRIMARY_SPACE_MODE 0 51#define PRIMARY_SPACE_MODE 0
55#define ACCESS_REGISTER_MODE 1 52#define ACCESS_REGISTER_MODE 1
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 1386fcaf4ef6..4bb2a4656163 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -30,7 +30,7 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
30 30
31obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o 31obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
32obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o 32obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
33obj-y += debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o 33obj-y += debug.o irq.o ipl.o dis.o diag.o sclp.o vdso.o
34obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o 34obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
35obj-y += dumpstack.o 35obj-y += dumpstack.o
36 36
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index fb8d8781a011..f703d91bf720 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -88,8 +88,8 @@ static struct mem_chunk *get_memory_layout(void)
88 struct mem_chunk *chunk_array; 88 struct mem_chunk *chunk_array;
89 89
90 chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk)); 90 chunk_array = kzalloc_panic(MEMORY_CHUNKS * sizeof(struct mem_chunk));
91 detect_memory_layout(chunk_array); 91 detect_memory_layout(chunk_array, 0);
92 create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE, CHUNK_CRASHK); 92 create_mem_hole(chunk_array, OLDMEM_BASE, OLDMEM_SIZE);
93 return chunk_array; 93 return chunk_array;
94} 94}
95 95
@@ -344,7 +344,7 @@ static int loads_init(Elf64_Phdr *phdr, u64 loads_offset)
344 for (i = 0; i < MEMORY_CHUNKS; i++) { 344 for (i = 0; i < MEMORY_CHUNKS; i++) {
345 mem_chunk = &chunk_array[i]; 345 mem_chunk = &chunk_array[i];
346 if (mem_chunk->size == 0) 346 if (mem_chunk->size == 0)
347 break; 347 continue;
348 if (chunk_array[i].type != CHUNK_READ_WRITE && 348 if (chunk_array[i].type != CHUNK_READ_WRITE &&
349 chunk_array[i].type != CHUNK_READ_ONLY) 349 chunk_array[i].type != CHUNK_READ_ONLY)
350 continue; 350 continue;
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index bda011e2f8ae..dc8770d7173c 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -482,7 +482,6 @@ void __init startup_init(void)
482 detect_machine_facilities(); 482 detect_machine_facilities();
483 setup_topology(); 483 setup_topology();
484 sclp_facilities_detect(); 484 sclp_facilities_detect();
485 detect_memory_layout(memory_chunk);
486#ifdef CONFIG_DYNAMIC_FTRACE 485#ifdef CONFIG_DYNAMIC_FTRACE
487 S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; 486 S390_lowcore.ftrace_func = (unsigned long)ftrace_caller;
488#endif 487#endif
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
deleted file mode 100644
index 22d502e885ed..000000000000
--- a/arch/s390/kernel/mem_detect.c
+++ /dev/null
@@ -1,145 +0,0 @@
1/*
2 * Copyright IBM Corp. 2008, 2009
3 *
4 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <asm/ipl.h>
10#include <asm/sclp.h>
11#include <asm/setup.h>
12
13#define ADDR2G (1ULL << 31)
14
15static void find_memory_chunks(struct mem_chunk chunk[])
16{
17 unsigned long long memsize, rnmax, rzm;
18 unsigned long addr = 0, size;
19 int i = 0, type;
20
21 rzm = sclp_get_rzm();
22 rnmax = sclp_get_rnmax();
23 memsize = rzm * rnmax;
24 if (!rzm)
25 rzm = 1ULL << 17;
26 if (sizeof(long) == 4) {
27 rzm = min(ADDR2G, rzm);
28 memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
29 }
30 do {
31 size = 0;
32 type = tprot(addr);
33 do {
34 size += rzm;
35 if (memsize && addr + size >= memsize)
36 break;
37 } while (type == tprot(addr + size));
38 if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
39 chunk[i].addr = addr;
40 chunk[i].size = size;
41 chunk[i].type = type;
42 i++;
43 }
44 addr += size;
45 } while (addr < memsize && i < MEMORY_CHUNKS);
46}
47
48void detect_memory_layout(struct mem_chunk chunk[])
49{
50 unsigned long flags, cr0;
51
52 memset(chunk, 0, MEMORY_CHUNKS * sizeof(struct mem_chunk));
53 /* Disable IRQs, DAT and low address protection so tprot does the
54 * right thing and we don't get scheduled away with low address
55 * protection disabled.
56 */
57 flags = __arch_local_irq_stnsm(0xf8);
58 __ctl_store(cr0, 0, 0);
59 __ctl_clear_bit(0, 28);
60 find_memory_chunks(chunk);
61 __ctl_load(cr0, 0, 0);
62 arch_local_irq_restore(flags);
63}
64EXPORT_SYMBOL(detect_memory_layout);
65
66/*
67 * Move memory chunks array from index "from" to index "to"
68 */
69static void mem_chunk_move(struct mem_chunk chunk[], int to, int from)
70{
71 int cnt = MEMORY_CHUNKS - to;
72
73 memmove(&chunk[to], &chunk[from], cnt * sizeof(struct mem_chunk));
74}
75
76/*
77 * Initialize memory chunk
78 */
79static void mem_chunk_init(struct mem_chunk *chunk, unsigned long addr,
80 unsigned long size, int type)
81{
82 chunk->type = type;
83 chunk->addr = addr;
84 chunk->size = size;
85}
86
87/*
88 * Create memory hole with given address, size, and type
89 */
90void create_mem_hole(struct mem_chunk chunk[], unsigned long addr,
91 unsigned long size, int type)
92{
93 unsigned long lh_start, lh_end, lh_size, ch_start, ch_end, ch_size;
94 int i, ch_type;
95
96 for (i = 0; i < MEMORY_CHUNKS; i++) {
97 if (chunk[i].size == 0)
98 continue;
99
100 /* Define chunk properties */
101 ch_start = chunk[i].addr;
102 ch_size = chunk[i].size;
103 ch_end = ch_start + ch_size - 1;
104 ch_type = chunk[i].type;
105
106 /* Is memory chunk hit by memory hole? */
107 if (addr + size <= ch_start)
108 continue; /* No: memory hole in front of chunk */
109 if (addr > ch_end)
110 continue; /* No: memory hole after chunk */
111
112 /* Yes: Define local hole properties */
113 lh_start = max(addr, chunk[i].addr);
114 lh_end = min(addr + size - 1, ch_end);
115 lh_size = lh_end - lh_start + 1;
116
117 if (lh_start == ch_start && lh_end == ch_end) {
118 /* Hole covers complete memory chunk */
119 mem_chunk_init(&chunk[i], lh_start, lh_size, type);
120 } else if (lh_end == ch_end) {
121 /* Hole starts in memory chunk and convers chunk end */
122 mem_chunk_move(chunk, i + 1, i);
123 mem_chunk_init(&chunk[i], ch_start, ch_size - lh_size,
124 ch_type);
125 mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type);
126 i += 1;
127 } else if (lh_start == ch_start) {
128 /* Hole ends in memory chunk */
129 mem_chunk_move(chunk, i + 1, i);
130 mem_chunk_init(&chunk[i], lh_start, lh_size, type);
131 mem_chunk_init(&chunk[i + 1], lh_end + 1,
132 ch_size - lh_size, ch_type);
133 break;
134 } else {
135 /* Hole splits memory chunk */
136 mem_chunk_move(chunk, i + 2, i);
137 mem_chunk_init(&chunk[i], ch_start,
138 lh_start - ch_start, ch_type);
139 mem_chunk_init(&chunk[i + 1], lh_start, lh_size, type);
140 mem_chunk_init(&chunk[i + 2], lh_end + 1,
141 ch_end - lh_end, ch_type);
142 break;
143 }
144 }
145}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0f419c5765c8..0a49095104c9 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -226,25 +226,17 @@ static void __init conmode_default(void)
226} 226}
227 227
228#ifdef CONFIG_ZFCPDUMP 228#ifdef CONFIG_ZFCPDUMP
229static void __init setup_zfcpdump(unsigned int console_devno) 229static void __init setup_zfcpdump(void)
230{ 230{
231 static char str[41];
232
233 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 231 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
234 return; 232 return;
235 if (OLDMEM_BASE) 233 if (OLDMEM_BASE)
236 return; 234 return;
237 if (console_devno != -1) 235 strcat(boot_command_line, " cio_ignore=all,!ipldev,!condev");
238 sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
239 ipl_info.data.fcp.dev_id.devno, console_devno);
240 else
241 sprintf(str, " cio_ignore=all,!0.0.%04x",
242 ipl_info.data.fcp.dev_id.devno);
243 strcat(boot_command_line, str);
244 console_loglevel = 2; 236 console_loglevel = 2;
245} 237}
246#else 238#else
247static inline void setup_zfcpdump(unsigned int console_devno) {} 239static inline void setup_zfcpdump(void) {}
248#endif /* CONFIG_ZFCPDUMP */ 240#endif /* CONFIG_ZFCPDUMP */
249 241
250 /* 242 /*
@@ -471,14 +463,10 @@ static void __init setup_resources(void)
471 for (i = 0; i < MEMORY_CHUNKS; i++) { 463 for (i = 0; i < MEMORY_CHUNKS; i++) {
472 if (!memory_chunk[i].size) 464 if (!memory_chunk[i].size)
473 continue; 465 continue;
474 if (memory_chunk[i].type == CHUNK_OLDMEM ||
475 memory_chunk[i].type == CHUNK_CRASHK)
476 continue;
477 res = alloc_bootmem_low(sizeof(*res)); 466 res = alloc_bootmem_low(sizeof(*res));
478 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM; 467 res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
479 switch (memory_chunk[i].type) { 468 switch (memory_chunk[i].type) {
480 case CHUNK_READ_WRITE: 469 case CHUNK_READ_WRITE:
481 case CHUNK_CRASHK:
482 res->name = "System RAM"; 470 res->name = "System RAM";
483 break; 471 break;
484 case CHUNK_READ_ONLY: 472 case CHUNK_READ_ONLY:
@@ -510,12 +498,10 @@ static void __init setup_resources(void)
510 } 498 }
511} 499}
512 500
513unsigned long real_memory_size;
514EXPORT_SYMBOL_GPL(real_memory_size);
515
516static void __init setup_memory_end(void) 501static void __init setup_memory_end(void)
517{ 502{
518 unsigned long vmax, vmalloc_size, tmp; 503 unsigned long vmax, vmalloc_size, tmp;
504 unsigned long real_memory_size = 0;
519 int i; 505 int i;
520 506
521 507
@@ -525,7 +511,6 @@ static void __init setup_memory_end(void)
525 memory_end_set = 1; 511 memory_end_set = 1;
526 } 512 }
527#endif 513#endif
528 real_memory_size = 0;
529 memory_end &= PAGE_MASK; 514 memory_end &= PAGE_MASK;
530 515
531 /* 516 /*
@@ -538,6 +523,8 @@ static void __init setup_memory_end(void)
538 unsigned long align; 523 unsigned long align;
539 524
540 chunk = &memory_chunk[i]; 525 chunk = &memory_chunk[i];
526 if (!chunk->size)
527 continue;
541 align = 1UL << (MAX_ORDER + PAGE_SHIFT - 1); 528 align = 1UL << (MAX_ORDER + PAGE_SHIFT - 1);
542 start = (chunk->addr + align - 1) & ~(align - 1); 529 start = (chunk->addr + align - 1) & ~(align - 1);
543 end = (chunk->addr + chunk->size) & ~(align - 1); 530 end = (chunk->addr + chunk->size) & ~(align - 1);
@@ -588,6 +575,8 @@ static void __init setup_memory_end(void)
588 for (i = 0; i < MEMORY_CHUNKS; i++) { 575 for (i = 0; i < MEMORY_CHUNKS; i++) {
589 struct mem_chunk *chunk = &memory_chunk[i]; 576 struct mem_chunk *chunk = &memory_chunk[i];
590 577
578 if (!chunk->size)
579 continue;
591 if (chunk->addr >= memory_end) { 580 if (chunk->addr >= memory_end) {
592 memset(chunk, 0, sizeof(*chunk)); 581 memset(chunk, 0, sizeof(*chunk));
593 continue; 582 continue;
@@ -688,15 +677,6 @@ static int __init verify_crash_base(unsigned long crash_base,
688} 677}
689 678
690/* 679/*
691 * Reserve kdump memory by creating a memory hole in the mem_chunk array
692 */
693static void __init reserve_kdump_bootmem(unsigned long addr, unsigned long size,
694 int type)
695{
696 create_mem_hole(memory_chunk, addr, size, type);
697}
698
699/*
700 * When kdump is enabled, we have to ensure that no memory from 680 * When kdump is enabled, we have to ensure that no memory from
701 * the area [0 - crashkernel memory size] and 681 * the area [0 - crashkernel memory size] and
702 * [crashk_res.start - crashk_res.end] is set offline. 682 * [crashk_res.start - crashk_res.end] is set offline.
@@ -727,16 +707,22 @@ static struct notifier_block kdump_mem_nb = {
727static void reserve_oldmem(void) 707static void reserve_oldmem(void)
728{ 708{
729#ifdef CONFIG_CRASH_DUMP 709#ifdef CONFIG_CRASH_DUMP
710 unsigned long real_size = 0;
711 int i;
712
730 if (!OLDMEM_BASE) 713 if (!OLDMEM_BASE)
731 return; 714 return;
715 for (i = 0; i < MEMORY_CHUNKS; i++) {
716 struct mem_chunk *chunk = &memory_chunk[i];
732 717
733 reserve_kdump_bootmem(OLDMEM_BASE, OLDMEM_SIZE, CHUNK_OLDMEM); 718 real_size = max(real_size, chunk->addr + chunk->size);
734 reserve_kdump_bootmem(OLDMEM_SIZE, memory_end - OLDMEM_SIZE, 719 }
735 CHUNK_OLDMEM); 720 create_mem_hole(memory_chunk, OLDMEM_BASE, OLDMEM_SIZE);
736 if (OLDMEM_BASE + OLDMEM_SIZE == real_memory_size) 721 create_mem_hole(memory_chunk, OLDMEM_SIZE, real_size - OLDMEM_SIZE);
722 if (OLDMEM_BASE + OLDMEM_SIZE == real_size)
737 saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1; 723 saved_max_pfn = PFN_DOWN(OLDMEM_BASE) - 1;
738 else 724 else
739 saved_max_pfn = PFN_DOWN(real_memory_size) - 1; 725 saved_max_pfn = PFN_DOWN(real_size) - 1;
740#endif 726#endif
741} 727}
742 728
@@ -775,7 +761,7 @@ static void __init reserve_crashkernel(void)
775 crashk_res.start = crash_base; 761 crashk_res.start = crash_base;
776 crashk_res.end = crash_base + crash_size - 1; 762 crashk_res.end = crash_base + crash_size - 1;
777 insert_resource(&iomem_resource, &crashk_res); 763 insert_resource(&iomem_resource, &crashk_res);
778 reserve_kdump_bootmem(crash_base, crash_size, CHUNK_CRASHK); 764 create_mem_hole(memory_chunk, crash_base, crash_size);
779 pr_info("Reserving %lluMB of memory at %lluMB " 765 pr_info("Reserving %lluMB of memory at %lluMB "
780 "for crashkernel (System RAM: %luMB)\n", 766 "for crashkernel (System RAM: %luMB)\n",
781 crash_size >> 20, crash_base >> 20, memory_end >> 20); 767 crash_size >> 20, crash_base >> 20, memory_end >> 20);
@@ -847,11 +833,10 @@ static void __init setup_memory(void)
847 * Register RAM areas with the bootmem allocator. 833 * Register RAM areas with the bootmem allocator.
848 */ 834 */
849 835
850 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { 836 for (i = 0; i < MEMORY_CHUNKS; i++) {
851 unsigned long start_chunk, end_chunk, pfn; 837 unsigned long start_chunk, end_chunk, pfn;
852 838
853 if (memory_chunk[i].type != CHUNK_READ_WRITE && 839 if (!memory_chunk[i].size)
854 memory_chunk[i].type != CHUNK_CRASHK)
855 continue; 840 continue;
856 start_chunk = PFN_DOWN(memory_chunk[i].addr); 841 start_chunk = PFN_DOWN(memory_chunk[i].addr);
857 end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size); 842 end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size);
@@ -1067,12 +1052,12 @@ void __init setup_arch(char **cmdline_p)
1067 memcpy(&uaccess, &uaccess_std, sizeof(uaccess)); 1052 memcpy(&uaccess, &uaccess_std, sizeof(uaccess));
1068 1053
1069 parse_early_param(); 1054 parse_early_param();
1070 1055 detect_memory_layout(memory_chunk, memory_end);
1071 os_info_init(); 1056 os_info_init();
1072 setup_ipl(); 1057 setup_ipl();
1058 reserve_oldmem();
1073 setup_memory_end(); 1059 setup_memory_end();
1074 setup_addressing_mode(); 1060 setup_addressing_mode();
1075 reserve_oldmem();
1076 reserve_crashkernel(); 1061 reserve_crashkernel();
1077 setup_memory(); 1062 setup_memory();
1078 setup_resources(); 1063 setup_resources();
@@ -1097,5 +1082,5 @@ void __init setup_arch(char **cmdline_p)
1097 set_preferred_console(); 1082 set_preferred_console();
1098 1083
1099 /* Setup zfcpdump support */ 1084 /* Setup zfcpdump support */
1100 setup_zfcpdump(console_devno); 1085 setup_zfcpdump();
1101} 1086}
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 466fb3383960..50ea137a2d3c 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -89,16 +89,19 @@ static unsigned long follow_table(struct mm_struct *mm,
89 if (unlikely(*table & _REGION_ENTRY_INV)) 89 if (unlikely(*table & _REGION_ENTRY_INV))
90 return -0x39UL; 90 return -0x39UL;
91 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); 91 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
92 /* fallthrough */
92 case _ASCE_TYPE_REGION2: 93 case _ASCE_TYPE_REGION2:
93 table = table + ((address >> 42) & 0x7ff); 94 table = table + ((address >> 42) & 0x7ff);
94 if (unlikely(*table & _REGION_ENTRY_INV)) 95 if (unlikely(*table & _REGION_ENTRY_INV))
95 return -0x3aUL; 96 return -0x3aUL;
96 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); 97 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
98 /* fallthrough */
97 case _ASCE_TYPE_REGION3: 99 case _ASCE_TYPE_REGION3:
98 table = table + ((address >> 31) & 0x7ff); 100 table = table + ((address >> 31) & 0x7ff);
99 if (unlikely(*table & _REGION_ENTRY_INV)) 101 if (unlikely(*table & _REGION_ENTRY_INV))
100 return -0x3bUL; 102 return -0x3bUL;
101 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN); 103 table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
104 /* fallthrough */
102 case _ASCE_TYPE_SEGMENT: 105 case _ASCE_TYPE_SEGMENT:
103 table = table + ((address >> 20) & 0x7ff); 106 table = table + ((address >> 20) & 0x7ff);
104 if (unlikely(*table & _SEGMENT_ENTRY_INV)) 107 if (unlikely(*table & _SEGMENT_ENTRY_INV))
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 640bea12303c..839592ca265c 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o 5obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o
6obj-y += page-states.o gup.o extable.o pageattr.o 6obj-y += page-states.o gup.o extable.o pageattr.o mem_detect.o
7 7
8obj-$(CONFIG_CMM) += cmm.o 8obj-$(CONFIG_CMM) += cmm.o
9obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o 9obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 0b09b2342302..89ebae4008f2 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/pagemap.h> 22#include <linux/pagemap.h>
23#include <linux/bootmem.h> 23#include <linux/bootmem.h>
24#include <linux/memory.h>
24#include <linux/pfn.h> 25#include <linux/pfn.h>
25#include <linux/poison.h> 26#include <linux/poison.h>
26#include <linux/initrd.h> 27#include <linux/initrd.h>
@@ -36,6 +37,7 @@
36#include <asm/tlbflush.h> 37#include <asm/tlbflush.h>
37#include <asm/sections.h> 38#include <asm/sections.h>
38#include <asm/ctl_reg.h> 39#include <asm/ctl_reg.h>
40#include <asm/sclp.h>
39 41
40pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); 42pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
41 43
@@ -214,6 +216,15 @@ int arch_add_memory(int nid, u64 start, u64 size)
214 return rc; 216 return rc;
215} 217}
216 218
219unsigned long memory_block_size_bytes(void)
220{
221 /*
222 * Make sure the memory block size is always greater
223 * or equal than the memory increment size.
224 */
225 return max_t(unsigned long, MIN_MEMORY_BLOCK_SIZE, sclp_get_rzm());
226}
227
217#ifdef CONFIG_MEMORY_HOTREMOVE 228#ifdef CONFIG_MEMORY_HOTREMOVE
218int arch_remove_memory(u64 start, u64 size) 229int arch_remove_memory(u64 start, u64 size)
219{ 230{
diff --git a/arch/s390/mm/mem_detect.c b/arch/s390/mm/mem_detect.c
new file mode 100644
index 000000000000..3cbd3b8bf311
--- /dev/null
+++ b/arch/s390/mm/mem_detect.c
@@ -0,0 +1,134 @@
1/*
2 * Copyright IBM Corp. 2008, 2009
3 *
4 * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
5 */
6
7#include <linux/kernel.h>
8#include <linux/module.h>
9#include <asm/ipl.h>
10#include <asm/sclp.h>
11#include <asm/setup.h>
12
13#define ADDR2G (1ULL << 31)
14
15static void find_memory_chunks(struct mem_chunk chunk[], unsigned long maxsize)
16{
17 unsigned long long memsize, rnmax, rzm;
18 unsigned long addr = 0, size;
19 int i = 0, type;
20
21 rzm = sclp_get_rzm();
22 rnmax = sclp_get_rnmax();
23 memsize = rzm * rnmax;
24 if (!rzm)
25 rzm = 1ULL << 17;
26 if (sizeof(long) == 4) {
27 rzm = min(ADDR2G, rzm);
28 memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
29 }
30 if (maxsize)
31 memsize = memsize ? min((unsigned long)memsize, maxsize) : maxsize;
32 do {
33 size = 0;
34 type = tprot(addr);
35 do {
36 size += rzm;
37 if (memsize && addr + size >= memsize)
38 break;
39 } while (type == tprot(addr + size));
40 if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
41 if (memsize && (addr + size > memsize))
42 size = memsize - addr;
43 chunk[i].addr = addr;
44 chunk[i].size = size;
45 chunk[i].type = type;
46 i++;
47 }
48 addr += size;
49 } while (addr < memsize && i < MEMORY_CHUNKS);
50}
51
52/**
53 * detect_memory_layout - fill mem_chunk array with memory layout data
54 * @chunk: mem_chunk array to be filled
55 * @maxsize: maximum address where memory detection should stop
56 *
57 * Fills the passed in memory chunk array with the memory layout of the
58 * machine. The array must have a size of at least MEMORY_CHUNKS and will
59 * be fully initialized afterwards.
60 * If the maxsize paramater has a value > 0 memory detection will stop at
61 * that address. It is guaranteed that all chunks have an ending address
62 * that is smaller than maxsize.
63 * If maxsize is 0 all memory will be detected.
64 */
65void detect_memory_layout(struct mem_chunk chunk[], unsigned long maxsize)
66{
67 unsigned long flags, flags_dat, cr0;
68
69 memset(chunk, 0, MEMORY_CHUNKS * sizeof(struct mem_chunk));
70 /*
71 * Disable IRQs, DAT and low address protection so tprot does the
72 * right thing and we don't get scheduled away with low address
73 * protection disabled.
74 */
75 local_irq_save(flags);
76 flags_dat = __arch_local_irq_stnsm(0xfb);
77 /*
78 * In case DAT was enabled, make sure chunk doesn't reside in vmalloc
79 * space. We have disabled DAT and any access to vmalloc area will
80 * cause an exception.
81 * If DAT was disabled we are called from early ipl code.
82 */
83 if (test_bit(5, &flags_dat)) {
84 if (WARN_ON_ONCE(is_vmalloc_or_module_addr(chunk)))
85 goto out;
86 }
87 __ctl_store(cr0, 0, 0);
88 __ctl_clear_bit(0, 28);
89 find_memory_chunks(chunk, maxsize);
90 __ctl_load(cr0, 0, 0);
91out:
92 __arch_local_irq_ssm(flags_dat);
93 local_irq_restore(flags);
94}
95EXPORT_SYMBOL(detect_memory_layout);
96
97/*
98 * Create memory hole with given address and size.
99 */
100void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
101 unsigned long size)
102{
103 int i;
104
105 for (i = 0; i < MEMORY_CHUNKS; i++) {
106 struct mem_chunk *chunk = &mem_chunk[i];
107
108 if (chunk->size == 0)
109 continue;
110 if (addr > chunk->addr + chunk->size)
111 continue;
112 if (addr + size <= chunk->addr)
113 continue;
114 /* Split */
115 if ((addr > chunk->addr) &&
116 (addr + size < chunk->addr + chunk->size)) {
117 struct mem_chunk *new = chunk + 1;
118
119 memmove(new, chunk, (MEMORY_CHUNKS-i-1) * sizeof(*new));
120 new->addr = addr + size;
121 new->size = chunk->addr + chunk->size - new->addr;
122 chunk->size = addr - chunk->addr;
123 continue;
124 } else if ((addr <= chunk->addr) &&
125 (addr + size >= chunk->addr + chunk->size)) {
126 memset(chunk, 0 , sizeof(*chunk));
127 } else if (addr + size < chunk->addr + chunk->size) {
128 chunk->size = chunk->addr + chunk->size - addr - size;
129 chunk->addr = addr + size;
130 } else if (addr > chunk->addr) {
131 chunk->size = addr - chunk->addr;
132 }
133 }
134}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index bd954e96f51c..7805ddca833d 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -454,9 +454,8 @@ unsigned long gmap_translate(unsigned long address, struct gmap *gmap)
454} 454}
455EXPORT_SYMBOL_GPL(gmap_translate); 455EXPORT_SYMBOL_GPL(gmap_translate);
456 456
457static int gmap_connect_pgtable(unsigned long segment, 457static int gmap_connect_pgtable(unsigned long address, unsigned long segment,
458 unsigned long *segment_ptr, 458 unsigned long *segment_ptr, struct gmap *gmap)
459 struct gmap *gmap)
460{ 459{
461 unsigned long vmaddr; 460 unsigned long vmaddr;
462 struct vm_area_struct *vma; 461 struct vm_area_struct *vma;
@@ -491,7 +490,9 @@ static int gmap_connect_pgtable(unsigned long segment,
491 /* Link gmap segment table entry location to page table. */ 490 /* Link gmap segment table entry location to page table. */
492 page = pmd_page(*pmd); 491 page = pmd_page(*pmd);
493 mp = (struct gmap_pgtable *) page->index; 492 mp = (struct gmap_pgtable *) page->index;
493 rmap->gmap = gmap;
494 rmap->entry = segment_ptr; 494 rmap->entry = segment_ptr;
495 rmap->vmaddr = address;
495 spin_lock(&mm->page_table_lock); 496 spin_lock(&mm->page_table_lock);
496 if (*segment_ptr == segment) { 497 if (*segment_ptr == segment) {
497 list_add(&rmap->list, &mp->mapper); 498 list_add(&rmap->list, &mp->mapper);
@@ -553,7 +554,7 @@ unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
553 if (!(segment & _SEGMENT_ENTRY_RO)) 554 if (!(segment & _SEGMENT_ENTRY_RO))
554 /* Nothing mapped in the gmap address space. */ 555 /* Nothing mapped in the gmap address space. */
555 break; 556 break;
556 rc = gmap_connect_pgtable(segment, segment_ptr, gmap); 557 rc = gmap_connect_pgtable(address, segment, segment_ptr, gmap);
557 if (rc) 558 if (rc)
558 return rc; 559 return rc;
559 } 560 }
@@ -619,6 +620,118 @@ void gmap_discard(unsigned long from, unsigned long to, struct gmap *gmap)
619} 620}
620EXPORT_SYMBOL_GPL(gmap_discard); 621EXPORT_SYMBOL_GPL(gmap_discard);
621 622
623static LIST_HEAD(gmap_notifier_list);
624static DEFINE_SPINLOCK(gmap_notifier_lock);
625
626/**
627 * gmap_register_ipte_notifier - register a pte invalidation callback
628 * @nb: pointer to the gmap notifier block
629 */
630void gmap_register_ipte_notifier(struct gmap_notifier *nb)
631{
632 spin_lock(&gmap_notifier_lock);
633 list_add(&nb->list, &gmap_notifier_list);
634 spin_unlock(&gmap_notifier_lock);
635}
636EXPORT_SYMBOL_GPL(gmap_register_ipte_notifier);
637
638/**
639 * gmap_unregister_ipte_notifier - remove a pte invalidation callback
640 * @nb: pointer to the gmap notifier block
641 */
642void gmap_unregister_ipte_notifier(struct gmap_notifier *nb)
643{
644 spin_lock(&gmap_notifier_lock);
645 list_del_init(&nb->list);
646 spin_unlock(&gmap_notifier_lock);
647}
648EXPORT_SYMBOL_GPL(gmap_unregister_ipte_notifier);
649
650/**
651 * gmap_ipte_notify - mark a range of ptes for invalidation notification
652 * @gmap: pointer to guest mapping meta data structure
653 * @address: virtual address in the guest address space
654 * @len: size of area
655 *
656 * Returns 0 if for each page in the given range a gmap mapping exists and
657 * the invalidation notification could be set. If the gmap mapping is missing
658 * for one or more pages -EFAULT is returned. If no memory could be allocated
659 * -ENOMEM is returned. This function establishes missing page table entries.
660 */
661int gmap_ipte_notify(struct gmap *gmap, unsigned long start, unsigned long len)
662{
663 unsigned long addr;
664 spinlock_t *ptl;
665 pte_t *ptep, entry;
666 pgste_t pgste;
667 int rc = 0;
668
669 if ((start & ~PAGE_MASK) || (len & ~PAGE_MASK))
670 return -EINVAL;
671 down_read(&gmap->mm->mmap_sem);
672 while (len) {
673 /* Convert gmap address and connect the page tables */
674 addr = __gmap_fault(start, gmap);
675 if (IS_ERR_VALUE(addr)) {
676 rc = addr;
677 break;
678 }
679 /* Get the page mapped */
680 if (get_user_pages(current, gmap->mm, addr, 1, 1, 0,
681 NULL, NULL) != 1) {
682 rc = -EFAULT;
683 break;
684 }
685 /* Walk the process page table, lock and get pte pointer */
686 ptep = get_locked_pte(gmap->mm, addr, &ptl);
687 if (unlikely(!ptep))
688 continue;
689 /* Set notification bit in the pgste of the pte */
690 entry = *ptep;
691 if ((pte_val(entry) & (_PAGE_INVALID | _PAGE_RO)) == 0) {
692 pgste = pgste_get_lock(ptep);
693 pgste_val(pgste) |= RCP_IN_BIT;
694 pgste_set_unlock(ptep, pgste);
695 start += PAGE_SIZE;
696 len -= PAGE_SIZE;
697 }
698 spin_unlock(ptl);
699 }
700 up_read(&gmap->mm->mmap_sem);
701 return rc;
702}
703EXPORT_SYMBOL_GPL(gmap_ipte_notify);
704
705/**
706 * gmap_do_ipte_notify - call all invalidation callbacks for a specific pte.
707 * @mm: pointer to the process mm_struct
708 * @addr: virtual address in the process address space
709 * @pte: pointer to the page table entry
710 *
711 * This function is assumed to be called with the page table lock held
712 * for the pte to notify.
713 */
714void gmap_do_ipte_notify(struct mm_struct *mm, unsigned long addr, pte_t *pte)
715{
716 unsigned long segment_offset;
717 struct gmap_notifier *nb;
718 struct gmap_pgtable *mp;
719 struct gmap_rmap *rmap;
720 struct page *page;
721
722 segment_offset = ((unsigned long) pte) & (255 * sizeof(pte_t));
723 segment_offset = segment_offset * (4096 / sizeof(pte_t));
724 page = pfn_to_page(__pa(pte) >> PAGE_SHIFT);
725 mp = (struct gmap_pgtable *) page->index;
726 spin_lock(&gmap_notifier_lock);
727 list_for_each_entry(rmap, &mp->mapper, list) {
728 list_for_each_entry(nb, &gmap_notifier_list, list)
729 nb->notifier_call(rmap->gmap,
730 rmap->vmaddr + segment_offset);
731 }
732 spin_unlock(&gmap_notifier_lock);
733}
734
622static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm, 735static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
623 unsigned long vmaddr) 736 unsigned long vmaddr)
624{ 737{
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 35837054f734..8b268fcc4612 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -375,9 +375,8 @@ void __init vmem_map_init(void)
375 375
376 ro_start = PFN_ALIGN((unsigned long)&_stext); 376 ro_start = PFN_ALIGN((unsigned long)&_stext);
377 ro_end = (unsigned long)&_eshared & PAGE_MASK; 377 ro_end = (unsigned long)&_eshared & PAGE_MASK;
378 for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) { 378 for (i = 0; i < MEMORY_CHUNKS; i++) {
379 if (memory_chunk[i].type == CHUNK_CRASHK || 379 if (!memory_chunk[i].size)
380 memory_chunk[i].type == CHUNK_OLDMEM)
381 continue; 380 continue;
382 start = memory_chunk[i].addr; 381 start = memory_chunk[i].addr;
383 end = memory_chunk[i].addr + memory_chunk[i].size; 382 end = memory_chunk[i].addr + memory_chunk[i].size;
@@ -412,9 +411,6 @@ static int __init vmem_convert_memory_chunk(void)
412 for (i = 0; i < MEMORY_CHUNKS; i++) { 411 for (i = 0; i < MEMORY_CHUNKS; i++) {
413 if (!memory_chunk[i].size) 412 if (!memory_chunk[i].size)
414 continue; 413 continue;
415 if (memory_chunk[i].type == CHUNK_CRASHK ||
416 memory_chunk[i].type == CHUNK_OLDMEM)
417 continue;
418 seg = kzalloc(sizeof(*seg), GFP_KERNEL); 414 seg = kzalloc(sizeof(*seg), GFP_KERNEL);
419 if (!seg) 415 if (!seg)
420 panic("Out of memory...\n"); 416 panic("Out of memory...\n");
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 178836ec252b..bf07c3a188d4 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -345,7 +345,6 @@ struct memory_increment {
345 struct list_head list; 345 struct list_head list;
346 u16 rn; 346 u16 rn;
347 int standby; 347 int standby;
348 int usecount;
349}; 348};
350 349
351struct assign_storage_sccb { 350struct assign_storage_sccb {
@@ -463,21 +462,10 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size,
463 break; 462 break;
464 if (start > istart + rzm - 1) 463 if (start > istart + rzm - 1)
465 continue; 464 continue;
466 if (online) { 465 if (online)
467 if (incr->usecount++)
468 continue;
469 /*
470 * Don't break the loop if one assign fails. Loop may
471 * be walked again on CANCEL and we can't save
472 * information if state changed before or not.
473 * So continue and increase usecount for all increments.
474 */
475 rc |= sclp_assign_storage(incr->rn); 466 rc |= sclp_assign_storage(incr->rn);
476 } else { 467 else
477 if (--incr->usecount)
478 continue;
479 sclp_unassign_storage(incr->rn); 468 sclp_unassign_storage(incr->rn);
480 }
481 } 469 }
482 return rc ? -EIO : 0; 470 return rc ? -EIO : 0;
483} 471}
@@ -561,8 +549,6 @@ static void __init sclp_add_standby_memory(void)
561 add_memory_merged(0); 549 add_memory_merged(0);
562} 550}
563 551
564#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS)
565
566static void __init insert_increment(u16 rn, int standby, int assigned) 552static void __init insert_increment(u16 rn, int standby, int assigned)
567{ 553{
568 struct memory_increment *incr, *new_incr; 554 struct memory_increment *incr, *new_incr;
@@ -574,8 +560,6 @@ static void __init insert_increment(u16 rn, int standby, int assigned)
574 return; 560 return;
575 new_incr->rn = rn; 561 new_incr->rn = rn;
576 new_incr->standby = standby; 562 new_incr->standby = standby;
577 if (!standby)
578 new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1;
579 last_rn = 0; 563 last_rn = 0;
580 prev = &sclp_mem_list; 564 prev = &sclp_mem_list;
581 list_for_each_entry(incr, &sclp_mem_list, list) { 565 list_for_each_entry(incr, &sclp_mem_list, list) {
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 22820610022c..9e5e14686e75 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -426,7 +426,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp)
426 GFP_KERNEL); 426 GFP_KERNEL);
427 if (!chunk_array) 427 if (!chunk_array)
428 return -ENOMEM; 428 return -ENOMEM;
429 detect_memory_layout(chunk_array); 429 detect_memory_layout(chunk_array, 0);
430 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL); 430 buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
431 if (!buf) { 431 if (!buf) {
432 kfree(chunk_array); 432 kfree(chunk_array);
@@ -557,7 +557,7 @@ static void __init set_lc_mask(struct save_area *map)
557/* 557/*
558 * Initialize dump globals for a given architecture 558 * Initialize dump globals for a given architecture
559 */ 559 */
560static int __init sys_info_init(enum arch_id arch) 560static int __init sys_info_init(enum arch_id arch, unsigned long mem_end)
561{ 561{
562 int rc; 562 int rc;
563 563
@@ -579,7 +579,7 @@ static int __init sys_info_init(enum arch_id arch)
579 rc = init_cpu_info(arch); 579 rc = init_cpu_info(arch);
580 if (rc) 580 if (rc)
581 return rc; 581 return rc;
582 sys_info.mem_size = real_memory_size; 582 sys_info.mem_size = mem_end;
583 583
584 return 0; 584 return 0;
585} 585}
@@ -601,7 +601,7 @@ static int __init check_sdias(void)
601 return 0; 601 return 0;
602} 602}
603 603
604static int __init get_mem_size(unsigned long *mem) 604static int __init get_mem_info(unsigned long *mem, unsigned long *end)
605{ 605{
606 int i; 606 int i;
607 struct mem_chunk *chunk_array; 607 struct mem_chunk *chunk_array;
@@ -610,33 +610,31 @@ static int __init get_mem_size(unsigned long *mem)
610 GFP_KERNEL); 610 GFP_KERNEL);
611 if (!chunk_array) 611 if (!chunk_array)
612 return -ENOMEM; 612 return -ENOMEM;
613 detect_memory_layout(chunk_array); 613 detect_memory_layout(chunk_array, 0);
614 for (i = 0; i < MEMORY_CHUNKS; i++) { 614 for (i = 0; i < MEMORY_CHUNKS; i++) {
615 if (chunk_array[i].size == 0) 615 if (chunk_array[i].size == 0)
616 break; 616 break;
617 *mem += chunk_array[i].size; 617 *mem += chunk_array[i].size;
618 *end = max(*end, chunk_array[i].addr + chunk_array[i].size);
618 } 619 }
619 kfree(chunk_array); 620 kfree(chunk_array);
620 return 0; 621 return 0;
621} 622}
622 623
623static int __init zcore_header_init(int arch, struct zcore_header *hdr) 624static void __init zcore_header_init(int arch, struct zcore_header *hdr,
625 unsigned long mem_size)
624{ 626{
625 int rc, i;
626 unsigned long memory = 0;
627 u32 prefix; 627 u32 prefix;
628 int i;
628 629
629 if (arch == ARCH_S390X) 630 if (arch == ARCH_S390X)
630 hdr->arch_id = DUMP_ARCH_S390X; 631 hdr->arch_id = DUMP_ARCH_S390X;
631 else 632 else
632 hdr->arch_id = DUMP_ARCH_S390; 633 hdr->arch_id = DUMP_ARCH_S390;
633 rc = get_mem_size(&memory); 634 hdr->mem_size = mem_size;
634 if (rc) 635 hdr->rmem_size = mem_size;
635 return rc;
636 hdr->mem_size = memory;
637 hdr->rmem_size = memory;
638 hdr->mem_end = sys_info.mem_size; 636 hdr->mem_end = sys_info.mem_size;
639 hdr->num_pages = memory / PAGE_SIZE; 637 hdr->num_pages = mem_size / PAGE_SIZE;
640 hdr->tod = get_tod_clock(); 638 hdr->tod = get_tod_clock();
641 get_cpu_id(&hdr->cpu_id); 639 get_cpu_id(&hdr->cpu_id);
642 for (i = 0; zfcpdump_save_areas[i]; i++) { 640 for (i = 0; zfcpdump_save_areas[i]; i++) {
@@ -647,7 +645,6 @@ static int __init zcore_header_init(int arch, struct zcore_header *hdr)
647 hdr->lc_vec[hdr->cpu_cnt] = prefix; 645 hdr->lc_vec[hdr->cpu_cnt] = prefix;
648 hdr->cpu_cnt++; 646 hdr->cpu_cnt++;
649 } 647 }
650 return 0;
651} 648}
652 649
653/* 650/*
@@ -682,9 +679,11 @@ static int __init zcore_reipl_init(void)
682 679
683static int __init zcore_init(void) 680static int __init zcore_init(void)
684{ 681{
682 unsigned long mem_size, mem_end;
685 unsigned char arch; 683 unsigned char arch;
686 int rc; 684 int rc;
687 685
686 mem_size = mem_end = 0;
688 if (ipl_info.type != IPL_TYPE_FCP_DUMP) 687 if (ipl_info.type != IPL_TYPE_FCP_DUMP)
689 return -ENODATA; 688 return -ENODATA;
690 if (OLDMEM_BASE) 689 if (OLDMEM_BASE)
@@ -727,13 +726,14 @@ static int __init zcore_init(void)
727 } 726 }
728#endif /* CONFIG_64BIT */ 727#endif /* CONFIG_64BIT */
729 728
730 rc = sys_info_init(arch); 729 rc = get_mem_info(&mem_size, &mem_end);
731 if (rc) 730 if (rc)
732 goto fail; 731 goto fail;
733 732
734 rc = zcore_header_init(arch, &zcore_header); 733 rc = sys_info_init(arch, mem_end);
735 if (rc) 734 if (rc)
736 goto fail; 735 goto fail;
736 zcore_header_init(arch, &zcore_header, mem_size);
737 737
738 rc = zcore_reipl_init(); 738 rc = zcore_reipl_init();
739 if (rc) 739 if (rc)
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 2d2a966a3b39..a9fe3de2dec1 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * S/390 common I/O routines -- blacklisting of specific devices 2 * S/390 common I/O routines -- blacklisting of specific devices
3 * 3 *
4 * Copyright IBM Corp. 1999, 2002 4 * Copyright IBM Corp. 1999, 2013
5 * Author(s): Ingo Adlung (adlung@de.ibm.com) 5 * Author(s): Ingo Adlung (adlung@de.ibm.com)
6 * Cornelia Huck (cornelia.huck@de.ibm.com) 6 * Cornelia Huck (cornelia.huck@de.ibm.com)
7 * Arnd Bergmann (arndb@de.ibm.com) 7 * Arnd Bergmann (arndb@de.ibm.com)
@@ -17,8 +17,9 @@
17#include <linux/ctype.h> 17#include <linux/ctype.h>
18#include <linux/device.h> 18#include <linux/device.h>
19 19
20#include <asm/cio.h>
21#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21#include <asm/cio.h>
22#include <asm/ipl.h>
22 23
23#include "blacklist.h" 24#include "blacklist.h"
24#include "cio.h" 25#include "cio.h"
@@ -172,6 +173,29 @@ static int blacklist_parse_parameters(char *str, range_action action,
172 to_cssid = __MAX_CSSID; 173 to_cssid = __MAX_CSSID;
173 to_ssid = __MAX_SSID; 174 to_ssid = __MAX_SSID;
174 to = __MAX_SUBCHANNEL; 175 to = __MAX_SUBCHANNEL;
176 } else if (strcmp(parm, "ipldev") == 0) {
177 if (ipl_info.type == IPL_TYPE_CCW) {
178 from_cssid = 0;
179 from_ssid = ipl_info.data.ccw.dev_id.ssid;
180 from = ipl_info.data.ccw.dev_id.devno;
181 } else if (ipl_info.type == IPL_TYPE_FCP ||
182 ipl_info.type == IPL_TYPE_FCP_DUMP) {
183 from_cssid = 0;
184 from_ssid = ipl_info.data.fcp.dev_id.ssid;
185 from = ipl_info.data.fcp.dev_id.devno;
186 } else {
187 continue;
188 }
189 to_cssid = from_cssid;
190 to_ssid = from_ssid;
191 to = from;
192 } else if (strcmp(parm, "condev") == 0) {
193 if (console_devno == -1)
194 continue;
195
196 from_cssid = to_cssid = 0;
197 from_ssid = to_ssid = 0;
198 from = to = console_devno;
175 } else { 199 } else {
176 rc = parse_busid(strsep(&parm, "-"), &from_cssid, 200 rc = parse_busid(strsep(&parm, "-"), &from_cssid,
177 &from_ssid, &from, msgtrigger); 201 &from_ssid, &from, msgtrigger);
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index b8b340ac5332..9de41aa14896 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -954,15 +954,11 @@ EXPORT_SYMBOL(ap_driver_unregister);
954 954
955void ap_bus_force_rescan(void) 955void ap_bus_force_rescan(void)
956{ 956{
957 /* Delete the AP bus rescan timer. */ 957 /* reconfigure the AP bus rescan timer. */
958 del_timer(&ap_config_timer); 958 mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
959 959 /* processing a asynchronous bus rescan */
960 /* processing a synchonuous bus rescan */ 960 queue_work(ap_work_queue, &ap_config_work);
961 ap_scan_bus(NULL); 961 flush_work(&ap_config_work);
962
963 /* Setup the AP bus rescan timer again. */
964 ap_config_timer.expires = jiffies + ap_config_time * HZ;
965 add_timer(&ap_config_timer);
966} 962}
967EXPORT_SYMBOL(ap_bus_force_rescan); 963EXPORT_SYMBOL(ap_bus_force_rescan);
968 964
@@ -1305,8 +1301,9 @@ static void ap_scan_bus(struct work_struct *unused)
1305 int rc, i; 1301 int rc, i;
1306 1302
1307 ap_query_configuration(); 1303 ap_query_configuration();
1308 if (ap_select_domain() != 0) 1304 if (ap_select_domain() != 0) {
1309 return; 1305 return;
1306 }
1310 for (i = 0; i < AP_DEVICES; i++) { 1307 for (i = 0; i < AP_DEVICES; i++) {
1311 qid = AP_MKQID(i, ap_domain_index); 1308 qid = AP_MKQID(i, ap_domain_index);
1312 dev = bus_find_device(&ap_bus_type, NULL, 1309 dev = bus_find_device(&ap_bus_type, NULL,