diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-02-22 13:40:13 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-02-22 13:40:13 +0000 |
commit | edf779ffccc836661a7b654d320571a6c220caea (patch) | |
tree | a2da1f139f832957716890525c94f105dc46713c /linux-user/qemu.h | |
parent | 121061dcdfdf5ef1d78cd2ae84b39b779a568e28 (diff) |
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.h | 118 |
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 |