stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] KVM: s390: fix guest fprs memory leak
@ 2016-02-24 15:24 David Hildenbrand
  2016-02-24 15:24 ` [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled David Hildenbrand
  0 siblings, 1 reply; 5+ messages in thread
From: David Hildenbrand @ 2016-02-24 15:24 UTC (permalink / raw)
  To: stable; +Cc: dahi, borntraeger, farman, gregkh

This is the backport of 9c7ebb613bff ("KVM: s390: fix guest fprs memory
leak") for 4.4-stable.

fprs is never freed, therefore resulting in a memory leak if
kvm_vcpu_init() fails or the vcpu is destroyed.

Fixes: 9977e886cbbc ("s390/kernel: lazy restore fpu registers")
Cc: stable@vger.kernel.org # v4.3+
Reported-by: Eric Farman <farman@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Eric Farman <farman@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/kvm/kvm-s390.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 713a91a..db7cca5 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1202,6 +1202,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 	if (vcpu->kvm->arch.use_cmma)
 		kvm_s390_vcpu_unsetup_cmma(vcpu);
+	kfree(vcpu->arch.guest_fpregs.fprs);
 	free_page((unsigned long)(vcpu->arch.sie_block));
 
 	kvm_vcpu_uninit(vcpu);
@@ -1516,12 +1517,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
-		goto out_free_sie_block;
+		goto out_free_fprs;
 	VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
 		 vcpu->arch.sie_block);
 	trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block);
 
 	return vcpu;
+out_free_fprs:
+	kfree(vcpu->arch.guest_fpregs.fprs);
 out_free_sie_block:
 	free_page((unsigned long)(vcpu->arch.sie_block));
 out_free_cpu:
-- 
2.3.9


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

* [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled
  2016-02-24 15:24 [PATCH 1/2] KVM: s390: fix guest fprs memory leak David Hildenbrand
@ 2016-02-24 15:24 ` David Hildenbrand
  2016-03-01  5:06   ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: David Hildenbrand @ 2016-02-24 15:24 UTC (permalink / raw)
  To: stable; +Cc: dahi, borntraeger, farman, gregkh

This is the backport of 9abc2a08a7d6 (KVM: s390: fix memory overwrites
when vx is disabled) for 4.4-stable.

The kernel now always uses vector registers when available, however KVM
has special logic if support is really enabled for a guest. If support
is disabled, guest_fpregs.fregs will only contain memory for the fpu.
The kernel, however, will store vector registers into that area,
resulting in crazy memory overwrites.

Simply extending that area is not enough, because the format of the
registers also changes. We would have to do additional conversions, making
the code even more complex. Therefore let's directly use one place for
the vector/fpu registers + fpc (in kvm_run). We just have to convert the
data properly when accessing it. This makes current code much easier.

Please note that vector/fpu registers are now always stored to
vcpu->run->s.regs.vrs. Although this data is visible to QEMU and
used for migration, we only guarantee valid values to user space  when
KVM_SYNC_VRS is set. As that is only the case when we have vector
register support, we are on the safe side.

Fixes: b5510d9b68c3 ("s390/fpu: always enable the vector facility if it is available")
Cc: stable@vger.kernel.org # v4.4 d9a3a09af54d s390/kvm: remove dependency on struct save_area definition
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
[adopt to d9a3a09af54d]
---
 arch/s390/include/asm/kvm_host.h |   1 -
 arch/s390/kvm/kvm-s390.c         | 128 +++++++++++++--------------------------
 2 files changed, 43 insertions(+), 86 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index efaac2c..e9a983f 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -506,7 +506,6 @@ struct kvm_vcpu_arch {
 	struct kvm_s390_sie_block *sie_block;
 	unsigned int      host_acrs[NUM_ACRS];
 	struct fpu	  host_fpregs;
-	struct fpu	  guest_fpregs;
 	struct kvm_s390_local_interrupt local_int;
 	struct hrtimer    ckc_timer;
 	struct kvm_s390_pgm_info pgm;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index db7cca5..a08d0af 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1202,7 +1202,6 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 
 	if (vcpu->kvm->arch.use_cmma)
 		kvm_s390_vcpu_unsetup_cmma(vcpu);
-	kfree(vcpu->arch.guest_fpregs.fprs);
 	free_page((unsigned long)(vcpu->arch.sie_block));
 
 	kvm_vcpu_uninit(vcpu);
@@ -1269,44 +1268,18 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 	return 0;
 }
 
-/*
- * Backs up the current FP/VX register save area on a particular
- * destination.  Used to switch between different register save
- * areas.
- */
-static inline void save_fpu_to(struct fpu *dst)
-{
-	dst->fpc = current->thread.fpu.fpc;
-	dst->regs = current->thread.fpu.regs;
-}
-
-/*
- * Switches the FP/VX register save area from which to lazy
- * restore register contents.
- */
-static inline void load_fpu_from(struct fpu *from)
-{
-	current->thread.fpu.fpc = from->fpc;
-	current->thread.fpu.regs = from->regs;
-}
-
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
 	/* Save host register state */
 	save_fpu_regs();
-	save_fpu_to(&vcpu->arch.host_fpregs);
-
-	if (test_kvm_facility(vcpu->kvm, 129)) {
-		current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
-		/*
-		 * Use the register save area in the SIE-control block
-		 * for register restore and save in kvm_arch_vcpu_put()
-		 */
-		current->thread.fpu.vxrs =
-			(__vector128 *)&vcpu->run->s.regs.vrs;
-	} else
-		load_fpu_from(&vcpu->arch.guest_fpregs);
+	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
+	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
 
+	/* Depending on MACHINE_HAS_VX, data stored to vrs either
+	 * has vector register or floating point register format.
+	 */
+	current->thread.fpu.regs = vcpu->run->s.regs.vrs;
+	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;
@@ -1322,19 +1295,13 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	gmap_disable(vcpu->arch.gmap);
 
+	/* Save guest register state */
 	save_fpu_regs();
+	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
 
-	if (test_kvm_facility(vcpu->kvm, 129))
-		/*
-		 * kvm_arch_vcpu_load() set up the register save area to
-		 * the &vcpu->run->s.regs.vrs and, thus, the vector registers
-		 * are already saved.  Only the floating-point control must be
-		 * copied.
-		 */
-		vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
-	else
-		save_fpu_to(&vcpu->arch.guest_fpregs);
-	load_fpu_from(&vcpu->arch.host_fpregs);
+	/* 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);
@@ -1352,8 +1319,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 	memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
 	vcpu->arch.sie_block->gcr[0]  = 0xE0UL;
 	vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
-	vcpu->arch.guest_fpregs.fpc = 0;
-	asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
+	/* make sure the new fpc will be lazily loaded */
+	save_fpu_regs();
+	current->thread.fpu.fpc = 0;
 	vcpu->arch.sie_block->gbea = 1;
 	vcpu->arch.sie_block->pp = 0;
 	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
@@ -1502,29 +1470,14 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
 	vcpu->arch.local_int.wq = &vcpu->wq;
 	vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
 
-	/*
-	 * Allocate a save area for floating-point registers.  If the vector
-	 * extension is available, register contents are saved in the SIE
-	 * control block.  The allocated save area is still required in
-	 * particular places, for example, in kvm_s390_vcpu_store_status().
-	 */
-	vcpu->arch.guest_fpregs.fprs = kzalloc(sizeof(freg_t) * __NUM_FPRS,
-					       GFP_KERNEL);
-	if (!vcpu->arch.guest_fpregs.fprs) {
-		rc = -ENOMEM;
-		goto out_free_sie_block;
-	}
-
 	rc = kvm_vcpu_init(vcpu, kvm, id);
 	if (rc)
-		goto out_free_fprs;
+		goto out_free_sie_block;
 	VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
 		 vcpu->arch.sie_block);
 	trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block);
 
 	return vcpu;
-out_free_fprs:
-	kfree(vcpu->arch.guest_fpregs.fprs);
 out_free_sie_block:
 	free_page((unsigned long)(vcpu->arch.sie_block));
 out_free_cpu:
@@ -1737,19 +1690,27 @@ 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;
-	memcpy(vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
-	vcpu->arch.guest_fpregs.fpc = fpu->fpc;
-	save_fpu_regs();
-	load_fpu_from(&vcpu->arch.guest_fpregs);
+	current->thread.fpu.fpc = fpu->fpc;
+	if (MACHINE_HAS_VX)
+		convert_fp_to_vx(current->thread.fpu.vxrs, (freg_t *)fpu->fprs);
+	else
+		memcpy(current->thread.fpu.fprs, &fpu->fprs, sizeof(fpu->fprs));
 	return 0;
 }
 
 int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-	memcpy(&fpu->fprs, vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
-	fpu->fpc = vcpu->arch.guest_fpregs.fpc;
+	/* make sure we have the latest values */
+	save_fpu_regs();
+	if (MACHINE_HAS_VX)
+		convert_vx_to_fp((freg_t *)fpu->fprs, current->thread.fpu.vxrs);
+	else
+		memcpy(fpu->fprs, current->thread.fpu.fprs, sizeof(fpu->fprs));
+	fpu->fpc = current->thread.fpu.fpc;
 	return 0;
 }
 
@@ -2269,6 +2230,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
 {
 	unsigned char archmode = 1;
+	freg_t fprs[NUM_FPRS];
 	unsigned int px;
 	u64 clkcomp;
 	int rc;
@@ -2284,8 +2246,16 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
 		gpa = px;
 	} else
 		gpa -= __LC_FPREGS_SAVE_AREA;
-	rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
-			     vcpu->arch.guest_fpregs.fprs, 128);
+
+	/* manually convert vector registers if necessary */
+	if (MACHINE_HAS_VX) {
+		convert_vx_to_fp(fprs, current->thread.fpu.vxrs);
+		rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
+				     fprs, 128);
+	} else {
+		rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
+				     vcpu->run->s.regs.vrs, 128);
+	}
 	rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
 			      vcpu->run->s.regs.gprs, 128);
 	rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA,
@@ -2293,7 +2263,7 @@ int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
 	rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA,
 			      &px, 4);
 	rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA,
-			      &vcpu->arch.guest_fpregs.fpc, 4);
+			      &vcpu->run->s.regs.fpc, 4);
 	rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
 			      &vcpu->arch.sie_block->todpr, 4);
 	rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
@@ -2316,19 +2286,7 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
 	 * it into the save area
 	 */
 	save_fpu_regs();
-	if (test_kvm_facility(vcpu->kvm, 129)) {
-		/*
-		 * If the vector extension is available, the vector registers
-		 * which overlaps with floating-point registers are saved in
-		 * the SIE-control block.  Hence, extract the floating-point
-		 * registers and the FPC value and store them in the
-		 * guest_fpregs structure.
-		 */
-		vcpu->arch.guest_fpregs.fpc = current->thread.fpu.fpc;
-		convert_vx_to_fp(vcpu->arch.guest_fpregs.fprs,
-				 current->thread.fpu.vxrs);
-	} else
-		save_fpu_to(&vcpu->arch.guest_fpregs);
+	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
 	save_access_regs(vcpu->run->s.regs.acrs);
 
 	return kvm_s390_store_status_unloaded(vcpu, addr);
-- 
2.3.9


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

* Re: [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled
  2016-02-24 15:24 ` [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled David Hildenbrand
@ 2016-03-01  5:06   ` Greg KH
  2016-03-01  7:19     ` David Hildenbrand
  0 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2016-03-01  5:06 UTC (permalink / raw)
  To: David Hildenbrand; +Cc: stable, borntraeger, farman

On Wed, Feb 24, 2016 at 04:24:55PM +0100, David Hildenbrand wrote:
> This is the backport of 9abc2a08a7d6 (KVM: s390: fix memory overwrites
> when vx is disabled) for 4.4-stable.

This backport didn't apply:

Applying kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch to linux-4.4.y
Applying patch kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch
patching file arch/s390/include/asm/kvm_host.h
patching file arch/s390/kvm/kvm-s390.c
Hunk #8 FAILED at 2246.
Hunk #9 FAILED at 2255.
2 out of 10 hunks FAILED -- rejects in file arch/s390/kvm/kvm-s390.c

Can you try it again?

thanks,

greg k-h

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

* Re: [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled
  2016-03-01  5:06   ` Greg KH
@ 2016-03-01  7:19     ` David Hildenbrand
  2016-03-01  8:16       ` Greg KH
  0 siblings, 1 reply; 5+ messages in thread
From: David Hildenbrand @ 2016-03-01  7:19 UTC (permalink / raw)
  To: Greg KH; +Cc: stable, borntraeger, farman

> On Wed, Feb 24, 2016 at 04:24:55PM +0100, David Hildenbrand wrote:
> > This is the backport of 9abc2a08a7d6 (KVM: s390: fix memory overwrites
> > when vx is disabled) for 4.4-stable.  
> 
> This backport didn't apply:
> 
> Applying kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch to linux-4.4.y
> Applying patch kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch
> patching file arch/s390/include/asm/kvm_host.h
> patching file arch/s390/kvm/kvm-s390.c
> Hunk #8 FAILED at 2246.
> Hunk #9 FAILED at 2255.
> 2 out of 10 hunks FAILED -- rejects in file arch/s390/kvm/kvm-s390.c
> 
> Can you try it again?
> 
> thanks,
> 
> greg k-h
> 

Hi Greg,

did you take care of the mentioned precondition?

# v4.4 d9a3a09af54d s390/kvm: remove dependency on struct save_area definition

But as I just received the mail saying this patch has been added to 4.4, I
assume that this problems is solved :)

Thanks!

David


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

* Re: [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled
  2016-03-01  7:19     ` David Hildenbrand
@ 2016-03-01  8:16       ` Greg KH
  0 siblings, 0 replies; 5+ messages in thread
From: Greg KH @ 2016-03-01  8:16 UTC (permalink / raw)
  To: David Hildenbrand; +Cc: stable, borntraeger, farman

On Tue, Mar 01, 2016 at 08:19:04AM +0100, David Hildenbrand wrote:
> > On Wed, Feb 24, 2016 at 04:24:55PM +0100, David Hildenbrand wrote:
> > > This is the backport of 9abc2a08a7d6 (KVM: s390: fix memory overwrites
> > > when vx is disabled) for 4.4-stable.  
> > 
> > This backport didn't apply:
> > 
> > Applying kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch to linux-4.4.y
> > Applying patch kvm-s390-fix-memory-overwrites-when-vx-is-disabled.patch
> > patching file arch/s390/include/asm/kvm_host.h
> > patching file arch/s390/kvm/kvm-s390.c
> > Hunk #8 FAILED at 2246.
> > Hunk #9 FAILED at 2255.
> > 2 out of 10 hunks FAILED -- rejects in file arch/s390/kvm/kvm-s390.c
> > 
> > Can you try it again?
> > 
> > thanks,
> > 
> > greg k-h
> > 
> 
> Hi Greg,
> 
> did you take care of the mentioned precondition?
> 
> # v4.4 d9a3a09af54d s390/kvm: remove dependency on struct save_area definition

I did not, I missed that as I assumed it was the previous patch here,
sorry.

> But as I just received the mail saying this patch has been added to 4.4, I
> assume that this problems is solved :)

No, that was a mistake, I then deleted it.  But, I've added it again now
and the dependency so all is fine, sorry for the noise.

greg k-h

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

end of thread, other threads:[~2016-03-01  8:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-24 15:24 [PATCH 1/2] KVM: s390: fix guest fprs memory leak David Hildenbrand
2016-02-24 15:24 ` [PATCH 2/2] KVM: s390: fix memory overwrites when vx is disabled David Hildenbrand
2016-03-01  5:06   ` Greg KH
2016-03-01  7:19     ` David Hildenbrand
2016-03-01  8:16       ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).