diff options
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r-- | virt/kvm/kvm_main.c | 173 |
1 files changed, 172 insertions, 1 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index aaac1a7a9ea8..5da9f02a2a67 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -504,6 +504,7 @@ static struct kvm *kvm_create_vm(unsigned long type) | |||
504 | mutex_init(&kvm->irq_lock); | 504 | mutex_init(&kvm->irq_lock); |
505 | mutex_init(&kvm->slots_lock); | 505 | mutex_init(&kvm->slots_lock); |
506 | atomic_set(&kvm->users_count, 1); | 506 | atomic_set(&kvm->users_count, 1); |
507 | INIT_LIST_HEAD(&kvm->devices); | ||
507 | 508 | ||
508 | r = kvm_init_mmu_notifier(kvm); | 509 | r = kvm_init_mmu_notifier(kvm); |
509 | if (r) | 510 | if (r) |
@@ -581,6 +582,19 @@ void kvm_free_physmem(struct kvm *kvm) | |||
581 | kfree(kvm->memslots); | 582 | kfree(kvm->memslots); |
582 | } | 583 | } |
583 | 584 | ||
585 | static void kvm_destroy_devices(struct kvm *kvm) | ||
586 | { | ||
587 | struct list_head *node, *tmp; | ||
588 | |||
589 | list_for_each_safe(node, tmp, &kvm->devices) { | ||
590 | struct kvm_device *dev = | ||
591 | list_entry(node, struct kvm_device, vm_node); | ||
592 | |||
593 | list_del(node); | ||
594 | dev->ops->destroy(dev); | ||
595 | } | ||
596 | } | ||
597 | |||
584 | static void kvm_destroy_vm(struct kvm *kvm) | 598 | static void kvm_destroy_vm(struct kvm *kvm) |
585 | { | 599 | { |
586 | int i; | 600 | int i; |
@@ -600,6 +614,7 @@ static void kvm_destroy_vm(struct kvm *kvm) | |||
600 | kvm_arch_flush_shadow_all(kvm); | 614 | kvm_arch_flush_shadow_all(kvm); |
601 | #endif | 615 | #endif |
602 | kvm_arch_destroy_vm(kvm); | 616 | kvm_arch_destroy_vm(kvm); |
617 | kvm_destroy_devices(kvm); | ||
603 | kvm_free_physmem(kvm); | 618 | kvm_free_physmem(kvm); |
604 | cleanup_srcu_struct(&kvm->srcu); | 619 | cleanup_srcu_struct(&kvm->srcu); |
605 | kvm_arch_free_vm(kvm); | 620 | kvm_arch_free_vm(kvm); |
@@ -2159,6 +2174,111 @@ out: | |||
2159 | } | 2174 | } |
2160 | #endif | 2175 | #endif |
2161 | 2176 | ||
2177 | static int kvm_device_ioctl_attr(struct kvm_device *dev, | ||
2178 | int (*accessor)(struct kvm_device *dev, | ||
2179 | struct kvm_device_attr *attr), | ||
2180 | unsigned long arg) | ||
2181 | { | ||
2182 | struct kvm_device_attr attr; | ||
2183 | |||
2184 | if (!accessor) | ||
2185 | return -EPERM; | ||
2186 | |||
2187 | if (copy_from_user(&attr, (void __user *)arg, sizeof(attr))) | ||
2188 | return -EFAULT; | ||
2189 | |||
2190 | return accessor(dev, &attr); | ||
2191 | } | ||
2192 | |||
2193 | static long kvm_device_ioctl(struct file *filp, unsigned int ioctl, | ||
2194 | unsigned long arg) | ||
2195 | { | ||
2196 | struct kvm_device *dev = filp->private_data; | ||
2197 | |||
2198 | switch (ioctl) { | ||
2199 | case KVM_SET_DEVICE_ATTR: | ||
2200 | return kvm_device_ioctl_attr(dev, dev->ops->set_attr, arg); | ||
2201 | case KVM_GET_DEVICE_ATTR: | ||
2202 | return kvm_device_ioctl_attr(dev, dev->ops->get_attr, arg); | ||
2203 | case KVM_HAS_DEVICE_ATTR: | ||
2204 | return kvm_device_ioctl_attr(dev, dev->ops->has_attr, arg); | ||
2205 | default: | ||
2206 | if (dev->ops->ioctl) | ||
2207 | return dev->ops->ioctl(dev, ioctl, arg); | ||
2208 | |||
2209 | return -ENOTTY; | ||
2210 | } | ||
2211 | } | ||
2212 | |||
2213 | static int kvm_device_release(struct inode *inode, struct file *filp) | ||
2214 | { | ||
2215 | struct kvm_device *dev = filp->private_data; | ||
2216 | struct kvm *kvm = dev->kvm; | ||
2217 | |||
2218 | kvm_put_kvm(kvm); | ||
2219 | return 0; | ||
2220 | } | ||
2221 | |||
2222 | static const struct file_operations kvm_device_fops = { | ||
2223 | .unlocked_ioctl = kvm_device_ioctl, | ||
2224 | .release = kvm_device_release, | ||
2225 | }; | ||
2226 | |||
2227 | struct kvm_device *kvm_device_from_filp(struct file *filp) | ||
2228 | { | ||
2229 | if (filp->f_op != &kvm_device_fops) | ||
2230 | return NULL; | ||
2231 | |||
2232 | return filp->private_data; | ||
2233 | } | ||
2234 | |||
2235 | static int kvm_ioctl_create_device(struct kvm *kvm, | ||
2236 | struct kvm_create_device *cd) | ||
2237 | { | ||
2238 | struct kvm_device_ops *ops = NULL; | ||
2239 | struct kvm_device *dev; | ||
2240 | bool test = cd->flags & KVM_CREATE_DEVICE_TEST; | ||
2241 | int ret; | ||
2242 | |||
2243 | switch (cd->type) { | ||
2244 | #ifdef CONFIG_KVM_MPIC | ||
2245 | case KVM_DEV_TYPE_FSL_MPIC_20: | ||
2246 | case KVM_DEV_TYPE_FSL_MPIC_42: | ||
2247 | ops = &kvm_mpic_ops; | ||
2248 | break; | ||
2249 | #endif | ||
2250 | default: | ||
2251 | return -ENODEV; | ||
2252 | } | ||
2253 | |||
2254 | if (test) | ||
2255 | return 0; | ||
2256 | |||
2257 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
2258 | if (!dev) | ||
2259 | return -ENOMEM; | ||
2260 | |||
2261 | dev->ops = ops; | ||
2262 | dev->kvm = kvm; | ||
2263 | |||
2264 | ret = ops->create(dev, cd->type); | ||
2265 | if (ret < 0) { | ||
2266 | kfree(dev); | ||
2267 | return ret; | ||
2268 | } | ||
2269 | |||
2270 | ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR); | ||
2271 | if (ret < 0) { | ||
2272 | ops->destroy(dev); | ||
2273 | return ret; | ||
2274 | } | ||
2275 | |||
2276 | list_add(&dev->vm_node, &kvm->devices); | ||
2277 | kvm_get_kvm(kvm); | ||
2278 | cd->fd = ret; | ||
2279 | return 0; | ||
2280 | } | ||
2281 | |||
2162 | static long kvm_vm_ioctl(struct file *filp, | 2282 | static long kvm_vm_ioctl(struct file *filp, |
2163 | unsigned int ioctl, unsigned long arg) | 2283 | unsigned int ioctl, unsigned long arg) |
2164 | { | 2284 | { |
@@ -2274,6 +2394,54 @@ static long kvm_vm_ioctl(struct file *filp, | |||
2274 | break; | 2394 | break; |
2275 | } | 2395 | } |
2276 | #endif | 2396 | #endif |
2397 | #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING | ||
2398 | case KVM_SET_GSI_ROUTING: { | ||
2399 | struct kvm_irq_routing routing; | ||
2400 | struct kvm_irq_routing __user *urouting; | ||
2401 | struct kvm_irq_routing_entry *entries; | ||
2402 | |||
2403 | r = -EFAULT; | ||
2404 | if (copy_from_user(&routing, argp, sizeof(routing))) | ||
2405 | goto out; | ||
2406 | r = -EINVAL; | ||
2407 | if (routing.nr >= KVM_MAX_IRQ_ROUTES) | ||
2408 | goto out; | ||
2409 | if (routing.flags) | ||
2410 | goto out; | ||
2411 | r = -ENOMEM; | ||
2412 | entries = vmalloc(routing.nr * sizeof(*entries)); | ||
2413 | if (!entries) | ||
2414 | goto out; | ||
2415 | r = -EFAULT; | ||
2416 | urouting = argp; | ||
2417 | if (copy_from_user(entries, urouting->entries, | ||
2418 | routing.nr * sizeof(*entries))) | ||
2419 | goto out_free_irq_routing; | ||
2420 | r = kvm_set_irq_routing(kvm, entries, routing.nr, | ||
2421 | routing.flags); | ||
2422 | out_free_irq_routing: | ||
2423 | vfree(entries); | ||
2424 | break; | ||
2425 | } | ||
2426 | #endif /* CONFIG_HAVE_KVM_IRQ_ROUTING */ | ||
2427 | case KVM_CREATE_DEVICE: { | ||
2428 | struct kvm_create_device cd; | ||
2429 | |||
2430 | r = -EFAULT; | ||
2431 | if (copy_from_user(&cd, argp, sizeof(cd))) | ||
2432 | goto out; | ||
2433 | |||
2434 | r = kvm_ioctl_create_device(kvm, &cd); | ||
2435 | if (r) | ||
2436 | goto out; | ||
2437 | |||
2438 | r = -EFAULT; | ||
2439 | if (copy_to_user(argp, &cd, sizeof(cd))) | ||
2440 | goto out; | ||
2441 | |||
2442 | r = 0; | ||
2443 | break; | ||
2444 | } | ||
2277 | default: | 2445 | default: |
2278 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); | 2446 | r = kvm_arch_vm_ioctl(filp, ioctl, arg); |
2279 | if (r == -ENOTTY) | 2447 | if (r == -ENOTTY) |
@@ -2403,8 +2571,11 @@ static long kvm_dev_ioctl_check_extension_generic(long arg) | |||
2403 | #ifdef CONFIG_HAVE_KVM_MSI | 2571 | #ifdef CONFIG_HAVE_KVM_MSI |
2404 | case KVM_CAP_SIGNAL_MSI: | 2572 | case KVM_CAP_SIGNAL_MSI: |
2405 | #endif | 2573 | #endif |
2574 | #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING | ||
2575 | case KVM_CAP_IRQFD_RESAMPLE: | ||
2576 | #endif | ||
2406 | return 1; | 2577 | return 1; |
2407 | #ifdef KVM_CAP_IRQ_ROUTING | 2578 | #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING |
2408 | case KVM_CAP_IRQ_ROUTING: | 2579 | case KVM_CAP_IRQ_ROUTING: |
2409 | return KVM_MAX_IRQ_ROUTES; | 2580 | return KVM_MAX_IRQ_ROUTES; |
2410 | #endif | 2581 | #endif |