diff mbox

[3/3] kvm-s390: streamline memslot handling

Message ID 1242826497-6797-4-git-send-email-ehrhardt@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

ehrhardt@linux.vnet.ibm.com May 20, 2009, 1:34 p.m. UTC
From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>

This patch relocates the variables kvm-s390 uses to track guest mem addr/size.
As discussed dropping the variables at struct kvm_arch level allows to use the
common vcpu->request based mechanism to reload guest memory if e.g. changes
via set_memory_region.
The kick mechanism introduced in this series is used to ensure running vcpus
leave guest state to catch the update.


Signed-off-by: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
---

[diffstat]
 include/asm/kvm_host.h |    4 +---
 kvm/gaccess.h          |   23 ++++++++++++-----------
 kvm/intercept.c        |    6 +++---
 kvm/kvm-s390.c         |   48 ++++++++++++++----------------------------------
 kvm/kvm-s390.h         |   29 ++++++++++++++++++++++++++++-
 kvm/sigp.c             |    4 ++--
 6 files changed, 60 insertions(+), 54 deletions(-)

[diff]
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Avi Kivity May 24, 2009, 2:39 p.m. UTC | #1
ehrhardt@linux.vnet.ibm.com wrote:
> From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
>
> This patch relocates the variables kvm-s390 uses to track guest mem addr/size.
> As discussed dropping the variables at struct kvm_arch level allows to use the
> common vcpu->request based mechanism to reload guest memory if e.g. changes
> via set_memory_region.
> The kick mechanism introduced in this series is used to ensure running vcpus
> leave guest state to catch the update.
>
>
>   
>
>  rerun_vcpu:
> +	if (vcpu->requests)
> +		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
> +			kvm_s390_vcpu_set_mem(vcpu);
> +
>  	/* verify, that memory has been registered */
> -	if (!vcpu->kvm->arch.guest_memsize) {
> +	if (!vcpu->arch.sie_block->gmslm) {
>  		vcpu_put(vcpu);
> +		VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
>  		return -EINVAL;
>  	}


x86 uses a double check: first we check vcpu->requests outside atomic 
context, then we enter the critical section and check again for signals 
and vcpu->requests.

This allows us (a) to do naughty things in vcpu->requests handlers, (b) 
keep the critical section short.

Does this apply here?

> -	/* update sie control blocks, and unlock all vcpus */
> +	/* request update of sie control block for all available vcpus */
>  	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
>  		if (kvm->vcpus[i]) {
> -			kvm->vcpus[i]->arch.sie_block->gmsor =
> -				kvm->arch.guest_origin;
> -			kvm->vcpus[i]->arch.sie_block->gmslm =
> -				kvm->arch.guest_memsize +
> -				kvm->arch.guest_origin +
> -				VIRTIODESCSPACE - 1ul;
> -			mutex_unlock(&kvm->vcpus[i]->mutex);
> +			set_bit(KVM_REQ_MMU_RELOAD, &kvm->vcpus[i]->requests);
> +			kvm_s390_inject_sigp_stop(kvm->vcpus[i],
> +						  ACTION_RELOADVCPU_ON_STOP);
>  		}
>  	}
>   

There already exists a loop which does this, see 
make_all_cpus_request().  It uses an IPI (Marcelo, can't it use the 
reschedule interrupt?).  It has a couple of optimizations -- if the 
request is already set, it skips the IPI, and it avoids the IPI for 
vcpus out of guest mode.  Maybe it could fit s390 too.
ehrhardt@linux.vnet.ibm.com May 25, 2009, 8:33 a.m. UTC | #2
Avi Kivity wrote:
> ehrhardt@linux.vnet.ibm.com wrote:
>> From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
>>
>> This patch relocates the variables kvm-s390 uses to track guest mem 
>> addr/size.
>> As discussed dropping the variables at struct kvm_arch level allows 
>> to use the
>> common vcpu->request based mechanism to reload guest memory if e.g. 
>> changes
>> via set_memory_region.
>> The kick mechanism introduced in this series is used to ensure 
>> running vcpus
>> leave guest state to catch the update.
>>
>>
>>  
>>  rerun_vcpu:
>> +    if (vcpu->requests)
>> +        if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
>> +            kvm_s390_vcpu_set_mem(vcpu);
>> +
>>      /* verify, that memory has been registered */
>> -    if (!vcpu->kvm->arch.guest_memsize) {
>> +    if (!vcpu->arch.sie_block->gmslm) {
>>          vcpu_put(vcpu);
>> +        VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
>>          return -EINVAL;
>>      }
>
>
> x86 uses a double check: first we check vcpu->requests outside atomic 
> context, then we enter the critical section and check again for 
> signals and vcpu->requests.
>
> This allows us (a) to do naughty things in vcpu->requests handlers, 
> (b) keep the critical section short.
>
> Does this apply here?

The patch already keeps the critical inner loop clear of extra code.
The check for vcpu->requests I added is only reached by either a 
heavyweight (userspace) exit/reentry or the explicit kickout of a vcpu 
to this label. Therefore weit fulfills a+b as you mentioned them above. 
Additionally the s390 reload is very rare as well as fast, therefore it 
would not even be an issue.

>> -    /* update sie control blocks, and unlock all vcpus */
>> +    /* request update of sie control block for all available vcpus */
>>      for (i = 0; i < KVM_MAX_VCPUS; ++i) {
>>          if (kvm->vcpus[i]) {
>> -            kvm->vcpus[i]->arch.sie_block->gmsor =
>> -                kvm->arch.guest_origin;
>> -            kvm->vcpus[i]->arch.sie_block->gmslm =
>> -                kvm->arch.guest_memsize +
>> -                kvm->arch.guest_origin +
>> -                VIRTIODESCSPACE - 1ul;
>> -            mutex_unlock(&kvm->vcpus[i]->mutex);
>> +            set_bit(KVM_REQ_MMU_RELOAD, &kvm->vcpus[i]->requests);
>> +            kvm_s390_inject_sigp_stop(kvm->vcpus[i],
>> +                          ACTION_RELOADVCPU_ON_STOP);
>>          }
>>      }
>>   
>
> There already exists a loop which does this, see 
> make_all_cpus_request().  It uses an IPI (Marcelo, can't it use the 
> reschedule interrupt?).  It has a couple of optimizations -- if the 
> request is already set, it skips the IPI, and it avoids the IPI for 
> vcpus out of guest mode.  Maybe it could fit s390 too.
I assume that the IPI on x86 is a implicit consequence of the 
smp_call_function_many function, but I think this doesn't work that way 
for us. The kick implied by that call would be recieved, but not reach 
the code the checke vcpu->request. I could add that behaviour, but that 
could make our normal interrupt handling much slower. Therefore I don't 
want to call that function, but on the other hand I like the "skip if 
the request is already set" functionality and think about adding that in 
my loop.
ehrhardt@linux.vnet.ibm.com May 25, 2009, 11:40 a.m. UTC | #3
Christian Ehrhardt wrote:
> Avi Kivity wrote:
>> ehrhardt@linux.vnet.ibm.com wrote:
>>> From: Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
>>>
> [...]
>>> -    /* update sie control blocks, and unlock all vcpus */
>>> +    /* request update of sie control block for all available vcpus */
>>>      for (i = 0; i < KVM_MAX_VCPUS; ++i) {
>>>          if (kvm->vcpus[i]) {
>>> -            kvm->vcpus[i]->arch.sie_block->gmsor =
>>> -                kvm->arch.guest_origin;
>>> -            kvm->vcpus[i]->arch.sie_block->gmslm =
>>> -                kvm->arch.guest_memsize +
>>> -                kvm->arch.guest_origin +
>>> -                VIRTIODESCSPACE - 1ul;
>>> -            mutex_unlock(&kvm->vcpus[i]->mutex);
>>> +            set_bit(KVM_REQ_MMU_RELOAD, &kvm->vcpus[i]->requests);
>>> +            kvm_s390_inject_sigp_stop(kvm->vcpus[i],
>>> +                          ACTION_RELOADVCPU_ON_STOP);
>>>          }
>>>      }
>>>   
>>
>> There already exists a loop which does this, see 
>> make_all_cpus_request().  It uses an IPI (Marcelo, can't it use the 
>> reschedule interrupt?).  It has a couple of optimizations -- if the 
>> request is already set, it skips the IPI, and it avoids the IPI for 
>> vcpus out of guest mode.  Maybe it could fit s390 too.
> I assume that the IPI on x86 is a implicit consequence of the 
> smp_call_function_many function, but I think this doesn't work that 
> way for us. The kick implied by that call would be recieved, but not 
> reach the code the checke vcpu->request. I could add that behaviour, 
> but that could make our normal interrupt handling much slower. 
> Therefore I don't want to call that function, but on the other hand I 
> like the "skip if the request is already set" functionality and think 
> about adding that in my loop.
>

For now I added the optimization to skip kicking vcpus out of guest that 
had the request bit already set to the s390 specific loop (sent as v2 in 
a few minutes).

We might one day consider standardizing some generic kickout levels e.g. 
kick to "inner loop", "arch vcpu run", "generic vcpu run", "userspace", 
... whatever levels fit *all* our use cases. And then let that kicks be 
implemented in an kvm_arch_* backend as it might be very different how 
they behave on different architectures. In case an architecture cannot 
achive reaching the specified kickout level it has to kick to the next 
available upper level which eventually will reach the desired step on 
the way to re-run the vcpu.
Alltogether this should lead to a much more reliable and transparent 
interface that finally should be used all across the generic code.
Avi Kivity May 26, 2009, 7:57 a.m. UTC | #4
Christian Ehrhardt wrote: 
>>
>> There already exists a loop which does this, see 
>> make_all_cpus_request().  It uses an IPI (Marcelo, can't it use the 
>> reschedule interrupt?).  It has a couple of optimizations -- if the 
>> request is already set, it skips the IPI, and it avoids the IPI for 
>> vcpus out of guest mode.  Maybe it could fit s390 too.
> I assume that the IPI on x86 is a implicit consequence of the 
> smp_call_function_many function, 

Yes.  It's only used to exit the guest, the IPI itself does nothing.

> but I think this doesn't work that way for us. The kick implied by 
> that call would be recieved, but not reach the code the checke 
> vcpu->request. 

vcpu->requests is not checked by the IPI.  Instead, it is checked just 
before entering guest mode, with interrupts disabled.

If the request is made before the check, no IPI is made, and the check 
finds the bit set.

If the request is made after the check, an IPI is made, and the guest 
exits immediately after entry.

> I could add that behaviour, but that could make our normal interrupt 
> handling much slower. Therefore I don't want to call that function, 
> but on the other hand I like the "skip if the request is already set" 
> functionality and think about adding that in my loop.

I don't understand why it would affect your interrupt handling.  We need 
someone that talks both x86 and s390 to break the language barrier...

I'll apply the patches, but please do look further into increasing 
commonality.
Christian Borntraeger May 26, 2009, 8:31 a.m. UTC | #5
Am Dienstag 26 Mai 2009 09:57:58 schrieb Avi Kivity:
> > I could add that behaviour, but that could make our normal interrupt
> > handling much slower. Therefore I don't want to call that function,
> > but on the other hand I like the "skip if the request is already set"
> > functionality and think about adding that in my loop.
>
> I don't understand why it would affect your interrupt handling.  We need

As far as I understand x86, every host interrupt causes a guest exit.

On s390 the SIE instruction is interruptible. On a host interrupt (like an 
IPI)  the host interrupt handler runs and finally jumps back into the SIE 
instruction.  The hardware will continue with guest execution. This has the 
advantage, that we dont have to load/save guest and host registers on host 
interrupts. (the low level interrupt handler saves the registers of the 
interrupted context)

In our low-level interrupt handler we do check for signal_pending, 
machine_check_pending and need_resched to leave the sie instruction. For 
anything else a the host sees a cpu bound guest always in the SIE instruction. 

Christian


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Avi Kivity May 26, 2009, 9:27 a.m. UTC | #6
Christian Bornträger wrote:
> Am Dienstag 26 Mai 2009 09:57:58 schrieb Avi Kivity:
>   
>>> I could add that behaviour, but that could make our normal interrupt
>>> handling much slower. Therefore I don't want to call that function,
>>> but on the other hand I like the "skip if the request is already set"
>>> functionality and think about adding that in my loop.
>>>       
>> I don't understand why it would affect your interrupt handling.  We need
>>     
>
> As far as I understand x86, every host interrupt causes a guest exit.
>   

Yes.

> On s390 the SIE instruction is interruptible. On a host interrupt (like an 
> IPI)  the host interrupt handler runs and finally jumps back into the SIE 
> instruction.  The hardware will continue with guest execution. This has the 
> advantage, that we dont have to load/save guest and host registers on host 
> interrupts. (the low level interrupt handler saves the registers of the 
> interrupted context)
>   

Neat stuff.  Wish I had something like that.

> In our low-level interrupt handler we do check for signal_pending, 
> machine_check_pending and need_resched to leave the sie instruction. For 
> anything else a the host sees a cpu bound guest always in the SIE instruction. 
>   

Okay, now I understand (and agree with) you multi-level kick thing.  
Maybe we could do it like so:

Interrupt handler (on s390 only) checks vcpu->requests, handles the ones 
it cans.  If bits are still set, it exits to arch loop, which handles 
the bits it cans.  If bits are still set, it exits to the generic code 
loop, which can finally exit to userspace.

Does this fit with s390 hardware?
ehrhardt@linux.vnet.ibm.com May 26, 2009, 10:31 a.m. UTC | #7
Avi Kivity wrote:
> Christian Bornträger wrote:
>> Am Dienstag 26 Mai 2009 09:57:58 schrieb Avi Kivity:
>>   
[...]
>> In our low-level interrupt handler we do check for signal_pending, 
>> machine_check_pending and need_resched to leave the sie instruction. 
>> For anything else a the host sees a cpu bound guest always in the SIE 
>> instruction.   
>
> Okay, now I understand (and agree with) you multi-level kick thing.  
> Maybe we could do it like so:
>
> Interrupt handler (on s390 only) checks vcpu->requests, handles the 
> ones it cans.  If bits are still set, it exits to arch loop, which 
> handles the bits it cans.  If bits are still set, it exits to the 
> generic code loop, which can finally exit to userspace.
>
> Does this fit with s390 hardware?
>
I like this idea instead of explicitly kicking to an (upper) level to 
use the lowest kick and exit if not able to handle.
I think it should work (no guarantee) and I try to come up with 
something in the next few days - either a updated patch series or 
additional discussion input :-).
diff mbox

Patch

Index: kvm/arch/s390/kvm/gaccess.h
===================================================================
--- kvm.orig/arch/s390/kvm/gaccess.h
+++ kvm/arch/s390/kvm/gaccess.h
@@ -1,7 +1,7 @@ 
 /*
  * gaccess.h -  access guest memory
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -16,13 +16,14 @@ 
 #include <linux/compiler.h>
 #include <linux/kvm_host.h>
 #include <asm/uaccess.h>
+#include "kvm-s390.h"
 
 static inline void __user *__guestaddr_to_user(struct kvm_vcpu *vcpu,
 					       unsigned long guestaddr)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->kvm->arch.guest_origin;
-	unsigned long memsize = vcpu->kvm->arch.guest_memsize;
+	unsigned long origin  = vcpu->arch.sie_block->gmsor;
+	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if (guestaddr < 2 * PAGE_SIZE)
 		guestaddr += prefix;
@@ -158,8 +159,8 @@  static inline int copy_to_guest(struct k
 				const void *from, unsigned long n)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->kvm->arch.guest_origin;
-	unsigned long memsize = vcpu->kvm->arch.guest_memsize;
+	unsigned long origin  = vcpu->arch.sie_block->gmsor;
+	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if ((guestdest < 2 * PAGE_SIZE) && (guestdest + n > 2 * PAGE_SIZE))
 		goto slowpath;
@@ -209,8 +210,8 @@  static inline int copy_from_guest(struct
 				  unsigned long guestsrc, unsigned long n)
 {
 	unsigned long prefix  = vcpu->arch.sie_block->prefix;
-	unsigned long origin  = vcpu->kvm->arch.guest_origin;
-	unsigned long memsize = vcpu->kvm->arch.guest_memsize;
+	unsigned long origin  = vcpu->arch.sie_block->gmsor;
+	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if ((guestsrc < 2 * PAGE_SIZE) && (guestsrc + n > 2 * PAGE_SIZE))
 		goto slowpath;
@@ -244,8 +245,8 @@  static inline int copy_to_guest_absolute
 					 unsigned long guestdest,
 					 const void *from, unsigned long n)
 {
-	unsigned long origin  = vcpu->kvm->arch.guest_origin;
-	unsigned long memsize = vcpu->kvm->arch.guest_memsize;
+	unsigned long origin  = vcpu->arch.sie_block->gmsor;
+	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if (guestdest + n > memsize)
 		return -EFAULT;
@@ -262,8 +263,8 @@  static inline int copy_from_guest_absolu
 					   unsigned long guestsrc,
 					   unsigned long n)
 {
-	unsigned long origin  = vcpu->kvm->arch.guest_origin;
-	unsigned long memsize = vcpu->kvm->arch.guest_memsize;
+	unsigned long origin  = vcpu->arch.sie_block->gmsor;
+	unsigned long memsize = kvm_s390_vcpu_get_memsize(vcpu);
 
 	if (guestsrc + n > memsize)
 		return -EFAULT;
Index: kvm/arch/s390/kvm/intercept.c
===================================================================
--- kvm.orig/arch/s390/kvm/intercept.c
+++ kvm/arch/s390/kvm/intercept.c
@@ -1,7 +1,7 @@ 
 /*
  * intercept.c - in-kernel handling for sie intercepts
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -164,9 +164,9 @@  static int handle_validity(struct kvm_vc
 
 	vcpu->stat.exit_validity++;
 	if ((viwhy == 0x37) && (vcpu->arch.sie_block->prefix
-		<= vcpu->kvm->arch.guest_memsize - 2*PAGE_SIZE)){
+		<= kvm_s390_vcpu_get_memsize(vcpu) - 2*PAGE_SIZE)) {
 		rc = fault_in_pages_writeable((char __user *)
-			 vcpu->kvm->arch.guest_origin +
+			 vcpu->arch.sie_block->gmsor +
 			 vcpu->arch.sie_block->prefix,
 			 2*PAGE_SIZE);
 		if (rc)
Index: kvm/arch/s390/kvm/kvm-s390.c
===================================================================
--- kvm.orig/arch/s390/kvm/kvm-s390.c
+++ kvm/arch/s390/kvm/kvm-s390.c
@@ -1,7 +1,7 @@ 
 /*
  * s390host.c --  hosting zSeries kernel virtual machines
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -10,6 +10,7 @@ 
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
  *               Heiko Carstens <heiko.carstens@de.ibm.com>
+ *               Christian Ehrhardt <ehrhardt@de.ibm.com>
  */
 
 #include <linux/compiler.h>
@@ -276,16 +277,10 @@  static void kvm_s390_vcpu_initial_reset(
 	vcpu->arch.sie_block->gbea = 1;
 }
 
-/* The current code can have up to 256 pages for virtio */
-#define VIRTIODESCSPACE (256ul * 4096ul)
-
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
-	vcpu->arch.sie_block->gmslm = vcpu->kvm->arch.guest_memsize +
-				      vcpu->kvm->arch.guest_origin +
-				      VIRTIODESCSPACE - 1ul;
-	vcpu->arch.sie_block->gmsor = vcpu->kvm->arch.guest_origin;
+	set_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests);
 	vcpu->arch.sie_block->ecb   = 2;
 	vcpu->arch.sie_block->eca   = 0xC1002001U;
 	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
@@ -488,9 +483,14 @@  int kvm_arch_vcpu_ioctl_run(struct kvm_v
 	vcpu_load(vcpu);
 
 rerun_vcpu:
+	if (vcpu->requests)
+		if (test_and_clear_bit(KVM_REQ_MMU_RELOAD, &vcpu->requests))
+			kvm_s390_vcpu_set_mem(vcpu);
+
 	/* verify, that memory has been registered */
-	if (!vcpu->kvm->arch.guest_memsize) {
+	if (!vcpu->arch.sie_block->gmslm) {
 		vcpu_put(vcpu);
+		VCPU_EVENT(vcpu, 3, "%s", "no memory registered to run vcpu");
 		return -EINVAL;
 	}
 
@@ -688,7 +688,7 @@  int kvm_arch_set_memory_region(struct kv
 	   vmas. It is okay to mmap() and munmap() stuff in this slot after
 	   doing this call at any time */
 
-	if (mem->slot || kvm->arch.guest_memsize)
+	if (mem->slot)
 		return -EINVAL;
 
 	if (mem->guest_phys_addr)
@@ -703,36 +703,16 @@  int kvm_arch_set_memory_region(struct kv
 	if (!user_alloc)
 		return -EINVAL;
 
-	/* lock all vcpus */
-	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
-		if (!kvm->vcpus[i])
-			continue;
-		if (!mutex_trylock(&kvm->vcpus[i]->mutex))
-			goto fail_out;
-	}
-
-	kvm->arch.guest_origin = mem->userspace_addr;
-	kvm->arch.guest_memsize = mem->memory_size;
-
-	/* update sie control blocks, and unlock all vcpus */
+	/* request update of sie control block for all available vcpus */
 	for (i = 0; i < KVM_MAX_VCPUS; ++i) {
 		if (kvm->vcpus[i]) {
-			kvm->vcpus[i]->arch.sie_block->gmsor =
-				kvm->arch.guest_origin;
-			kvm->vcpus[i]->arch.sie_block->gmslm =
-				kvm->arch.guest_memsize +
-				kvm->arch.guest_origin +
-				VIRTIODESCSPACE - 1ul;
-			mutex_unlock(&kvm->vcpus[i]->mutex);
+			set_bit(KVM_REQ_MMU_RELOAD, &kvm->vcpus[i]->requests);
+			kvm_s390_inject_sigp_stop(kvm->vcpus[i],
+						  ACTION_RELOADVCPU_ON_STOP);
 		}
 	}
 
 	return 0;
-
-fail_out:
-	for (; i >= 0; i--)
-		mutex_unlock(&kvm->vcpus[i]->mutex);
-	return -EINVAL;
 }
 
 void kvm_arch_flush_shadow(struct kvm *kvm)
Index: kvm/arch/s390/kvm/kvm-s390.h
===================================================================
--- kvm.orig/arch/s390/kvm/kvm-s390.h
+++ kvm/arch/s390/kvm/kvm-s390.h
@@ -1,7 +1,7 @@ 
 /*
  * kvm_s390.h -  definition for kvm on s390
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -9,6 +9,7 @@ 
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
+ *               Christian Ehrhardt <ehrhardt@de.ibm.com>
  */
 
 #ifndef ARCH_S390_KVM_S390_H
@@ -18,6 +19,9 @@ 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 
+/* The current code can have up to 256 pages for virtio */
+#define VIRTIODESCSPACE (256ul * 4096ul)
+
 typedef int (*intercept_handler_t)(struct kvm_vcpu *vcpu);
 
 /* negativ values are error codes, positive values for internal conditions */
@@ -54,6 +58,29 @@  int kvm_s390_inject_vcpu(struct kvm_vcpu
 int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action);
 
+static inline int kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.sie_block->gmslm
+		- vcpu->arch.sie_block->gmsor
+		- VIRTIODESCSPACE + 1ul;
+}
+
+static inline void kvm_s390_vcpu_set_mem(struct kvm_vcpu *vcpu)
+{
+	struct kvm_memory_slot *mem;
+
+	down_read(&vcpu->kvm->slots_lock);
+	mem = &vcpu->kvm->memslots[0];
+
+	vcpu->arch.sie_block->gmsor = mem->userspace_addr;
+	vcpu->arch.sie_block->gmslm =
+		mem->userspace_addr +
+		(mem->npages << PAGE_SHIFT) +
+		VIRTIODESCSPACE - 1ul;
+
+	up_read(&vcpu->kvm->slots_lock);
+}
+
 /* implemented in priv.c */
 int kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
 
Index: kvm/arch/s390/include/asm/kvm_host.h
===================================================================
--- kvm.orig/arch/s390/include/asm/kvm_host.h
+++ kvm/arch/s390/include/asm/kvm_host.h
@@ -1,7 +1,7 @@ 
 /*
  * asm-s390/kvm_host.h - definition for kernel virtual machines on s390
  *
- * Copyright IBM Corp. 2008
+ * Copyright IBM Corp. 2008,2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
@@ -226,8 +226,6 @@  struct kvm_vm_stat {
 };
 
 struct kvm_arch{
-	unsigned long guest_origin;
-	unsigned long guest_memsize;
 	struct sca_block *sca;
 	debug_info_t *dbf;
 	struct kvm_s390_float_interrupt float_int;
Index: kvm/arch/s390/kvm/sigp.c
===================================================================
--- kvm.orig/arch/s390/kvm/sigp.c
+++ kvm/arch/s390/kvm/sigp.c
@@ -189,9 +189,9 @@  static int __sigp_set_prefix(struct kvm_
 	/* make sure that the new value is valid memory */
 	address = address & 0x7fffe000u;
 	if ((copy_from_guest(vcpu, &tmp,
-		(u64) (address + vcpu->kvm->arch.guest_origin) , 1)) ||
+		(u64) (address + vcpu->arch.sie_block->gmsor) , 1)) ||
 	   (copy_from_guest(vcpu, &tmp, (u64) (address +
-			vcpu->kvm->arch.guest_origin + PAGE_SIZE), 1))) {
+			vcpu->arch.sie_block->gmsor + PAGE_SIZE), 1))) {
 		*reg |= SIGP_STAT_INVALID_PARAMETER;
 		return 1; /* invalid parameter */
 	}