diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/main.c | 5 | ||||
-rw-r--r-- | linux-user/qemu.h | 63 | ||||
-rw-r--r-- | linux-user/signal.c | 22 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 2 |
4 files changed, 47 insertions, 45 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index 15bacb9a30..0181bc2112 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -57,7 +57,12 @@ int have_guest_base; * This way we will never overlap with our own libraries or binaries or stack * or anything else that QEMU maps. */ +# ifdef TARGET_MIPS +/* MIPS only supports 31 bits of virtual address space for user space */ +unsigned long reserved_va = 0x77000000; +# else unsigned long reserved_va = 0xf7000000; +# endif #else unsigned long reserved_va; #endif diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 8a3538c631..31a220af81 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -287,36 +287,39 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0; } -/* NOTE __get_user and __put_user use host pointers and don't check access. */ -/* These are usually used to access struct data members once the - * struct has been locked - usually with lock_user_struct(). - */ -#define __put_user(x, hptr)\ -({ __typeof(*hptr) pu_ = (x);\ - switch(sizeof(*hptr)) {\ - case 1: break;\ - case 2: pu_ = tswap16(pu_); break; \ - case 4: pu_ = tswap32(pu_); break; \ - case 8: pu_ = tswap64(pu_); break; \ - default: abort();\ - }\ - memcpy(hptr, &pu_, sizeof(pu_)); \ - 0;\ -}) - -#define __get_user(x, hptr) \ -({ __typeof(*hptr) gu_; \ - memcpy(&gu_, hptr, sizeof(gu_)); \ - switch(sizeof(*hptr)) {\ - case 1: break; \ - case 2: gu_ = tswap16(gu_); break; \ - case 4: gu_ = tswap32(gu_); break; \ - case 8: gu_ = tswap64(gu_); break; \ - default: abort();\ - }\ - (x) = gu_; \ - 0;\ -}) +/* NOTE __get_user and __put_user use host pointers and don't check access. + These are usually used to access struct data members once the struct has + been locked - usually with lock_user_struct. */ + +/* Tricky points: + - Use __builtin_choose_expr to avoid type promotion from ?:, + - Invalid sizes result in a compile time error stemming from + the fact that abort has no parameters. + - It's easier to use the endian-specific unaligned load/store + functions than host-endian unaligned load/store plus tswapN. */ + +#define __put_user_e(x, hptr, e) \ + (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort)))) \ + ((hptr), (x)), 0) + +#define __get_user_e(x, hptr, e) \ + ((x) = \ + __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p, \ + __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort)))) \ + (hptr), 0) + +#ifdef TARGET_WORDS_BIGENDIAN +# define __put_user(x, hptr) __put_user_e(x, hptr, be) +# define __get_user(x, hptr) __get_user_e(x, hptr, be) +#else +# define __put_user(x, hptr) __put_user_e(x, hptr, le) +# define __get_user(x, hptr) __get_user_e(x, hptr, le) +#endif /* put_user()/get_user() take a guest address and check access */ /* These are usually used to access an atomic data type, such as an int, diff --git a/linux-user/signal.c b/linux-user/signal.c index 95e2ffa007..407619ac4e 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -607,28 +607,22 @@ int do_sigaction(int sig, const struct target_sigaction *act, sig, act, oact); #endif if (oact) { - oact->_sa_handler = tswapal(k->_sa_handler); -#if defined(TARGET_MIPS) || defined (TARGET_ALPHA) - oact->sa_flags = bswap32(k->sa_flags); -#else - oact->sa_flags = tswapal(k->sa_flags); -#endif + __put_user(k->_sa_handler, &oact->_sa_handler); + __put_user(k->sa_flags, &oact->sa_flags); #if !defined(TARGET_MIPS) - oact->sa_restorer = tswapal(k->sa_restorer); + __put_user(k->sa_restorer, &oact->sa_restorer); #endif + /* Not swapped. */ oact->sa_mask = k->sa_mask; } if (act) { /* FIXME: This is not threadsafe. */ - k->_sa_handler = tswapal(act->_sa_handler); -#if defined(TARGET_MIPS) || defined (TARGET_ALPHA) - k->sa_flags = bswap32(act->sa_flags); -#else - k->sa_flags = tswapal(act->sa_flags); -#endif + __get_user(k->_sa_handler, &act->_sa_handler); + __get_user(k->sa_flags, &act->sa_flags); #if !defined(TARGET_MIPS) - k->sa_restorer = tswapal(act->sa_restorer); + __get_user(k->sa_restorer, &act->sa_restorer); #endif + /* To be swapped in target_to_host_sigset. */ k->sa_mask = act->sa_mask; /* we update the host linux signal state */ diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index d4589e7906..f8f553915d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -544,7 +544,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, struct target_old_sigaction { abi_ulong _sa_handler; abi_ulong sa_mask; - abi_ulong sa_flags; + int32_t sa_flags; }; struct target_rt_sigaction { |