aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-05-27 16:03:52 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-21 03:43:44 -0400
commitadbf16985c387851fd3454ca34893705dbde7f98 (patch)
treeda60441f03e9b218ea1a8f822b46558c2da92756
parent1b7029bec18718eca8cfc5c1c0917444f019be1e (diff)
KVM: s390: vsie: speed up VCPU irq delivery when handling vsie
Whenever we want to wake up a VCPU (e.g. when injecting an IRQ), we have to kick it out of vsie, so the request will be handled faster. Acked-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/include/asm/kvm_host.h2
-rw-r--r--arch/s390/kvm/interrupt.c5
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--arch/s390/kvm/vsie.c35
4 files changed, 43 insertions, 0 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 190ad63291fb..946fc86202fd 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -549,6 +549,8 @@ struct kvm_guestdbg_info_arch {
549 549
550struct kvm_vcpu_arch { 550struct kvm_vcpu_arch {
551 struct kvm_s390_sie_block *sie_block; 551 struct kvm_s390_sie_block *sie_block;
552 /* if vsie is active, currently executed shadow sie control block */
553 struct kvm_s390_sie_block *vsie_block;
552 unsigned int host_acrs[NUM_ACRS]; 554 unsigned int host_acrs[NUM_ACRS];
553 struct fpu host_fpregs; 555 struct fpu host_fpregs;
554 struct kvm_s390_local_interrupt local_int; 556 struct kvm_s390_local_interrupt local_int;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index d72c4a877622..ca19627779db 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -995,6 +995,11 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
995 swake_up(&vcpu->wq); 995 swake_up(&vcpu->wq);
996 vcpu->stat.halt_wakeup++; 996 vcpu->stat.halt_wakeup++;
997 } 997 }
998 /*
999 * The VCPU might not be sleeping but is executing the VSIE. Let's
1000 * kick it, so it leaves the SIE to process the request.
1001 */
1002 kvm_s390_vsie_kick(vcpu);
998} 1003}
999 1004
1000enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) 1005enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index b137fbaac91c..ffbbdd285385 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -254,6 +254,7 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
254 254
255/* implemented in vsie.c */ 255/* implemented in vsie.c */
256int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); 256int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu);
257void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu);
257void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, 258void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start,
258 unsigned long end); 259 unsigned long end);
259void kvm_s390_vsie_init(struct kvm *kvm); 260void kvm_s390_vsie_init(struct kvm *kvm);
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 7482488d21d0..c8c8763e7822 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -838,6 +838,23 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
838} 838}
839 839
840/* 840/*
841 * Register the shadow scb at the VCPU, e.g. for kicking out of vsie.
842 */
843static void register_shadow_scb(struct kvm_vcpu *vcpu,
844 struct vsie_page *vsie_page)
845{
846 WRITE_ONCE(vcpu->arch.vsie_block, &vsie_page->scb_s);
847}
848
849/*
850 * Unregister a shadow scb from a VCPU.
851 */
852static void unregister_shadow_scb(struct kvm_vcpu *vcpu)
853{
854 WRITE_ONCE(vcpu->arch.vsie_block, NULL);
855}
856
857/*
841 * Run the vsie on a shadowed scb, managing the gmap shadow, handling 858 * Run the vsie on a shadowed scb, managing the gmap shadow, handling
842 * prefix pages and faults. 859 * prefix pages and faults.
843 * 860 *
@@ -860,6 +877,7 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
860 rc = do_vsie_run(vcpu, vsie_page); 877 rc = do_vsie_run(vcpu, vsie_page);
861 gmap_enable(vcpu->arch.gmap); 878 gmap_enable(vcpu->arch.gmap);
862 } 879 }
880 atomic_andnot(PROG_BLOCK_SIE, &scb_s->prog20);
863 881
864 if (rc == -EAGAIN) 882 if (rc == -EAGAIN)
865 rc = 0; 883 rc = 0;
@@ -1000,7 +1018,9 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu)
1000 rc = pin_blocks(vcpu, vsie_page); 1018 rc = pin_blocks(vcpu, vsie_page);
1001 if (rc) 1019 if (rc)
1002 goto out_unshadow; 1020 goto out_unshadow;
1021 register_shadow_scb(vcpu, vsie_page);
1003 rc = vsie_run(vcpu, vsie_page); 1022 rc = vsie_run(vcpu, vsie_page);
1023 unregister_shadow_scb(vcpu);
1004 unpin_blocks(vcpu, vsie_page); 1024 unpin_blocks(vcpu, vsie_page);
1005out_unshadow: 1025out_unshadow:
1006 unshadow_scb(vcpu, vsie_page); 1026 unshadow_scb(vcpu, vsie_page);
@@ -1039,3 +1059,18 @@ void kvm_s390_vsie_destroy(struct kvm *kvm)
1039 kvm->arch.vsie.page_count = 0; 1059 kvm->arch.vsie.page_count = 0;
1040 mutex_unlock(&kvm->arch.vsie.mutex); 1060 mutex_unlock(&kvm->arch.vsie.mutex);
1041} 1061}
1062
1063void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu)
1064{
1065 struct kvm_s390_sie_block *scb = READ_ONCE(vcpu->arch.vsie_block);
1066
1067 /*
1068 * Even if the VCPU lets go of the shadow sie block reference, it is
1069 * still valid in the cache. So we can safely kick it.
1070 */
1071 if (scb) {
1072 atomic_or(PROG_BLOCK_SIE, &scb->prog20);
1073 if (scb->prog0c & PROG_IN_SIE)
1074 atomic_or(CPUSTAT_STOP_INT, &scb->cpuflags);
1075 }
1076}