aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2012-01-04 04:25:20 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:18 -0500
commite08b96371625aaa84cb03f51acc4c8e0be27403a (patch)
treed0b140e8558c6145e1a3183809c7797be443bd68
parenta138fe7535c0ec778465c7b54b1aaaf4cfd885b7 (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.txt7
-rw-r--r--arch/ia64/kvm/kvm-ia64.c5
-rw-r--r--arch/powerpc/kvm/powerpc.c5
-rw-r--r--arch/s390/kvm/Kconfig9
-rw-r--r--arch/s390/kvm/kvm-s390.c24
-rw-r--r--arch/s390/kvm/kvm-s390.h10
-rw-r--r--arch/x86/kvm/x86.c5
-rw-r--r--include/linux/kvm.h3
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--virt/kvm/kvm_main.c13
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.
95Capability: basic 95Capability: basic
96Architectures: all 96Architectures: all
97Type: system ioctl 97Type: system ioctl
98Parameters: none 98Parameters: machine type identifier (KVM_VM_*)
99Returns: a VM fd that can be used to control the new virtual machine. 99Returns: a VM fd that can be used to control the new virtual machine.
100 100
101The new VM has no virtual cpus and no memory. An mmap() of a VM fd 101The 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
103corresponds to guest physical address zero. Use of mmap() on a VM fd 103corresponds to guest physical address zero. Use of mmap() on a VM fd
104is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is 104is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is
105available. 105available.
106You most certainly want to use 0 as machine type.
107
108In order to create user controlled virtual machines on S390, check
109KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
110privileged user (CAP_SYS_ADMIN).
106 111
1074.3 KVM_GET_MSR_INDEX_LIST 1124.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
812int kvm_arch_init_vm(struct kvm *kvm) 812int 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
174int kvm_arch_init_vm(struct kvm *kvm) 174int 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
37config 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.
39source drivers/vhost/Kconfig 48source 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
174int kvm_arch_init_vm(struct kvm *kvm) 174int 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;
206out_nogmap: 220out_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
50static 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}
50int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); 60int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
51enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); 61enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
52void kvm_s390_tasklet(unsigned long parm); 62void 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
6034int kvm_arch_init_vm(struct kvm *kvm) 6034int 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
523int kvm_arch_init_vm(struct kvm *kvm); 523int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
524void kvm_arch_destroy_vm(struct kvm *kvm); 524void kvm_arch_destroy_vm(struct kvm *kvm);
525void kvm_free_all_assigned_devices(struct kvm *kvm); 525void kvm_free_all_assigned_devices(struct kvm *kvm);
526void kvm_arch_sync_events(struct kvm *kvm); 526void 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
452static struct kvm *kvm_create_vm(void) 452static 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
2201static int kvm_dev_ioctl_create_vm(void) 2201static 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);