mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 03:10:12 +00:00
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>
This commit is contained in:
parent
1b7029bec1
commit
adbf16985c
4 changed files with 43 additions and 0 deletions
|
@ -549,6 +549,8 @@ struct kvm_guestdbg_info_arch {
|
|||
|
||||
struct kvm_vcpu_arch {
|
||||
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];
|
||||
struct fpu host_fpregs;
|
||||
struct kvm_s390_local_interrupt local_int;
|
||||
|
|
|
@ -995,6 +995,11 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu)
|
|||
swake_up(&vcpu->wq);
|
||||
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)
|
||||
|
|
|
@ -254,6 +254,7 @@ int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
|
|||
|
||||
/* implemented in vsie.c */
|
||||
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,
|
||||
unsigned long end);
|
||||
void kvm_s390_vsie_init(struct kvm *kvm);
|
||||
|
|
|
@ -837,6 +837,23 @@ static int acquire_gmap_shadow(struct kvm_vcpu *vcpu,
|
|||
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
|
||||
* prefix pages and faults.
|
||||
|
@ -860,6 +877,7 @@ static int vsie_run(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
|
|||
rc = do_vsie_run(vcpu, vsie_page);
|
||||
gmap_enable(vcpu->arch.gmap);
|
||||
}
|
||||
atomic_andnot(PROG_BLOCK_SIE, &scb_s->prog20);
|
||||
|
||||
if (rc == -EAGAIN)
|
||||
rc = 0;
|
||||
|
@ -1000,7 +1018,9 @@ int kvm_s390_handle_vsie(struct kvm_vcpu *vcpu)
|
|||
rc = pin_blocks(vcpu, vsie_page);
|
||||
if (rc)
|
||||
goto out_unshadow;
|
||||
register_shadow_scb(vcpu, vsie_page);
|
||||
rc = vsie_run(vcpu, vsie_page);
|
||||
unregister_shadow_scb(vcpu);
|
||||
unpin_blocks(vcpu, vsie_page);
|
||||
out_unshadow:
|
||||
unshadow_scb(vcpu, vsie_page);
|
||||
|
@ -1039,3 +1059,18 @@ void kvm_s390_vsie_destroy(struct kvm *kvm)
|
|||
kvm->arch.vsie.page_count = 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue