aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86.c
diff options
context:
space:
mode:
authorCarsten Otte <cotte@de.ibm.com>2007-10-29 11:08:35 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:57 -0500
commit1fe779f8eccd16e527315e1bafd2b3a876ff2489 (patch)
tree1af54558db85a9dcb8c9a78861849c2798d86cf5 /drivers/kvm/x86.c
parentb733bfb524af69612f85c36a511f0109c5e3fe8d (diff)
KVM: Portability: Split kvm_vm_ioctl v3
This patch splits kvm_vm_ioctl into archtecture independent parts, and x86 specific parts which go to kvm_arch_vcpu_ioctl in x86.c. The patch is unchanged since last submission. Common ioctls for all architectures are: KVM_CREATE_VCPU, KVM_GET_DIRTY_LOG, KVM_SET_USER_MEMORY_REGION x86 specific ioctls are: KVM_SET_MEMORY_REGION, KVM_GET/SET_NR_MMU_PAGES, KVM_SET_MEMORY_ALIAS, KVM_CREATE_IRQCHIP, KVM_CREATE_IRQ_LINE, KVM_GET/SET_IRQCHIP KVM_SET_TSS_ADDR Signed-off-by: Carsten Otte <cotte@de.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Acked-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86.c')
-rw-r--r--drivers/kvm/x86.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
index 1fe209dd4caf..b84cb6707f78 100644
--- a/drivers/kvm/x86.c
+++ b/drivers/kvm/x86.c
@@ -300,6 +300,264 @@ out:
300 return r; 300 return r;
301} 301}
302 302
303static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
304{
305 int ret;
306
307 if (addr > (unsigned int)(-3 * PAGE_SIZE))
308 return -1;
309 ret = kvm_x86_ops->set_tss_addr(kvm, addr);
310 return ret;
311}
312
313static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
314 u32 kvm_nr_mmu_pages)
315{
316 if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
317 return -EINVAL;
318
319 mutex_lock(&kvm->lock);
320
321 kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
322 kvm->n_requested_mmu_pages = kvm_nr_mmu_pages;
323
324 mutex_unlock(&kvm->lock);
325 return 0;
326}
327
328static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
329{
330 return kvm->n_alloc_mmu_pages;
331}
332
333/*
334 * Set a new alias region. Aliases map a portion of physical memory into
335 * another portion. This is useful for memory windows, for example the PC
336 * VGA region.
337 */
338static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
339 struct kvm_memory_alias *alias)
340{
341 int r, n;
342 struct kvm_mem_alias *p;
343
344 r = -EINVAL;
345 /* General sanity checks */
346 if (alias->memory_size & (PAGE_SIZE - 1))
347 goto out;
348 if (alias->guest_phys_addr & (PAGE_SIZE - 1))
349 goto out;
350 if (alias->slot >= KVM_ALIAS_SLOTS)
351 goto out;
352 if (alias->guest_phys_addr + alias->memory_size
353 < alias->guest_phys_addr)
354 goto out;
355 if (alias->target_phys_addr + alias->memory_size
356 < alias->target_phys_addr)
357 goto out;
358
359 mutex_lock(&kvm->lock);
360
361 p = &kvm->aliases[alias->slot];
362 p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
363 p->npages = alias->memory_size >> PAGE_SHIFT;
364 p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
365
366 for (n = KVM_ALIAS_SLOTS; n > 0; --n)
367 if (kvm->aliases[n - 1].npages)
368 break;
369 kvm->naliases = n;
370
371 kvm_mmu_zap_all(kvm);
372
373 mutex_unlock(&kvm->lock);
374
375 return 0;
376
377out:
378 return r;
379}
380
381static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
382{
383 int r;
384
385 r = 0;
386 switch (chip->chip_id) {
387 case KVM_IRQCHIP_PIC_MASTER:
388 memcpy(&chip->chip.pic,
389 &pic_irqchip(kvm)->pics[0],
390 sizeof(struct kvm_pic_state));
391 break;
392 case KVM_IRQCHIP_PIC_SLAVE:
393 memcpy(&chip->chip.pic,
394 &pic_irqchip(kvm)->pics[1],
395 sizeof(struct kvm_pic_state));
396 break;
397 case KVM_IRQCHIP_IOAPIC:
398 memcpy(&chip->chip.ioapic,
399 ioapic_irqchip(kvm),
400 sizeof(struct kvm_ioapic_state));
401 break;
402 default:
403 r = -EINVAL;
404 break;
405 }
406 return r;
407}
408
409static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
410{
411 int r;
412
413 r = 0;
414 switch (chip->chip_id) {
415 case KVM_IRQCHIP_PIC_MASTER:
416 memcpy(&pic_irqchip(kvm)->pics[0],
417 &chip->chip.pic,
418 sizeof(struct kvm_pic_state));
419 break;
420 case KVM_IRQCHIP_PIC_SLAVE:
421 memcpy(&pic_irqchip(kvm)->pics[1],
422 &chip->chip.pic,
423 sizeof(struct kvm_pic_state));
424 break;
425 case KVM_IRQCHIP_IOAPIC:
426 memcpy(ioapic_irqchip(kvm),
427 &chip->chip.ioapic,
428 sizeof(struct kvm_ioapic_state));
429 break;
430 default:
431 r = -EINVAL;
432 break;
433 }
434 kvm_pic_update_irq(pic_irqchip(kvm));
435 return r;
436}
437
438long kvm_arch_vm_ioctl(struct file *filp,
439 unsigned int ioctl, unsigned long arg)
440{
441 struct kvm *kvm = filp->private_data;
442 void __user *argp = (void __user *)arg;
443 int r = -EINVAL;
444
445 switch (ioctl) {
446 case KVM_SET_TSS_ADDR:
447 r = kvm_vm_ioctl_set_tss_addr(kvm, arg);
448 if (r < 0)
449 goto out;
450 break;
451 case KVM_SET_MEMORY_REGION: {
452 struct kvm_memory_region kvm_mem;
453 struct kvm_userspace_memory_region kvm_userspace_mem;
454
455 r = -EFAULT;
456 if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
457 goto out;
458 kvm_userspace_mem.slot = kvm_mem.slot;
459 kvm_userspace_mem.flags = kvm_mem.flags;
460 kvm_userspace_mem.guest_phys_addr = kvm_mem.guest_phys_addr;
461 kvm_userspace_mem.memory_size = kvm_mem.memory_size;
462 r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 0);
463 if (r)
464 goto out;
465 break;
466 }
467 case KVM_SET_NR_MMU_PAGES:
468 r = kvm_vm_ioctl_set_nr_mmu_pages(kvm, arg);
469 if (r)
470 goto out;
471 break;
472 case KVM_GET_NR_MMU_PAGES:
473 r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
474 break;
475 case KVM_SET_MEMORY_ALIAS: {
476 struct kvm_memory_alias alias;
477
478 r = -EFAULT;
479 if (copy_from_user(&alias, argp, sizeof alias))
480 goto out;
481 r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
482 if (r)
483 goto out;
484 break;
485 }
486 case KVM_CREATE_IRQCHIP:
487 r = -ENOMEM;
488 kvm->vpic = kvm_create_pic(kvm);
489 if (kvm->vpic) {
490 r = kvm_ioapic_init(kvm);
491 if (r) {
492 kfree(kvm->vpic);
493 kvm->vpic = NULL;
494 goto out;
495 }
496 } else
497 goto out;
498 break;
499 case KVM_IRQ_LINE: {
500 struct kvm_irq_level irq_event;
501
502 r = -EFAULT;
503 if (copy_from_user(&irq_event, argp, sizeof irq_event))
504 goto out;
505 if (irqchip_in_kernel(kvm)) {
506 mutex_lock(&kvm->lock);
507 if (irq_event.irq < 16)
508 kvm_pic_set_irq(pic_irqchip(kvm),
509 irq_event.irq,
510 irq_event.level);
511 kvm_ioapic_set_irq(kvm->vioapic,
512 irq_event.irq,
513 irq_event.level);
514 mutex_unlock(&kvm->lock);
515 r = 0;
516 }
517 break;
518 }
519 case KVM_GET_IRQCHIP: {
520 /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
521 struct kvm_irqchip chip;
522
523 r = -EFAULT;
524 if (copy_from_user(&chip, argp, sizeof chip))
525 goto out;
526 r = -ENXIO;
527 if (!irqchip_in_kernel(kvm))
528 goto out;
529 r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
530 if (r)
531 goto out;
532 r = -EFAULT;
533 if (copy_to_user(argp, &chip, sizeof chip))
534 goto out;
535 r = 0;
536 break;
537 }
538 case KVM_SET_IRQCHIP: {
539 /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
540 struct kvm_irqchip chip;
541
542 r = -EFAULT;
543 if (copy_from_user(&chip, argp, sizeof chip))
544 goto out;
545 r = -ENXIO;
546 if (!irqchip_in_kernel(kvm))
547 goto out;
548 r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
549 if (r)
550 goto out;
551 r = 0;
552 break;
553 }
554 default:
555 ;
556 }
557out:
558 return r;
559}
560
303static __init void kvm_init_msr_list(void) 561static __init void kvm_init_msr_list(void)
304{ 562{
305 u32 dummy[2]; 563 u32 dummy[2];