aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/pgtable.h1
-rw-r--r--arch/s390/mm/fault.c21
-rw-r--r--arch/s390/mm/init.c1
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 @@
38extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); 38extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
39extern void paging_init(void); 39extern void paging_init(void);
40extern void vmem_map_init(void); 40extern void vmem_map_init(void);
41extern 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
55static unsigned long store_indication;
56
57void 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
55static inline int notify_page_fault(struct pt_regs *regs) 68static 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
129void __init mem_init(void) 130void __init mem_init(void)