Commit 1dda606c authored by Alexander Graf's avatar Alexander Graf Committed by Avi Kivity

KVM: Add compat ioctl for KVM_SET_SIGNAL_MASK

KVM has an ioctl to define which signal mask should be used while running
inside VCPU_RUN. At least for big endian systems, this mask is different
on 32-bit and 64-bit systems (though the size is identical).

Add a compat wrapper that converts the mask to whatever the kernel accepts,
allowing 32-bit kvm user space to set signal masks.

This patch fixes qemu with --enable-io-thread on ppc64 hosts when running
32-bit user land.
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent 91e3d71d
...@@ -890,6 +890,7 @@ sigset_from_compat (sigset_t *set, compat_sigset_t *compat) ...@@ -890,6 +890,7 @@ sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
} }
} }
EXPORT_SYMBOL_GPL(sigset_from_compat);
asmlinkage long asmlinkage long
compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
......
...@@ -84,6 +84,10 @@ struct dentry *kvm_debugfs_dir; ...@@ -84,6 +84,10 @@ struct dentry *kvm_debugfs_dir;
static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
unsigned long arg); unsigned long arg);
#ifdef CONFIG_COMPAT
static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl,
unsigned long arg);
#endif
static int hardware_enable_all(void); static int hardware_enable_all(void);
static void hardware_disable_all(void); static void hardware_disable_all(void);
...@@ -1586,7 +1590,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp) ...@@ -1586,7 +1590,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
static struct file_operations kvm_vcpu_fops = { static struct file_operations kvm_vcpu_fops = {
.release = kvm_vcpu_release, .release = kvm_vcpu_release,
.unlocked_ioctl = kvm_vcpu_ioctl, .unlocked_ioctl = kvm_vcpu_ioctl,
.compat_ioctl = kvm_vcpu_ioctl, #ifdef CONFIG_COMPAT
.compat_ioctl = kvm_vcpu_compat_ioctl,
#endif
.mmap = kvm_vcpu_mmap, .mmap = kvm_vcpu_mmap,
.llseek = noop_llseek, .llseek = noop_llseek,
}; };
...@@ -1875,6 +1881,50 @@ static long kvm_vcpu_ioctl(struct file *filp, ...@@ -1875,6 +1881,50 @@ static long kvm_vcpu_ioctl(struct file *filp,
return r; return r;
} }
#ifdef CONFIG_COMPAT
static long kvm_vcpu_compat_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
struct kvm_vcpu *vcpu = filp->private_data;
void __user *argp = compat_ptr(arg);
int r;
if (vcpu->kvm->mm != current->mm)
return -EIO;
switch (ioctl) {
case KVM_SET_SIGNAL_MASK: {
struct kvm_signal_mask __user *sigmask_arg = argp;
struct kvm_signal_mask kvm_sigmask;
compat_sigset_t csigset;
sigset_t sigset;
if (argp) {
r = -EFAULT;
if (copy_from_user(&kvm_sigmask, argp,
sizeof kvm_sigmask))
goto out;
r = -EINVAL;
if (kvm_sigmask.len != sizeof csigset)
goto out;
r = -EFAULT;
if (copy_from_user(&csigset, sigmask_arg->sigset,
sizeof csigset))
goto out;
}
sigset_from_compat(&sigset, &csigset);
r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
break;
}
default:
r = kvm_vcpu_ioctl(filp, ioctl, arg);
}
out:
return r;
}
#endif
static long kvm_vm_ioctl(struct file *filp, static long kvm_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg) unsigned int ioctl, unsigned long arg)
{ {
......
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