]> git.karo-electronics.de Git - linux-beck.git/commitdiff
KVM: s390: ucontrol: per vcpu address spaces
authorCarsten Otte <cotte@de.ibm.com>
Wed, 4 Jan 2012 09:25:21 +0000 (10:25 +0100)
committerAvi Kivity <avi@redhat.com>
Mon, 5 Mar 2012 12:52:18 +0000 (14:52 +0200)
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>
Documentation/virtual/kvm/api.txt
arch/s390/kvm/kvm-s390.c
include/linux/kvm.h

index 579d40b26a5a5484f7ca7f8f81d7555670dfa16a..ee394b263261dceb9a833b3f7aa6da1d7ba0e861 100644 (file)
@@ -1496,6 +1496,44 @@ following algorithm:
 Some guests configure the LINT1 NMI input to cause a panic, aiding in
 debugging.
 
+4.64 KVM_S390_UCAS_MAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl maps the memory at "user_addr" with the length "length" to
+the vcpu's address space starting at "vcpu_addr". All parameters need to
+be alligned by 1 megabyte.
+
+4.65 KVM_S390_UCAS_UNMAP
+
+Capability: KVM_CAP_S390_UCONTROL
+Architectures: s390
+Type: vcpu ioctl
+Parameters: struct kvm_s390_ucas_mapping (in)
+Returns: 0 in case of success
+
+The parameter is defined like this:
+       struct kvm_s390_ucas_mapping {
+               __u64 user_addr;
+               __u64 vcpu_addr;
+               __u64 length;
+       };
+
+This ioctl unmaps the memory in the vcpu's address space starting at
+"vcpu_addr" with the length "length". The field "user_addr" is ignored.
+All parameters need to be alligned by 1 megabyte.
+
 5. The kvm_run structure
 
 Application code obtains a pointer to the kvm_run structure by
index f0937552175b11be23a44bff6815aac82ed83a17..2d3248895defc67ceea1e4be38a2567a58f013a6 100644 (file)
@@ -233,6 +233,10 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
                (__u64) vcpu->arch.sie_block)
                vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
        smp_mb();
+
+       if (kvm_is_ucontrol(vcpu->kvm))
+               gmap_free(vcpu->arch.gmap);
+
        free_page((unsigned long)(vcpu->arch.sie_block));
        kvm_vcpu_uninit(vcpu);
        kfree(vcpu);
@@ -263,12 +267,20 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
        kvm_free_vcpus(kvm);
        free_page((unsigned long)(kvm->arch.sca));
        debug_unregister(kvm->arch.dbf);
-       gmap_free(kvm->arch.gmap);
+       if (!kvm_is_ucontrol(kvm))
+               gmap_free(kvm->arch.gmap);
 }
 
 /* Section: vcpu related */
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
+       if (kvm_is_ucontrol(vcpu->kvm)) {
+               vcpu->arch.gmap = gmap_alloc(current->mm);
+               if (!vcpu->arch.gmap)
+                       return -ENOMEM;
+               return 0;
+       }
+
        vcpu->arch.gmap = vcpu->kvm->arch.gmap;
        return 0;
 }
@@ -687,6 +699,42 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        case KVM_S390_INITIAL_RESET:
                r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
                break;
+#ifdef CONFIG_KVM_S390_UCONTROL
+       case KVM_S390_UCAS_MAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
+                                    ucasmap.vcpu_addr, ucasmap.length);
+               break;
+       }
+       case KVM_S390_UCAS_UNMAP: {
+               struct kvm_s390_ucas_mapping ucasmap;
+
+               if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
+                       r = -EFAULT;
+                       break;
+               }
+
+               if (!kvm_is_ucontrol(vcpu->kvm)) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
+                       ucasmap.length);
+               break;
+       }
+#endif
        default:
                r = -EINVAL;
        }
index bba393a6760fa50ebf64eb4f156bd1c688580c40..0a66c10726914f04fd73e24c024e4a63c7df3927 100644 (file)
@@ -658,6 +658,16 @@ struct kvm_clock_data {
                                        struct kvm_userspace_memory_region)
 #define KVM_SET_TSS_ADDR          _IO(KVMIO,   0x47)
 #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO,  0x48, __u64)
+
+/* enable ucontrol for s390 */
+struct kvm_s390_ucas_mapping {
+       __u64 user_addr;
+       __u64 vcpu_addr;
+       __u64 length;
+};
+#define KVM_S390_UCAS_MAP        _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping)
+#define KVM_S390_UCAS_UNMAP      _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping)
+
 /* Device model IOC */
 #define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
 #define KVM_IRQ_LINE              _IOW(KVMIO,  0x61, struct kvm_irq_level)