From patchwork Sun May 31 18:59:16 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Michael S. Tsirkin" X-Patchwork-Id: 27132 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n4VIxXso006399 for ; Sun, 31 May 2009 18:59:33 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751915AbZEaS73 (ORCPT ); Sun, 31 May 2009 14:59:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751614AbZEaS73 (ORCPT ); Sun, 31 May 2009 14:59:29 -0400 Received: from mx2.redhat.com ([66.187.237.31]:43312 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751853AbZEaS72 (ORCPT ); Sun, 31 May 2009 14:59:28 -0400 Received: from int-mx2.corp.redhat.com (int-mx2.corp.redhat.com [172.16.27.26]) by mx2.redhat.com (8.13.8/8.13.8) with ESMTP id n4VIxUpJ016095; Sun, 31 May 2009 14:59:30 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n4VIxThZ019023; Sun, 31 May 2009 14:59:29 -0400 Received: from redhat.com (vpn-10-98.str.redhat.com [10.32.10.98]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n4VIxQhn019743; Sun, 31 May 2009 14:59:27 -0400 Date: Sun, 31 May 2009 21:59:16 +0300 From: "Michael S. Tsirkin" To: Gregory Haskins , kvm@vger.kernel.org, avi@redhat.com, mtosatti@redhat.com Subject: [PATCH 2/3] kvm: virtual device support Message-ID: <20090531185916.GC10043@redhat.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Implement virt_hypervisor in kvm, and add support for creating virtual devices. Signed-off-by: Michael S. Tsirkin --- include/linux/kvm.h | 13 ++++++++++++ include/linux/kvm_host.h | 3 ++ virt/kvm/kvm_main.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 0 deletions(-) diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 8cc1379..8f6cc79 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h @@ -487,6 +487,8 @@ struct kvm_irq_routing { #define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) #define KVM_DEASSIGN_PCI_DEVICE _IOW(KVMIO, 0x72, \ struct kvm_assigned_pci_dev) +#define KVM_CREATE_VIRT_DEVICE _IOW(KVMIO, 0x73, \ + struct kvm_create_virt_device) /* * ioctls for vcpu fds @@ -602,6 +604,17 @@ struct kvm_assigned_irq { }; }; +struct kvm_create_virt_device { + __s32 flags; /* flags from open(2). Only O_CLOEXEC supported for now. */ + __u32 id_len; + union { + __u32 reserved[12]; + }; + /* Followed by up to MAX_ID_LEN byte id. */ +}; + +#define KVM_VIRT_DEVICE_MAX_ID_LEN 200 + #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_IRQ_ASSIGN_MSI_ACTION KVM_DEV_IRQ_ASSIGN_ENABLE_MSI diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 894a56e..7131851 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -26,6 +26,8 @@ #include +#include + /* * vcpu->requests bit members */ @@ -152,6 +154,7 @@ struct kvm { unsigned long mmu_notifier_seq; long mmu_notifier_count; #endif + struct virt_hypervisor hypervisor; }; /* The guest did something we don't support. */ diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 1ecbe23..c0487f0 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -766,6 +766,24 @@ static void kvm_mmu_notifier_release(struct mmu_notifier *mn, kvm_arch_flush_shadow(kvm); } +static void kvm_hypervisor_get(struct virt_hypervisor *h) +{ + struct kvm *kvm = container_of(h, struct kvm, hypervisor); + kvm_get_kvm(kvm); +} + +static void kvm_hypervisor_put(struct virt_hypervisor *h) +{ + struct kvm *kvm = container_of(h, struct kvm, hypervisor); + kvm_put_kvm(kvm); +} +static int kvm_hypervisor_set_irq(struct virt_hypervisor *h, + int source, int irq, int level) +{ + struct kvm *kvm = container_of(h, struct kvm, hypervisor); + return kvm_set_irq(kvm, source, irq, level); +} + static const struct mmu_notifier_ops kvm_mmu_notifier_ops = { .invalidate_page = kvm_mmu_notifier_invalidate_page, .invalidate_range_start = kvm_mmu_notifier_invalidate_range_start, @@ -828,6 +846,10 @@ static struct kvm *kvm_create_vm(void) #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET kvm_coalesced_mmio_init(kvm); #endif + kvm->hypervisor.get = kvm_hypervisor_get; + kvm->hypervisor.put = kvm_hypervisor_put; + kvm->hypervisor.set_irq = kvm_hypervisor_set_irq; + virt_hypervisor_register(&kvm->hypervisor); out: return kvm; } @@ -865,6 +887,7 @@ static void kvm_destroy_vm(struct kvm *kvm) { struct mm_struct *mm = kvm->mm; + virt_hypervisor_unregister(&kvm->hypervisor); kvm_arch_sync_events(kvm); spin_lock(&kvm_lock); list_del(&kvm->vm_list); @@ -1917,6 +1940,30 @@ static long kvm_vm_ioctl(struct file *filp, vfree(entries); break; } + case KVM_CREATE_VIRT_DEVICE: { + struct kvm_create_virt_device d; + u8 *id; + r = -EFAULT; + if (copy_from_user(&d, argp, sizeof d)) + goto out; + r = -EINVAL; + if (d.id_len > KVM_VIRT_DEVICE_MAX_ID_LEN) + goto out; + if (d.flags & ~O_CLOEXEC) + goto out; + r = -ENOMEM; + id = kmalloc(d.id_len, GFP_KERNEL); + if (!id) + goto out_free_id; + r = -EFAULT; + if (copy_from_user(id, argp + sizeof d, d.id_len)) + goto out_free_id; + r = virt_device_create(&kvm->hypervisor, d.flags, + id, d.id_len); + out_free_id: + kfree(id); + break; + } #endif default: r = kvm_arch_vm_ioctl(filp, ioctl, arg);