summaryrefslogtreecommitdiff
path: root/linux-user/qemu.h
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-02-22 13:40:13 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-02-22 13:40:13 +0000
commitedf779ffccc836661a7b654d320571a6c220caea (patch)
treea2da1f139f832957716890525c94f105dc46713c /linux-user/qemu.h
parent121061dcdfdf5ef1d78cd2ae84b39b779a568e28 (diff)
downloadqemu-edf779ffccc836661a7b654d320571a6c220caea.tar.gz
use kernel like macros for user access (will be useful someday to have a better error checking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@634 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/qemu.h')
-rw-r--r--linux-user/qemu.h118
1 files changed, 118 insertions, 0 deletions
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 1a3ad6274a..be95ff9183 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -4,6 +4,7 @@
#include "thunk.h"
#include <signal.h>
+#include <string.h>
#include "syscall_defs.h"
#include "cpu.h"
@@ -120,4 +121,121 @@ long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_addr);
int target_msync(unsigned long start, unsigned long len, int flags);
+/* user access */
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#define access_ok(type,addr,size) (1)
+
+#define __put_user(x,ptr)\
+({\
+ int size = sizeof(*ptr);\
+ switch(size) {\
+ case 1:\
+ stb(ptr, (typeof(*ptr))(x));\
+ break;\
+ case 2:\
+ stw(ptr, (typeof(*ptr))(x));\
+ break;\
+ case 4:\
+ stl(ptr, (typeof(*ptr))(x));\
+ break;\
+ case 8:\
+ stq(ptr, (typeof(*ptr))(x));\
+ break;\
+ default:\
+ abort();\
+ }\
+ 0;\
+})
+
+#define __get_user(x, ptr) \
+({\
+ int size = sizeof(*ptr);\
+ switch(size) {\
+ case 1:\
+ x = (typeof(*ptr))ldub(ptr);\
+ break;\
+ case 2:\
+ x = (typeof(*ptr))lduw(ptr);\
+ break;\
+ case 4:\
+ x = (typeof(*ptr))ldl(ptr);\
+ break;\
+ case 8:\
+ x = (typeof(*ptr))ldq(ptr);\
+ break;\
+ default:\
+ abort();\
+ }\
+ 0;\
+})
+
+static inline unsigned long __copy_to_user(void *dst, const void *src,
+ unsigned long size)
+{
+ memcpy(dst, src, size);
+ return 0;
+}
+
+static inline unsigned long __copy_from_user(void *dst, const void *src,
+ unsigned long size)
+{
+ memcpy(dst, src, size);
+ return 0;
+}
+
+static inline unsigned long __clear_user(void *dst, unsigned long size)
+{
+ memset(dst, 0, size);
+ return 0;
+}
+
+#define put_user(x,ptr)\
+({\
+ int __ret;\
+ if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
+ __ret = __put_user(x, ptr);\
+ else\
+ __ret = -EFAULT;\
+ __ret;\
+})
+
+#define get_user(x,ptr)\
+({\
+ int __ret;\
+ if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
+ __ret = __get_user(x, ptr);\
+ else\
+ __ret = -EFAULT;\
+ __ret;\
+})
+
+static inline unsigned long copy_to_user(void *dst, const void *src,
+ unsigned long size)
+{
+ if (access_ok(VERIFY_WRITE, dst, size))
+ return __copy_to_user(dst, src, size);
+ else
+ return size;
+}
+
+static inline unsigned long copy_from_user(void *dst, const void *src,
+ unsigned long size)
+{
+ if (access_ok(VERIFY_READ, src, size))
+ return __copy_from_user(dst, src, size);
+ else
+ return size;
+}
+
+static inline unsigned long clear_user(void *dst, unsigned long size)
+{
+ if (access_ok(VERIFY_WRITE, dst, size))
+ return __clear_user(dst, size);
+ else
+ return size;
+}
+
#endif