aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/cmm.c30
-rw-r--r--arch/s390/mm/fault.c40
-rw-r--r--arch/s390/mm/init.c36
3 files changed, 60 insertions, 46 deletions
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index ceea51cff03b..786a44dba5bf 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -53,22 +53,6 @@ static void cmm_timer_fn(unsigned long);
53static void cmm_set_timer(void); 53static void cmm_set_timer(void);
54 54
55static long 55static long
56cmm_strtoul(const char *cp, char **endp)
57{
58 unsigned int base = 10;
59
60 if (*cp == '0') {
61 base = 8;
62 cp++;
63 if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) {
64 base = 16;
65 cp++;
66 }
67 }
68 return simple_strtoul(cp, endp, base);
69}
70
71static long
72cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list) 56cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list)
73{ 57{
74 struct cmm_page_array *pa; 58 struct cmm_page_array *pa;
@@ -276,7 +260,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp,
276 return -EFAULT; 260 return -EFAULT;
277 buf[sizeof(buf) - 1] = '\0'; 261 buf[sizeof(buf) - 1] = '\0';
278 cmm_skip_blanks(buf, &p); 262 cmm_skip_blanks(buf, &p);
279 pages = cmm_strtoul(p, &p); 263 pages = simple_strtoul(p, &p, 0);
280 if (ctl == &cmm_table[0]) 264 if (ctl == &cmm_table[0])
281 cmm_set_pages(pages); 265 cmm_set_pages(pages);
282 else 266 else
@@ -317,9 +301,9 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp,
317 return -EFAULT; 301 return -EFAULT;
318 buf[sizeof(buf) - 1] = '\0'; 302 buf[sizeof(buf) - 1] = '\0';
319 cmm_skip_blanks(buf, &p); 303 cmm_skip_blanks(buf, &p);
320 pages = cmm_strtoul(p, &p); 304 pages = simple_strtoul(p, &p, 0);
321 cmm_skip_blanks(p, &p); 305 cmm_skip_blanks(p, &p);
322 seconds = cmm_strtoul(p, &p); 306 seconds = simple_strtoul(p, &p, 0);
323 cmm_set_timeout(pages, seconds); 307 cmm_set_timeout(pages, seconds);
324 } else { 308 } else {
325 len = sprintf(buf, "%ld %ld\n", 309 len = sprintf(buf, "%ld %ld\n",
@@ -382,24 +366,24 @@ cmm_smsg_target(char *from, char *msg)
382 if (strncmp(msg, "SHRINK", 6) == 0) { 366 if (strncmp(msg, "SHRINK", 6) == 0) {
383 if (!cmm_skip_blanks(msg + 6, &msg)) 367 if (!cmm_skip_blanks(msg + 6, &msg))
384 return; 368 return;
385 pages = cmm_strtoul(msg, &msg); 369 pages = simple_strtoul(msg, &msg, 0);
386 cmm_skip_blanks(msg, &msg); 370 cmm_skip_blanks(msg, &msg);
387 if (*msg == '\0') 371 if (*msg == '\0')
388 cmm_set_pages(pages); 372 cmm_set_pages(pages);
389 } else if (strncmp(msg, "RELEASE", 7) == 0) { 373 } else if (strncmp(msg, "RELEASE", 7) == 0) {
390 if (!cmm_skip_blanks(msg + 7, &msg)) 374 if (!cmm_skip_blanks(msg + 7, &msg))
391 return; 375 return;
392 pages = cmm_strtoul(msg, &msg); 376 pages = simple_strtoul(msg, &msg, 0);
393 cmm_skip_blanks(msg, &msg); 377 cmm_skip_blanks(msg, &msg);
394 if (*msg == '\0') 378 if (*msg == '\0')
395 cmm_add_timed_pages(pages); 379 cmm_add_timed_pages(pages);
396 } else if (strncmp(msg, "REUSE", 5) == 0) { 380 } else if (strncmp(msg, "REUSE", 5) == 0) {
397 if (!cmm_skip_blanks(msg + 5, &msg)) 381 if (!cmm_skip_blanks(msg + 5, &msg))
398 return; 382 return;
399 pages = cmm_strtoul(msg, &msg); 383 pages = simple_strtoul(msg, &msg, 0);
400 if (!cmm_skip_blanks(msg, &msg)) 384 if (!cmm_skip_blanks(msg, &msg))
401 return; 385 return;
402 seconds = cmm_strtoul(msg, &msg); 386 seconds = simple_strtoul(msg, &msg, 0);
403 cmm_skip_blanks(msg, &msg); 387 cmm_skip_blanks(msg, &msg);
404 if (*msg == '\0') 388 if (*msg == '\0')
405 cmm_set_timeout(pages, seconds); 389 cmm_set_timeout(pages, seconds);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 7cd82575813d..44f0cda7e72e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -25,10 +25,12 @@
25#include <linux/console.h> 25#include <linux/console.h>
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/hardirq.h> 27#include <linux/hardirq.h>
28#include <linux/kprobes.h>
28 29
29#include <asm/system.h> 30#include <asm/system.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
31#include <asm/pgtable.h> 32#include <asm/pgtable.h>
33#include <asm/kdebug.h>
32 34
33#ifndef CONFIG_64BIT 35#ifndef CONFIG_64BIT
34#define __FAIL_ADDR_MASK 0x7ffff000 36#define __FAIL_ADDR_MASK 0x7ffff000
@@ -48,6 +50,38 @@ extern int sysctl_userprocess_debug;
48 50
49extern void die(const char *,struct pt_regs *,long); 51extern void die(const char *,struct pt_regs *,long);
50 52
53#ifdef CONFIG_KPROBES
54ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
55int register_page_fault_notifier(struct notifier_block *nb)
56{
57 return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
58}
59
60int unregister_page_fault_notifier(struct notifier_block *nb)
61{
62 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
63}
64
65static inline int notify_page_fault(enum die_val val, const char *str,
66 struct pt_regs *regs, long err, int trap, int sig)
67{
68 struct die_args args = {
69 .regs = regs,
70 .str = str,
71 .err = err,
72 .trapnr = trap,
73 .signr = sig
74 };
75 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
76}
77#else
78static inline int notify_page_fault(enum die_val val, const char *str,
79 struct pt_regs *regs, long err, int trap, int sig)
80{
81 return NOTIFY_DONE;
82}
83#endif
84
51extern spinlock_t timerlist_lock; 85extern spinlock_t timerlist_lock;
52 86
53/* 87/*
@@ -159,7 +193,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
159 * 11 Page translation -> Not present (nullification) 193 * 11 Page translation -> Not present (nullification)
160 * 3b Region third trans. -> Not present (nullification) 194 * 3b Region third trans. -> Not present (nullification)
161 */ 195 */
162static inline void 196static inline void __kprobes
163do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) 197do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
164{ 198{
165 struct task_struct *tsk; 199 struct task_struct *tsk;
@@ -173,6 +207,10 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
173 tsk = current; 207 tsk = current;
174 mm = tsk->mm; 208 mm = tsk->mm;
175 209
210 if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
211 SIGSEGV) == NOTIFY_STOP)
212 return;
213
176 /* 214 /*
177 * Check for low-address protection. This needs to be treated 215 * Check for low-address protection. This needs to be treated
178 * as a special case because the translation exception code 216 * as a special case because the translation exception code
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 6e6b6de77770..cfd9b8f7a523 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -108,16 +108,23 @@ void __init paging_init(void)
108 unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; 108 unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
109 static const int ssm_mask = 0x04000000L; 109 static const int ssm_mask = 0x04000000L;
110 unsigned long ro_start_pfn, ro_end_pfn; 110 unsigned long ro_start_pfn, ro_end_pfn;
111 unsigned long zones_size[MAX_NR_ZONES];
111 112
112 ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); 113 ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata);
113 ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); 114 ro_end_pfn = PFN_UP((unsigned long)&__end_rodata);
114 115
116 memset(zones_size, 0, sizeof(zones_size));
117 zones_size[ZONE_DMA] = max_low_pfn;
118 free_area_init_node(0, &contig_page_data, zones_size,
119 __pa(PAGE_OFFSET) >> PAGE_SHIFT,
120 zholes_size);
121
115 /* unmap whole virtual address space */ 122 /* unmap whole virtual address space */
116 123
117 pg_dir = swapper_pg_dir; 124 pg_dir = swapper_pg_dir;
118 125
119 for (i=0;i<KERNEL_PGD_PTRS;i++) 126 for (i = 0; i < PTRS_PER_PGD; i++)
120 pmd_clear((pmd_t*)pg_dir++); 127 pmd_clear((pmd_t *) pg_dir++);
121 128
122 /* 129 /*
123 * map whole physical memory to virtual memory (identity mapping) 130 * map whole physical memory to virtual memory (identity mapping)
@@ -131,10 +138,7 @@ void __init paging_init(void)
131 */ 138 */
132 pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); 139 pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
133 140
134 pg_dir->pgd0 = (_PAGE_TABLE | __pa(pg_table)); 141 pmd_populate_kernel(&init_mm, (pmd_t *) pg_dir, pg_table);
135 pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024));
136 pg_dir->pgd2 = (_PAGE_TABLE | (__pa(pg_table)+2048));
137 pg_dir->pgd3 = (_PAGE_TABLE | (__pa(pg_table)+3072));
138 pg_dir++; 142 pg_dir++;
139 143
140 for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { 144 for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
@@ -143,8 +147,8 @@ void __init paging_init(void)
143 else 147 else
144 pte = pfn_pte(pfn, PAGE_KERNEL); 148 pte = pfn_pte(pfn, PAGE_KERNEL);
145 if (pfn >= max_low_pfn) 149 if (pfn >= max_low_pfn)
146 pte_clear(&init_mm, 0, &pte); 150 pte_val(pte) = _PAGE_TYPE_EMPTY;
147 set_pte(pg_table, pte); 151 set_pte(pg_table, pte);
148 pfn++; 152 pfn++;
149 } 153 }
150 } 154 }
@@ -159,16 +163,6 @@ void __init paging_init(void)
159 : : "m" (pgdir_k), "m" (ssm_mask)); 163 : : "m" (pgdir_k), "m" (ssm_mask));
160 164
161 local_flush_tlb(); 165 local_flush_tlb();
162
163 {
164 unsigned long zones_size[MAX_NR_ZONES];
165
166 memset(zones_size, 0, sizeof(zones_size));
167 zones_size[ZONE_DMA] = max_low_pfn;
168 free_area_init_node(0, &contig_page_data, zones_size,
169 __pa(PAGE_OFFSET) >> PAGE_SHIFT,
170 zholes_size);
171 }
172 return; 166 return;
173} 167}
174 168
@@ -236,10 +230,8 @@ void __init paging_init(void)
236 pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); 230 pte = pfn_pte(pfn, __pgprot(_PAGE_RO));
237 else 231 else
238 pte = pfn_pte(pfn, PAGE_KERNEL); 232 pte = pfn_pte(pfn, PAGE_KERNEL);
239 if (pfn >= max_low_pfn) { 233 if (pfn >= max_low_pfn)
240 pte_clear(&init_mm, 0, &pte); 234 pte_val(pte) = _PAGE_TYPE_EMPTY;
241 continue;
242 }
243 set_pte(pt_dir, pte); 235 set_pte(pt_dir, pte);
244 pfn++; 236 pfn++;
245 } 237 }