diff options
Diffstat (limited to 'arch/s390/mm')
-rw-r--r-- | arch/s390/mm/cmm.c | 30 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 40 | ||||
-rw-r--r-- | arch/s390/mm/init.c | 36 |
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); | |||
53 | static void cmm_set_timer(void); | 53 | static void cmm_set_timer(void); |
54 | 54 | ||
55 | static long | 55 | static long |
56 | cmm_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 | |||
71 | static long | ||
72 | cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list) | 56 | cmm_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 | ||
49 | extern void die(const char *,struct pt_regs *,long); | 51 | extern void die(const char *,struct pt_regs *,long); |
50 | 52 | ||
53 | #ifdef CONFIG_KPROBES | ||
54 | ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); | ||
55 | int register_page_fault_notifier(struct notifier_block *nb) | ||
56 | { | ||
57 | return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); | ||
58 | } | ||
59 | |||
60 | int unregister_page_fault_notifier(struct notifier_block *nb) | ||
61 | { | ||
62 | return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); | ||
63 | } | ||
64 | |||
65 | static 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(¬ify_page_fault_chain, val, &args); | ||
76 | } | ||
77 | #else | ||
78 | static 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 | |||
51 | extern spinlock_t timerlist_lock; | 85 | extern 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 | */ |
162 | static inline void | 196 | static inline void __kprobes |
163 | do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) | 197 | do_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 | } |