From: Martin Schwidefsky <schwidef...@de.ibm.com>

Add FAULT_FLAG_RETRY_NOWAIT to the fault flags if the host is processing
a guest fault. In case of a fault retry exit sie64a() with the gmap_fault
indication set. This makes it possible to handle asynchronous page faults
without the need for mm notifiers.

Signed-off-by: Martin Schwidefsky <schwidef...@de.ibm.com>
---

 arch/s390/include/asm/pgtable.h   |    1 +
 arch/s390/include/asm/processor.h |    1 +
 arch/s390/mm/fault.c              |   28 +++++++++++++++++++++++-----
 arch/s390/mm/pgtable.c            |    7 +++++++
 4 files changed, 32 insertions(+), 5 deletions(-)

diff -urpN linux-2.6/arch/s390/include/asm/pgtable.h 
linux-2.6-patched/arch/s390/include/asm/pgtable.h
--- linux-2.6/arch/s390/include/asm/pgtable.h   2011-11-17 10:03:47.000000000 
+0100
+++ linux-2.6-patched/arch/s390/include/asm/pgtable.h   2011-11-17 
10:03:53.000000000 +0100
@@ -688,6 +688,7 @@ int gmap_unmap_segment(struct gmap *gmap
 unsigned long __gmap_fault(unsigned long address, struct gmap *);
 unsigned long gmap_fault(unsigned long address, struct gmap *);
 void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
+int gmap_pfault(struct gmap *gmap);
 
 /*
  * Certain architectures need to do special things when PTEs
diff -urpN linux-2.6/arch/s390/include/asm/processor.h 
linux-2.6-patched/arch/s390/include/asm/processor.h
--- linux-2.6/arch/s390/include/asm/processor.h 2011-11-17 10:03:39.000000000 
+0100
+++ linux-2.6-patched/arch/s390/include/asm/processor.h 2011-11-17 
10:03:53.000000000 +0100
@@ -83,6 +83,7 @@ struct thread_struct {
         unsigned long prot_addr;        /* address of protection-excep.     */
         unsigned int trap_no;
        unsigned long gmap_addr;        /* address of last gmap fault. */
+       unsigned int gmap_pfault;       /* bool to indicate a guest pfault */
        struct per_regs per_user;       /* User specified PER registers */
        struct per_event per_event;     /* Cause of the last PER trap */
         /* pfault_wait is used to block the process on a pfault event */
diff -urpN linux-2.6/arch/s390/mm/fault.c linux-2.6-patched/arch/s390/mm/fault.c
--- linux-2.6/arch/s390/mm/fault.c      2011-11-17 10:03:49.000000000 +0100
+++ linux-2.6-patched/arch/s390/mm/fault.c      2011-11-17 10:03:53.000000000 
+0100
@@ -52,6 +52,7 @@
 #define VM_FAULT_BADCONTEXT    0x010000
 #define VM_FAULT_BADMAP                0x020000
 #define VM_FAULT_BADACCESS     0x040000
+#define VM_FAULT_PFAULT                0x080000
 
 static unsigned long store_indication;
 
@@ -242,6 +243,7 @@ static noinline void do_fault_error(stru
                        return;
                }
        case VM_FAULT_BADCONTEXT:
+       case VM_FAULT_PFAULT:
                do_no_context(regs, int_code, trans_exc_code);
                break;
        default: /* fault & VM_FAULT_ERROR */
@@ -276,6 +278,9 @@ static noinline void do_fault_error(stru
 static inline int do_exception(struct pt_regs *regs, int access,
                               unsigned long trans_exc_code)
 {
+#ifdef CONFIG_PGSTE
+       struct gmap *gmap;
+#endif
        struct task_struct *tsk;
        struct mm_struct *mm;
        struct vm_area_struct *vma;
@@ -306,9 +311,10 @@ static inline int do_exception(struct pt
        down_read(&mm->mmap_sem);
 
 #ifdef CONFIG_PGSTE
-       if (test_tsk_thread_flag(current, TIF_SIE) && S390_lowcore.gmap) {
-               address = __gmap_fault(address,
-                                    (struct gmap *) S390_lowcore.gmap);
+       gmap = (struct gmap *)
+               (test_thread_flag(TIF_SIE) ? S390_lowcore.gmap : 0);
+       if (gmap) {
+               address = __gmap_fault(address, gmap);
                if (address == -EFAULT) {
                        fault = VM_FAULT_BADMAP;
                        goto out_up;
@@ -317,6 +323,7 @@ static inline int do_exception(struct pt
                        fault = VM_FAULT_OOM;
                        goto out_up;
                }
+               flags |= FAULT_FLAG_RETRY_NOWAIT;
        }
 #endif
 
@@ -368,10 +375,21 @@ retry:
                                      regs, address);
                }
                if (fault & VM_FAULT_RETRY) {
+#ifdef CONFIG_PGSTE
+                       if (gmap) {
+                               /* FAULT_FLAG_RETRY_NOWAIT has been set,
+                                * mmap_sem has not been released. */
+                               if (gmap_pfault(gmap)) {
+                                       fault = VM_FAULT_PFAULT;
+                                       goto out_up;
+                               }
+                       } else
+#endif
+                       down_read(&mm->mmap_sem);
                        /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
                         * of starvation. */
-                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
-                       down_read(&mm->mmap_sem);
+                       flags &= ~(FAULT_FLAG_ALLOW_RETRY |
+                                  FAULT_FLAG_RETRY_NOWAIT);
                        goto retry;
                }
        }
diff -urpN linux-2.6/arch/s390/mm/pgtable.c 
linux-2.6-patched/arch/s390/mm/pgtable.c
--- linux-2.6/arch/s390/mm/pgtable.c    2011-11-17 10:03:47.000000000 +0100
+++ linux-2.6-patched/arch/s390/mm/pgtable.c    2011-11-17 10:03:53.000000000 
+0100
@@ -398,6 +398,7 @@ unsigned long __gmap_fault(unsigned long
        pmd_t *pmd;
 
        current->thread.gmap_addr = address;
+       current->thread.gmap_pfault = 0;
        mm = gmap->mm;
        /* Walk the gmap address space page table */
        table = gmap->table + ((address >> 53) & 0x7ff);
@@ -514,6 +515,12 @@ void gmap_discard(unsigned long from, un
 }
 EXPORT_SYMBOL_GPL(gmap_discard);
 
+int gmap_pfault(struct gmap *gmap)
+{
+       current->thread.gmap_pfault = 1;
+       return 1;
+}
+
 void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
 {
        struct gmap_rmap *rmap, *next;

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to