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>
This commit is contained in:
parent
a138fe7535
commit
e08b963716
@ -95,7 +95,7 @@ described as 'basic' will be available.
|
||||
Capability: basic
|
||||
Architectures: all
|
||||
Type: system ioctl
|
||||
Parameters: none
|
||||
Parameters: machine type identifier (KVM_VM_*)
|
||||
Returns: a VM fd that can be used to control the new virtual machine.
|
||||
|
||||
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
|
||||
corresponds to guest physical address zero. Use of mmap() on a VM fd
|
||||
is discouraged if userspace memory allocation (KVM_CAP_USER_MEMORY) is
|
||||
available.
|
||||
You most certainly want to use 0 as machine type.
|
||||
|
||||
In order to create user controlled virtual machines on S390, check
|
||||
KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
|
||||
privileged user (CAP_SYS_ADMIN).
|
||||
|
||||
4.3 KVM_GET_MSR_INDEX_LIST
|
||||
|
||||
|
@ -809,10 +809,13 @@ static void kvm_build_io_pmt(struct kvm *kvm)
|
||||
#define GUEST_PHYSICAL_RR4 0x2739
|
||||
#define VMM_INIT_RR 0x1660
|
||||
|
||||
int kvm_arch_init_vm(struct kvm *kvm)
|
||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
{
|
||||
BUG_ON(!kvm);
|
||||
|
||||
if (type)
|
||||
return -EINVAL;
|
||||
|
||||
kvm->arch.is_sn2 = ia64_platform_is("sn2");
|
||||
|
||||
kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
|
||||
|
@ -171,8 +171,11 @@ void kvm_arch_check_processor_compat(void *rtn)
|
||||
*(int *)rtn = kvmppc_core_check_processor_compat();
|
||||
}
|
||||
|
||||
int kvm_arch_init_vm(struct kvm *kvm)
|
||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
{
|
||||
if (type)
|
||||
return -EINVAL;
|
||||
|
||||
return kvmppc_core_init_vm(kvm);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,15 @@ config KVM
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config KVM_S390_UCONTROL
|
||||
bool "Userspace controlled virtual machines"
|
||||
depends on KVM
|
||||
---help---
|
||||
Allow CAP_SYS_ADMIN users to create KVM virtual machines that are
|
||||
controlled by userspace.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
# OK, it's a little counter-intuitive to do this, but it puts it neatly under
|
||||
# the virtualization menu.
|
||||
source drivers/vhost/Kconfig
|
||||
|
@ -171,11 +171,22 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
||||
return r;
|
||||
}
|
||||
|
||||
int kvm_arch_init_vm(struct kvm *kvm)
|
||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
{
|
||||
int rc;
|
||||
char debug_name[16];
|
||||
|
||||
rc = -EINVAL;
|
||||
#ifdef CONFIG_KVM_S390_UCONTROL
|
||||
if (type & ~KVM_VM_S390_UCONTROL)
|
||||
goto out_err;
|
||||
if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
|
||||
goto out_err;
|
||||
#else
|
||||
if (type)
|
||||
goto out_err;
|
||||
#endif
|
||||
|
||||
rc = s390_enable_sie();
|
||||
if (rc)
|
||||
goto out_err;
|
||||
@ -198,10 +209,13 @@ int kvm_arch_init_vm(struct kvm *kvm)
|
||||
debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
|
||||
VM_EVENT(kvm, 3, "%s", "vm created");
|
||||
|
||||
kvm->arch.gmap = gmap_alloc(current->mm);
|
||||
if (!kvm->arch.gmap)
|
||||
goto out_nogmap;
|
||||
|
||||
if (type & KVM_VM_S390_UCONTROL) {
|
||||
kvm->arch.gmap = NULL;
|
||||
} else {
|
||||
kvm->arch.gmap = gmap_alloc(current->mm);
|
||||
if (!kvm->arch.gmap)
|
||||
goto out_nogmap;
|
||||
}
|
||||
return 0;
|
||||
out_nogmap:
|
||||
debug_unregister(kvm->arch.dbf);
|
||||
|
@ -47,6 +47,16 @@ static inline int __cpu_is_stopped(struct kvm_vcpu *vcpu)
|
||||
return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOP_INT;
|
||||
}
|
||||
|
||||
static inline int kvm_is_ucontrol(struct kvm *kvm)
|
||||
{
|
||||
#ifdef CONFIG_KVM_S390_UCONTROL
|
||||
if (kvm->arch.gmap)
|
||||
return 0;
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
|
||||
enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
|
||||
void kvm_s390_tasklet(unsigned long parm);
|
||||
|
@ -6031,8 +6031,11 @@ void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
|
||||
free_page((unsigned long)vcpu->arch.pio_data);
|
||||
}
|
||||
|
||||
int kvm_arch_init_vm(struct kvm *kvm)
|
||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
{
|
||||
if (type)
|
||||
return -EINVAL;
|
||||
|
||||
INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
|
||||
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);
|
||||
|
||||
|
@ -431,6 +431,9 @@ struct kvm_ppc_pvinfo {
|
||||
|
||||
#define KVMIO 0xAE
|
||||
|
||||
/* machine type bits, to be used as argument to KVM_CREATE_VM */
|
||||
#define KVM_VM_S390_UCONTROL 1
|
||||
|
||||
/*
|
||||
* ioctls for /dev/kvm fds:
|
||||
*/
|
||||
|
@ -520,7 +520,7 @@ static inline void kvm_arch_free_vm(struct kvm *kvm)
|
||||
}
|
||||
#endif
|
||||
|
||||
int kvm_arch_init_vm(struct kvm *kvm);
|
||||
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type);
|
||||
void kvm_arch_destroy_vm(struct kvm *kvm);
|
||||
void kvm_free_all_assigned_devices(struct kvm *kvm);
|
||||
void kvm_arch_sync_events(struct kvm *kvm);
|
||||
|
@ -449,7 +449,7 @@ static void kvm_init_memslots_id(struct kvm *kvm)
|
||||
slots->id_to_index[i] = slots->memslots[i].id = i;
|
||||
}
|
||||
|
||||
static struct kvm *kvm_create_vm(void)
|
||||
static struct kvm *kvm_create_vm(unsigned long type)
|
||||
{
|
||||
int r, i;
|
||||
struct kvm *kvm = kvm_arch_alloc_vm();
|
||||
@ -457,7 +457,7 @@ static struct kvm *kvm_create_vm(void)
|
||||
if (!kvm)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
r = kvm_arch_init_vm(kvm);
|
||||
r = kvm_arch_init_vm(kvm, type);
|
||||
if (r)
|
||||
goto out_err_nodisable;
|
||||
|
||||
@ -2198,12 +2198,12 @@ static struct file_operations kvm_vm_fops = {
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
static int kvm_dev_ioctl_create_vm(void)
|
||||
static int kvm_dev_ioctl_create_vm(unsigned long type)
|
||||
{
|
||||
int r;
|
||||
struct kvm *kvm;
|
||||
|
||||
kvm = kvm_create_vm();
|
||||
kvm = kvm_create_vm(type);
|
||||
if (IS_ERR(kvm))
|
||||
return PTR_ERR(kvm);
|
||||
#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET
|
||||
@ -2254,10 +2254,7 @@ static long kvm_dev_ioctl(struct file *filp,
|
||||
r = KVM_API_VERSION;
|
||||
break;
|
||||
case KVM_CREATE_VM:
|
||||
r = -EINVAL;
|
||||
if (arg)
|
||||
goto out;
|
||||
r = kvm_dev_ioctl_create_vm();
|
||||
r = kvm_dev_ioctl_create_vm(arg);
|
||||
break;
|
||||
case KVM_CHECK_EXTENSION:
|
||||
r = kvm_dev_ioctl_check_extension_generic(arg);
|
||||
|
Loading…
Reference in New Issue
Block a user