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