aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2010-10-25 10:10:13 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 10:10:15 -0400
commit92f842eac7ee321c8a0749aba2513541b4ac226f (patch)
tree06a9c2302729ecd6d2941f8629da1646c11c714c
parent6931be0803ddae2791f3c646c8e1e0f82ca26013 (diff)
[S390] store indication fault optimization
Use the store indication bit in the translation exception code on page faults to avoid the protection faults that immediatly follow the page fault if the access has been a write. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-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)