Skip to content

Commit

Permalink
KVM: s390: add parameter for KVM_CREATE_VM
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
Carsten Otte authored and avikivity committed Mar 5, 2012
1 parent a138fe7 commit e08b963
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 18 deletions.
7 changes: 6 additions & 1 deletion Documentation/virtual/kvm/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,19 @@ 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
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

Expand Down
5 changes: 4 additions & 1 deletion arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion arch/powerpc/kvm/powerpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
9 changes: 9 additions & 0 deletions arch/s390/kvm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 19 additions & 5 deletions arch/s390/kvm/kvm-s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions arch/s390/kvm/kvm-s390.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
*/
Expand Down
2 changes: 1 addition & 1 deletion include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
13 changes: 5 additions & 8 deletions virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,15 @@ 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();

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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e08b963

Please sign in to comment.