aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Borntraeger <borntraeger@de.ibm.com>2016-11-22 03:29:38 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-11-22 13:32:35 -0500
commite1788bb995befed5831c99cee6527dfb080a46c0 (patch)
tree62cfe675eaef6a446b0c25724fcdee6be5257051
parent31d8b8d41a7e3e8db081972a63ef1de276ef8ab4 (diff)
KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load
Right now we switch the host fprs/vrs in kvm_arch_vcpu_load and switch back in kvm_arch_vcpu_put. This process is already optimized since commit 9977e886cbbc7 ("s390/kernel: lazy restore fpu registers") avoiding double save/restores on schedule. We still reload the pointers and test the guest fpc on each context switch, though. We can minimize the cost of vcpu_load/put by doing the test in the VCPU_RUN ioctl itself. As most VCPU threads almost never exit to userspace in the common fast path, this allows to avoid this overhead for the common case (eventfd driven I/O, all exits including sleep handled in the kernel) - making kvm_arch_vcpu_load/put basically disappear in perf top. Also adapt the fpu get/set ioctls. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/kvm/kvm-s390.c45
1 files changed, 21 insertions, 24 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 4105e1ea8dda..bec71e902be3 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1812,19 +1812,6 @@ __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)
1812 1812
1813void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 1813void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
1814{ 1814{
1815 /* Save host register state */
1816 save_fpu_regs();
1817 vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
1818 vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
1819
1820 if (MACHINE_HAS_VX)
1821 current->thread.fpu.regs = vcpu->run->s.regs.vrs;
1822 else
1823 current->thread.fpu.regs = vcpu->run->s.regs.fprs;
1824 current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
1825 if (test_fp_ctl(current->thread.fpu.fpc))
1826 /* User space provided an invalid FPC, let's clear it */
1827 current->thread.fpu.fpc = 0;
1828 1815
1829 gmap_enable(vcpu->arch.enabled_gmap); 1816 gmap_enable(vcpu->arch.enabled_gmap);
1830 atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); 1817 atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -1842,13 +1829,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
1842 vcpu->arch.enabled_gmap = gmap_get_enabled(); 1829 vcpu->arch.enabled_gmap = gmap_get_enabled();
1843 gmap_disable(vcpu->arch.enabled_gmap); 1830 gmap_disable(vcpu->arch.enabled_gmap);
1844 1831
1845 /* Save guest register state */
1846 save_fpu_regs();
1847 vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
1848
1849 /* Restore host register state */
1850 current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
1851 current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
1852} 1832}
1853 1833
1854static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) 1834static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
@@ -2251,11 +2231,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
2251 2231
2252int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 2232int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
2253{ 2233{
2254 /* make sure the new values will be lazily loaded */
2255 save_fpu_regs();
2256 if (test_fp_ctl(fpu->fpc)) 2234 if (test_fp_ctl(fpu->fpc))
2257 return -EINVAL; 2235 return -EINVAL;
2258 current->thread.fpu.fpc = fpu->fpc; 2236 vcpu->run->s.regs.fpc = fpu->fpc;
2259 if (MACHINE_HAS_VX) 2237 if (MACHINE_HAS_VX)
2260 convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs, 2238 convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
2261 (freg_t *) fpu->fprs); 2239 (freg_t *) fpu->fprs);
@@ -2273,7 +2251,7 @@ int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
2273 (__vector128 *) vcpu->run->s.regs.vrs); 2251 (__vector128 *) vcpu->run->s.regs.vrs);
2274 else 2252 else
2275 memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs)); 2253 memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs));
2276 fpu->fpc = current->thread.fpu.fpc; 2254 fpu->fpc = vcpu->run->s.regs.fpc;
2277 return 0; 2255 return 0;
2278} 2256}
2279 2257
@@ -2736,6 +2714,18 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2736 } 2714 }
2737 save_access_regs(vcpu->arch.host_acrs); 2715 save_access_regs(vcpu->arch.host_acrs);
2738 restore_access_regs(vcpu->run->s.regs.acrs); 2716 restore_access_regs(vcpu->run->s.regs.acrs);
2717 /* save host (userspace) fprs/vrs */
2718 save_fpu_regs();
2719 vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
2720 vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
2721 if (MACHINE_HAS_VX)
2722 current->thread.fpu.regs = vcpu->run->s.regs.vrs;
2723 else
2724 current->thread.fpu.regs = vcpu->run->s.regs.fprs;
2725 current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
2726 if (test_fp_ctl(current->thread.fpu.fpc))
2727 /* User space provided an invalid FPC, let's clear it */
2728 current->thread.fpu.fpc = 0;
2739 2729
2740 kvm_run->kvm_dirty_regs = 0; 2730 kvm_run->kvm_dirty_regs = 0;
2741} 2731}
@@ -2756,6 +2746,13 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
2756 kvm_run->s.regs.pfc = vcpu->arch.pfault_compare; 2746 kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
2757 save_access_regs(vcpu->run->s.regs.acrs); 2747 save_access_regs(vcpu->run->s.regs.acrs);
2758 restore_access_regs(vcpu->arch.host_acrs); 2748 restore_access_regs(vcpu->arch.host_acrs);
2749 /* Save guest register state */
2750 save_fpu_regs();
2751 vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
2752 /* Restore will be done lazily at return */
2753 current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
2754 current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
2755
2759} 2756}
2760 2757
2761int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 2758int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)