Re: [PATCH] vhost: introduce O(1) vq metadata cache

2016-12-14 Thread Jason Wang



On 2016年12月14日 16:14, kbuild test robot wrote:

Hi Jason,

[auto build test WARNING on vhost/linux-next]
[also build test WARNING on v4.9 next-20161214]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-introduce-O-1-vq-metadata-cache/20161214-160153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-randconfig-x005-201650 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
 # save the attached .config to linux build tree


Thanks, V2 will be posted soon.



Re: [PATCH] vhost: introduce O(1) vq metadata cache

2016-12-14 Thread Jason Wang



On 2016年12月14日 16:14, kbuild test robot wrote:

Hi Jason,

[auto build test WARNING on vhost/linux-next]
[also build test WARNING on v4.9 next-20161214]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-introduce-O-1-vq-metadata-cache/20161214-160153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-randconfig-x005-201650 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
 # save the attached .config to linux build tree


Thanks, V2 will be posted soon.



Re: [PATCH] vhost: introduce O(1) vq metadata cache

2016-12-14 Thread kbuild test robot
Hi Jason,

[auto build test WARNING on vhost/linux-next]
[also build test WARNING on v4.9 next-20161214]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-introduce-O-1-vq-metadata-cache/20161214-160153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-randconfig-x005-201650 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/vhost/vhost.c: In function 'vhost_vq_meta_fetch':
>> drivers/vhost/vhost.c:719:9: warning: cast to pointer from integer of 
>> different size [-Wint-to-pointer-cast]
 return (void *)(node->userspace_addr + (u64)addr - node->start);
^

vim +719 drivers/vhost/vhost.c

   703 node->start,
   704 node->size))
   705  return 0;
   706  }
   707  return 1;
   708  }
   709  
   710  static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue 
*vq,
   711 u64 addr, unsigned int 
size,
   712 int type)
   713  {
   714  const struct vhost_umem_node *node = vq->meta_iotlb[type];
   715  
   716  if (!node)
   717  return NULL;
   718  
 > 719  return (void *)(node->userspace_addr + (u64)addr - node->start);
   720  }
   721  
   722  /* Can we switch to this memory table? */
   723  /* Caller should have device mutex but not vq mutex */
   724  static int memory_access_ok(struct vhost_dev *d, struct vhost_umem 
*umem,
   725  int log_all)
   726  {
   727  int i;

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


Re: [PATCH] vhost: introduce O(1) vq metadata cache

2016-12-14 Thread kbuild test robot
Hi Jason,

[auto build test WARNING on vhost/linux-next]
[also build test WARNING on v4.9 next-20161214]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/Jason-Wang/vhost-introduce-O-1-vq-metadata-cache/20161214-160153
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next
config: i386-randconfig-x005-201650 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All warnings (new ones prefixed by >>):

   drivers/vhost/vhost.c: In function 'vhost_vq_meta_fetch':
>> drivers/vhost/vhost.c:719:9: warning: cast to pointer from integer of 
>> different size [-Wint-to-pointer-cast]
 return (void *)(node->userspace_addr + (u64)addr - node->start);
^

vim +719 drivers/vhost/vhost.c

   703 node->start,
   704 node->size))
   705  return 0;
   706  }
   707  return 1;
   708  }
   709  
   710  static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue 
*vq,
   711 u64 addr, unsigned int 
size,
   712 int type)
   713  {
   714  const struct vhost_umem_node *node = vq->meta_iotlb[type];
   715  
   716  if (!node)
   717  return NULL;
   718  
 > 719  return (void *)(node->userspace_addr + (u64)addr - node->start);
   720  }
   721  
   722  /* Can we switch to this memory table? */
   723  /* Caller should have device mutex but not vq mutex */
   724  static int memory_access_ok(struct vhost_dev *d, struct vhost_umem 
*umem,
   725  int log_all)
   726  {
   727  int i;

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH] vhost: introduce O(1) vq metadata cache

2016-12-13 Thread Jason Wang
When device IOTLB is enabled, all address translations were stored in
interval tree. O(lgN) searching time could be slow for virtqueue
metadata (avail, used and descriptors) since they were accessed much
often than other addresses. So this patch introduces an O(1) array
which points to the interval tree nodes that store the translations of
vq metadata. Those array were update during vq IOTLB prefetching and
were reset during each invalidation and tlb update. Each time we want
to access vq metadata, this small array were queried before interval
tree. This would be sufficient for static mappings but not dynamic
mappings, we could do optimizations on top.

Test were done with l2fwd in guest (2M hugepage):

   noiommu  | before| after
tx 1.32Mpps | 1.06Mpps(82%) | 1.30Mpps(98%)
rx 2.33Mpps | 1.46Mpps(63%) | 2.29Mpps(98%)

We can almost reach the same performance as noiommu mode.

Signed-off-by: Jason Wang 
---
 drivers/vhost/vhost.c | 136 --
 drivers/vhost/vhost.h |   8 +++
 2 files changed, 118 insertions(+), 26 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c6f2d89..89e40b6 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -282,6 +282,22 @@ void vhost_poll_queue(struct vhost_poll *poll)
 }
 EXPORT_SYMBOL_GPL(vhost_poll_queue);
 
+static void __vhost_vq_meta_reset(struct vhost_virtqueue *vq)
+{
+   int j;
+
+   for (j = 0; j < VHOST_NUM_ADDRS; j++)
+   vq->meta_iotlb[j] = NULL;
+}
+
+static void vhost_vq_meta_reset(struct vhost_dev *d)
+{
+   int i;
+
+   for (i = 0; i < d->nvqs; ++i)
+   __vhost_vq_meta_reset(d->vqs[i]);
+}
+
 static void vhost_vq_reset(struct vhost_dev *dev,
   struct vhost_virtqueue *vq)
 {
@@ -311,6 +327,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
+   __vhost_vq_meta_reset(vq);
 }
 
 static int vhost_worker(void *data)
@@ -690,6 +707,18 @@ static int vq_memory_access_ok(void __user *log_base, 
struct vhost_umem *umem,
return 1;
 }
 
+static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue *vq,
+  u64 addr, unsigned int size,
+  int type)
+{
+   const struct vhost_umem_node *node = vq->meta_iotlb[type];
+
+   if (!node)
+   return NULL;
+
+   return (void *)(node->userspace_addr + (u64)addr - node->start);
+}
+
 /* Can we switch to this memory table? */
 /* Caller should have device mutex but not vq mutex */
 static int memory_access_ok(struct vhost_dev *d, struct vhost_umem *umem,
@@ -732,8 +761,14 @@ static int vhost_copy_to_user(struct vhost_virtqueue *vq, 
void *to,
 * could be access through iotlb. So -EAGAIN should
 * not happen in this case.
 */
-   /* TODO: more fast path */
struct iov_iter t;
+   void __user *uaddr = vhost_vq_meta_fetch(vq,
+(u64)(uintptr_t)to, size,
+VHOST_ADDR_DESC);
+
+   if (uaddr)
+   return __copy_to_user(uaddr, from, size);
+
ret = translate_desc(vq, (u64)(uintptr_t)to, size, 
vq->iotlb_iov,
 ARRAY_SIZE(vq->iotlb_iov),
 VHOST_ACCESS_WO);
@@ -761,8 +796,14 @@ static int vhost_copy_from_user(struct vhost_virtqueue 
*vq, void *to,
 * could be access through iotlb. So -EAGAIN should
 * not happen in this case.
 */
-   /* TODO: more fast path */
+   void __user *uaddr = vhost_vq_meta_fetch(vq,
+(u64)(uintptr_t)from, size,
+VHOST_ADDR_DESC);
struct iov_iter f;
+
+   if (uaddr)
+   return __copy_from_user(to, uaddr, size);
+
ret = translate_desc(vq, (u64)(uintptr_t)from, size, 
vq->iotlb_iov,
 ARRAY_SIZE(vq->iotlb_iov),
 VHOST_ACCESS_RO);
@@ -782,17 +823,12 @@ static int vhost_copy_from_user(struct vhost_virtqueue 
*vq, void *to,
return ret;
 }
 
-static void __user *__vhost_get_user(struct vhost_virtqueue *vq,
-void *addr, unsigned size)
+static void __user *__vhost_get_user_slow(struct vhost_virtqueue *vq,
+ void *addr, unsigned int size,
+ int type)
 {
int ret;
 
-   /* This function should be called after iotlb
-* prefetch, which means we're sure that vq
-* could be access through iotlb. So -EAGAIN should
-* not happen in this case.
- 

[PATCH] vhost: introduce O(1) vq metadata cache

2016-12-13 Thread Jason Wang
When device IOTLB is enabled, all address translations were stored in
interval tree. O(lgN) searching time could be slow for virtqueue
metadata (avail, used and descriptors) since they were accessed much
often than other addresses. So this patch introduces an O(1) array
which points to the interval tree nodes that store the translations of
vq metadata. Those array were update during vq IOTLB prefetching and
were reset during each invalidation and tlb update. Each time we want
to access vq metadata, this small array were queried before interval
tree. This would be sufficient for static mappings but not dynamic
mappings, we could do optimizations on top.

Test were done with l2fwd in guest (2M hugepage):

   noiommu  | before| after
tx 1.32Mpps | 1.06Mpps(82%) | 1.30Mpps(98%)
rx 2.33Mpps | 1.46Mpps(63%) | 2.29Mpps(98%)

We can almost reach the same performance as noiommu mode.

Signed-off-by: Jason Wang 
---
 drivers/vhost/vhost.c | 136 --
 drivers/vhost/vhost.h |   8 +++
 2 files changed, 118 insertions(+), 26 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index c6f2d89..89e40b6 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -282,6 +282,22 @@ void vhost_poll_queue(struct vhost_poll *poll)
 }
 EXPORT_SYMBOL_GPL(vhost_poll_queue);
 
+static void __vhost_vq_meta_reset(struct vhost_virtqueue *vq)
+{
+   int j;
+
+   for (j = 0; j < VHOST_NUM_ADDRS; j++)
+   vq->meta_iotlb[j] = NULL;
+}
+
+static void vhost_vq_meta_reset(struct vhost_dev *d)
+{
+   int i;
+
+   for (i = 0; i < d->nvqs; ++i)
+   __vhost_vq_meta_reset(d->vqs[i]);
+}
+
 static void vhost_vq_reset(struct vhost_dev *dev,
   struct vhost_virtqueue *vq)
 {
@@ -311,6 +327,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
vq->busyloop_timeout = 0;
vq->umem = NULL;
vq->iotlb = NULL;
+   __vhost_vq_meta_reset(vq);
 }
 
 static int vhost_worker(void *data)
@@ -690,6 +707,18 @@ static int vq_memory_access_ok(void __user *log_base, 
struct vhost_umem *umem,
return 1;
 }
 
+static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue *vq,
+  u64 addr, unsigned int size,
+  int type)
+{
+   const struct vhost_umem_node *node = vq->meta_iotlb[type];
+
+   if (!node)
+   return NULL;
+
+   return (void *)(node->userspace_addr + (u64)addr - node->start);
+}
+
 /* Can we switch to this memory table? */
 /* Caller should have device mutex but not vq mutex */
 static int memory_access_ok(struct vhost_dev *d, struct vhost_umem *umem,
@@ -732,8 +761,14 @@ static int vhost_copy_to_user(struct vhost_virtqueue *vq, 
void *to,
 * could be access through iotlb. So -EAGAIN should
 * not happen in this case.
 */
-   /* TODO: more fast path */
struct iov_iter t;
+   void __user *uaddr = vhost_vq_meta_fetch(vq,
+(u64)(uintptr_t)to, size,
+VHOST_ADDR_DESC);
+
+   if (uaddr)
+   return __copy_to_user(uaddr, from, size);
+
ret = translate_desc(vq, (u64)(uintptr_t)to, size, 
vq->iotlb_iov,
 ARRAY_SIZE(vq->iotlb_iov),
 VHOST_ACCESS_WO);
@@ -761,8 +796,14 @@ static int vhost_copy_from_user(struct vhost_virtqueue 
*vq, void *to,
 * could be access through iotlb. So -EAGAIN should
 * not happen in this case.
 */
-   /* TODO: more fast path */
+   void __user *uaddr = vhost_vq_meta_fetch(vq,
+(u64)(uintptr_t)from, size,
+VHOST_ADDR_DESC);
struct iov_iter f;
+
+   if (uaddr)
+   return __copy_from_user(to, uaddr, size);
+
ret = translate_desc(vq, (u64)(uintptr_t)from, size, 
vq->iotlb_iov,
 ARRAY_SIZE(vq->iotlb_iov),
 VHOST_ACCESS_RO);
@@ -782,17 +823,12 @@ static int vhost_copy_from_user(struct vhost_virtqueue 
*vq, void *to,
return ret;
 }
 
-static void __user *__vhost_get_user(struct vhost_virtqueue *vq,
-void *addr, unsigned size)
+static void __user *__vhost_get_user_slow(struct vhost_virtqueue *vq,
+ void *addr, unsigned int size,
+ int type)
 {
int ret;
 
-   /* This function should be called after iotlb
-* prefetch, which means we're sure that vq
-* could be access through iotlb. So -EAGAIN should
-* not happen in this case.
-*/
-   /*