[patch 1/2] [PATCH] kvm: nowait retry for asynchronous page faults

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Martin Schwidefsky <schwidefsky@xxxxxxxxxx>

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 <schwidefsky@xxxxxxxxxx>
---

 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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux