Skip to content

Commit

Permalink
KVM: Add compat ioctl for KVM_SET_SIGNAL_MASK
Browse files Browse the repository at this point in the history
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: Alexander Graf <[email protected]>
Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
agraf authored and avikivity committed Jul 12, 2011
1 parent 91e3d71 commit 1dda606
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
1 change: 1 addition & 0 deletions kernel/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
}
EXPORT_SYMBOL_GPL(sigset_from_compat);

asmlinkage long
compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese,
Expand Down
52 changes: 51 additions & 1 deletion virt/kvm/kvm_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ struct dentry *kvm_debugfs_dir;

static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
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 void hardware_disable_all(void);

Expand Down Expand Up @@ -1586,7 +1590,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
static struct file_operations kvm_vcpu_fops = {
.release = kvm_vcpu_release,
.unlocked_ioctl = kvm_vcpu_ioctl,
.compat_ioctl = kvm_vcpu_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = kvm_vcpu_compat_ioctl,
#endif
.mmap = kvm_vcpu_mmap,
.llseek = noop_llseek,
};
Expand Down Expand Up @@ -1875,6 +1881,50 @@ static long kvm_vcpu_ioctl(struct file *filp,
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,
unsigned int ioctl, unsigned long arg)
{
Expand Down

0 comments on commit 1dda606

Please sign in to comment.