zanghongyong at huawei.com
2011-Dec-16 05:32 UTC
[PATCH 0/2] vhot-net: Use kvm_memslots instead of vhost_memory to translate GPA to HVA
From: Hongyong Zang <zanghongyong at huawei.com> Vhost-net uses its own vhost_memory, which results from user space (qemu) info, to translate GPA to HVA. Since kernel's kvm structure already maintains the address relationship in its member *kvm_memslots*, these patches use kernel's kvm_memslots directly without the need of initialization and maintenance of vhost_memory. Hongyong Zang (2): kvm: Introduce get_kvm_from_task vhost-net: Use kvm_memslots for address translation drivers/vhost/vhost.c | 53 +++++++++++++++++---------------------------- include/linux/kvm_host.h | 2 +- virt/kvm/kvm_main.c | 13 +++++++++++ 3 files changed, 34 insertions(+), 34 deletions(-)
zanghongyong at huawei.com
2011-Dec-16 05:32 UTC
[PATCH 1/2] kvm: Introduce get_kvm_from_task
From: Hongyong Zang <zanghongyong at huawei.com> This function finds the kvm structure from its corresponding user space process, such as qemu process. Signed-off-by: Hongyong Zang <zanghongyong at huawei.com> --- include/linux/kvm_host.h | 2 +- virt/kvm/kvm_main.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 8c5c303..1b2f027 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -801,4 +801,4 @@ static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu) } #endif - +struct kvm *get_kvm_from_task(struct task_struct *task); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index e289486..458fe29 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2664,6 +2664,19 @@ static const struct file_operations *stat_fops[] = { [KVM_STAT_VM] = &vm_stat_fops, }; +struct kvm* get_kvm_from_task(struct task_struct *task) +{ + struct kvm *kvm; + + list_for_each_entry(kvm, &vm_list, vm_list) { + if(kvm->mm == task->mm) + return kvm; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(get_kvm_from_task); + static void kvm_init_debug(void) { struct kvm_stats_debugfs_item *p; -- 1.7.1
zanghongyong at huawei.com
2011-Dec-16 05:32 UTC
[PATCH 2/2] vhost-net: Use kvm_memslots for address translation
From: Hongyong Zang <zanghongyong at huawei.com> Use kvm's memslots instead of vhost_memory to traslate address from GPA to HVA. Signed-off-by: Hongyong Zang <zanghongyong at huawei.com> --- drivers/vhost/vhost.c | 53 ++++++++++++++++++------------------------------ 1 files changed, 20 insertions(+), 33 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c14c42b..63e4322 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -11,6 +11,7 @@ * Generic code for virtio server in host kernel. */ +#include <linux/kvm_host.h> #include <linux/eventfd.h> #include <linux/vhost.h> #include <linux/virtio_net.h> @@ -904,23 +905,6 @@ done: return r; } -static const struct vhost_memory_region *find_region(struct vhost_memory *mem, - __u64 addr, __u32 len) -{ - struct vhost_memory_region *reg; - int i; - - /* linear search is not brilliant, but we really have on the order of 6 - * regions in practice */ - for (i = 0; i < mem->nregions; ++i) { - reg = mem->regions + i; - if (reg->guest_phys_addr <= addr && - reg->guest_phys_addr + reg->memory_size - 1 >= addr) - return reg; - } - return NULL; -} - /* TODO: This is really inefficient. We need something like get_user() * (instruction directly accesses the data, with an exception table entry * returning -EFAULT). See Documentation/x86/exception-tables.txt. @@ -1046,40 +1030,36 @@ int vhost_init_used(struct vhost_virtqueue *vq) return get_user(vq->last_used_idx, &vq->used->idx); } -static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, +static int translate_desc(struct kvm *kvm, u64 addr, u32 len, struct iovec iov[], int iov_size) { - const struct vhost_memory_region *reg; - struct vhost_memory *mem; + const struct kvm_memory_slot *slot; + gfn_t gfn = addr >> PAGE_SHIFT; struct iovec *_iov; u64 s = 0; int ret = 0; - rcu_read_lock(); - - mem = rcu_dereference(dev->memory); while ((u64)len > s) { u64 size; if (unlikely(ret >= iov_size)) { ret = -ENOBUFS; break; } - reg = find_region(mem, addr, len); - if (unlikely(!reg)) { + slot = gfn_to_memslot(kvm, gfn); + if (unlikely(!slot)) { ret = -EFAULT; break; } _iov = iov + ret; - size = reg->memory_size - addr + reg->guest_phys_addr; + size = slot->npages*VHOST_PAGE_SIZE - addr + (slot->base_gfn<<PAGE_SHIFT); _iov->iov_len = min((u64)len, size); _iov->iov_base = (void __user *)(unsigned long) - (reg->userspace_addr + addr - reg->guest_phys_addr); + (slot->userspace_addr + addr - (slot->base_gfn<<PAGE_SHIFT)); s += size; addr += size; ++ret; } - rcu_read_unlock(); return ret; } @@ -1104,7 +1084,7 @@ static unsigned next_desc(struct vring_desc *desc) return next; } -static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, +static int get_indirect(struct kvm *kvm, struct vhost_virtqueue *vq, struct iovec iov[], unsigned int iov_size, unsigned int *out_num, unsigned int *in_num, struct vhost_log *log, unsigned int *log_num, @@ -1123,7 +1103,7 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, return -EINVAL; } - ret = translate_desc(dev, indirect->addr, indirect->len, vq->indirect, + ret = translate_desc(kvm, indirect->addr, indirect->len, vq->indirect, UIO_MAXIOV); if (unlikely(ret < 0)) { vq_err(vq, "Translation failure %d in indirect.\n", ret); @@ -1163,7 +1143,7 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq, return -EINVAL; } - ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count, + ret = translate_desc(kvm, desc.addr, desc.len, iov + iov_count, iov_size - iov_count); if (unlikely(ret < 0)) { vq_err(vq, "Translation failure %d indirect idx %d\n", @@ -1209,6 +1189,13 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, unsigned int i, head, found = 0; u16 last_avail_idx; int ret; + struct kvm *kvm = get_kvm_from_task(current); + + if(unlikely(kvm == NULL)){ + vq_err(vq, "Failed to get corresponding kvm struct of vhost-%d\n", + current->pid); + return -EFAULT; + } /* Check it isn't doing very strange things with descriptor numbers. */ last_avail_idx = vq->last_avail_idx; @@ -1274,7 +1261,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, return -EFAULT; } if (desc.flags & VRING_DESC_F_INDIRECT) { - ret = get_indirect(dev, vq, iov, iov_size, + ret = get_indirect(kvm, vq, iov, iov_size, out_num, in_num, log, log_num, &desc); if (unlikely(ret < 0)) { @@ -1285,7 +1272,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq, continue; } - ret = translate_desc(dev, desc.addr, desc.len, iov + iov_count, + ret = translate_desc(kvm, desc.addr, desc.len, iov + iov_count, iov_size - iov_count); if (unlikely(ret < 0)) { vq_err(vq, "Translation failure %d descriptor idx %d\n", -- 1.7.1
Takuya Yoshikawa
2011-Dec-16 07:05 UTC
[PATCH 0/2] vhot-net: Use kvm_memslots instead of vhost_memory to translate GPA to HVA
(2011/12/16 14:32), zanghongyong at huawei.com wrote:> From: Hongyong Zang<zanghongyong at huawei.com> > > Vhost-net uses its own vhost_memory, which results from user space (qemu) info, > to translate GPA to HVA. Since kernel's kvm structure already maintains the > address relationship in its member *kvm_memslots*, these patches use kernel's > kvm_memslots directly without the need of initialization and maintenance of > vhost_memory.Isn't vhost independent from KVM? Takuya
Sasha Levin
2011-Dec-16 07:05 UTC
[PATCH 0/2] vhot-net: Use kvm_memslots instead of vhost_memory to translate GPA to HVA
On Fri, 2011-12-16 at 13:32 +0800, zanghongyong at huawei.com wrote:> From: Hongyong Zang <zanghongyong at huawei.com> > > Vhost-net uses its own vhost_memory, which results from user space (qemu) info, > to translate GPA to HVA. Since kernel's kvm structure already maintains the > address relationship in its member *kvm_memslots*, these patches use kernel's > kvm_memslots directly without the need of initialization and maintenance of > vhost_memory.Conceptually, vhost isn't aware of KVM - it's just a driver which moves data from vq to a tap device and back. You can't simply add KVM specific code into vhost. Whats the performance benefit? -- Sasha.