aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2012-01-04 04:25:21 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:18 -0500
commit27e0393f15fc8bc855c6a888387ff5ffd2181089 (patch)
tree7dd5f6f49f6e11ee5cfbbc4d00fb39f649caa61b /arch
parente08b96371625aaa84cb03f51acc4c8e0be27403a (diff)
KVM: s390: ucontrol: per vcpu address spaces
This patch introduces two ioctls for virtual cpus, that are only valid for kernel virtual machines that are controlled by userspace. Each virtual cpu has its individual address space in this mode of operation, and each address space is backed by the gmap implementation just like the address space for regular KVM guests. KVM_S390_UCAS_MAP allows to map a part of the user's virtual address space to the vcpu. Starting offset and length in both the user and the vcpu address space need to be aligned to 1M. KVM_S390_UCAS_UNMAP can be used to unmap a range of memory from a virtual cpu in a similar way. Signed-off-by: Carsten Otte <cotte@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/kvm/kvm-s390.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index f0937552175b..2d3248895def 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -233,6 +233,10 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
233 (__u64) vcpu->arch.sie_block) 233 (__u64) vcpu->arch.sie_block)
234 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0; 234 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
235 smp_mb(); 235 smp_mb();
236
237 if (kvm_is_ucontrol(vcpu->kvm))
238 gmap_free(vcpu->arch.gmap);
239
236 free_page((unsigned long)(vcpu->arch.sie_block)); 240 free_page((unsigned long)(vcpu->arch.sie_block));
237 kvm_vcpu_uninit(vcpu); 241 kvm_vcpu_uninit(vcpu);
238 kfree(vcpu); 242 kfree(vcpu);
@@ -263,12 +267,20 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
263 kvm_free_vcpus(kvm); 267 kvm_free_vcpus(kvm);
264 free_page((unsigned long)(kvm->arch.sca)); 268 free_page((unsigned long)(kvm->arch.sca));
265 debug_unregister(kvm->arch.dbf); 269 debug_unregister(kvm->arch.dbf);
266 gmap_free(kvm->arch.gmap); 270 if (!kvm_is_ucontrol(kvm))
271 gmap_free(kvm->arch.gmap);
267} 272}
268 273
269/* Section: vcpu related */ 274/* Section: vcpu related */
270int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) 275int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
271{ 276{
277 if (kvm_is_ucontrol(vcpu->kvm)) {
278 vcpu->arch.gmap = gmap_alloc(current->mm);
279 if (!vcpu->arch.gmap)
280 return -ENOMEM;
281 return 0;
282 }
283
272 vcpu->arch.gmap = vcpu->kvm->arch.gmap; 284 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
273 return 0; 285 return 0;
274} 286}
@@ -687,6 +699,42 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
687 case KVM_S390_INITIAL_RESET: 699 case KVM_S390_INITIAL_RESET:
688 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu); 700 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
689 break; 701 break;
702#ifdef CONFIG_KVM_S390_UCONTROL
703 case KVM_S390_UCAS_MAP: {
704 struct kvm_s390_ucas_mapping ucasmap;
705
706 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
707 r = -EFAULT;
708 break;
709 }
710
711 if (!kvm_is_ucontrol(vcpu->kvm)) {
712 r = -EINVAL;
713 break;
714 }
715
716 r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
717 ucasmap.vcpu_addr, ucasmap.length);
718 break;
719 }
720 case KVM_S390_UCAS_UNMAP: {
721 struct kvm_s390_ucas_mapping ucasmap;
722
723 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
724 r = -EFAULT;
725 break;
726 }
727
728 if (!kvm_is_ucontrol(vcpu->kvm)) {
729 r = -EINVAL;
730 break;
731 }
732
733 r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
734 ucasmap.length);
735 break;
736 }
737#endif
690 default: 738 default:
691 r = -EINVAL; 739 r = -EINVAL;
692 } 740 }