|
@@ -797,6 +797,30 @@ static int kvm_mips_set_reg(struct kvm_vcpu *vcpu,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
|
|
|
+ struct kvm_enable_cap *cap)
|
|
|
+{
|
|
|
+ int r = 0;
|
|
|
+
|
|
|
+ if (!kvm_vm_ioctl_check_extension(vcpu->kvm, cap->cap))
|
|
|
+ return -EINVAL;
|
|
|
+ if (cap->flags)
|
|
|
+ return -EINVAL;
|
|
|
+ if (cap->args[0])
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (cap->cap) {
|
|
|
+ case KVM_CAP_MIPS_FPU:
|
|
|
+ vcpu->arch.fpu_enabled = true;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ r = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
|
|
|
unsigned long arg)
|
|
|
{
|
|
@@ -854,6 +878,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl,
|
|
|
r = kvm_vcpu_ioctl_interrupt(vcpu, &irq);
|
|
|
break;
|
|
|
}
|
|
|
+ case KVM_ENABLE_CAP: {
|
|
|
+ struct kvm_enable_cap cap;
|
|
|
+
|
|
|
+ r = -EFAULT;
|
|
|
+ if (copy_from_user(&cap, argp, sizeof(cap)))
|
|
|
+ goto out;
|
|
|
+ r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
|
|
|
+ break;
|
|
|
+ }
|
|
|
default:
|
|
|
r = -ENOIOCTLCMD;
|
|
|
}
|
|
@@ -962,11 +995,15 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
|
|
|
|
|
switch (ext) {
|
|
|
case KVM_CAP_ONE_REG:
|
|
|
+ case KVM_CAP_ENABLE_CAP:
|
|
|
r = 1;
|
|
|
break;
|
|
|
case KVM_CAP_COALESCED_MMIO:
|
|
|
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
|
|
|
break;
|
|
|
+ case KVM_CAP_MIPS_FPU:
|
|
|
+ r = !!cpu_has_fpu;
|
|
|
+ break;
|
|
|
default:
|
|
|
r = 0;
|
|
|
break;
|