aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDominik Dingel <dingel@linux.vnet.ibm.com>2013-06-17 10:25:18 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-01-30 06:50:39 -0500
commit24eb3a824c4f3ccfaa2305dc1d9d9e2a708828c5 (patch)
treea889cb48f43502fb8db57d40ef6f342382d638b6 /arch
parenta91b8ebe8671980151e0a19ee9fec6b0e1ae1d58 (diff)
KVM: s390: Add FAULT_FLAG_RETRY_NOWAIT for guest fault
In the case of a fault, we will retry to exit sie64 but with gmap fault indication for this thread set. This makes it possible to handle async page faults. Based on a patch from Martin Schwidefsky. Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/pgtable.h2
-rw-r--r--arch/s390/include/asm/processor.h1
-rw-r--r--arch/s390/kvm/kvm-s390.c23
-rw-r--r--arch/s390/mm/fault.c26
4 files changed, 46 insertions, 6 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 2204400d0bd5..66101f6c6d81 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -767,6 +767,7 @@ static inline void pgste_set_pte(pte_t *ptep, pte_t entry)
767 * @table: pointer to the page directory 767 * @table: pointer to the page directory
768 * @asce: address space control element for gmap page table 768 * @asce: address space control element for gmap page table
769 * @crst_list: list of all crst tables used in the guest address space 769 * @crst_list: list of all crst tables used in the guest address space
770 * @pfault_enabled: defines if pfaults are applicable for the guest
770 */ 771 */
771struct gmap { 772struct gmap {
772 struct list_head list; 773 struct list_head list;
@@ -775,6 +776,7 @@ struct gmap {
775 unsigned long asce; 776 unsigned long asce;
776 void *private; 777 void *private;
777 struct list_head crst_list; 778 struct list_head crst_list;
779 bool pfault_enabled;
778}; 780};
779 781
780/** 782/**
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 0a876bc543d3..dc5fc4f90e52 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -79,6 +79,7 @@ struct thread_struct {
79 unsigned long ksp; /* kernel stack pointer */ 79 unsigned long ksp; /* kernel stack pointer */
80 mm_segment_t mm_segment; 80 mm_segment_t mm_segment;
81 unsigned long gmap_addr; /* address of last gmap fault. */ 81 unsigned long gmap_addr; /* address of last gmap fault. */
82 unsigned int gmap_pfault; /* signal of a pending guest pfault */
82 struct per_regs per_user; /* User specified PER registers */ 83 struct per_regs per_user; /* User specified PER registers */
83 struct per_event per_event; /* Cause of the last PER trap */ 84 struct per_event per_event; /* Cause of the last PER trap */
84 unsigned long per_flags; /* Flags to control debug behavior */ 85 unsigned long per_flags; /* Flags to control debug behavior */
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 782420f3c4d5..9eec794caa7f 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -255,6 +255,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
255 if (!kvm->arch.gmap) 255 if (!kvm->arch.gmap)
256 goto out_nogmap; 256 goto out_nogmap;
257 kvm->arch.gmap->private = kvm; 257 kvm->arch.gmap->private = kvm;
258 kvm->arch.gmap->pfault_enabled = 0;
258 } 259 }
259 260
260 kvm->arch.css_support = 0; 261 kvm->arch.css_support = 0;
@@ -701,6 +702,17 @@ static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
701 return 0; 702 return 0;
702} 703}
703 704
705static long kvm_arch_fault_in_sync(struct kvm_vcpu *vcpu)
706{
707 long rc;
708 hva_t fault = gmap_fault(current->thread.gmap_addr, vcpu->arch.gmap);
709 struct mm_struct *mm = current->mm;
710 down_read(&mm->mmap_sem);
711 rc = get_user_pages(current, mm, fault, 1, 1, 0, NULL, NULL);
712 up_read(&mm->mmap_sem);
713 return rc;
714}
715
704static int vcpu_pre_run(struct kvm_vcpu *vcpu) 716static int vcpu_pre_run(struct kvm_vcpu *vcpu)
705{ 717{
706 int rc, cpuflags; 718 int rc, cpuflags;
@@ -730,7 +742,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
730 742
731static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) 743static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
732{ 744{
733 int rc; 745 int rc = -1;
734 746
735 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", 747 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
736 vcpu->arch.sie_block->icptcode); 748 vcpu->arch.sie_block->icptcode);
@@ -744,7 +756,14 @@ static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
744 current->thread.gmap_addr; 756 current->thread.gmap_addr;
745 vcpu->run->s390_ucontrol.pgm_code = 0x10; 757 vcpu->run->s390_ucontrol.pgm_code = 0x10;
746 rc = -EREMOTE; 758 rc = -EREMOTE;
747 } else { 759
760 } else if (current->thread.gmap_pfault) {
761 current->thread.gmap_pfault = 0;
762 if (kvm_arch_fault_in_sync(vcpu) >= 0)
763 rc = 0;
764 }
765
766 if (rc == -1) {
748 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); 767 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
749 trace_kvm_s390_sie_fault(vcpu); 768 trace_kvm_s390_sie_fault(vcpu);
750 rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); 769 rc = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index d95265b2719f..88cef505453b 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -50,6 +50,7 @@
50#define VM_FAULT_BADMAP 0x020000 50#define VM_FAULT_BADMAP 0x020000
51#define VM_FAULT_BADACCESS 0x040000 51#define VM_FAULT_BADACCESS 0x040000
52#define VM_FAULT_SIGNAL 0x080000 52#define VM_FAULT_SIGNAL 0x080000
53#define VM_FAULT_PFAULT 0x100000
53 54
54static unsigned long store_indication __read_mostly; 55static unsigned long store_indication __read_mostly;
55 56
@@ -227,6 +228,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
227 return; 228 return;
228 } 229 }
229 case VM_FAULT_BADCONTEXT: 230 case VM_FAULT_BADCONTEXT:
231 case VM_FAULT_PFAULT:
230 do_no_context(regs); 232 do_no_context(regs);
231 break; 233 break;
232 case VM_FAULT_SIGNAL: 234 case VM_FAULT_SIGNAL:
@@ -264,6 +266,9 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
264 */ 266 */
265static inline int do_exception(struct pt_regs *regs, int access) 267static inline int do_exception(struct pt_regs *regs, int access)
266{ 268{
269#ifdef CONFIG_PGSTE
270 struct gmap *gmap;
271#endif
267 struct task_struct *tsk; 272 struct task_struct *tsk;
268 struct mm_struct *mm; 273 struct mm_struct *mm;
269 struct vm_area_struct *vma; 274 struct vm_area_struct *vma;
@@ -304,9 +309,10 @@ static inline int do_exception(struct pt_regs *regs, int access)
304 down_read(&mm->mmap_sem); 309 down_read(&mm->mmap_sem);
305 310
306#ifdef CONFIG_PGSTE 311#ifdef CONFIG_PGSTE
307 if ((current->flags & PF_VCPU) && S390_lowcore.gmap) { 312 gmap = (struct gmap *)
308 address = __gmap_fault(address, 313 ((current->flags & PF_VCPU) ? S390_lowcore.gmap : 0);
309 (struct gmap *) S390_lowcore.gmap); 314 if (gmap) {
315 address = __gmap_fault(address, gmap);
310 if (address == -EFAULT) { 316 if (address == -EFAULT) {
311 fault = VM_FAULT_BADMAP; 317 fault = VM_FAULT_BADMAP;
312 goto out_up; 318 goto out_up;
@@ -315,6 +321,8 @@ static inline int do_exception(struct pt_regs *regs, int access)
315 fault = VM_FAULT_OOM; 321 fault = VM_FAULT_OOM;
316 goto out_up; 322 goto out_up;
317 } 323 }
324 if (gmap->pfault_enabled)
325 flags |= FAULT_FLAG_RETRY_NOWAIT;
318 } 326 }
319#endif 327#endif
320 328
@@ -371,9 +379,19 @@ retry:
371 regs, address); 379 regs, address);
372 } 380 }
373 if (fault & VM_FAULT_RETRY) { 381 if (fault & VM_FAULT_RETRY) {
382#ifdef CONFIG_PGSTE
383 if (gmap && (flags & FAULT_FLAG_RETRY_NOWAIT)) {
384 /* FAULT_FLAG_RETRY_NOWAIT has been set,
385 * mmap_sem has not been released */
386 current->thread.gmap_pfault = 1;
387 fault = VM_FAULT_PFAULT;
388 goto out_up;
389 }
390#endif
374 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk 391 /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
375 * of starvation. */ 392 * of starvation. */
376 flags &= ~FAULT_FLAG_ALLOW_RETRY; 393 flags &= ~(FAULT_FLAG_ALLOW_RETRY |
394 FAULT_FLAG_RETRY_NOWAIT);
377 flags |= FAULT_FLAG_TRIED; 395 flags |= FAULT_FLAG_TRIED;
378 down_read(&mm->mmap_sem); 396 down_read(&mm->mmap_sem);
379 goto retry; 397 goto retry;