All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next)
@ 2016-11-28  9:06 Christian Borntraeger
  2016-11-28  9:06 ` [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load Christian Borntraeger
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Christian Borntraeger @ 2016-11-28  9:06 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář
  Cc: KVM, Christian Borntraeger, Cornelia Huck, Jens Freimann, linux-s390

Paolo, Radim,

several things in the making but not ready yet. So here is a very
small set of patches for the next merge window.

The following changes since commit 813ae37e6aed72cc457094b6066aa38efd66c9e9:

  Merge branch 'x86/cpufeature' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into kvm/next (2016-11-16 22:07:36 +0100)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git  tags/kvm-s390-next-4.10-1

for you to fetch changes up to e1788bb995befed5831c99cee6527dfb080a46c0:

  KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load (2016-11-22 19:32:35 +0100)

----------------------------------------------------------------
KVM: s390: Changes for 4.10 (via kvm/next)

Two small optimizations to not do register reloading in
vcpu_put/get, instead do it in the ioctl path. This reduces
the overhead for schedule-intense workload that does not
exit to QEMU. (e.g. KVM guest with eventfd/irqfd that
does a lot of context switching with vhost or iothreads).

----------------------------------------------------------------
Christian Borntraeger (2):
      KVM: s390: handle access registers in the run ioctl not in vcpu_put/load
      KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load

 arch/s390/kvm/interrupt.c |  2 +-
 arch/s390/kvm/kvm-s390.c  | 57 +++++++++++++++++++++--------------------------
 2 files changed, 27 insertions(+), 32 deletions(-)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load
  2016-11-28  9:06 [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Christian Borntraeger
@ 2016-11-28  9:06 ` Christian Borntraeger
  2016-12-01 12:28   ` David Hildenbrand
  2016-11-28  9:06 ` [GIT PULL 2/2] KVM: s390: handle floating point " Christian Borntraeger
  2016-11-30 17:20 ` [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Radim Krčmář
  2 siblings, 1 reply; 7+ messages in thread
From: Christian Borntraeger @ 2016-11-28  9:06 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář
  Cc: KVM, Christian Borntraeger, Cornelia Huck, Jens Freimann, linux-s390

Right now we save the host access registers in kvm_arch_vcpu_load
and load them in kvm_arch_vcpu_put. Vice versa for the guest access
registers. On schedule this means, that we load/save access registers
multiple times.

e.g. VCPU_RUN with just one reschedule and then return does

[from user space via VCPU_RUN]
- save the host registers in kvm_arch_vcpu_load (via ioctl)
- load the guest registers in kvm_arch_vcpu_load (via ioctl)
- do guest stuff
- decide to schedule/sleep
- save the guest registers in kvm_arch_vcpu_put (via sched)
- load the host registers in kvm_arch_vcpu_put (via sched)
- save the host registers in switch_to (via sched)
- schedule
- return
- load the host registers in switch_to (via sched)
- save the host registers in kvm_arch_vcpu_load (via sched)
- load the guest registers in kvm_arch_vcpu_load (via sched)
- do guest stuff
- decide to go to userspace
- save the guest registers in kvm_arch_vcpu_put (via ioctl)
- load the host registers in kvm_arch_vcpu_put (via ioctl)
[back to user space]

As the kernel does not use access registers, we can avoid
this reloading and simply piggy back on switch_to (let it save
the guest values instead of host values in thread.acrs) by
moving the host/guest switch into the VCPU_RUN ioctl function.
We now do

[from user space via VCPU_RUN]
- save the host registers in kvm_arch_vcpu_ioctl_run
- load the guest registers in kvm_arch_vcpu_ioctl_run
- do guest stuff
- decide to schedule/sleep
- save the guest registers in switch_to
- schedule
- return
- load the guest registers in switch_to (via sched)
- do guest stuff
- decide to go to userspace
- save the guest registers in kvm_arch_vcpu_ioctl_run
- load the host registers in kvm_arch_vcpu_ioctl_run

This seems to save about 10% of the vcpu_put/load functions
according to perf.

As vcpu_load no longer switches the acrs, We can also loading
the acrs in kvm_arch_vcpu_ioctl_set_sregs.

Suggested-by: Fan Zhang <zhangfan@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/kvm/interrupt.c |  2 +-
 arch/s390/kvm/kvm-s390.c  | 12 +++++-------
 2 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index be4db07..af13f1a 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -415,7 +415,7 @@ static int __write_machine_check(struct kvm_vcpu *vcpu,
 	int rc;
 
 	mci.val = mchk->mcic;
-	/* take care of lazy register loading via vcpu load/put */
+	/* take care of lazy register loading */
 	save_fpu_regs();
 	save_access_regs(vcpu->run->s.regs.acrs);
 
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 9c7a1ec..4105e1e 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1826,8 +1826,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 		/* User space provided an invalid FPC, let's clear it */
 		current->thread.fpu.fpc = 0;
 
-	save_access_regs(vcpu->arch.host_acrs);
-	restore_access_regs(vcpu->run->s.regs.acrs);
 	gmap_enable(vcpu->arch.enabled_gmap);
 	atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
@@ -1851,9 +1849,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	/* Restore host register state */
 	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
 	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
-
-	save_access_regs(vcpu->run->s.regs.acrs);
-	restore_access_regs(vcpu->arch.host_acrs);
 }
 
 static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
@@ -2243,7 +2238,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 {
 	memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
 	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
-	restore_access_regs(vcpu->run->s.regs.acrs);
 	return 0;
 }
 
@@ -2740,6 +2734,8 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 		if (riccb->valid)
 			vcpu->arch.sie_block->ecb3 |= 0x01;
 	}
+	save_access_regs(vcpu->arch.host_acrs);
+	restore_access_regs(vcpu->run->s.regs.acrs);
 
 	kvm_run->kvm_dirty_regs = 0;
 }
@@ -2758,6 +2754,8 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	kvm_run->s.regs.pft = vcpu->arch.pfault_token;
 	kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
 	kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
+	save_access_regs(vcpu->run->s.regs.acrs);
+	restore_access_regs(vcpu->arch.host_acrs);
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -2874,7 +2872,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
 {
 	/*
 	 * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy
-	 * copying in vcpu load/put. Lets update our copies before we save
+	 * switch in the run ioctl. Let's update our copies before we save
 	 * it into the save area
 	 */
 	save_fpu_regs();
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [GIT PULL 2/2] KVM: s390: handle floating point registers in the run ioctl not in vcpu_put/load
  2016-11-28  9:06 [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Christian Borntraeger
  2016-11-28  9:06 ` [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load Christian Borntraeger
@ 2016-11-28  9:06 ` Christian Borntraeger
  2016-11-30 17:20 ` [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Radim Krčmář
  2 siblings, 0 replies; 7+ messages in thread
From: Christian Borntraeger @ 2016-11-28  9:06 UTC (permalink / raw)
  To: Paolo Bonzini, Radim Krčmář
  Cc: KVM, Christian Borntraeger, Cornelia Huck, Jens Freimann, linux-s390

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>
---
 arch/s390/kvm/kvm-s390.c | 45 +++++++++++++++++++++------------------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 4105e1e..bec71e9 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)
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
-	/* Save host register state */
-	save_fpu_regs();
-	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
-	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
-
-	if (MACHINE_HAS_VX)
-		current->thread.fpu.regs = vcpu->run->s.regs.vrs;
-	else
-		current->thread.fpu.regs = vcpu->run->s.regs.fprs;
-	current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
-	if (test_fp_ctl(current->thread.fpu.fpc))
-		/* User space provided an invalid FPC, let's clear it */
-		current->thread.fpu.fpc = 0;
 
 	gmap_enable(vcpu->arch.enabled_gmap);
 	atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
@@ -1842,13 +1829,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	vcpu->arch.enabled_gmap = gmap_get_enabled();
 	gmap_disable(vcpu->arch.enabled_gmap);
 
-	/* Save guest register state */
-	save_fpu_regs();
-	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
-
-	/* Restore host register state */
-	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
-	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
 }
 
 static 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,
 
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-	/* make sure the new values will be lazily loaded */
-	save_fpu_regs();
 	if (test_fp_ctl(fpu->fpc))
 		return -EINVAL;
-	current->thread.fpu.fpc = fpu->fpc;
+	vcpu->run->s.regs.fpc = fpu->fpc;
 	if (MACHINE_HAS_VX)
 		convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
 				 (freg_t *) fpu->fprs);
@@ -2273,7 +2251,7 @@ int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 				 (__vector128 *) vcpu->run->s.regs.vrs);
 	else
 		memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs));
-	fpu->fpc = current->thread.fpu.fpc;
+	fpu->fpc = vcpu->run->s.regs.fpc;
 	return 0;
 }
 
@@ -2736,6 +2714,18 @@ static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	}
 	save_access_regs(vcpu->arch.host_acrs);
 	restore_access_regs(vcpu->run->s.regs.acrs);
+	/* save host (userspace) fprs/vrs */
+	save_fpu_regs();
+	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
+	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
+	if (MACHINE_HAS_VX)
+		current->thread.fpu.regs = vcpu->run->s.regs.vrs;
+	else
+		current->thread.fpu.regs = vcpu->run->s.regs.fprs;
+	current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
+	if (test_fp_ctl(current->thread.fpu.fpc))
+		/* User space provided an invalid FPC, let's clear it */
+		current->thread.fpu.fpc = 0;
 
 	kvm_run->kvm_dirty_regs = 0;
 }
@@ -2756,6 +2746,13 @@ static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 	kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
 	save_access_regs(vcpu->run->s.regs.acrs);
 	restore_access_regs(vcpu->arch.host_acrs);
+	/* Save guest register state */
+	save_fpu_regs();
+	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
+	/* Restore will be done lazily at return */
+	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
+	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
+
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next)
  2016-11-28  9:06 [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Christian Borntraeger
  2016-11-28  9:06 ` [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load Christian Borntraeger
  2016-11-28  9:06 ` [GIT PULL 2/2] KVM: s390: handle floating point " Christian Borntraeger
@ 2016-11-30 17:20 ` Radim Krčmář
  2 siblings, 0 replies; 7+ messages in thread
From: Radim Krčmář @ 2016-11-30 17:20 UTC (permalink / raw)
  To: Christian Borntraeger
  Cc: Paolo Bonzini, KVM, Cornelia Huck, Jens Freimann, linux-s390

2016-11-28 10:06+0100, Christian Borntraeger:
> Paolo, Radim,
> 
> several things in the making but not ready yet. So here is a very
> small set of patches for the next merge window.

Pulled, thanks.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load
  2016-11-28  9:06 ` [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load Christian Borntraeger
@ 2016-12-01 12:28   ` David Hildenbrand
  2016-12-01 12:38     ` Christian Borntraeger
  0 siblings, 1 reply; 7+ messages in thread
From: David Hildenbrand @ 2016-12-01 12:28 UTC (permalink / raw)
  To: Christian Borntraeger, Paolo Bonzini, Radim Krčmář
  Cc: KVM, Cornelia Huck, Jens Freimann, linux-s390

Am 28.11.2016 um 10:06 schrieb Christian Borntraeger:
> Right now we save the host access registers in kvm_arch_vcpu_load
> and load them in kvm_arch_vcpu_put. Vice versa for the guest access
> registers. On schedule this means, that we load/save access registers
> multiple times.

Wasn't the main point about this to also protect from scheduling
another VCPU (maybe even from another VM)? (which in return would have
its own set of access registers and therefore would now use the wrong
set of access registers)

Must likely I am forgetting something very important here :)

-- 

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load
  2016-12-01 12:28   ` David Hildenbrand
@ 2016-12-01 12:38     ` Christian Borntraeger
  2016-12-01 12:41       ` David Hildenbrand
  0 siblings, 1 reply; 7+ messages in thread
From: Christian Borntraeger @ 2016-12-01 12:38 UTC (permalink / raw)
  To: David Hildenbrand, Paolo Bonzini, Radim Krčmář
  Cc: KVM, Cornelia Huck, Jens Freimann, linux-s390

On 12/01/2016 01:28 PM, David Hildenbrand wrote:
> Am 28.11.2016 um 10:06 schrieb Christian Borntraeger:
>> Right now we save the host access registers in kvm_arch_vcpu_load
>> and load them in kvm_arch_vcpu_put. Vice versa for the guest access
>> registers. On schedule this means, that we load/save access registers
>> multiple times.
> 
> Wasn't the main point about this to also protect from scheduling
> another VCPU (maybe even from another VM)? (which in return would have
> its own set of access registers and therefore would now use the wrong
> set of access registers)

The thing is that the scheduler already loads and save old/new registers
(see arch/s390/include/asm/switch_to.h), so the new process will get
its correct registers. The only difference is that we store in
prev->thread.acrs[0] now the guest registers of prev instead of the host
registers of prev. But the host registers have been taken care of by KVM.



> 
> Must likely I am forgetting something very important here :)
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load
  2016-12-01 12:38     ` Christian Borntraeger
@ 2016-12-01 12:41       ` David Hildenbrand
  0 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2016-12-01 12:41 UTC (permalink / raw)
  To: Christian Borntraeger, Paolo Bonzini, Radim Krčmář
  Cc: KVM, Cornelia Huck, Jens Freimann, linux-s390

Am 01.12.2016 um 13:38 schrieb Christian Borntraeger:
> On 12/01/2016 01:28 PM, David Hildenbrand wrote:
>> Am 28.11.2016 um 10:06 schrieb Christian Borntraeger:
>>> Right now we save the host access registers in kvm_arch_vcpu_load
>>> and load them in kvm_arch_vcpu_put. Vice versa for the guest access
>>> registers. On schedule this means, that we load/save access registers
>>> multiple times.
>>
>> Wasn't the main point about this to also protect from scheduling
>> another VCPU (maybe even from another VM)? (which in return would have
>> its own set of access registers and therefore would now use the wrong
>> set of access registers)
>
> The thing is that the scheduler already loads and save old/new registers
> (see arch/s390/include/asm/switch_to.h), so the new process will get
> its correct registers. The only difference is that we store in
> prev->thread.acrs[0] now the guest registers of prev instead of the host
> registers of prev. But the host registers have been taken care of by KVM.
>

Cool, thanks for the explanation. So this makes very much sense.

-- 

David

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2016-12-01 12:41 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-28  9:06 [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Christian Borntraeger
2016-11-28  9:06 ` [GIT PULL 1/2] KVM: s390: handle access registers in the run ioctl not in vcpu_put/load Christian Borntraeger
2016-12-01 12:28   ` David Hildenbrand
2016-12-01 12:38     ` Christian Borntraeger
2016-12-01 12:41       ` David Hildenbrand
2016-11-28  9:06 ` [GIT PULL 2/2] KVM: s390: handle floating point " Christian Borntraeger
2016-11-30 17:20 ` [GIT PULL 0/2] KVM: s390: Changes for 4.10 (via kvm/next) Radim Krčmář

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.