diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 1 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 21 | ||||
-rw-r--r-- | arch/s390/mm/init.c | 1 |
3 files changed, 20 insertions, 3 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 785229ae39cb..85cd4b039de6 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -38,6 +38,7 @@ | |||
38 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); | 38 | extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); |
39 | extern void paging_init(void); | 39 | extern void paging_init(void); |
40 | extern void vmem_map_init(void); | 40 | extern void vmem_map_init(void); |
41 | extern void fault_init(void); | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * The S390 doesn't have any external MMU info: the kernel page | 44 | * The S390 doesn't have any external MMU info: the kernel page |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 2505b2ea0ef1..b49d12073f10 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -52,6 +52,19 @@ | |||
52 | #define VM_FAULT_BADMAP 0x020000 | 52 | #define VM_FAULT_BADMAP 0x020000 |
53 | #define VM_FAULT_BADACCESS 0x040000 | 53 | #define VM_FAULT_BADACCESS 0x040000 |
54 | 54 | ||
55 | static unsigned long store_indication; | ||
56 | |||
57 | void fault_init(void) | ||
58 | { | ||
59 | unsigned long long facility_list[2]; | ||
60 | |||
61 | if (stfle(facility_list, 2) < 2) | ||
62 | return; | ||
63 | if ((facility_list[0] & (1ULL << 61)) && | ||
64 | (facility_list[1] & (1ULL << 52))) | ||
65 | store_indication = 0xc00; | ||
66 | } | ||
67 | |||
55 | static inline int notify_page_fault(struct pt_regs *regs) | 68 | static inline int notify_page_fault(struct pt_regs *regs) |
56 | { | 69 | { |
57 | int ret = 0; | 70 | int ret = 0; |
@@ -294,7 +307,7 @@ static inline int do_exception(struct pt_regs *regs, int access, | |||
294 | struct mm_struct *mm; | 307 | struct mm_struct *mm; |
295 | struct vm_area_struct *vma; | 308 | struct vm_area_struct *vma; |
296 | unsigned long address; | 309 | unsigned long address; |
297 | int fault; | 310 | int fault, write; |
298 | 311 | ||
299 | if (notify_page_fault(regs)) | 312 | if (notify_page_fault(regs)) |
300 | return 0; | 313 | return 0; |
@@ -348,8 +361,10 @@ static inline int do_exception(struct pt_regs *regs, int access, | |||
348 | * make sure we exit gracefully rather than endlessly redo | 361 | * make sure we exit gracefully rather than endlessly redo |
349 | * the fault. | 362 | * the fault. |
350 | */ | 363 | */ |
351 | fault = handle_mm_fault(mm, vma, address, | 364 | write = (access == VM_WRITE || |
352 | (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0); | 365 | (trans_exc_code & store_indication) == 0x400) ? |
366 | FAULT_FLAG_WRITE : 0; | ||
367 | fault = handle_mm_fault(mm, vma, address, write); | ||
353 | if (unlikely(fault & VM_FAULT_ERROR)) | 368 | if (unlikely(fault & VM_FAULT_ERROR)) |
354 | goto out_up; | 369 | goto out_up; |
355 | 370 | ||
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 852a3fec1ece..bb409332a484 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c | |||
@@ -124,6 +124,7 @@ void __init paging_init(void) | |||
124 | #endif | 124 | #endif |
125 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; | 125 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; |
126 | free_area_init_nodes(max_zone_pfns); | 126 | free_area_init_nodes(max_zone_pfns); |
127 | fault_init(); | ||
127 | } | 128 | } |
128 | 129 | ||
129 | void __init mem_init(void) | 130 | void __init mem_init(void) |