Instead of creating a full shadow for vSIE control blocks only create a minimal shadow for SIGP purposes for currently not running guest-3 control blocks. This reduces the overhead to shadow the whole guest-3 configuration. The minimal shadow only contains the information needed for SIGPI and SRSI. The shadow will still be recreated fully when a vSIE is entered with that SCB later. Signed-off-by: Christoph Schlameuss --- arch/s390/kvm/vsie.c | 54 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index a1b679b4aa36..3a7c58dddf22 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -365,8 +365,7 @@ static void update_intervention_requests(struct vsie_page *vsie_page) static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; - struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; - int newflags, cpuflags = atomic_read(&scb_o->cpuflags); + int newflags, cpuflags = atomic_read(&vsie_page->scb_o->cpuflags); /* we don't allow ESA/390 guests unless explicitly enabled */ if (!(cpuflags & CPUSTAT_ZARCH) && !vcpu->kvm->arch.allow_vsie_esamode) @@ -709,6 +708,39 @@ static void unshadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) scb_o->ihcpu = scb_s->ihcpu; } +static int shadow_scb_minimal(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +{ + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; + int rc; + + /* make sure we don't have any leftovers when reusing the scb */ + scb_s->icptcode = 0; + scb_s->eca = 0; + scb_s->ecb = 0; + scb_s->ecb2 = 0; + scb_s->ecb3 = 0; + scb_s->ecd = 0; + scb_s->fac = 0; + scb_s->fpf = 0; + + rc = prepare_cpuflags(vcpu, vsie_page); + if (rc) + return rc; + + scb_s->icpua = scb_o->icpua; + scb_s->ecb2 |= scb_o->ecb2 & ECB2_ESCA; + + if (vsie_page->vsie_sca) { + scb_s->eca |= scb_o->eca & ECA_SIGPI; + scb_s->ecb |= scb_o->ecb & ECB_SRSI; + write_scao(scb_s, virt_to_phys(&vsie_page->vsie_sca->ssca)); + scb_s->osda = virt_to_phys(scb_o); + } + + return 0; +} + /* * Setup the shadow scb by copying and checking the relevant parts of the g2 * provided scb. @@ -728,17 +760,7 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) unsigned long new_mso = 0; int rc; - /* make sure we don't have any leftovers when reusing the scb */ - scb_s->icptcode = 0; - scb_s->eca = 0; - scb_s->ecb = 0; - scb_s->ecb2 = 0; - scb_s->ecb3 = 0; - scb_s->ecd = 0; - scb_s->fac = 0; - scb_s->fpf = 0; - - rc = prepare_cpuflags(vcpu, vsie_page); + rc = shadow_scb_minimal(vcpu, vsie_page); if (rc) goto out; @@ -768,8 +790,6 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) if (!(atomic_read(&scb_s->cpuflags) & CPUSTAT_KSS)) scb_s->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; - scb_s->icpua = scb_o->icpua; - if (!(atomic_read(&scb_s->cpuflags) & CPUSTAT_ZARCH)) new_prefix &= GUEST_PREFIX_MASK_ESA; else @@ -2138,7 +2158,7 @@ static int _shadow_sca(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, __set_bit(VSIE_SCA_ESCA, &vsie_sca->flags); sca_mcn_copy(vsie_sca, phys_to_virt(sca_o_hpa(vsie_sca))); - /* pin and make shadow for ALL scb in the sca */ + /* pin and make minimal shadow for ALL scb in the sca */ cpu_slots = is_esca ? KVM_S390_MAX_VSIE_VCPUS : KVM_S390_BSCA_CPU_SLOTS; for_each_set_bit_inv(cpu_nr, (unsigned long *)&vsie_sca->mcn, cpu_slots) { rc = get_sca_entry_addr(vcpu->kvm, vsie_sca, cpu_nr, NULL, &sca_o_entry_hpa); @@ -2164,7 +2184,7 @@ static int _shadow_sca(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, rc = PTR_ERR(vsie_page_n); if (rc) goto err; - rc = shadow_scb(vcpu, vsie_page_n); + rc = shadow_scb_minimal(vcpu, vsie_page_n); vsie_sca_update(vsie_sca, cpu_nr, vsie_page_n, sca_o_entry_hpa); put_vsie_page(vsie_page_n); if (rc) -- 2.55.0