diff options
author | Carsten Otte <cotte@de.ibm.com> | 2012-01-04 04:25:20 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2012-03-05 07:52:18 -0500 |
commit | e08b96371625aaa84cb03f51acc4c8e0be27403a (patch) | |
tree | d0b140e8558c6145e1a3183809c7797be443bd68 | |
parent | a138fe7535c0ec778465c7b54b1aaaf4cfd885b7 (diff) |
KVM: s390: add parameter for KVM_CREATE_VM
This patch introduces a new config option for user controlled kernel
virtual machines. It introduces a parameter to KVM_CREATE_VM that
allows to set bits that alter the capabilities of the newly created
virtual machine.
The parameter is passed to kvm_arch_init_vm for all architectures.
The only valid modifier bit for now is KVM_VM_S390_UCONTROL.
This requires CAP_SYS_ADMIN privileges and creates a user controlled
virtual machine on s390 architectures.
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>
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 7 | ||||
-rw-r--r-- | arch/ia64/kvm/kvm-ia64.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 5 | ||||
-rw-r--r-- | arch/s390/kvm/Kconfig | 9 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 24 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 10 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 5 | ||||
-rw-r--r-- | include/linux/kvm.h | 3 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 13 |
10 files changed, 65 insertions, 18 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e1d94bf4056e..579d40b26a5a 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -95,7 +95,7 @@ described as 'basic' will be available. | |||
95 | Capability: basic | 95 | Capability: basic |
96 | Architectures: all | 96 | Architectures: all |
97 | Type: system ioctl | 97 | Type: system ioctl |
98 | Parameters: none | 98 | Parameters: machine type identifier (KVM_VM_*) |
99 | Returns: a VM fd that can be used to control the new virtual machine. | 99 | Returns: a VM fd that can be used to control the new virtual machine. |
100 | 100 | ||
101 | The new VM has no virtual cpus and no memory. An mmap() of a VM fd | 101 | The new VM has no virtual cpus and no memory. An mmap() of a VM fd |
@@ -103,6 +103,11 @@ will access the virtual machine's physical address space; offset zero | |||
103 | corresponds to guest physical address zero. Use of mmap() on a VM fd | 103 | corresponds to guest physical address zero. Use of mmap() on a VM fd |
104 | is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is | 104 | is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is |
105 | available. | 105 | available. |
106 | You most certainly want to use 0 as machine type. | ||
107 | |||
108 | In order to create user controlled virtual machines on S390, check | ||
109 | KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as | ||
110 | privileged user (CAP_SYS_ADMIN). | ||
106 | 111 | ||
107 | 4.3 KVM_GET_MSR_INDEX_LIST | 112 | 4.3 KVM_GET_MSR_INDEX_LIST |
108 | 113 | ||
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c index 405052002493..df6b14194051 100644 --- a/arch/ia64/kvm/kvm-ia64.c +++ b/arch/ia64/kvm/kvm-ia64.c | |||
@@ -809,10 +809,13 @@ static void kvm_build_io_pmt(struct kvm *kvm) | |||
809 | #define GUEST_PHYSICAL_RR4 0x2739 | 809 | #define GUEST_PHYSICAL_RR4 0x2739 |
810 | #define VMM_INIT_RR 0x1660 | 810 | #define VMM_INIT_RR 0x1660 |
811 | 811 | ||
812 | int kvm_arch_init_vm(struct kvm *kvm) | 812 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
813 | { | 813 | { |
814 | BUG_ON(!kvm); | 814 | BUG_ON(!kvm); |
815 | 815 | ||
816 | if (type) | ||
817 | return -EINVAL; | ||
818 | |||
816 | kvm->arch.is_sn2 = ia64_platform_is("sn2"); | 819 | kvm->arch.is_sn2 = ia64_platform_is("sn2"); |
817 | 820 | ||
818 | kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0; | 821 | kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0; |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 607fbdf24b84..83f244569874 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -171,8 +171,11 @@ void kvm_arch_check_processor_compat(void *rtn) | |||
171 | *(int *)rtn = kvmppc_core_check_processor_compat(); | 171 | *(int *)rtn = kvmppc_core_check_processor_compat(); |
172 | } | 172 | } |
173 | 173 | ||
174 | int kvm_arch_init_vm(struct kvm *kvm) | 174 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
175 | { | 175 | { |
176 | if (type) | ||
177 | return -EINVAL; | ||
178 | |||
176 | return kvmppc_core_init_vm(kvm); | 179 | return kvmppc_core_init_vm(kvm); |
177 | } | 180 | } |
178 | 181 | ||
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index a21634173a66..78eb9847008f 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig | |||
@@ -34,6 +34,15 @@ config KVM | |||
34 | 34 | ||
35 | If unsure, say N. | 35 | If unsure, say N. |
36 | 36 | ||
37 | config KVM_S390_UCONTROL | ||
38 | bool "Userspace controlled virtual machines" | ||
39 | depends on KVM | ||
40 | ---help--- | ||
41 | Allow CAP_SYS_ADMIN users to create KVM virtual machines that are | ||
42 | controlled by userspace. | ||
43 | |||
44 | If unsure, say N. | ||
45 | |||
37 | # OK, it's a little counter-intuitive to do this, but it puts it neatly under | 46 | # OK, it's a little counter-intuitive to do this, but it puts it neatly under |
38 | # the virtualization menu. | 47 | # the virtualization menu. |
39 | source drivers/vhost/Kconfig | 48 | source drivers/vhost/Kconfig |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index d1c445732451..f0937552175b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -171,11 +171,22 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
171 | return r; | 171 | return r; |
172 | } | 172 | } |
173 | 173 | ||
174 | int kvm_arch_init_vm(struct kvm *kvm) | 174 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
175 | { | 175 | { |
176 | int rc; | 176 | int rc; |
177 | char debug_name[16]; | 177 | char debug_name[16]; |
178 | 178 | ||
179 | rc = -EINVAL; | ||
180 | #ifdef CONFIG_KVM_S390_UCONTROL | ||
181 | if (type & ~KVM_VM_S390_UCONTROL) | ||
182 | goto out_err; | ||
183 | if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN))) | ||
184 | goto out_err; | ||
185 | #else | ||
186 | if (type) | ||
187 | goto out_err; | ||
188 | #endif | ||
189 | |||
179 | rc = s390_enable_sie(); | 190 | rc = s390_enable_sie(); |
180 | if (rc) | 191 | if (rc) |
181 | goto out_err; | 192 | goto out_err; |
@@ -198,10 +209,13 @@ int kvm_arch_init_vm(struct kvm *kvm) | |||
198 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); | 209 | debug_register_view(kvm->arch.dbf, &debug_sprintf_view); |
199 | VM_EVENT(kvm, 3, "%s", "vm created"); | 210 | VM_EVENT(kvm, 3, "%s", "vm created"); |
200 | 211 | ||
201 | kvm->arch.gmap = gmap_alloc(current->mm); | 212 | if (type & KVM_VM_S390_UCONTROL) { |
202 | if (!kvm->arch.gmap) | 213 | kvm->arch.gmap = NULL; |
203 | goto out_nogmap; | 214 | } else { |
204 | 215 | kvm->arch.gmap = gmap_alloc(current->mm); | |
216 | if (!kvm->arch.gmap) | ||
217 | goto out_nogmap; | ||
218 | } | ||
205 | return 0; | 219 | return 0; |
206 | out_nogmap: | 220 | out_nogmap: |
207 | debug_unregister(kvm->arch.dbf); | 221 | debug_unregister(kvm->arch.dbf); |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 99b0b7597115..45b236a7c730 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -47,6 +47,16 @@ static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu) | |||
47 | return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT; | 47 | return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT; |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline int kvm_is_ucontrol(struct kvm *kvm) | ||
51 | { | ||
52 | #ifdef CONFIG_KVM_S390_UCONTROL | ||
53 | if (kvm->arch.gmap) | ||
54 | return 0; | ||
55 | return 1; | ||
56 | #else | ||
57 | return 0; | ||
58 | #endif | ||
59 | } | ||
50 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); | 60 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); |
51 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); | 61 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); |
52 | void kvm_s390_tasklet(unsigned long parm); | 62 | void kvm_s390_tasklet(unsigned long parm); |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 9cbfc0698118..06925b4bcc27 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -6031,8 +6031,11 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) | |||
6031 | free_page((unsigned long)vcpu->arch.pio_data); | 6031 | free_page((unsigned long)vcpu->arch.pio_data); |
6032 | } | 6032 | } |
6033 | 6033 | ||
6034 | int kvm_arch_init_vm(struct kvm *kvm) | 6034 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
6035 | { | 6035 | { |
6036 | if (type) | ||
6037 | return -EINVAL; | ||
6038 | |||
6036 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); | 6039 | INIT_LIST_HEAD(&kvm->arch.active_mmu_pages); |
6037 | INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); | 6040 | INIT_LIST_HEAD(&kvm->arch.assigned_dev_head); |
6038 | 6041 | ||
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 68e67e50d028..bba393a6760f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -431,6 +431,9 @@ struct kvm_ppc_pvinfo { | |||
431 | 431 | ||
432 | #define KVMIO 0xAE | 432 | #define KVMIO 0xAE |
433 | 433 | ||
434 | /* machine type bits, to be used as argument to KVM_CREATE_VM */ | ||
435 | #define KVM_VM_S390_UCONTROL 1 | ||
436 | |||
434 | /* | 437 | /* |
435 | * ioctls for /dev/kvm fds: | 438 | * ioctls for /dev/kvm fds: |
436 | */ | 439 | */ |
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 900c76337e8f..82375e145e64 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -520,7 +520,7 @@ static inline void kvm_arch_free_vm(struct kvm *kvm) | |||
520 | } | 520 | } |
521 | #endif | 521 | #endif |
522 | 522 | ||
523 | int kvm_arch_init_vm(struct kvm *kvm); | 523 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type); |
524 | void kvm_arch_destroy_vm(struct kvm *kvm); | 524 | void kvm_arch_destroy_vm(struct kvm *kvm); |
525 | void kvm_free_all_assigned_devices(struct kvm *kvm); | 525 | void kvm_free_all_assigned_devices(struct kvm *kvm); |
526 | void kvm_arch_sync_events(struct kvm *kvm); | 526 | void kvm_arch_sync_events(struct kvm *kvm); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index a91f980077d8..32e3b048a6cf 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -449,7 +449,7 @@ static void kvm_init_memslots_id(struct kvm *kvm) | |||
449 | slots->id_to_index[i] = slots->memslots[i].id = i; | 449 | slots->id_to_index[i] = slots->memslots[i].id = i; |
450 | } | 450 | } |
451 | 451 | ||
452 | static struct kvm *kvm_create_vm(void) | 452 | static struct kvm *kvm_create_vm(unsigned long type) |
453 | { | 453 | { |
454 | int r, i; | 454 | int r, i; |
455 | struct kvm *kvm = kvm_arch_alloc_vm(); | 455 | struct kvm *kvm = kvm_arch_alloc_vm(); |
@@ -457,7 +457,7 @@ static struct kvm *kvm_create_vm(void) | |||
457 | if (!kvm) | 457 | if (!kvm) |
458 | return ERR_PTR(-ENOMEM); | 458 | return ERR_PTR(-ENOMEM); |
459 | 459 | ||
460 | r = kvm_arch_init_vm(kvm); | 460 | r = kvm_arch_init_vm(kvm, type); |
461 | if (r) | 461 | if (r) |
462 | goto out_err_nodisable; | 462 | goto out_err_nodisable; |
463 | 463 | ||
@@ -2198,12 +2198,12 @@ static struct file_operations kvm_vm_fops = { | |||
2198 | .llseek = noop_llseek, | 2198 | .llseek = noop_llseek, |
2199 | }; | 2199 | }; |
2200 | 2200 | ||
2201 | static int kvm_dev_ioctl_create_vm(void) | 2201 | static int kvm_dev_ioctl_create_vm(unsigned long type) |
2202 | { | 2202 | { |
2203 | int r; | 2203 | int r; |
2204 | struct kvm *kvm; | 2204 | struct kvm *kvm; |
2205 | 2205 | ||
2206 | kvm = kvm_create_vm(); | 2206 | kvm = kvm_create_vm(type); |
2207 | if (IS_ERR(kvm)) | 2207 | if (IS_ERR(kvm)) |
2208 | return PTR_ERR(kvm); | 2208 | return PTR_ERR(kvm); |
2209 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET | 2209 | #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET |
@@ -2254,10 +2254,7 @@ static long kvm_dev_ioctl(struct file *filp, | |||
2254 | r = KVM_API_VERSION; | 2254 | r = KVM_API_VERSION; |
2255 | break; | 2255 | break; |
2256 | case KVM_CREATE_VM: | 2256 | case KVM_CREATE_VM: |
2257 | r = -EINVAL; | 2257 | r = kvm_dev_ioctl_create_vm(arg); |
2258 | if (arg) | ||
2259 | goto out; | ||
2260 | r = kvm_dev_ioctl_create_vm(); | ||
2261 | break; | 2258 | break; |
2262 | case KVM_CHECK_EXTENSION: | 2259 | case KVM_CHECK_EXTENSION: |
2263 | r = kvm_dev_ioctl_check_extension_generic(arg); | 2260 | r = kvm_dev_ioctl_check_extension_generic(arg); |