Commit 5cb0944c authored by Paolo Bonzini's avatar Paolo Bonzini

KVM: introduce kvm_arch_vcpu_async_ioctl

After the vcpu_load/vcpu_put pushdown, the handling of asynchronous VCPU
ioctl is already much clearer in that it is obvious that they bypass
vcpu_load and vcpu_put.

However, it is still not perfect in that the different state of the VCPU
mutex is still hidden in the caller.  Separate those ioctls into a new
function kvm_arch_vcpu_async_ioctl that returns -ENOIOCTLCMD for more
"traditional" synchronous ioctls.

Cc: James Hogan <jhogan@kernel.org>
Cc: Paul Mackerras <paulus@ozlabs.org>
Cc: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: default avatarCornelia Huck <cohuck@redhat.com>
Suggested-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9b062471
...@@ -22,6 +22,7 @@ config KVM ...@@ -22,6 +22,7 @@ config KVM
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select ANON_INODES select ANON_INODES
select KVM_GENERIC_DIRTYLOG_READ_PROTECT select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select HAVE_KVM_VCPU_ASYNC_IOCTL
select KVM_MMIO select KVM_MMIO
select MMU_NOTIFIER select MMU_NOTIFIER
select SRCU select SRCU
......
...@@ -903,12 +903,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, ...@@ -903,12 +903,11 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
return r; return r;
} }
long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, long kvm_arch_vcpu_async_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg) unsigned long arg)
{ {
struct kvm_vcpu *vcpu = filp->private_data; struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
long r;
if (ioctl == KVM_INTERRUPT) { if (ioctl == KVM_INTERRUPT) {
struct kvm_mips_interrupt irq; struct kvm_mips_interrupt irq;
...@@ -921,6 +920,16 @@ long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, ...@@ -921,6 +920,16 @@ long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
return kvm_vcpu_ioctl_interrupt(vcpu, &irq); return kvm_vcpu_ioctl_interrupt(vcpu, &irq);
} }
return -ENOIOCTLCMD;
}
long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
unsigned long arg)
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
long r;
vcpu_load(vcpu); vcpu_load(vcpu);
switch (ioctl) { switch (ioctl) {
......
...@@ -22,6 +22,7 @@ config KVM ...@@ -22,6 +22,7 @@ config KVM
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select ANON_INODES select ANON_INODES
select HAVE_KVM_EVENTFD select HAVE_KVM_EVENTFD
select HAVE_KVM_VCPU_ASYNC_IOCTL
select SRCU select SRCU
select KVM_VFIO select KVM_VFIO
select IRQ_BYPASS_MANAGER select IRQ_BYPASS_MANAGER
......
...@@ -1607,12 +1607,11 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, ...@@ -1607,12 +1607,11 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
return -EINVAL; return -EINVAL;
} }
long kvm_arch_vcpu_ioctl(struct file *filp, long kvm_arch_vcpu_async_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg) unsigned int ioctl, unsigned long arg)
{ {
struct kvm_vcpu *vcpu = filp->private_data; struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
long r;
if (ioctl == KVM_INTERRUPT) { if (ioctl == KVM_INTERRUPT) {
struct kvm_interrupt irq; struct kvm_interrupt irq;
...@@ -1620,6 +1619,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, ...@@ -1620,6 +1619,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
return -EFAULT; return -EFAULT;
return kvm_vcpu_ioctl_interrupt(vcpu, &irq); return kvm_vcpu_ioctl_interrupt(vcpu, &irq);
} }
return -ENOIOCTLCMD;
}
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
long r;
vcpu_load(vcpu); vcpu_load(vcpu);
......
...@@ -23,6 +23,7 @@ config KVM ...@@ -23,6 +23,7 @@ config KVM
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select ANON_INODES select ANON_INODES
select HAVE_KVM_CPU_RELAX_INTERCEPT select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_VCPU_ASYNC_IOCTL
select HAVE_KVM_EVENTFD select HAVE_KVM_EVENTFD
select KVM_ASYNC_PF select KVM_ASYNC_PF
select KVM_ASYNC_PF_SYNC select KVM_ASYNC_PF_SYNC
......
...@@ -3725,13 +3725,11 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu, ...@@ -3725,13 +3725,11 @@ static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
return r; return r;
} }
long kvm_arch_vcpu_ioctl(struct file *filp, long kvm_arch_vcpu_async_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg) unsigned int ioctl, unsigned long arg)
{ {
struct kvm_vcpu *vcpu = filp->private_data; struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int idx;
long r;
switch (ioctl) { switch (ioctl) {
case KVM_S390_IRQ: { case KVM_S390_IRQ: {
...@@ -3752,6 +3750,16 @@ long kvm_arch_vcpu_ioctl(struct file *filp, ...@@ -3752,6 +3750,16 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
return kvm_s390_inject_vcpu(vcpu, &s390irq); return kvm_s390_inject_vcpu(vcpu, &s390irq);
} }
} }
return -ENOIOCTLCMD;
}
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = (void __user *)arg;
int idx;
long r;
vcpu_load(vcpu); vcpu_load(vcpu);
......
...@@ -1260,4 +1260,16 @@ static inline bool vcpu_valid_wakeup(struct kvm_vcpu *vcpu) ...@@ -1260,4 +1260,16 @@ static inline bool vcpu_valid_wakeup(struct kvm_vcpu *vcpu)
} }
#endif /* CONFIG_HAVE_KVM_INVALID_WAKEUPS */ #endif /* CONFIG_HAVE_KVM_INVALID_WAKEUPS */
#ifdef CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL
long kvm_arch_vcpu_async_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg);
#else
static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
unsigned int ioctl,
unsigned long arg)
{
return -ENOIOCTLCMD;
}
#endif /* CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL */
#endif #endif
...@@ -51,3 +51,6 @@ config KVM_COMPAT ...@@ -51,3 +51,6 @@ config KVM_COMPAT
config HAVE_KVM_IRQ_BYPASS config HAVE_KVM_IRQ_BYPASS
bool bool
config HAVE_KVM_VCPU_ASYNC_IOCTL
bool
...@@ -2544,15 +2544,13 @@ static long kvm_vcpu_ioctl(struct file *filp, ...@@ -2544,15 +2544,13 @@ static long kvm_vcpu_ioctl(struct file *filp,
if (unlikely(_IOC_TYPE(ioctl) != KVMIO)) if (unlikely(_IOC_TYPE(ioctl) != KVMIO))
return -EINVAL; return -EINVAL;
#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_MIPS)
/* /*
* Special cases: vcpu ioctls that are asynchronous to vcpu execution, * Some architectures have vcpu ioctls that are asynchronous to vcpu
* so vcpu_load() would break it. * execution; mutex_lock() would break them.
*/ */
if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_S390_IRQ || ioctl == KVM_INTERRUPT) r = kvm_arch_vcpu_async_ioctl(filp, ioctl, arg);
return kvm_arch_vcpu_ioctl(filp, ioctl, arg); if (r != -ENOIOCTLCMD)
#endif return r;
if (mutex_lock_killable(&vcpu->mutex)) if (mutex_lock_killable(&vcpu->mutex))
return -EINTR; return -EINTR;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment