diff options
author | David Hildenbrand <dahi@linux.vnet.ibm.com> | 2016-05-27 16:03:52 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2016-06-21 03:43:44 -0400 |
commit | adbf16985c387851fd3454ca34893705dbde7f98 (patch) | |
tree | da60441f03e9b218ea1a8f822b46558c2da92756 | |
parent | 1b7029bec18718eca8cfc5c1c0917444f019be1e (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.h | 2 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 5 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 1 | ||||
-rw-r--r-- | arch/s390/kvm/vsie.c | 35 |
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 | ||
550 | struct kvm_vcpu_arch { | 550 | struct 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 | ||
1000 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) | 1005 | enum 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 */ |
256 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); | 256 | int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); |
257 | void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu); | ||
257 | void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, | 258 | void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, |
258 | unsigned long end); | 259 | unsigned long end); |
259 | void kvm_s390_vsie_init(struct kvm *kvm); | 260 | void 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 | */ | ||
843 | static 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 | */ | ||
852 | static 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); |
1005 | out_unshadow: | 1025 | out_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 | |||
1063 | void 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 | } | ||