[RFC PATCH 2/4] vhost: add byteswap routines

Cédric Le Goater
2014-10-29T08:38:43Z

This patch adds a few helper routines around get_user and put_user
to ease byteswapping.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---

I am not sure these routines belong to this file. There is room for
improvement to remove the ugly switch (sizeof(*(ptr))). Please
comment !

drivers/vhost/vhost.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 93 insertions(+)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 72c21b790ba3..afcb3368370c 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -25,6 +25,7 @@
#include <linux/kthread.h>
#include <linux/cgroup.h>
#include <linux/module.h>
+#include <linux/swab.h>

#include "vhost.h"

@@ -1001,6 +1002,98 @@ int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
}
EXPORT_SYMBOL_GPL(vhost_log_write);

+#define vq_get_user(vq, x, ptr) \
+({ \
+ int ret = get_user(x, ptr); \
+ if (vq->byteswap) { \
+ switch (sizeof(*(ptr))) { \
+ case 2: \
+ x = swab16(x); \
+ break; \
+ case 4: \
+ x = swab32(x); \
+ break; \
+ case 8: \
+ x = swab64(x); \
+ break; \
+ default: \
+ break; \
+ } \
+ } \
+ ret; \
+})
+
+#define vq_put_user(vq, x, ptr) \
+({ \
+ __typeof__(*(ptr)) y = (x); \
+ if (vq->byteswap) { \
+ switch (sizeof(*(ptr))) { \
+ case 2: \
+ y = swab16(x); \
+ break; \
+ case 4: \
+ y = swab32(x); \
+ break; \
+ case 8: \
+ y = swab64(x); \
+ break; \
+ default: \
+ break; \
+ } \
+ } \
+ put_user(y, ptr); \
+})
+
+#define __vq_get_user(vq, x, ptr) \
+({ \
+ int ret = __get_user(x, ptr); \
+ if (vq->byteswap) { \
+ switch (sizeof(*(ptr))) { \
+ case 2: \
+ x = swab16(x); \
+ break; \
+ case 4: \
+ x = swab32(x); \
+ break; \
+ case 8: \
+ x = swab64(x); \
+ break; \
+ default: \
+ break; \
+ } \
+ } \
+ ret; \
+})
+
+#define __vq_put_user(vq, x, ptr) \
+({ \
+ __typeof__(*(ptr)) y = (x); \
+ if (vq->byteswap) { \
+ switch (sizeof(*(ptr))) { \
+ case 2: \
+ y = swab16(x); \
+ break; \
+ case 4: \
+ y = swab32(x); \
+ break; \
+ case 8: \
+ y = swab64(x); \
+ break; \
+ default: \
+ break; \
+ } \
+ } \
+ __put_user(y, ptr); \
+})
+
+static void vring_desc_swap(struct vring_desc *desc)
+{
+ desc->addr = swab64(desc->addr);
+ desc->len = swab32(desc->len);
+ desc->flags = swab16(desc->flags);
+ desc->next = swab16(desc->next);
+}
+
static int vhost_update_used_flags(struct vhost_virtqueue *vq)
{
void __user *used;
--
1.7.10.4