They're hidden inside net/core/iovec.c. It'd be nice to just link to that
but they're not too generic and come with tons of net/ specific code we
don't want. So we just copy over the relevant parts.

Signed-off-by: Sasha Levin <[email protected]>
---
 tools/kvm/Makefile               |   1 +
 tools/kvm/include/kvm/iovec.h    |  21 +++++++
 tools/kvm/include/linux/kernel.h |  10 ++++
 tools/kvm/util/iovec.c           | 126 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 158 insertions(+)
 create mode 100644 tools/kvm/include/kvm/iovec.h
 create mode 100644 tools/kvm/util/iovec.c

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index a0a0a9b..70accaa 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -86,6 +86,7 @@ OBJS  += net/uip/csum.o
 OBJS   += net/uip/dhcp.o
 OBJS   += kvm-cmd.o
 OBJS   += util/init.o
+OBJS    += util/iovec.o
 OBJS   += util/rbtree.o
 OBJS   += util/threadpool.o
 OBJS   += util/parse-options.o
diff --git a/tools/kvm/include/kvm/iovec.h b/tools/kvm/include/kvm/iovec.h
new file mode 100644
index 0000000..fe79dd4
--- /dev/null
+++ b/tools/kvm/include/kvm/iovec.h
@@ -0,0 +1,21 @@
+#ifndef KVM_UTIL_IOVEC_H_
+#define KVM_UTIL_IOVEC_H_
+
+extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
+                               size_t offset, int len);
+extern int memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
+                               size_t offset, int len);
+
+static inline size_t iov_size(const struct iovec *iovec, size_t len)
+{
+       size_t size = 0, i;
+
+       for (i = 0; i < len; i++)
+               size += iovec[i].iov_len;
+
+       return size;
+}
+
+#endif
diff --git a/tools/kvm/include/linux/kernel.h b/tools/kvm/include/linux/kernel.h
index 1e9abe9..f2bff5f 100644
--- a/tools/kvm/include/linux/kernel.h
+++ b/tools/kvm/include/linux/kernel.h
@@ -36,6 +36,16 @@
        (void) (&_max1 == &_max2);              \
        _max1 > _max2 ? _max1 : _max2; })
 
+#define min_t(type, x, y) ({                    \
+       type __min1 = (x);                      \
+       type __min2 = (y);                      \
+       __min1 < __min2 ? __min1: __min2; })
+
+#define max_t(type, x, y) ({                    \
+       type __max1 = (x);                      \
+       type __max2 = (y);                      \
+       __max1 > __max2 ? __max1: __max2; })
+
 #define true 1
 
 #endif
diff --git a/tools/kvm/util/iovec.c b/tools/kvm/util/iovec.c
new file mode 100644
index 0000000..0c8b9cf
--- /dev/null
+++ b/tools/kvm/util/iovec.c
@@ -0,0 +1,126 @@
+/*
+ *     iovec manipulation routines.
+ *
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ *
+ *     Fixes:
+ *             Andrew Lunn     :       Errors in iovec copying.
+ *             Pedro Roque     :       Added memcpy_fromiovecend and
+ *                                     csum_..._fromiovecend.
+ *             Andi Kleen      :       fixed error handling for 2.1
+ *             Alexey Kuznetsov:       2.1 optimisations
+ *             Andi Kleen      :       Fix csum*fromiovecend for IPv6.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <sys/uio.h>
+#include <kvm/iovec.h>
+#include <string.h>
+
+/*
+ *     Copy kernel to iovec. Returns -EFAULT on error.
+ *
+ *     Note: this modifies the original iovec.
+ */
+
+int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
+{
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, iov->iov_len, len);
+                       memcpy(iov->iov_base, kdata, copy);
+                       kdata += copy;
+                       len -= copy;
+                       iov->iov_len -= copy;
+                       iov->iov_base += copy;
+               }
+               iov++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_toiovec);
+
+/*
+ *     Copy kernel to iovec. Returns -EFAULT on error.
+ */
+
+int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata,
+                     size_t offset, int len)
+{
+       int copy;
+       for (; len > 0; ++iov) {
+               /* Skip over the finished iovecs */
+               if (unlikely(offset >= iov->iov_len)) {
+                       offset -= iov->iov_len;
+                       continue;
+               }
+               copy = min_t(unsigned int, iov->iov_len - offset, len);
+               memcpy(iov->iov_base + offset, kdata, copy);
+               offset = 0;
+               kdata += copy;
+               len -= copy;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_toiovecend);
+
+/*
+ *     Copy iovec to kernel. Returns -EFAULT on error.
+ *
+ *     Note: this modifies the original iovec.
+ */
+
+int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
+{
+       while (len > 0) {
+               if (iov->iov_len) {
+                       int copy = min_t(unsigned int, len, iov->iov_len);
+                       memcpy(kdata, iov->iov_base, copy);
+                       len -= copy;
+                       kdata += copy;
+                       iov->iov_base += copy;
+                       iov->iov_len -= copy;
+               }
+               iov++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_fromiovec);
+
+/*
+ *     Copy iovec from kernel. Returns -EFAULT on error.
+ */
+
+int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
+                       size_t offset, int len)
+{
+       /* Skip over the finished iovecs */
+       while (offset >= iov->iov_len) {
+               offset -= iov->iov_len;
+               iov++;
+       }
+
+       while (len > 0) {
+               char *base = iov->iov_base + offset;
+               int copy = min_t(unsigned int, len, iov->iov_len - offset);
+
+               offset = 0;
+               memcpy(kdata, base, copy);
+               len -= copy;
+               kdata += copy;
+               iov++;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(memcpy_fromiovecend);
-- 
1.8.2.1

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to