File: vu_wrapper_utils.h

package info (click to toggle)
vuos 0.9.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,616 kB
  • sloc: ansic: 22,155; python: 284; makefile: 28; sh: 4
file content (160 lines) | stat: -rw-r--r-- 4,549 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifndef VU_WRAPPER_UTILS_H
#define VU_WRAPPER_UTILS_H
#include <stdlib.h>
#include <xcommon.h>
#include <sys/uio.h>

/* macro for wrappers.
 * stucture for read wrappers/large buffers:
 *    vu_alloc_arg(addr, var, size, nested)
 *    vu_poke_arg(addr, var, size, nested)
 *    vu_free_arg(var, nested)
 * stucture for write wrappers/large buffers:
 *    vu_alloc_peek_arg(addr, var, size, nested)
 *    vu_free_arg(var, nested)
 * stucture for read wrappers/small buffers (stack allocation)
 *    vu_alloc_local_arg(addr, var, size, nested)
 *    vu_poke_arg(addr, var, size, nested)
 * stucture for write wrappers/small buffers (stack allocation)
 *    vu_alloc_peek_local_arg(addr, var, size, nested)
 * stucture for read wrappers IOVEC
 *    vu_alloc_iov_arg(iovaddr, iov, iovcnt, buf, bufsize, nested)
 *          it assigns buf and bufsize...
 *    vu_poke_iov_arg(iovaddr, iov, iovcnt, buf, len, nested)
 *    vu_free_iov_arg(iov, buf, nested)
 * stucture for write wrappers IOVEC
 *    vu_alloc_peek_iov_arg(iovaddr, iov, iovcnt, buf, bufsize, nested)
 *    vu_free_iov_arg(iov, buf, nested)
 * warning: local_arg macros define a local var.
 */

/* the callers of nested system calls run in the memory space of the
 * hypervisor, thus pointers can be simply used as such, there is no need to
 * allocate memory or copy data */

#define vu_alloc_arg(addr, var, size, nested) \
	do { \
		if (nested) { \
			var = (typeof(var)) addr; \
		} else { \
			var = malloc(size); \
		} \
	} while(0)

#define vu_alloc_peek_arg(addr, var, size, nested) \
	do { \
		if (nested) { \
			var = (typeof(var)) addr; \
		} else { \
			var = malloc(size); \
			umvu_peek_data(addr, var, size); \
		} \
	} while(0)

#if 0
#define vu_peek_local_arg(addr, var, count, nested) \
	typeof(* var) __ ## var[(nested) ? 0 : count]; \
	var = (nested) ? (typeof(var)) addr : __ ## var
#endif
#define vu_alloc_local_arg(addr, var, size, nested) \
	char *__ ## var[(nested) ? 0 : size]; \
	var = (nested) ? (typeof(var)) addr : (typeof(var)) __ ## var

#define vu_alloc_peek_local_arg(addr, var, size, nested) \
	char *__ ## var[(nested) ? 0 : size]; \
	do { \
		if (nested) {\
			var = (typeof(var)) addr; \
		} else { \
			var = (typeof(var)) __ ## var ;\
			umvu_peek_data(addr, var, size); \
		} \
	} while(0)

#define vu_alloc_peek_local_strarg(addr, var, size, nested) \
	char *__ ## var[(nested) ? 0 : size]; \
	do { \
		if (nested) {\
			var = (typeof(var)) addr; \
		} else { \
			var = (typeof(var)) __ ## var ;\
			umvu_peek_str(addr, var, size); \
		} \
	} while(0)

#define vu_poke_arg(addr, var, size, nested) \
	do { \
		if (!nested) umvu_poke_data(addr, var, size); \
	} while(0)

#define vu_peek_arg(addr, var, size, nested) \
	do { \
		if (!nested) umvu_peek_data(addr, var, size); \
	} while(0)

#define vu_free_arg(var, nested) \
	do { \
		if (!nested) xfree(var); \
	} while(0)

__attribute__((always_inline))
	static inline size_t iovec_bufsize(struct iovec *iov, int iovcnt) {
		int i;
		size_t ret_value = 0;
		for (i = 0; i < iovcnt; i++)
			ret_value += iov[i].iov_len;
		return ret_value;
	}

__attribute__((always_inline))
	static inline void vu_peek_iov_arg(uintptr_t iovaddr,
			struct iovec *iov, int iovcnt, void *buf, int nested) {
		char *cbuf = (char *) buf;
		int i;
		for (i = 0; i < iovcnt; i++) {
			ssize_t len = iov[i].iov_len;
			vu_peek_arg((uintptr_t) iov[i].iov_base, cbuf, len, nested);
			cbuf += len;
		}
	}

__attribute__((always_inline))
	static inline void vu_poke_iov_arg(uintptr_t iovaddr,
			struct iovec *iov, int iovcnt, void *buf, size_t len, int nested) {
		int i;
		char *cbuf = (char *) buf;
		for (i = 0; i < iovcnt && len > 0; i++) {
			size_t iov_len = iov[i].iov_len;
			if (len < iov_len) iov_len = len;
			vu_poke_arg((uintptr_t) iov[i].iov_base, cbuf, iov_len, nested);
			len -= iov_len;
			cbuf += iov_len;
		}
	}

#define vu_alloc_iov_arg(iovaddr, iov, iovcnt, buf, bufsize, nested) \
	do { \
		vu_alloc_peek_arg(iovaddr, iov, sizeof(struct iovec) * iovcnt, nested); \
		bufsize = iovec_bufsize(iov, iovcnt); \
		buf = malloc(bufsize); \
	} while(0)

#define vu_alloc_peek_iov_arg(iovaddr, iov, iovcnt, buf, bufsize, nested) \
	do { \
		vu_alloc_iov_arg(iovaddr, iov, iovcnt, buf, bufsize, nested); \
		vu_peek_iov_arg(iovaddr, iov, iovcnt, buf, nested); \
	} while(0)

#define vu_free_iov_arg(iov, buf, nested) \
	do {\
		vu_free_arg(iov, nested); \
		xfree(buf); \
	} while(0)

#define default_nosys(sd) \
	do {\
		(sd)->action = SKIPIT; \
		(sd)->ret_value = -ENOSYS; \
		return; \
	} while(0)
#endif