Commit adbf1698 authored by David Hildenbrand's avatar David Hildenbrand Committed by Christian Borntraeger

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: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent 1b7029be
...@@ -549,6 +549,8 @@ struct kvm_guestdbg_info_arch { ...@@ -549,6 +549,8 @@ struct kvm_guestdbg_info_arch {
struct kvm_vcpu_arch { struct kvm_vcpu_arch {
struct kvm_s390_sie_block *sie_block; struct kvm_s390_sie_block *sie_block;
/* if vsie is active, currently executed shadow sie control block */
struct kvm_s390_sie_block *vsie_block;
unsigned int host_acrs[NUM_ACRS]; unsigned int host_acrs[NUM_ACRS];
struct fpu host_fpregs; struct fpu host_fpregs;
struct kvm_s390_local_interrupt local_int; struct kvm_s390_local_interrupt local_int;
......
...@@ -995,6 +995,11 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) ...@@ -995,6 +995,11 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
swake_up(&vcpu->wq); swake_up(&vcpu->wq);
vcpu->stat.halt_wakeup++; vcpu->stat.halt_wakeup++;
} }
/*
* The VCPU might not be sleeping but is executing the VSIE. Let's
* kick it, so it leaves the SIE to process the request.
*/
kvm_s390_vsie_kick(vcpu);
} }
enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer)
......
...@@ -254,6 +254,7 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); ...@@ -254,6 +254,7 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
/* implemented in vsie.c */ /* implemented in vsie.c */
int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu);
void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu);
void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start,
unsigned long end); unsigned long end);
void kvm_s390_vsie_init(struct kvm *kvm); void kvm_s390_vsie_init(struct kvm *kvm);
......
...@@ -837,6 +837,23 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu, ...@@ -837,6 +837,23 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
return 0; return 0;
} }
/*
* Register the shadow scb at the VCPU, e.g. for kicking out of vsie.
*/
static void register_shadow_scb(struct kvm_vcpu *vcpu,
struct vsie_page *vsie_page)
{
WRITE_ONCE(vcpu->arch.vsie_block, &vsie_page->scb_s);
}
/*
* Unregister a shadow scb from a VCPU.
*/
static void unregister_shadow_scb(struct kvm_vcpu *vcpu)
{
WRITE_ONCE(vcpu->arch.vsie_block, NULL);
}
/* /*
* Run the vsie on a shadowed scb, managing the gmap shadow, handling * Run the vsie on a shadowed scb, managing the gmap shadow, handling
* prefix pages and faults. * prefix pages and faults.
...@@ -860,6 +877,7 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) ...@@ -860,6 +877,7 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
rc = do_vsie_run(vcpu, vsie_page); rc = do_vsie_run(vcpu, vsie_page);
gmap_enable(vcpu->arch.gmap); gmap_enable(vcpu->arch.gmap);
} }
atomic_andnot(PROG_BLOCK_SIE, &scb_s->prog20);
if (rc == -EAGAIN) if (rc == -EAGAIN)
rc = 0; rc = 0;
...@@ -1000,7 +1018,9 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu) ...@@ -1000,7 +1018,9 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu)
rc = pin_blocks(vcpu, vsie_page); rc = pin_blocks(vcpu, vsie_page);
if (rc) if (rc)
goto out_unshadow; goto out_unshadow;
register_shadow_scb(vcpu, vsie_page);
rc = vsie_run(vcpu, vsie_page); rc = vsie_run(vcpu, vsie_page);
unregister_shadow_scb(vcpu);
unpin_blocks(vcpu, vsie_page); unpin_blocks(vcpu, vsie_page);
out_unshadow: out_unshadow:
unshadow_scb(vcpu, vsie_page); unshadow_scb(vcpu, vsie_page);
...@@ -1039,3 +1059,18 @@ void kvm_s390_vsie_destroy(struct kvm *kvm) ...@@ -1039,3 +1059,18 @@ void kvm_s390_vsie_destroy(struct kvm *kvm)
kvm->arch.vsie.page_count = 0; kvm->arch.vsie.page_count = 0;
mutex_unlock(&kvm->arch.vsie.mutex); mutex_unlock(&kvm->arch.vsie.mutex);
} }
void kvm_s390_vsie_kick(struct kvm_vcpu *vcpu)
{
struct kvm_s390_sie_block *scb = READ_ONCE(vcpu->arch.vsie_block);
/*
* Even if the VCPU lets go of the shadow sie block reference, it is
* still valid in the cache. So we can safely kick it.
*/
if (scb) {
atomic_or(PROG_BLOCK_SIE, &scb->prog20);
if (scb->prog0c & PROG_IN_SIE)
atomic_or(CPUSTAT_STOP_INT, &scb->cpuflags);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment