KVM userspace interface updates for 2.6.21
cover KVM userspace interface updates for 2.6.21
The following patchset moves the kvm userspace interface from having a single fd, to having three types of file descriptors:
- one fd returned by open("/dev/kvm") is used for generic access to the kvm driver, for example to get the API version and to create virtual machines
- when you create a virtual machine, you get back an fd that can be used to control vm-wide aspects, like guest memory configuratio
- when you create a virtual cpu, you get an fd that can be used to control the vcpu, for example getting and setting registers, and if you're really serious, running the guest
The motivation for this change is twofold:
- prevent having a 'struct inode' and 'struct file' with different file operation callbacks
- prevent cacheline bouncing of the 'struct file' when we support guest smp (by giving each vcpu its own file structure)
A side effect is that the code becomes somewhat cleaner, due to the vcpu number not being passed around and validated.
The change was discussed on kvm-devel some time ago. Thanks to Arnd Bergmann for useful suggestions and to the epoll code for inspiration.
Signature · 8 lines
error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 1/6 KVM: Add internal filesystem for generating inodes
The kvmfs inodes will represent virtual machines and vcpus, as necessary, reducing cacheline bouncing due to inodes and filps being shared.
--- drivers/kvm/kvm_main.c | 33 ++++++++++++++++++++++++++++++++- 1 files changed, 32 insertions(+), 1 deletions(-)
drivers/kvm/kvm_main.c +32 -1
@@ -36,6 +36,8 @@#include <asm/desc.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/fs.h> +#include <linux/mount.h> #include "x86_emulate.h" #include "segment_descriptor.h"
@@ -72,6 +74,9 @@ static struct kvm_stats_debugfs_item {static struct dentry *debugfs_dir; +#define KVMFS_MAGIC 0x19700426 +struct vfsmount *kvmfs_mnt; +#define MAX_IO_MSRS 256#define CR0_RESEVED_BITS 0xffffffff1ffaffc0ULL
@@ -2252,6 +2257,18 @@ static struct sys_device kvm_sysdev = {hpa_t bad_page_address; +static int kvmfs_get_sb (struct file_system_type *fs_type,int flags, +const char *dev_name,void *data,struct vfsmount *mnt) +{ +return get_sb_pseudo (fs_type,"kvm:" ,NULL ,KVMFS_MAGIC , mnt); +} + +static struct file_system_type kvm_fs_type = { + .name ="kvmfs" , + .get_sb = kvmfs_get_sb, + .kill_sb = kill_anon_super, +}; +int kvm_init_arch (struct kvm_arch_ops *ops,struct module *module) {int r;
@@ -2328,8 +2345,16 @@ void kvm_exit_arch(void)static __init int kvm_init (void ) {static struct page *bad_page; -int r =0 ; +int r; + + r =register_filesystem (&kvm_fs_type); +if (r) + goto out3; + kvmfs_mnt =kern_mount (&kvm_fs_type); + r =PTR_ERR (kvmfs_mnt); +if (IS_ERR (kvmfs_mnt)) + goto out2;kvm_init_debug ();kvm_init_msr_list ();
@@ -2346,6 +2371,10 @@ static __init int kvm_init(void) out:kvm_exit_debug (); +mntput (kvmfs_mnt); +out2: +unregister_filesystem (&kvm_fs_type); +out3:return r; }
@@ -2353,6 +2382,8 @@ static __exit void kvm_exit(void) {kvm_exit_debug ();__free_page (pfn_to_page (bad_page_address >>PAGE_SHIFT )); +mntput (kvmfs_mnt); +unregister_filesystem (&kvm_fs_type); }module_init (kvm_init)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 2/6 KVM: Create an inode per virtual machine
In reply to Avi KivityThis avoids having filp->f_op and the corresponding inode->i_fop different, which is a little unorthodox.
The ioctl list is split into two: global kvm ioctls and per-vm ioctls. A new ioctl, KVM_CREATE_VM, is used to create VMs and return the VM fd.
--- drivers/kvm/kvm_main.c | 212 ++++++++++++++++++++++++++++++++++++++--------- include/linux/kvm.h | 10 ++- 2 files changed, 180 insertions(+), 42 deletions(-)
drivers/kvm/kvm_main.c +171 -41
@@ -36,6 +36,7 @@#include <asm/desc.h> #include <linux/sysdev.h> #include <linux/cpu.h> +#include <linux/file.h> #include <linux/fs.h> #include <linux/mount.h>
@@ -95,6 +96,55 @@ struct segment_descriptor_64 {#endif +static struct inode *kvmfs_inode (struct file_operations *fops) +{ +int error = -ENOMEM ; +struct inode *inode =new_inode (kvmfs_mnt->mnt_sb); + +if (!inode) + goto eexit_1; + + inode->i_fop = fops; + +/* +* Mark the inode dirty from the very beginning, +* that way it will never be moved to the dirty +* list because mark_inode_dirty() will think +* that it already _is_ on the dirty list. +*/ + inode->i_state =I_DIRTY ; + inode->i_mode =S_IRUSR |S_IWUSR ; + inode->i_uid = current->fsuid; + inode->i_gid = current->fsgid; + inode->i_atime = inode->i_mtime = inode->i_ctime =CURRENT_TIME ; +return inode; + +eexit_1: +return ERR_PTR (error); +} + +static struct file *kvmfs_file (struct inode *inode,void *private_data) +{ +struct file *file =get_empty_filp (); + +if (!file) +return ERR_PTR (-ENFILE ); + + file->f_path.mnt =mntget (kvmfs_mnt); + file->f_path.dentry =d_alloc_anon (inode); +if (!file->f_path.dentry) +return ERR_PTR (-ENOMEM ); + file->f_mapping = inode->i_mapping; + + file->f_pos =0 ; + file->f_flags =O_RDWR ; + file->f_op = inode->i_fop; + file->f_mode =FMODE_READ |FMODE_WRITE ; + file->f_version =0 ; + file->private_data = private_data; +return file; +} +unsigned long segment_base (u16 selector) {struct descriptor_table gdt;
@@ -222,13 +272,13 @@ static void vcpu_put(struct kvm_vcpu *vcpu)mutex_unlock (&vcpu->mutex); } -static int kvm_dev_open (struct inode *inode,struct file *filp) +static struct kvm *kvm_create_vm (void ) {struct kvm *kvm =kzalloc (sizeof (struct kvm ),GFP_KERNEL );int i;if (!kvm) -return -ENOMEM ; +return ERR_PTR (-ENOMEM );spin_lock_init (&kvm->lock);INIT_LIST_HEAD (&kvm->active_mmu_pages);
@@ -244,7 +294,11 @@ static int kvm_dev_open(struct inode *inode, struct file *filp)list_add (&kvm->vm_list, &vm_list);spin_unlock (&kvm_lock); } - filp->private_data = kvm; +return kvm; +} + +static int kvm_dev_open (struct inode *inode,struct file *filp) +{return 0 ; }
@@ -300,14 +354,24 @@ static void kvm_free_vcpus(struct kvm *kvm)static int kvm_dev_release (struct inode *inode,struct file *filp) { -struct kvm *kvm = filp->private_data; +return 0 ; +} +static void kvm_destroy_vm (struct kvm *kvm) +{spin_lock (&kvm_lock);list_del (&kvm->vm_list);spin_unlock (&kvm_lock);kvm_free_vcpus (kvm);kvm_free_physmem (kvm);kfree (kvm); +} + +static int kvm_vm_release (struct inode *inode,struct file *filp) +{ +struct kvm *kvm = filp->private_data; + +kvm_destroy_vm (kvm);return 0 ; }
@@ -1900,17 +1964,14 @@ static int kvm_dev_ioctl_debug_guest(struct kvm *kvm,return r; } -static long kvm_dev_ioctl (struct file *filp, -unsigned int ioctl,unsigned long arg) +static long kvm_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_GET_API_VERSION : - r =KVM_API_VERSION ; -break ;case KVM_CREATE_VCPU : r =kvm_dev_ioctl_create_vcpu (kvm, arg);if (r)
@@ -2052,6 +2113,107 @@ static long kvm_dev_ioctl(struct file *filp,case KVM_SET_MSRS : r =msr_io (kvm, argp, do_set_msr,0 );break ; +default : + ; + } +out: +return r; +} + +static struct page *kvm_vm_nopage (struct vm_area_struct *vma, +unsigned long address, +int *type) +{ +struct kvm *kvm = vma->vm_file->private_data; +unsigned long pgoff; +struct kvm_memory_slot *slot; +struct page *page; + + *type =VM_FAULT_MINOR ; + pgoff = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_pgoff; + slot =gfn_to_memslot (kvm, pgoff); +if (!slot) +return NOPAGE_SIGBUS ; + page =gfn_to_page (slot, pgoff); +if (!page) +return NOPAGE_SIGBUS ; +get_page (page); +return page; +} + +static struct vm_operations_struct kvm_vm_vm_ops = { + .nopage = kvm_vm_nopage, +}; + +static int kvm_vm_mmap (struct file *file,struct vm_area_struct *vma) +{ + vma->vm_ops = &kvm_vm_vm_ops; +return 0 ; +} + +static struct file_operations kvm_vm_fops = { + .release = kvm_vm_release, + .unlocked_ioctl = kvm_vm_ioctl, + .compat_ioctl = kvm_vm_ioctl, + .mmap = kvm_vm_mmap, +}; + +static int kvm_dev_ioctl_create_vm (void ) +{ +int fd, r; +struct inode *inode; +struct file *file; +struct kvm *kvm; + + inode =kvmfs_inode (&kvm_vm_fops); +if (IS_ERR (inode)) { + r =PTR_ERR (inode); + goto out1; + } + + kvm =kvm_create_vm (); +if (IS_ERR (kvm)) { + r =PTR_ERR (kvm); + goto out2; + } + + file =kvmfs_file (inode, kvm); +if (IS_ERR (file)) { + r =PTR_ERR (file); + goto out3; + } + + r =get_unused_fd (); +if (r <0 ) + goto out4; + fd = r; +fd_install (fd, file); + +return fd; + +out4: +fput (file); +out3: +kvm_destroy_vm (kvm); +out2: +iput (inode); +out1: +return r; +} + +static long kvm_dev_ioctl (struct file *filp, +unsigned int ioctl,unsigned long arg) +{ +void __user *argp = (void __user *)arg; +int r = -EINVAL ; + +switch (ioctl) { +case KVM_GET_API_VERSION : + r =KVM_API_VERSION ; +break ; +case KVM_CREATE_VM : + r =kvm_dev_ioctl_create_vm (); +break ;case KVM_GET_MSR_INDEX_LIST : {struct kvm_msr_list __user *user_msr_list = argp;struct kvm_msr_list msr_list;
@@ -2086,43 +2248,11 @@ out:return r; } -static struct page *kvm_dev_nopage (struct vm_area_struct *vma, -unsigned long address, -int *type) -{ -struct kvm *kvm = vma->vm_file->private_data; -unsigned long pgoff; -struct kvm_memory_slot *slot; -struct page *page; - - *type =VM_FAULT_MINOR ; - pgoff = ((address - vma->vm_start) >>PAGE_SHIFT ) + vma->vm_pgoff; - slot =gfn_to_memslot (kvm, pgoff); -if (!slot) -return NOPAGE_SIGBUS ; - page =gfn_to_page (slot, pgoff); -if (!page) -return NOPAGE_SIGBUS ; -get_page (page); -return page; -} - -static struct vm_operations_struct kvm_dev_vm_ops = { - .nopage = kvm_dev_nopage, -}; - -static int kvm_dev_mmap (struct file *file,struct vm_area_struct *vma) -{ - vma->vm_ops = &kvm_dev_vm_ops; -return 0 ; -} -static struct file_operations kvm_chardev_ops = { .open = kvm_dev_open, .release = kvm_dev_release, .unlocked_ioctl = kvm_dev_ioctl, .compat_ioctl = kvm_dev_ioctl, - .mmap = kvm_dev_mmap, };static struct miscdevice kvm_dev = {
include/linux/kvm.h +9 -1
@@ -224,7 +224,16 @@ struct kvm_dirty_log {#define KVMIO 0xAE +/* +* ioctls for /dev/kvm fds: +*/ #define KVM_GET_API_VERSION _IO(KVMIO, 1) +#define KVM_CREATE_VM _IO(KVMIO, 2)/* returns a VM fd */ +#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 15, struct kvm_msr_list) + +/* +* ioctls for VM fds +*/ #define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run)#define KVM_GET_REGS _IOWR(KVMIO, 3, struct kvm_regs)#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs)
@@ -238,6 +247,5 @@ struct kvm_dirty_log {#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs)#define KVM_SET_MSRS _IOWR(KVMIO, 14, struct kvm_msrs) -#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 15, struct kvm_msr_list)#endif
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 3/6 KVM: Rename some kvm_dev_ioctl_*() functions to kvm_vm_ioctl_*()
In reply to Avi KivityThis reflects the changed scope, from device-wide to single vm (previously every device open created a virtual machine).
--- drivers/kvm/kvm_main.c | 48 ++++++++++++++++++++++++------------------------ 1 files changed, 24 insertions(+), 24 deletions(-)
drivers/kvm/kvm_main.c +24 -24
@@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(fx_init);/* * Creates some virtual cpus. Good luck creating more than one. */ -static int kvm_dev_ioctl_create_vcpu (struct kvm *kvm,int n) +static int kvm_vm_ioctl_create_vcpu (struct kvm *kvm,int n) {int r;struct kvm_vcpu *vcpu;
@@ -655,8 +655,8 @@ out:* * Discontiguous memory is allowed, mostly for framebuffers. */ -static int kvm_dev_ioctl_set_memory_region (struct kvm *kvm, -struct kvm_memory_region *mem) +static int kvm_vm_ioctl_set_memory_region (struct kvm *kvm, +struct kvm_memory_region *mem) {int r;gfn_t base_gfn;
@@ -804,8 +804,8 @@ static void do_remove_write_access(struct kvm_vcpu *vcpu, int slot)/* * Get (and clear) the dirty memory log for a memory slot. */ -static int kvm_dev_ioctl_get_dirty_log (struct kvm *kvm, -struct kvm_dirty_log *log) +static int kvm_vm_ioctl_get_dirty_log (struct kvm *kvm, +struct kvm_dirty_log *log) {struct kvm_memory_slot *memslot;int r, i;
@@ -1535,7 +1535,7 @@ void save_msrs(struct vmx_msr_entry *e, int n) }EXPORT_SYMBOL_GPL (save_msrs); -static int kvm_dev_ioctl_run (struct kvm *kvm,struct kvm_run *kvm_run) +static int kvm_vm_ioctl_run (struct kvm *kvm,struct kvm_run *kvm_run) {struct kvm_vcpu *vcpu;int r;
@@ -1568,7 +1568,7 @@ static int kvm_dev_ioctl_run(struct kvm *kvm, struct kvm_run *kvm_run)return r; } -static int kvm_dev_ioctl_get_regs (struct kvm *kvm,struct kvm_regs *regs) +static int kvm_vm_ioctl_get_regs (struct kvm *kvm,struct kvm_regs *regs) {struct kvm_vcpu *vcpu;
@@ -1614,7 +1614,7 @@ static int kvm_dev_ioctl_get_regs(struct kvm *kvm, struct kvm_regs *regs)return 0 ; } -static int kvm_dev_ioctl_set_regs (struct kvm *kvm,struct kvm_regs *regs) +static int kvm_vm_ioctl_set_regs (struct kvm *kvm,struct kvm_regs *regs) {struct kvm_vcpu *vcpu;
@@ -1660,7 +1660,7 @@ static void get_segment(struct kvm_vcpu *vcpu,return kvm_arch_ops->get_segment (vcpu, var, seg); } -static int kvm_dev_ioctl_get_sregs (struct kvm *kvm,struct kvm_sregs *sregs) +static int kvm_vm_ioctl_get_sregs (struct kvm *kvm,struct kvm_sregs *sregs) {struct kvm_vcpu *vcpu;struct descriptor_table dt;
@@ -1711,7 +1711,7 @@ static void set_segment(struct kvm_vcpu *vcpu,return kvm_arch_ops->set_segment (vcpu, var, seg); } -static int kvm_dev_ioctl_set_sregs (struct kvm *kvm,struct kvm_sregs *sregs) +static int kvm_vm_ioctl_set_sregs (struct kvm *kvm,struct kvm_sregs *sregs) {struct kvm_vcpu *vcpu;int mmu_reset_needed =0 ;
@@ -1904,7 +1904,7 @@ out:/* * Translate a guest virtual address to a guest physical address. */ -static int kvm_dev_ioctl_translate (struct kvm *kvm,struct kvm_translation *tr) +static int kvm_vm_ioctl_translate (struct kvm *kvm,struct kvm_translation *tr) {unsigned long vaddr = tr->linear_address;struct kvm_vcpu *vcpu;
@@ -1925,7 +1925,7 @@ static int kvm_dev_ioctl_translate(struct kvm *kvm, struct kvm_translation *tr)return 0 ; } -static int kvm_dev_ioctl_interrupt (struct kvm *kvm,struct kvm_interrupt *irq) +static int kvm_vm_ioctl_interrupt (struct kvm *kvm,struct kvm_interrupt *irq) {struct kvm_vcpu *vcpu;
@@ -1945,7 +1945,7 @@ static int kvm_dev_ioctl_interrupt(struct kvm *kvm, struct kvm_interrupt *irq)return 0 ; } -static int kvm_dev_ioctl_debug_guest (struct kvm *kvm, +static int kvm_vm_ioctl_debug_guest (struct kvm *kvm,struct kvm_debug_guest *dbg) {struct kvm_vcpu *vcpu;
@@ -1973,7 +1973,7 @@ static long kvm_vm_ioctl(struct file *filp,switch (ioctl) {case KVM_CREATE_VCPU : - r =kvm_dev_ioctl_create_vcpu (kvm, arg); + r =kvm_vm_ioctl_create_vcpu (kvm, arg);if (r) goto out;break ;
@@ -1983,7 +1983,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_run, argp,sizeof kvm_run)) goto out; - r =kvm_dev_ioctl_run (kvm, &kvm_run); + r =kvm_vm_ioctl_run (kvm, &kvm_run);if (r <0 && r != -EINTR ) goto out;if (copy_to_user (argp, &kvm_run,sizeof kvm_run)) {
@@ -1998,7 +1998,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_regs, argp,sizeof kvm_regs)) goto out; - r =kvm_dev_ioctl_get_regs (kvm, &kvm_regs); + r =kvm_vm_ioctl_get_regs (kvm, &kvm_regs);if (r) goto out; r = -EFAULT ;
@@ -2013,7 +2013,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_regs, argp,sizeof kvm_regs)) goto out; - r =kvm_dev_ioctl_set_regs (kvm, &kvm_regs); + r =kvm_vm_ioctl_set_regs (kvm, &kvm_regs);if (r) goto out; r =0 ;
@@ -2025,7 +2025,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_sregs, argp,sizeof kvm_sregs)) goto out; - r =kvm_dev_ioctl_get_sregs (kvm, &kvm_sregs); + r =kvm_vm_ioctl_get_sregs (kvm, &kvm_sregs);if (r) goto out; r = -EFAULT ;
@@ -2040,7 +2040,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_sregs, argp,sizeof kvm_sregs)) goto out; - r =kvm_dev_ioctl_set_sregs (kvm, &kvm_sregs); + r =kvm_vm_ioctl_set_sregs (kvm, &kvm_sregs);if (r) goto out; r =0 ;
@@ -2052,7 +2052,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&tr, argp,sizeof tr)) goto out; - r =kvm_dev_ioctl_translate (kvm, &tr); + r =kvm_vm_ioctl_translate (kvm, &tr);if (r) goto out; r = -EFAULT ;
@@ -2067,7 +2067,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&irq, argp,sizeof irq)) goto out; - r =kvm_dev_ioctl_interrupt (kvm, &irq); + r =kvm_vm_ioctl_interrupt (kvm, &irq);if (r) goto out; r =0 ;
@@ -2079,7 +2079,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&dbg, argp,sizeof dbg)) goto out; - r =kvm_dev_ioctl_debug_guest (kvm, &dbg); + r =kvm_vm_ioctl_debug_guest (kvm, &dbg);if (r) goto out; r =0 ;
@@ -2091,7 +2091,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&kvm_mem, argp,sizeof kvm_mem)) goto out; - r =kvm_dev_ioctl_set_memory_region (kvm, &kvm_mem); + r =kvm_vm_ioctl_set_memory_region (kvm, &kvm_mem);if (r) goto out;break ;
@@ -2102,7 +2102,7 @@ static long kvm_vm_ioctl(struct file *filp, r = -EFAULT ;if (copy_from_user (&log, argp,sizeof log)) goto out; - r =kvm_dev_ioctl_get_dirty_log (kvm, &log); + r =kvm_vm_ioctl_get_dirty_log (kvm, &log);if (r) goto out;break ;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 4/6 KVM: Move kvm_vm_ioctl_create_vcpu() around
In reply to Avi KivityIn preparation of some hacking.
--- drivers/kvm/kvm_main.c | 102 ++++++++++++++++++++++++------------------------ 1 files changed, 51 insertions(+), 51 deletions(-)
drivers/kvm/kvm_main.c +51 -51
@@ -599,57 +599,6 @@ void fx_init(struct kvm_vcpu *vcpu)EXPORT_SYMBOL_GPL (fx_init);/* -* Creates some virtual cpus. Good luck creating more than one. -*/ -static int kvm_vm_ioctl_create_vcpu (struct kvm *kvm,int n) -{ -int r; -struct kvm_vcpu *vcpu; - - r = -EINVAL ; -if (!valid_vcpu (n)) - goto out; - - vcpu = &kvm->vcpus[n]; - -mutex_lock (&vcpu->mutex); - -if (vcpu->vmcs) { -mutex_unlock (&vcpu->mutex); -return -EEXIST ; - } - - vcpu->host_fx_image = (char *)ALIGN ((hva_t )vcpu->fx_buf, -FX_IMAGE_ALIGN ); - vcpu->guest_fx_image = vcpu->host_fx_image +FX_IMAGE_SIZE ; - - r = kvm_arch_ops->vcpu_create (vcpu); -if (r <0 ) - goto out_free_vcpus; - - r =kvm_mmu_create (vcpu); -if (r <0 ) - goto out_free_vcpus; - - kvm_arch_ops->vcpu_load (vcpu); - r =kvm_mmu_setup (vcpu); -if (r >=0 ) - r = kvm_arch_ops->vcpu_setup (vcpu); -vcpu_put (vcpu); - -if (r <0 ) - goto out_free_vcpus; - -return 0 ; - -out_free_vcpus: -kvm_free_vcpu (vcpu); -mutex_unlock (&vcpu->mutex); -out: -return r; -} - -/* * Allocate some memory and give it an address in the guest physical address * space. *
@@ -1964,6 +1913,57 @@ static int kvm_vm_ioctl_debug_guest(struct kvm *kvm,return r; } +/* +* Creates some virtual cpus. Good luck creating more than one. +*/ +static int kvm_vm_ioctl_create_vcpu (struct kvm *kvm,int n) +{ +int r; +struct kvm_vcpu *vcpu; + + r = -EINVAL ; +if (!valid_vcpu (n)) + goto out; + + vcpu = &kvm->vcpus[n]; + +mutex_lock (&vcpu->mutex); + +if (vcpu->vmcs) { +mutex_unlock (&vcpu->mutex); +return -EEXIST ; + } + + vcpu->host_fx_image = (char *)ALIGN ((hva_t )vcpu->fx_buf, +FX_IMAGE_ALIGN ); + vcpu->guest_fx_image = vcpu->host_fx_image +FX_IMAGE_SIZE ; + + r = kvm_arch_ops->vcpu_create (vcpu); +if (r <0 ) + goto out_free_vcpus; + + r =kvm_mmu_create (vcpu); +if (r <0 ) + goto out_free_vcpus; + + kvm_arch_ops->vcpu_load (vcpu); + r =kvm_mmu_setup (vcpu); +if (r >=0 ) + r = kvm_arch_ops->vcpu_setup (vcpu); +vcpu_put (vcpu); + +if (r <0 ) + goto out_free_vcpus; + +return 0 ; + +out_free_vcpus: +kvm_free_vcpu (vcpu); +mutex_unlock (&vcpu->mutex); +out: +return r; +} +static long kvm_vm_ioctl (struct file *filp,unsigned int ioctl,unsigned long arg) {
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 5/6 KVM: Per-vcpu inodes
In reply to Avi KivityAllocate a distinct inode for every vcpu in a VM. This has the following benefits:
- the filp cachelines are no longer bounced when f_count is incremented on every ioctl()
- the API and internal code are distinctly clearer; for example, on the KVM_GET_REGS ioctl, there is no need to copy the vcpu number from userspace and then copy the registers back; the vcpu identity is derived from the fd used to make the call
Right now the performance benefits are completely theoretical since (a) we don't support more than one vcpu per VM and (b) virtualization hardware inefficiencies completely everwhelm any cacheline bouncing effects. But both of these will change, and we need to prepare the API today.
--- drivers/kvm/kvm.h | 3 +- drivers/kvm/kvm_main.c | 263 +++++++++++++++++++++++++++--------------------- drivers/kvm/svm.c | 3 +- drivers/kvm/vmx.c | 3 +- include/linux/kvm.h | 38 +++---- 5 files changed, 170 insertions(+), 140 deletions(-)
drivers/kvm/kvm.h +2 -1
@@ -309,6 +309,7 @@ struct kvm {int busy;unsigned long rmap_overflow;struct list_head vm_list; +struct file *filp; };struct kvm_stat {
@@ -343,7 +344,7 @@ struct kvm_arch_ops {int (*vcpu_create)(struct kvm_vcpu *vcpu);void (*vcpu_free)(struct kvm_vcpu *vcpu); -struct kvm_vcpu *(*vcpu_load)(struct kvm_vcpu *vcpu); +void (*vcpu_load)(struct kvm_vcpu *vcpu);void (*vcpu_put)(struct kvm_vcpu *vcpu);void (*vcpu_decache)(struct kvm_vcpu *vcpu);
drivers/kvm/kvm_main.c +149 -114
500 lines not on this page · raw message
drivers/kvm/svm.c +1 -2
@@ -600,10 +600,9 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu)kfree (vcpu->svm); } -static struct kvm_vcpu *svm_vcpu_load (struct kvm_vcpu *vcpu) +static void svm_vcpu_load (struct kvm_vcpu *vcpu) {get_cpu (); -return vcpu; }static void svm_vcpu_put (struct kvm_vcpu *vcpu)
drivers/kvm/vmx.c +1 -2
@@ -204,7 +204,7 @@ static void vmcs_write64(unsigned long field, u64 value)* Switches to specified vcpu, until a matching vcpu_put(), but assumes * vcpu mutex is already taken. */ -static struct kvm_vcpu *vmx_vcpu_load (struct kvm_vcpu *vcpu) +static void vmx_vcpu_load (struct kvm_vcpu *vcpu) {u64 phys_addr =__pa (vcpu->vmcs);int cpu;
@@ -242,7 +242,6 @@ static struct kvm_vcpu *vmx_vcpu_load(struct kvm_vcpu *vcpu)rdmsrl (MSR_IA32_SYSENTER_ESP , sysenter_esp);vmcs_writel (HOST_IA32_SYSENTER_ESP , sysenter_esp);/* 22.2.3 */ } -return vcpu; }static void vmx_vcpu_put (struct kvm_vcpu *vcpu)
include/linux/kvm.h +17 -21
@@ -52,11 +52,10 @@ enum kvm_exit_reason {/* for KVM_RUN */ struct kvm_run {/* in */ -__u32 vcpu;__u32 emulated;/* skip current instruction */ __u32 mmio_completed;/* mmio request completed */ __u8 request_interrupt_window; -__u8 padding1[3 ]; +__u8 padding1[7 ];/* out */ __u32 exit_type;
@@ -111,10 +110,6 @@ struct kvm_run {/* for KVM_GET_REGS and KVM_SET_REGS */ struct kvm_regs { -/* in */ -__u32 vcpu; -__u32 padding; -/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ __u64 rax, rbx, rcx, rdx;__u64 rsi, rdi, rsp, rbp;
@@ -141,10 +136,6 @@ struct kvm_dtable {/* for KVM_GET_SREGS and KVM_SET_SREGS */ struct kvm_sregs { -/* in */ -__u32 vcpu; -__u32 padding; -/* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */ struct kvm_segment cs, ds, es, fs, gs, ss;struct kvm_segment tr, ldt;
@@ -163,8 +154,8 @@ struct kvm_msr_entry {/* for KVM_GET_MSRS and KVM_SET_MSRS */ struct kvm_msrs { -__u32 vcpu;__u32 nmsrs;/* number of msrs in entries */ +__u32 pad;struct kvm_msr_entry entries[0 ]; };
@@ -179,8 +170,6 @@ struct kvm_msr_list {struct kvm_translation {/* in */ __u64 linear_address; -__u32 vcpu; -__u32 padding;/* out */ __u64 physical_address;
@@ -193,7 +182,6 @@ struct kvm_translation {/* for KVM_INTERRUPT */ struct kvm_interrupt {/* in */ -__u32 vcpu;__u32 irq; };
@@ -206,8 +194,8 @@ struct kvm_breakpoint {/* for KVM_DEBUG_GUEST */ struct kvm_debug_guest {/* int */ -__u32 vcpu;__u32 enabled; +__u32 pad;struct kvm_breakpoint breakpoints[4 ];__u32 singlestep; };
@@ -234,18 +222,26 @@ struct kvm_dirty_log {/* * ioctls for VM fds */ +#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region) +/* +* KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns +* a vcpu fd. +*/ +#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int) +#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log) + +/* +* ioctls for vcpu fds +*/ #define KVM_RUN _IOWR(KVMIO, 2, struct kvm_run) -#define KVM_GET_REGS _IOWR(KVMIO, 3, struct kvm_regs) +#define KVM_GET_REGS _IOR(KVMIO, 3, struct kvm_regs)#define KVM_SET_REGS _IOW(KVMIO, 4, struct kvm_regs) -#define KVM_GET_SREGS _IOWR(KVMIO, 5, struct kvm_sregs) +#define KVM_GET_SREGS _IOR(KVMIO, 5, struct kvm_sregs)#define KVM_SET_SREGS _IOW(KVMIO, 6, struct kvm_sregs)#define KVM_TRANSLATE _IOWR(KVMIO, 7, struct kvm_translation)#define KVM_INTERRUPT _IOW(KVMIO, 8, struct kvm_interrupt)#define KVM_DEBUG_GUEST _IOW(KVMIO, 9, struct kvm_debug_guest) -#define KVM_SET_MEMORY_REGION _IOW(KVMIO, 10, struct kvm_memory_region) -#define KVM_CREATE_VCPU _IOW(KVMIO, 11, int /* vcpu_slot */) -#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 12, struct kvm_dirty_log)#define KVM_GET_MSRS _IOWR(KVMIO, 13, struct kvm_msrs) -#define KVM_SET_MSRS _IOWR(KVMIO, 14, struct kvm_msrs) +#define KVM_SET_MSRS _IOW(KVMIO, 14, struct kvm_msrs)#endif
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
PATCH 6/6 KVM: Bump API version
In reply to Avi Kivity--- include/linux/kvm.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/kvm.h +1 -1
@@ -11,7 +11,7 @@#include <asm/types.h> #include <linux/ioctl.h> -#define KVM_API_VERSION 3 +#define KVM_API_VERSION 4/* * Architectural interrupt line count, and the size of the bitmap needed
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Quoted 2 lines · Avi Kivity
The following patchset moves the kvm userspace interface from having a single fd, to having three types of file descriptors:
Andrew, while the 2.6.21 merge window has closed, please consider applying this to 2.6.21 anyway. At least one major distribution (Fedora) is planning to ship 2.6.21 in its next release, and it would be a shame not to give them the stable API they have come not to expect, especially as they will support it in their GUI management tools.
I plan two or three other changes over the next few days, and then devote the rest of 2.6.21 to working out kinks. Not that I expect many -- the changes are fairly simple. The last change would be adding a forwards and backwards compatible feature availability interface so we can extend it later.
The patchset, along with the previous fixset, is available as a git tree from git://kvm.qumranet.com/home/avi/kvm/linux-2.6. You may wish to plant it in your little git forest.
[Non-Andrews: please don't clone from this. Read
http://kvm.qumranet.com/kvmwiki/Code instead]
Signature · 8 lines
error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Quoted 6 lines · Avi Kivity
Quoted 2 lines · Avi Kivity
The following patchset moves the kvm userspace interface from having a single fd, to having three types of file descriptors:
Andrew, while the 2.6.21 merge window has closed, please consider applying this to 2.6.21 anyway.
Oh yeah, me too!
Lguest now offers a level of instability users of 2.6.21 should enjoy.
Plus, despite lguest having no stable ABI, I've only changed it once vs. kvm's twice. I hope to do better in future, but until it's in mainline that's hard.
Rusty.
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Quoted 5 lines · Avi Kivity
The patchset, along with the previous fixset, is available as a git tree from
git://kvm.qumranet.com/home/avi/kvm/linux-2.6. You may wish to plant it in your little git forest.
This is now git://kvm.qumranet.com/home/avi/kvm.git, as a bare 'git pull' will pull the current branch instead of master, giving you whatever I was working on at the moment. The kvm.git repo will always have 'master' as the current branch.
Signature · 8 lines
error compiling committee.c: too many arguments to function ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
Quoted 8 lines · On Sun, 25 Feb 2007 11:58:23 +0200 Avi Kivity…
Quoted 5 lines · Avi Kivity
The patchset, along with the previous fixset, is available as a git tree from
git://kvm.qumranet.com/home/avi/kvm/linux-2.6. You may wish to plant it in your little git forest.
Quoted 4 lines
This is now
git://kvm.qumranet.com/home/avi/kvm.git, as a bare 'git pull' will pull the current branch instead of master, giving you whatever I was working on at the moment. The kvm.git repo will always have 'master' as the current branch.
OK.
drivers/kvm/kvm.h | 13 + drivers/kvm/kvm_main.c | 774 ++++++++++++++++++++++++++++++++------------- drivers/kvm/kvm_svm.h | 3 drivers/kvm/mmu.c | 36 +- drivers/kvm/paging_tmpl.h | 18 + drivers/kvm/svm.c | 42 ++ drivers/kvm/vmx.c | 33 ++ include/linux/kvm.h | 50 ++- include/linux/kvm_para.h | 73 ++++
However things might get messy later on if that tree starts introducing changes outside drivers/kvm. There's a ton of activity in x86-world.
But if there are problems, you'll hear about it ;)
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV