[PATCH 3/3] KVM: Convert x86 vcpu ioctls to use dispatch_ioctl_extensible()
From: Avi Kivity
Date: Sat Sep 27 2008 - 11:45:50 EST
Signed-off-by: Avi Kivity <avi@xxxxxxxxxx>
---
arch/x86/kvm/x86.c | 241 +++++++++++++++++-----------------------------------
1 files changed, 77 insertions(+), 164 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4cfdd1b..aa9d228 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1084,26 +1084,24 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
*
* @return number of msrs set successfully.
*/
-static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
+static int msr_io(const struct ioctl_arg *iarg,
int (*do_msr)(struct kvm_vcpu *vcpu,
- unsigned index, u64 *data),
- int writeback)
+ unsigned index, u64 *data))
{
- struct kvm_msrs msrs;
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_msrs *msrs = iarg->argp;
+ struct kvm_msrs __user *user_msrs =
+ (void __user *)iarg->argl + _IOC_SIZE(iarg->cmd);
struct kvm_msr_entry *entries;
- int r, n;
+ int r;
unsigned size;
- r = -EFAULT;
- if (copy_from_user(&msrs, user_msrs, sizeof msrs))
- goto out;
-
r = -E2BIG;
- if (msrs.nmsrs >= MAX_IO_MSRS)
+ if (msrs->nmsrs >= MAX_IO_MSRS)
goto out;
r = -ENOMEM;
- size = sizeof(struct kvm_msr_entry) * msrs.nmsrs;
+ size = sizeof(struct kvm_msr_entry) * msrs->nmsrs;
entries = vmalloc(size);
if (!entries)
goto out;
@@ -1112,22 +1110,26 @@ static int msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs __user *user_msrs,
if (copy_from_user(entries, user_msrs->entries, size))
goto out_free;
- r = n = __msr_io(vcpu, &msrs, entries, do_msr);
+ r = __msr_io(vcpu, msrs, entries, do_msr);
if (r < 0)
goto out_free;
- r = -EFAULT;
- if (writeback && copy_to_user(user_msrs->entries, entries, size))
- goto out_free;
-
- r = n;
-
out_free:
vfree(entries);
out:
return r;
}
+static long kvm_vcpu_ioctl_get_msrs(const struct ioctl_arg *iarg)
+{
+ return msr_io(iarg, kvm_get_msr);
+}
+
+static long kvm_vcpu_ioctl_set_msrs(const struct ioctl_arg *iarg)
+{
+ return msr_io(iarg, do_set_msr);
+}
+
int kvm_dev_ioctl_check_extension(long ext)
{
int r;
@@ -1271,10 +1273,12 @@ static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
}
/* when an old userspace process fills a new kernel module */
-static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
- struct kvm_cpuid *cpuid,
- struct kvm_cpuid_entry __user *entries)
+static long kvm_vcpu_ioctl_set_cpuid(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_cpuid *cpuid = iarg->argp;
+ struct kvm_cpuid_entry __user *entries
+ = (void __user *)iarg->argl + _IOC_SIZE(iarg->cmd);
int r, i;
struct kvm_cpuid_entry *cpuid_entries;
@@ -1311,10 +1315,12 @@ out:
return r;
}
-static int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu,
- struct kvm_cpuid2 *cpuid,
- struct kvm_cpuid_entry2 __user *entries)
+static long kvm_vcpu_ioctl_set_cpuid2(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_cpuid2 *cpuid = iarg->argp;
+ struct kvm_cpuid_entry2 __user *entries
+ = (void __user *)iarg->argl + _IOC_SIZE(iarg->cmd);
int r;
r = -E2BIG;
@@ -1331,10 +1337,12 @@ out:
return r;
}
-static int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
- struct kvm_cpuid2 *cpuid,
- struct kvm_cpuid_entry2 __user *entries)
+static long kvm_vcpu_ioctl_get_cpuid2(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_cpuid2 *cpuid = iarg->argp;
+ struct kvm_cpuid_entry2 __user *entries
+ = (void __user *)iarg->argl + _IOC_SIZE(iarg->cmd);
int r;
r = -E2BIG;
@@ -1513,19 +1521,22 @@ out:
return r;
}
-static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
- struct kvm_lapic_state *s)
+static long kvm_vcpu_ioctl_get_lapic(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_lapic_state *s = iarg->argp;
+
vcpu_load(vcpu);
memcpy(s->regs, vcpu->arch.apic->regs, sizeof *s);
vcpu_put(vcpu);
-
return 0;
}
-static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
- struct kvm_lapic_state *s)
+static long kvm_vcpu_ioctl_set_lapic(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_lapic_state *s = iarg->argp;
+
vcpu_load(vcpu);
memcpy(vcpu->arch.apic->regs, s->regs, sizeof *s);
kvm_apic_post_state_restore(vcpu);
@@ -1534,9 +1545,11 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu,
return 0;
}
-static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
- struct kvm_interrupt *irq)
+static long kvm_vcpu_ioctl_interrupt(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_interrupt *irq = iarg->argp;
+
if (irq->irq < 0 || irq->irq >= 256)
return -EINVAL;
if (irqchip_in_kernel(vcpu->kvm))
@@ -1551,148 +1564,48 @@ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
return 0;
}
-static int vcpu_ioctl_tpr_access_reporting(struct kvm_vcpu *vcpu,
- struct kvm_tpr_access_ctl *tac)
+static long vcpu_ioctl_tpr_access_reporting(const struct ioctl_arg *iarg)
{
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_tpr_access_ctl *tac = iarg->argp;
+
if (tac->flags)
return -EINVAL;
vcpu->arch.tpr_access_reporting = !!tac->enabled;
return 0;
}
-long kvm_arch_vcpu_ioctl(struct file *filp,
- unsigned int ioctl, unsigned long arg)
+static long vcpu_ioctl_set_vapic_addr(const struct ioctl_arg *iarg)
{
- struct kvm_vcpu *vcpu = filp->private_data;
- void __user *argp = (void __user *)arg;
- int r;
- struct kvm_lapic_state *lapic = NULL;
-
- switch (ioctl) {
- case KVM_GET_LAPIC: {
- lapic = kzalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
-
- r = -ENOMEM;
- if (!lapic)
- goto out;
- r = kvm_vcpu_ioctl_get_lapic(vcpu, lapic);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(argp, lapic, sizeof(struct kvm_lapic_state)))
- goto out;
- r = 0;
- break;
- }
- case KVM_SET_LAPIC: {
- lapic = kmalloc(sizeof(struct kvm_lapic_state), GFP_KERNEL);
- r = -ENOMEM;
- if (!lapic)
- goto out;
- r = -EFAULT;
- if (copy_from_user(lapic, argp, sizeof(struct kvm_lapic_state)))
- goto out;
- r = kvm_vcpu_ioctl_set_lapic(vcpu, lapic);
- if (r)
- goto out;
- r = 0;
- break;
- }
- case KVM_INTERRUPT: {
- struct kvm_interrupt irq;
-
- r = -EFAULT;
- if (copy_from_user(&irq, argp, sizeof irq))
- goto out;
- r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
- if (r)
- goto out;
- r = 0;
- break;
- }
- case KVM_SET_CPUID: {
- struct kvm_cpuid __user *cpuid_arg = argp;
- struct kvm_cpuid cpuid;
-
- r = -EFAULT;
- if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
- r = kvm_vcpu_ioctl_set_cpuid(vcpu, &cpuid, cpuid_arg->entries);
- if (r)
- goto out;
- break;
- }
- case KVM_SET_CPUID2: {
- struct kvm_cpuid2 __user *cpuid_arg = argp;
- struct kvm_cpuid2 cpuid;
+ struct kvm_vcpu *vcpu = iarg->file->private_data;
+ struct kvm_vapic_addr *va = iarg->argp;
- r = -EFAULT;
- if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
- r = kvm_vcpu_ioctl_set_cpuid2(vcpu, &cpuid,
- cpuid_arg->entries);
- if (r)
- goto out;
- break;
- }
- case KVM_GET_CPUID2: {
- struct kvm_cpuid2 __user *cpuid_arg = argp;
- struct kvm_cpuid2 cpuid;
+ if (!irqchip_in_kernel(vcpu->kvm))
+ return -EINVAL;
- r = -EFAULT;
- if (copy_from_user(&cpuid, cpuid_arg, sizeof cpuid))
- goto out;
- r = kvm_vcpu_ioctl_get_cpuid2(vcpu, &cpuid,
- cpuid_arg->entries);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(cpuid_arg, &cpuid, sizeof cpuid))
- goto out;
- r = 0;
- break;
- }
- case KVM_GET_MSRS:
- r = msr_io(vcpu, argp, kvm_get_msr, 1);
- break;
- case KVM_SET_MSRS:
- r = msr_io(vcpu, argp, do_set_msr, 0);
- break;
- case KVM_TPR_ACCESS_REPORTING: {
- struct kvm_tpr_access_ctl tac;
+ kvm_lapic_set_vapic_addr(vcpu, va->vapic_addr);
+ return 0;
+}
- r = -EFAULT;
- if (copy_from_user(&tac, argp, sizeof tac))
- goto out;
- r = vcpu_ioctl_tpr_access_reporting(vcpu, &tac);
- if (r)
- goto out;
- r = -EFAULT;
- if (copy_to_user(argp, &tac, sizeof tac))
- goto out;
- r = 0;
- break;
- };
- case KVM_SET_VAPIC_ADDR: {
- struct kvm_vapic_addr va;
+static const struct ioctl_handler vcpu_ioctl_handlers[] = {
+ { KVM_GET_LAPIC, kvm_vcpu_ioctl_get_lapic },
+ { KVM_SET_LAPIC, kvm_vcpu_ioctl_set_lapic },
+ { KVM_INTERRUPT, kvm_vcpu_ioctl_interrupt },
+ { KVM_SET_CPUID, kvm_vcpu_ioctl_set_cpuid },
+ { KVM_SET_CPUID2, kvm_vcpu_ioctl_set_cpuid2 },
+ { KVM_GET_CPUID2, kvm_vcpu_ioctl_get_cpuid2 },
+ { KVM_GET_MSRS, kvm_vcpu_ioctl_get_msrs },
+ { KVM_SET_MSRS, kvm_vcpu_ioctl_set_msrs },
+ { KVM_TPR_ACCESS_REPORTING, vcpu_ioctl_tpr_access_reporting },
+ { KVM_SET_VAPIC_ADDR, vcpu_ioctl_set_vapic_addr },
+ { }
+};
- r = -EINVAL;
- if (!irqchip_in_kernel(vcpu->kvm))
- goto out;
- r = -EFAULT;
- if (copy_from_user(&va, argp, sizeof va))
- goto out;
- r = 0;
- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr);
- break;
- }
- default:
- r = -EINVAL;
- }
-out:
- if (lapic)
- kfree(lapic);
- return r;
+long kvm_arch_vcpu_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ return dispatch_ioctl_extensible(NULL, filp, ioctl, arg,
+ vcpu_ioctl_handlers, NULL);
}
static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
--
1.6.0.1
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/