Acked-by: Hollis Blanchard <[EMAIL PROTECTED]>

On Fri, 2007-10-26 at 14:01 +0200, Carsten Otte wrote:
> 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 has been updated to current git, and it leaves out memory slot
> registration work which is currently subject to a detailed discussion.
> 
> Common ioctls for all architectures are:
> KVM_CREATE_VCPU, KVM_GET_DIRTY_LOG, KVM_SET_USER_MEMORY_REGION
> 
> KVM_SET_USER_MEMORY_REGION implementation is no longer moved to x86.c.
> It seems to me that more fine-grained refinement then just moving the
> code is required here.
> 
> 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
> 
> KVM_SET_TSS_ADDR has been added to the list of x86 specifics, as Izik's
> commit states it is used for emulating real mode on intel.
> 
> 
>  kvm.h      |    7 +
>  kvm_main.c |  255
> +-----------------------------------------------------------
>  x86.c      |  258
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 271 insertions(+), 249 deletions(-)
> Signed-off-by: Carsten Otte <[EMAIL PROTECTED]>
> ---
> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
> index b08fc9e..438d4a9 100644
> --- a/drivers/kvm/kvm.h
> +++ b/drivers/kvm/kvm.h
> @@ -621,6 +621,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>                        unsigned int ioctl, unsigned long arg);
>  void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
>  void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu);
> +int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> +                                struct
> +                                kvm_userspace_memory_region *mem,
> +                                int user_alloc);
> +long kvm_arch_vm_ioctl(struct file *filp,
> +                    unsigned int ioctl, unsigned long arg);
> +void kvm_arch_destroy_vm(struct kvm *kvm);
> 
>  __init void kvm_arch_init(void);
> 
> diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
> index 9a3d663..7a85be9 100644
> --- a/drivers/kvm/kvm_main.c
> +++ b/drivers/kvm/kvm_main.c
> @@ -792,36 +792,16 @@ out:
>  }
>  EXPORT_SYMBOL_GPL(kvm_set_memory_region);
> 
> -static int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> -                                       struct
> -                                       kvm_userspace_memory_region *mem,
> -                                       int user_alloc)
> +int kvm_vm_ioctl_set_memory_region(struct kvm *kvm,
> +                                struct
> +                                kvm_userspace_memory_region *mem,
> +                                int user_alloc)
>  {
>       if (mem->slot >= KVM_MEMORY_SLOTS)
>               return -EINVAL;
>       return kvm_set_memory_region(kvm, mem, user_alloc);
>  }
> 
> -static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
> -                                       u32 kvm_nr_mmu_pages)
> -{
> -     if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
> -             return -EINVAL;
> -
> -     mutex_lock(&kvm->lock);
> -
> -     kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
> -     kvm->n_requested_mmu_pages = kvm_nr_mmu_pages;
> -
> -     mutex_unlock(&kvm->lock);
> -     return 0;
> -}
> -
> -static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
> -{
> -     return kvm->n_alloc_mmu_pages;
> -}
> -
>  /*
>   * Get (and clear) the dirty memory log for a memory slot.
>   */
> @@ -867,111 +847,6 @@ out:
>       return r;
>  }
> 
> -/*
> - * Set a new alias region.  Aliases map a portion of physical memory into
> - * another portion.  This is useful for memory windows, for example the PC
> - * VGA region.
> - */
> -static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
> -                                      struct kvm_memory_alias *alias)
> -{
> -     int r, n;
> -     struct kvm_mem_alias *p;
> -
> -     r = -EINVAL;
> -     /* General sanity checks */
> -     if (alias->memory_size & (PAGE_SIZE - 1))
> -             goto out;
> -     if (alias->guest_phys_addr & (PAGE_SIZE - 1))
> -             goto out;
> -     if (alias->slot >= KVM_ALIAS_SLOTS)
> -             goto out;
> -     if (alias->guest_phys_addr + alias->memory_size
> -         < alias->guest_phys_addr)
> -             goto out;
> -     if (alias->target_phys_addr + alias->memory_size
> -         < alias->target_phys_addr)
> -             goto out;
> -
> -     mutex_lock(&kvm->lock);
> -
> -     p = &kvm->aliases[alias->slot];
> -     p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
> -     p->npages = alias->memory_size >> PAGE_SHIFT;
> -     p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
> -
> -     for (n = KVM_ALIAS_SLOTS; n > 0; --n)
> -             if (kvm->aliases[n - 1].npages)
> -                     break;
> -     kvm->naliases = n;
> -
> -     kvm_mmu_zap_all(kvm);
> -
> -     mutex_unlock(&kvm->lock);
> -
> -     return 0;
> -
> -out:
> -     return r;
> -}
> -
> -static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip 
> *chip)
> -{
> -     int r;
> -
> -     r = 0;
> -     switch (chip->chip_id) {
> -     case KVM_IRQCHIP_PIC_MASTER:
> -             memcpy(&chip->chip.pic,
> -                     &pic_irqchip(kvm)->pics[0],
> -                     sizeof(struct kvm_pic_state));
> -             break;
> -     case KVM_IRQCHIP_PIC_SLAVE:
> -             memcpy(&chip->chip.pic,
> -                     &pic_irqchip(kvm)->pics[1],
> -                     sizeof(struct kvm_pic_state));
> -             break;
> -     case KVM_IRQCHIP_IOAPIC:
> -             memcpy(&chip->chip.ioapic,
> -                     ioapic_irqchip(kvm),
> -                     sizeof(struct kvm_ioapic_state));
> -             break;
> -     default:
> -             r = -EINVAL;
> -             break;
> -     }
> -     return r;
> -}
> -
> -static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip 
> *chip)
> -{
> -     int r;
> -
> -     r = 0;
> -     switch (chip->chip_id) {
> -     case KVM_IRQCHIP_PIC_MASTER:
> -             memcpy(&pic_irqchip(kvm)->pics[0],
> -                     &chip->chip.pic,
> -                     sizeof(struct kvm_pic_state));
> -             break;
> -     case KVM_IRQCHIP_PIC_SLAVE:
> -             memcpy(&pic_irqchip(kvm)->pics[1],
> -                     &chip->chip.pic,
> -                     sizeof(struct kvm_pic_state));
> -             break;
> -     case KVM_IRQCHIP_IOAPIC:
> -             memcpy(ioapic_irqchip(kvm),
> -                     &chip->chip.ioapic,
> -                     sizeof(struct kvm_ioapic_state));
> -             break;
> -     default:
> -             r = -EINVAL;
> -             break;
> -     }
> -     kvm_pic_update_irq(pic_irqchip(kvm));
> -     return r;
> -}
> -
>  int is_error_page(struct page *page)
>  {
>       return page == bad_page;
> @@ -2669,16 +2544,6 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu)
>       return fd;
>  }
> 
> -static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
> -{
> -     int ret;
> -
> -     if (addr > (unsigned int)(-3 * PAGE_SIZE))
> -             return -1;
> -     ret = kvm_x86_ops->set_tss_addr(kvm, addr);
> -     return ret;
> -}
> -
>  /*
>   * Creates some virtual cpus.  Good luck creating more than one.
>   */
> @@ -2972,35 +2837,14 @@ static long kvm_vm_ioctl(struct file *filp,
>  {
>       struct kvm *kvm = filp->private_data;
>       void __user *argp = (void __user *)arg;
> -     int r = -EINVAL;
> +     int r;
> 
>       switch (ioctl) {
> -     case KVM_SET_TSS_ADDR:
> -             r = kvm_vm_ioctl_set_tss_addr(kvm, arg);
> -             if (r < 0)
> -                     goto out;
> -             break;
>       case KVM_CREATE_VCPU:
>               r = kvm_vm_ioctl_create_vcpu(kvm, arg);
>               if (r < 0)
>                       goto out;
>               break;
> -     case KVM_SET_MEMORY_REGION: {
> -             struct kvm_memory_region kvm_mem;
> -             struct kvm_userspace_memory_region kvm_userspace_mem;
> -
> -             r = -EFAULT;
> -             if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
> -                     goto out;
> -             kvm_userspace_mem.slot = kvm_mem.slot;
> -             kvm_userspace_mem.flags = kvm_mem.flags;
> -             kvm_userspace_mem.guest_phys_addr = kvm_mem.guest_phys_addr;
> -             kvm_userspace_mem.memory_size = kvm_mem.memory_size;
> -             r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 0);
> -             if (r)
> -                     goto out;
> -             break;
> -     }
>       case KVM_SET_USER_MEMORY_REGION: {
>               struct kvm_userspace_memory_region kvm_userspace_mem;
> 
> @@ -3014,14 +2858,6 @@ static long kvm_vm_ioctl(struct file *filp,
>                       goto out;
>               break;
>       }
> -     case KVM_SET_NR_MMU_PAGES:
> -             r = kvm_vm_ioctl_set_nr_mmu_pages(kvm, arg);
> -             if (r)
> -                     goto out;
> -             break;
> -     case KVM_GET_NR_MMU_PAGES:
> -             r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
> -             break;
>       case KVM_GET_DIRTY_LOG: {
>               struct kvm_dirty_log log;
> 
> @@ -3033,87 +2869,8 @@ static long kvm_vm_ioctl(struct file *filp,
>                       goto out;
>               break;
>       }
> -     case KVM_SET_MEMORY_ALIAS: {
> -             struct kvm_memory_alias alias;
> -
> -             r = -EFAULT;
> -             if (copy_from_user(&alias, argp, sizeof alias))
> -                     goto out;
> -             r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
> -             if (r)
> -                     goto out;
> -             break;
> -     }
> -     case KVM_CREATE_IRQCHIP:
> -             r = -ENOMEM;
> -             kvm->vpic = kvm_create_pic(kvm);
> -             if (kvm->vpic) {
> -                     r = kvm_ioapic_init(kvm);
> -                     if (r) {
> -                             kfree(kvm->vpic);
> -                             kvm->vpic = NULL;
> -                             goto out;
> -                     }
> -             } else
> -                     goto out;
> -             break;
> -     case KVM_IRQ_LINE: {
> -             struct kvm_irq_level irq_event;
> -
> -             r = -EFAULT;
> -             if (copy_from_user(&irq_event, argp, sizeof irq_event))
> -                     goto out;
> -             if (irqchip_in_kernel(kvm)) {
> -                     mutex_lock(&kvm->lock);
> -                     if (irq_event.irq < 16)
> -                             kvm_pic_set_irq(pic_irqchip(kvm),
> -                                     irq_event.irq,
> -                                     irq_event.level);
> -                     kvm_ioapic_set_irq(kvm->vioapic,
> -                                     irq_event.irq,
> -                                     irq_event.level);
> -                     mutex_unlock(&kvm->lock);
> -                     r = 0;
> -             }
> -             break;
> -     }
> -     case KVM_GET_IRQCHIP: {
> -             /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
> -             struct kvm_irqchip chip;
> -
> -             r = -EFAULT;
> -             if (copy_from_user(&chip, argp, sizeof chip))
> -                     goto out;
> -             r = -ENXIO;
> -             if (!irqchip_in_kernel(kvm))
> -                     goto out;
> -             r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
> -             if (r)
> -                     goto out;
> -             r = -EFAULT;
> -             if (copy_to_user(argp, &chip, sizeof chip))
> -                     goto out;
> -             r = 0;
> -             break;
> -     }
> -     case KVM_SET_IRQCHIP: {
> -             /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
> -             struct kvm_irqchip chip;
> -
> -             r = -EFAULT;
> -             if (copy_from_user(&chip, argp, sizeof chip))
> -                     goto out;
> -             r = -ENXIO;
> -             if (!irqchip_in_kernel(kvm))
> -                     goto out;
> -             r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
> -             if (r)
> -                     goto out;
> -             r = 0;
> -             break;
> -     }
>       default:
> -             ;
> +             r = kvm_arch_vm_ioctl(filp, ioctl, arg);
>       }
>  out:
>       return r;
> diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c
> index 1fe209d..b84cb67 100644
> --- a/drivers/kvm/x86.c
> +++ b/drivers/kvm/x86.c
> @@ -300,6 +300,264 @@ out:
>       return r;
>  }
> 
> +static int kvm_vm_ioctl_set_tss_addr(struct kvm *kvm, unsigned long addr)
> +{
> +     int ret;
> +
> +     if (addr > (unsigned int)(-3 * PAGE_SIZE))
> +             return -1;
> +     ret = kvm_x86_ops->set_tss_addr(kvm, addr);
> +     return ret;
> +}
> +
> +static int kvm_vm_ioctl_set_nr_mmu_pages(struct kvm *kvm,
> +                                       u32 kvm_nr_mmu_pages)
> +{
> +     if (kvm_nr_mmu_pages < KVM_MIN_ALLOC_MMU_PAGES)
> +             return -EINVAL;
> +
> +     mutex_lock(&kvm->lock);
> +
> +     kvm_mmu_change_mmu_pages(kvm, kvm_nr_mmu_pages);
> +     kvm->n_requested_mmu_pages = kvm_nr_mmu_pages;
> +
> +     mutex_unlock(&kvm->lock);
> +     return 0;
> +}
> +
> +static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
> +{
> +     return kvm->n_alloc_mmu_pages;
> +}
> +
> +/*
> + * Set a new alias region.  Aliases map a portion of physical memory into
> + * another portion.  This is useful for memory windows, for example the PC
> + * VGA region.
> + */
> +static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
> +                                      struct kvm_memory_alias *alias)
> +{
> +     int r, n;
> +     struct kvm_mem_alias *p;
> +
> +     r = -EINVAL;
> +     /* General sanity checks */
> +     if (alias->memory_size & (PAGE_SIZE - 1))
> +             goto out;
> +     if (alias->guest_phys_addr & (PAGE_SIZE - 1))
> +             goto out;
> +     if (alias->slot >= KVM_ALIAS_SLOTS)
> +             goto out;
> +     if (alias->guest_phys_addr + alias->memory_size
> +         < alias->guest_phys_addr)
> +             goto out;
> +     if (alias->target_phys_addr + alias->memory_size
> +         < alias->target_phys_addr)
> +             goto out;
> +
> +     mutex_lock(&kvm->lock);
> +
> +     p = &kvm->aliases[alias->slot];
> +     p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
> +     p->npages = alias->memory_size >> PAGE_SHIFT;
> +     p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
> +
> +     for (n = KVM_ALIAS_SLOTS; n > 0; --n)
> +             if (kvm->aliases[n - 1].npages)
> +                     break;
> +     kvm->naliases = n;
> +
> +     kvm_mmu_zap_all(kvm);
> +
> +     mutex_unlock(&kvm->lock);
> +
> +     return 0;
> +
> +out:
> +     return r;
> +}
> +
> +static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip 
> *chip)
> +{
> +     int r;
> +
> +     r = 0;
> +     switch (chip->chip_id) {
> +     case KVM_IRQCHIP_PIC_MASTER:
> +             memcpy(&chip->chip.pic,
> +                     &pic_irqchip(kvm)->pics[0],
> +                     sizeof(struct kvm_pic_state));
> +             break;
> +     case KVM_IRQCHIP_PIC_SLAVE:
> +             memcpy(&chip->chip.pic,
> +                     &pic_irqchip(kvm)->pics[1],
> +                     sizeof(struct kvm_pic_state));
> +             break;
> +     case KVM_IRQCHIP_IOAPIC:
> +             memcpy(&chip->chip.ioapic,
> +                     ioapic_irqchip(kvm),
> +                     sizeof(struct kvm_ioapic_state));
> +             break;
> +     default:
> +             r = -EINVAL;
> +             break;
> +     }
> +     return r;
> +}
> +
> +static int kvm_vm_ioctl_set_irqchip(struct kvm *kvm, struct kvm_irqchip 
> *chip)
> +{
> +     int r;
> +
> +     r = 0;
> +     switch (chip->chip_id) {
> +     case KVM_IRQCHIP_PIC_MASTER:
> +             memcpy(&pic_irqchip(kvm)->pics[0],
> +                     &chip->chip.pic,
> +                     sizeof(struct kvm_pic_state));
> +             break;
> +     case KVM_IRQCHIP_PIC_SLAVE:
> +             memcpy(&pic_irqchip(kvm)->pics[1],
> +                     &chip->chip.pic,
> +                     sizeof(struct kvm_pic_state));
> +             break;
> +     case KVM_IRQCHIP_IOAPIC:
> +             memcpy(ioapic_irqchip(kvm),
> +                     &chip->chip.ioapic,
> +                     sizeof(struct kvm_ioapic_state));
> +             break;
> +     default:
> +             r = -EINVAL;
> +             break;
> +     }
> +     kvm_pic_update_irq(pic_irqchip(kvm));
> +     return r;
> +}
> +
> +long kvm_arch_vm_ioctl(struct file *filp,
> +                    unsigned int ioctl, unsigned long arg)
> +{
> +     struct kvm *kvm = filp->private_data;
> +     void __user *argp = (void __user *)arg;
> +     int r = -EINVAL;
> +
> +     switch (ioctl) {
> +     case KVM_SET_TSS_ADDR:
> +             r = kvm_vm_ioctl_set_tss_addr(kvm, arg);
> +             if (r < 0)
> +                     goto out;
> +             break;
> +     case KVM_SET_MEMORY_REGION: {
> +             struct kvm_memory_region kvm_mem;
> +             struct kvm_userspace_memory_region kvm_userspace_mem;
> +
> +             r = -EFAULT;
> +             if (copy_from_user(&kvm_mem, argp, sizeof kvm_mem))
> +                     goto out;
> +             kvm_userspace_mem.slot = kvm_mem.slot;
> +             kvm_userspace_mem.flags = kvm_mem.flags;
> +             kvm_userspace_mem.guest_phys_addr = kvm_mem.guest_phys_addr;
> +             kvm_userspace_mem.memory_size = kvm_mem.memory_size;
> +             r = kvm_vm_ioctl_set_memory_region(kvm, &kvm_userspace_mem, 0);
> +             if (r)
> +                     goto out;
> +             break;
> +     }
> +     case KVM_SET_NR_MMU_PAGES:
> +             r = kvm_vm_ioctl_set_nr_mmu_pages(kvm, arg);
> +             if (r)
> +                     goto out;
> +             break;
> +     case KVM_GET_NR_MMU_PAGES:
> +             r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
> +             break;
> +     case KVM_SET_MEMORY_ALIAS: {
> +             struct kvm_memory_alias alias;
> +
> +             r = -EFAULT;
> +             if (copy_from_user(&alias, argp, sizeof alias))
> +                     goto out;
> +             r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
> +             if (r)
> +                     goto out;
> +             break;
> +     }
> +     case KVM_CREATE_IRQCHIP:
> +             r = -ENOMEM;
> +             kvm->vpic = kvm_create_pic(kvm);
> +             if (kvm->vpic) {
> +                     r = kvm_ioapic_init(kvm);
> +                     if (r) {
> +                             kfree(kvm->vpic);
> +                             kvm->vpic = NULL;
> +                             goto out;
> +                     }
> +             } else
> +                     goto out;
> +             break;
> +     case KVM_IRQ_LINE: {
> +             struct kvm_irq_level irq_event;
> +
> +             r = -EFAULT;
> +             if (copy_from_user(&irq_event, argp, sizeof irq_event))
> +                     goto out;
> +             if (irqchip_in_kernel(kvm)) {
> +                     mutex_lock(&kvm->lock);
> +                     if (irq_event.irq < 16)
> +                             kvm_pic_set_irq(pic_irqchip(kvm),
> +                                     irq_event.irq,
> +                                     irq_event.level);
> +                     kvm_ioapic_set_irq(kvm->vioapic,
> +                                     irq_event.irq,
> +                                     irq_event.level);
> +                     mutex_unlock(&kvm->lock);
> +                     r = 0;
> +             }
> +             break;
> +     }
> +     case KVM_GET_IRQCHIP: {
> +             /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
> +             struct kvm_irqchip chip;
> +
> +             r = -EFAULT;
> +             if (copy_from_user(&chip, argp, sizeof chip))
> +                     goto out;
> +             r = -ENXIO;
> +             if (!irqchip_in_kernel(kvm))
> +                     goto out;
> +             r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
> +             if (r)
> +                     goto out;
> +             r = -EFAULT;
> +             if (copy_to_user(argp, &chip, sizeof chip))
> +                     goto out;
> +             r = 0;
> +             break;
> +     }
> +     case KVM_SET_IRQCHIP: {
> +             /* 0: PIC master, 1: PIC slave, 2: IOAPIC */
> +             struct kvm_irqchip chip;
> +
> +             r = -EFAULT;
> +             if (copy_from_user(&chip, argp, sizeof chip))
> +                     goto out;
> +             r = -ENXIO;
> +             if (!irqchip_in_kernel(kvm))
> +                     goto out;
> +             r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
> +             if (r)
> +                     goto out;
> +             r = 0;
> +             break;
> +     }
> +     default:
> +             ;
> +     }
> +out:
> +     return r;
> +}
> +
>  static __init void kvm_init_msr_list(void)
>  {
>       u32 dummy[2];
> 
> 
-- 
Hollis Blanchard
IBM Linux Technology Center


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to