* [Qemu-devel] [PATCH 1/8] fdt: Use bswapN instead of bswap_N
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 2/8] bswap: Tidy base definitions of bswapN Richard Henderson
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Fixes the libfdt enabled build for hosts that have <machine/bswap.h>.
The code at the beginning of qemu/bswap.h is attempting to standardize
on bswapN. In the case of CONFIG_MACHINE_BSWAP_H, this is all we get.
In the case of CONFIG_BYTESWAP_H, we get bswap_N from the system header
and then wrap these with inline functions to get bswapN.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/libfdt_env.h | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 7938d73..3667d4c 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -22,15 +22,15 @@
#include "qemu/bswap.h"
#ifdef HOST_WORDS_BIGENDIAN
-#define fdt32_to_cpu(x) (x)
-#define cpu_to_fdt32(x) (x)
-#define fdt64_to_cpu(x) (x)
-#define cpu_to_fdt64(x) (x)
+#define fdt32_to_cpu(x) (x)
+#define cpu_to_fdt32(x) (x)
+#define fdt64_to_cpu(x) (x)
+#define cpu_to_fdt64(x) (x)
#else
-#define fdt32_to_cpu(x) (bswap_32((x)))
-#define cpu_to_fdt32(x) (bswap_32((x)))
-#define fdt64_to_cpu(x) (bswap_64((x)))
-#define cpu_to_fdt64(x) (bswap_64((x)))
+#define fdt32_to_cpu(x) bswap32(x)
+#define cpu_to_fdt32(x) bswap32(x)
+#define fdt64_to_cpu(x) bswap64(x)
+#define cpu_to_fdt64(x) bswap64(x)
#endif
#endif /* _LIBFDT_ENV_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/8] bswap: Tidy base definitions of bswapN
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 1/8] fdt: Use bswapN instead of bswap_N Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 3/8] bswap: Add host endian unaligned access functions Richard Henderson
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Move the bswap_N -> bswapN wrappers inside CONFIG_BYTESWAP_H.
Change the ultimate fallback defintions from macros to inline functions.
The proper types recieved by the function arguments means we can remove
unnecessary casts, making the code more readable.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/qemu/bswap.h | 72 ++++++++++++++++++++++------------------------------
1 file changed, 30 insertions(+), 42 deletions(-)
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 2006fcd..b2a8f94 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -7,48 +7,11 @@
#include "fpu/softfloat.h"
#ifdef CONFIG_MACHINE_BSWAP_H
-#include <sys/endian.h>
-#include <sys/types.h>
-#include <machine/bswap.h>
-#else
-
-#ifdef CONFIG_BYTESWAP_H
-#include <byteswap.h>
-#else
-
-#define bswap_16(x) \
-({ \
- uint16_t __x = (x); \
- ((uint16_t)( \
- (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
- (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
-})
-
-#define bswap_32(x) \
-({ \
- uint32_t __x = (x); \
- ((uint32_t)( \
- (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
- (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
- (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
- (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
-})
-
-#define bswap_64(x) \
-({ \
- uint64_t __x = (x); \
- ((uint64_t)( \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
- (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
-})
-
-#endif /* !CONFIG_BYTESWAP_H */
+# include <sys/endian.h>
+# include <sys/types.h>
+# include <machine/bswap.h>
+#elif defined(CONFIG_BYTESWAP_H)
+# include <byteswap.h>
static inline uint16_t bswap16(uint16_t x)
{
@@ -64,7 +27,32 @@ static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
+# else
+static inline uint16_t bswap16(uint16_t x)
+{
+ return (((x & 0x00ff) << 8) |
+ ((x & 0xff00) >> 8));
+}
+static inline uint32_t bswap32(uint32_t x)
+{
+ return (((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24));
+}
+
+static inline uint64_t bswap64(uint64_t x)
+{
+ return (((x & 0x00000000000000ffULL) << 56) |
+ ((x & 0x000000000000ff00ULL) << 40) |
+ ((x & 0x0000000000ff0000ULL) << 24) |
+ ((x & 0x00000000ff000000ULL) << 8) |
+ ((x & 0x000000ff00000000ULL) >> 8) |
+ ((x & 0x0000ff0000000000ULL) >> 24) |
+ ((x & 0x00ff000000000000ULL) >> 40) |
+ ((x & 0xff00000000000000ULL) >> 56));
+}
#endif /* ! CONFIG_MACHINE_BSWAP_H */
static inline void bswap16s(uint16_t *s)
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/8] bswap: Add host endian unaligned access functions
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 1/8] fdt: Use bswapN instead of bswap_N Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 2/8] bswap: Tidy base definitions of bswapN Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 4/8] bswap: Rewrite all ld<type>_<endian>_p functions Richard Henderson
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/qemu/bswap.h | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index b2a8f94..381554b 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -226,6 +226,8 @@ static inline uint32_t qemu_bswap_len(uint32_t value, int len)
return bswap32(value) >> (32 - 8 * len);
}
+/* Unions for reinterpreting between floats and integers. */
+
typedef union {
float32 f;
uint32_t l;
@@ -309,7 +311,7 @@ typedef union {
* q: 64 bits
*
* endian is:
- * (empty): 8 bit access
+ * (empty): host endian
* be : big endian
* le : little endian
*/
@@ -328,6 +330,53 @@ static inline void stb_p(void *ptr, int v)
*(uint8_t *)ptr = v;
}
+/* Any compiler worth its salt will turn these memcpy into native unaligned
+ operations. Thus we don't need to play games with packed attributes, or
+ inline byte-by-byte stores. */
+
+static inline int lduw_p(const void *ptr)
+{
+ uint16_t r;
+ memcpy(&r, ptr, sizeof(r));
+ return r;
+}
+
+static inline int ldsw_p(const void *ptr)
+{
+ int16_t r;
+ memcpy(&r, ptr, sizeof(r));
+ return r;
+}
+
+static inline void stw_p(void *ptr, uint16_t v)
+{
+ memcpy(ptr, &v, sizeof(v));
+}
+
+static inline int ldl_p(const void *ptr)
+{
+ int32_t r;
+ memcpy(&r, ptr, sizeof(r));
+ return r;
+}
+
+static inline void stl_p(void *ptr, uint32_t v)
+{
+ memcpy(ptr, &v, sizeof(v));
+}
+
+static inline uint64_t ldq_p(const void *ptr)
+{
+ uint64_t r;
+ memcpy(&r, ptr, sizeof(r));
+ return r;
+}
+
+static inline void stq_p(void *ptr, uint64_t v)
+{
+ memcpy(ptr, &v, sizeof(v));
+}
+
/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
kernel handles unaligned load/stores may give better results, but
it is a system wide setting : bad */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 4/8] bswap: Rewrite all ld<type>_<endian>_p functions
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (2 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 3/8] bswap: Add host endian unaligned access functions Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 5/8] bswap: Rewrite cpu_to_<endian><type>u with {ld, st}<type>_<endian>_p Richard Henderson
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Use the new host endian unaligned access functions instead of
open coding byte-by-byte references. Remove assembly special
cases for i386 and ppc -- we've now exposed the operation to
the compiler sufficiently for these to be optimized automatically.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/qemu/bswap.h | 300 ++++++---------------------------------------------
1 file changed, 30 insertions(+), 270 deletions(-)
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 381554b..68cda6a 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -215,11 +215,6 @@ static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
#define leul_to_cpu(v) (v)
#endif
-#undef le_bswap
-#undef be_bswap
-#undef le_bswaps
-#undef be_bswaps
-
/* len must be one of 1, 2, 4 */
static inline uint32_t qemu_bswap_len(uint32_t value, int len)
{
@@ -377,115 +372,61 @@ static inline void stq_p(void *ptr, uint64_t v)
memcpy(ptr, &v, sizeof(v));
}
-/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
- kernel handles unaligned load/stores may give better results, but
- it is a system wide setting : bad */
-#if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
-/* conservative code for little endian unaligned accesses */
static inline int lduw_le_p(const void *ptr)
{
-#ifdef _ARCH_PPC
- int val;
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return val;
-#else
- const uint8_t *p = ptr;
- return p[0] | (p[1] << 8);
-#endif
+ return (uint16_t)le_bswap(lduw_p(ptr), 16);
}
static inline int ldsw_le_p(const void *ptr)
{
-#ifdef _ARCH_PPC
- int val;
- __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return (int16_t)val;
-#else
- const uint8_t *p = ptr;
- return (int16_t)(p[0] | (p[1] << 8));
-#endif
+ return (int16_t)le_bswap(lduw_p(ptr), 16);
}
static inline int ldl_le_p(const void *ptr)
{
-#ifdef _ARCH_PPC
- int val;
- __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
- return val;
-#else
- const uint8_t *p = ptr;
- return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
-#endif
+ return le_bswap(ldl_p(ptr), 32);
}
static inline uint64_t ldq_le_p(const void *ptr)
{
- const uint8_t *p = ptr;
- uint32_t v1, v2;
- v1 = ldl_le_p(p);
- v2 = ldl_le_p(p + 4);
- return v1 | ((uint64_t)v2 << 32);
+ return le_bswap(ldq_p(ptr), 64);
}
static inline void stw_le_p(void *ptr, int v)
{
-#ifdef _ARCH_PPC
- __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
-#else
- uint8_t *p = ptr;
- p[0] = v;
- p[1] = v >> 8;
-#endif
+ stw_p(ptr, le_bswap(v, 16));
}
static inline void stl_le_p(void *ptr, int v)
{
-#ifdef _ARCH_PPC
- __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
-#else
- uint8_t *p = ptr;
- p[0] = v;
- p[1] = v >> 8;
- p[2] = v >> 16;
- p[3] = v >> 24;
-#endif
+ stl_p(ptr, le_bswap(v, 32));
}
static inline void stq_le_p(void *ptr, uint64_t v)
{
- uint8_t *p = ptr;
- stl_le_p(p, (uint32_t)v);
- stl_le_p(p + 4, v >> 32);
+ stq_p(ptr, le_bswap(v, 64));
}
/* float access */
static inline float32 ldfl_le_p(const void *ptr)
{
- union {
- float32 f;
- uint32_t i;
- } u;
- u.i = ldl_le_p(ptr);
+ CPU_FloatU u;
+ u.l = ldl_le_p(ptr);
return u.f;
}
static inline void stfl_le_p(void *ptr, float32 v)
{
- union {
- float32 f;
- uint32_t i;
- } u;
+ CPU_FloatU u;
u.f = v;
- stl_le_p(ptr, u.i);
+ stl_le_p(ptr, u.l);
}
static inline float64 ldfq_le_p(const void *ptr)
{
CPU_DoubleU u;
- u.l.lower = ldl_le_p(ptr);
- u.l.upper = ldl_le_p(ptr + 4);
+ u.ll = ldq_le_p(ptr);
return u.d;
}
@@ -493,188 +434,64 @@ static inline void stfq_le_p(void *ptr, float64 v)
{
CPU_DoubleU u;
u.d = v;
- stl_le_p(ptr, u.l.lower);
- stl_le_p(ptr + 4, u.l.upper);
+ stq_le_p(ptr, u.ll);
}
-#else
-
-static inline int lduw_le_p(const void *ptr)
-{
- return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_le_p(const void *ptr)
-{
- return *(int16_t *)ptr;
-}
-
-static inline int ldl_le_p(const void *ptr)
-{
- return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_le_p(const void *ptr)
-{
- return *(uint64_t *)ptr;
-}
-
-static inline void stw_le_p(void *ptr, int v)
-{
- *(uint16_t *)ptr = v;
-}
-
-static inline void stl_le_p(void *ptr, int v)
-{
- *(uint32_t *)ptr = v;
-}
-
-static inline void stq_le_p(void *ptr, uint64_t v)
-{
- *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_le_p(const void *ptr)
-{
- return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_le_p(const void *ptr)
-{
- return *(float64 *)ptr;
-}
-
-static inline void stfl_le_p(void *ptr, float32 v)
-{
- *(float32 *)ptr = v;
-}
-
-static inline void stfq_le_p(void *ptr, float64 v)
-{
- *(float64 *)ptr = v;
-}
-#endif
-
-#if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
-
static inline int lduw_be_p(const void *ptr)
{
-#if defined(__i386__)
- int val;
- asm volatile ("movzwl %1, %0\n"
- "xchgb %b0, %h0\n"
- : "=q" (val)
- : "m" (*(uint16_t *)ptr));
- return val;
-#else
- const uint8_t *b = ptr;
- return ((b[0] << 8) | b[1]);
-#endif
+ return (uint16_t)be_bswap(lduw_p(ptr), 16);
}
static inline int ldsw_be_p(const void *ptr)
{
-#if defined(__i386__)
- int val;
- asm volatile ("movzwl %1, %0\n"
- "xchgb %b0, %h0\n"
- : "=q" (val)
- : "m" (*(uint16_t *)ptr));
- return (int16_t)val;
-#else
- const uint8_t *b = ptr;
- return (int16_t)((b[0] << 8) | b[1]);
-#endif
+ return (int16_t)be_bswap(lduw_p(ptr), 16);
}
static inline int ldl_be_p(const void *ptr)
{
-#if defined(__i386__) || defined(__x86_64__)
- int val;
- asm volatile ("movl %1, %0\n"
- "bswap %0\n"
- : "=r" (val)
- : "m" (*(uint32_t *)ptr));
- return val;
-#else
- const uint8_t *b = ptr;
- return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
-#endif
+ return be_bswap(ldl_p(ptr), 32);
}
static inline uint64_t ldq_be_p(const void *ptr)
{
- uint32_t a,b;
- a = ldl_be_p(ptr);
- b = ldl_be_p((uint8_t *)ptr + 4);
- return (((uint64_t)a<<32)|b);
+ return be_bswap(ldq_p(ptr), 64);
}
static inline void stw_be_p(void *ptr, int v)
{
-#if defined(__i386__)
- asm volatile ("xchgb %b0, %h0\n"
- "movw %w0, %1\n"
- : "=q" (v)
- : "m" (*(uint16_t *)ptr), "0" (v));
-#else
- uint8_t *d = (uint8_t *) ptr;
- d[0] = v >> 8;
- d[1] = v;
-#endif
+ stw_p(ptr, be_bswap(v, 16));
}
static inline void stl_be_p(void *ptr, int v)
{
-#if defined(__i386__) || defined(__x86_64__)
- asm volatile ("bswap %0\n"
- "movl %0, %1\n"
- : "=r" (v)
- : "m" (*(uint32_t *)ptr), "0" (v));
-#else
- uint8_t *d = (uint8_t *) ptr;
- d[0] = v >> 24;
- d[1] = v >> 16;
- d[2] = v >> 8;
- d[3] = v;
-#endif
+ stl_p(ptr, be_bswap(v, 32));
}
static inline void stq_be_p(void *ptr, uint64_t v)
{
- stl_be_p(ptr, v >> 32);
- stl_be_p((uint8_t *)ptr + 4, v);
+ stq_p(ptr, be_bswap(v, 64));
}
/* float access */
static inline float32 ldfl_be_p(const void *ptr)
{
- union {
- float32 f;
- uint32_t i;
- } u;
- u.i = ldl_be_p(ptr);
+ CPU_FloatU u;
+ u.l = ldl_be_p(ptr);
return u.f;
}
static inline void stfl_be_p(void *ptr, float32 v)
{
- union {
- float32 f;
- uint32_t i;
- } u;
+ CPU_FloatU u;
u.f = v;
- stl_be_p(ptr, u.i);
+ stl_be_p(ptr, u.l);
}
static inline float64 ldfq_be_p(const void *ptr)
{
CPU_DoubleU u;
- u.l.upper = ldl_be_p(ptr);
- u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
+ u.ll = ldq_be_p(ptr);
return u.d;
}
@@ -682,69 +499,12 @@ static inline void stfq_be_p(void *ptr, float64 v)
{
CPU_DoubleU u;
u.d = v;
- stl_be_p(ptr, u.l.upper);
- stl_be_p((uint8_t *)ptr + 4, u.l.lower);
-}
-
-#else
-
-static inline int lduw_be_p(const void *ptr)
-{
- return *(uint16_t *)ptr;
-}
-
-static inline int ldsw_be_p(const void *ptr)
-{
- return *(int16_t *)ptr;
-}
-
-static inline int ldl_be_p(const void *ptr)
-{
- return *(uint32_t *)ptr;
-}
-
-static inline uint64_t ldq_be_p(const void *ptr)
-{
- return *(uint64_t *)ptr;
-}
-
-static inline void stw_be_p(void *ptr, int v)
-{
- *(uint16_t *)ptr = v;
-}
-
-static inline void stl_be_p(void *ptr, int v)
-{
- *(uint32_t *)ptr = v;
-}
-
-static inline void stq_be_p(void *ptr, uint64_t v)
-{
- *(uint64_t *)ptr = v;
-}
-
-/* float access */
-
-static inline float32 ldfl_be_p(const void *ptr)
-{
- return *(float32 *)ptr;
-}
-
-static inline float64 ldfq_be_p(const void *ptr)
-{
- return *(float64 *)ptr;
-}
-
-static inline void stfl_be_p(void *ptr, float32 v)
-{
- *(float32 *)ptr = v;
-}
-
-static inline void stfq_be_p(void *ptr, float64 v)
-{
- *(float64 *)ptr = v;
+ stq_be_p(ptr, u.ll);
}
-#endif
+#undef le_bswap
+#undef be_bswap
+#undef le_bswaps
+#undef be_bswaps
#endif /* BSWAP_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 5/8] bswap: Rewrite cpu_to_<endian><type>u with {ld, st}<type>_<endian>_p
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (3 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 4/8] bswap: Rewrite all ld<type>_<endian>_p functions Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 6/8] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
We've now optimized the ld/st versions; reuse that for the "legacy"
versions. Always use inlines so that we get the type checking that
we expect.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
include/qemu/bswap.h | 147 +++++++++++++++++++--------------------------------
1 file changed, 53 insertions(+), 94 deletions(-)
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 68cda6a..be9b035 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -121,100 +121,6 @@ CPU_CONVERT(le, 16, uint16_t)
CPU_CONVERT(le, 32, uint32_t)
CPU_CONVERT(le, 64, uint64_t)
-/* unaligned versions (optimized for frequent unaligned accesses)*/
-
-#if defined(__i386__) || defined(_ARCH_PPC)
-
-#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
-#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
-#define le16_to_cpupu(p) le16_to_cpup(p)
-#define le32_to_cpupu(p) le32_to_cpup(p)
-#define be32_to_cpupu(p) be32_to_cpup(p)
-
-#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
-#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
-#define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
-
-#else
-
-static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
-{
- uint8_t *p1 = (uint8_t *)p;
-
- p1[0] = v & 0xff;
- p1[1] = v >> 8;
-}
-
-static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
-{
- uint8_t *p1 = (uint8_t *)p;
-
- p1[0] = v & 0xff;
- p1[1] = v >> 8;
- p1[2] = v >> 16;
- p1[3] = v >> 24;
-}
-
-static inline uint16_t le16_to_cpupu(const uint16_t *p)
-{
- const uint8_t *p1 = (const uint8_t *)p;
- return p1[0] | (p1[1] << 8);
-}
-
-static inline uint32_t le32_to_cpupu(const uint32_t *p)
-{
- const uint8_t *p1 = (const uint8_t *)p;
- return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
-}
-
-static inline uint32_t be32_to_cpupu(const uint32_t *p)
-{
- const uint8_t *p1 = (const uint8_t *)p;
- return p1[3] | (p1[2] << 8) | (p1[1] << 16) | (p1[0] << 24);
-}
-
-static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
-{
- uint8_t *p1 = (uint8_t *)p;
-
- p1[0] = v >> 8;
- p1[1] = v & 0xff;
-}
-
-static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
-{
- uint8_t *p1 = (uint8_t *)p;
-
- p1[0] = v >> 24;
- p1[1] = v >> 16;
- p1[2] = v >> 8;
- p1[3] = v & 0xff;
-}
-
-static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
-{
- uint8_t *p1 = (uint8_t *)p;
-
- p1[0] = v >> 56;
- p1[1] = v >> 48;
- p1[2] = v >> 40;
- p1[3] = v >> 32;
- p1[4] = v >> 24;
- p1[5] = v >> 16;
- p1[6] = v >> 8;
- p1[7] = v & 0xff;
-}
-
-#endif
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define cpu_to_32wu cpu_to_be32wu
-#define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
-#else
-#define cpu_to_32wu cpu_to_le32wu
-#define leul_to_cpu(v) (v)
-#endif
-
/* len must be one of 1, 2, 4 */
static inline uint32_t qemu_bswap_len(uint32_t value, int len)
{
@@ -310,6 +216,7 @@ typedef union {
* be : big endian
* le : little endian
*/
+
static inline int ldub_p(const void *ptr)
{
return *(uint8_t *)ptr;
@@ -502,6 +409,58 @@ static inline void stfq_be_p(void *ptr, float64 v)
stq_be_p(ptr, u.ll);
}
+/* Legacy unaligned versions. Note that we never had a complete set. */
+
+static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
+{
+ stw_le_p(p, v);
+}
+
+static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
+{
+ stl_le_p(p, v);
+}
+
+static inline uint16_t le16_to_cpupu(const uint16_t *p)
+{
+ return lduw_le_p(p);
+}
+
+static inline uint32_t le32_to_cpupu(const uint32_t *p)
+{
+ return ldl_le_p(p);
+}
+
+static inline uint32_t be32_to_cpupu(const uint32_t *p)
+{
+ return ldl_be_p(p);
+}
+
+static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
+{
+ stw_be_p(p, v);
+}
+
+static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
+{
+ stl_be_p(p, v);
+}
+
+static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
+{
+ stq_be_p(p, v);
+}
+
+static inline void cpu_to_32wu(uint32_t *p, uint32_t v)
+{
+ stl_p(p, v);
+}
+
+static inline unsigned long leul_to_cpu(unsigned long v)
+{
+ return le_bswap(v, HOST_LONG_BITS);
+}
+
#undef le_bswap
#undef be_bswap
#undef le_bswaps
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 6/8] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (4 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 5/8] bswap: Rewrite cpu_to_<endian><type>u with {ld, st}<type>_<endian>_p Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 7/8] alpha-linux-user: Fix sigaction Richard Henderson
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
The previous formuation with multiple assignments to __typeof(*hptr) falls
down when hptr is qualified const. E.g. with const struct S *p, p->f is
also qualified const.
With this formulation, there's no assignment to any local variable.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/qemu.h | 63 +++++++++++++++++++++++++++++--------------------------
1 file changed, 33 insertions(+), 30 deletions(-)
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 8a3538c..31a220a 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,
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 7/8] alpha-linux-user: Fix sigaction
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (5 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 6/8] linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-05 0:39 ` [Qemu-devel] [PATCH 8/8] user: Consider symbolic links as possible directories Richard Henderson
2013-01-12 16:07 ` [Qemu-devel] [PATCH v2 0/8] linux-user fixes Blue Swirl
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Unconditional bswap replaced by __get_user/__put_user.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/signal.c | 22 ++++++++--------------
linux-user/syscall_defs.h | 2 +-
2 files changed, 9 insertions(+), 15 deletions(-)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 95e2ffa..407619a 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 d4589e7..f8f5539 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 {
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 8/8] user: Consider symbolic links as possible directories
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (6 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 7/8] alpha-linux-user: Fix sigaction Richard Henderson
@ 2013-01-05 0:39 ` Richard Henderson
2013-01-12 16:07 ` [Qemu-devel] [PATCH v2 0/8] linux-user fixes Blue Swirl
8 siblings, 0 replies; 10+ messages in thread
From: Richard Henderson @ 2013-01-05 0:39 UTC (permalink / raw)
To: qemu-devel; +Cc: Blue Swirl, Riku Voipio
Commit 2296f194dfde4c0a54f249d3fdb8c8ca21dc611b reduced the number
of syscalls performed during user emulation startup, but failed to
consider the use of symbolic links in creating directory structures.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
path.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/path.c b/path.c
index ef3f277..4c5b0f6 100644
--- a/path.c
+++ b/path.c
@@ -58,9 +58,10 @@ static struct pathelem *new_entry(const char *root,
#define streq(a,b) (strcmp((a), (b)) == 0)
/* Not all systems provide this feature */
-#if defined(DT_DIR) && defined(DT_UNKNOWN)
+#if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK)
# define dirent_type(dirent) ((dirent)->d_type)
-# define is_dir_maybe(type) ((type) == DT_DIR || (type) == DT_UNKNOWN)
+# define is_dir_maybe(type) \
+ ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK)
#else
# define dirent_type(dirent) (1)
# define is_dir_maybe(type) (type)
--
1.7.11.7
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 0/8] linux-user fixes
2013-01-05 0:39 [Qemu-devel] [PATCH v2 0/8] linux-user fixes Richard Henderson
` (7 preceding siblings ...)
2013-01-05 0:39 ` [Qemu-devel] [PATCH 8/8] user: Consider symbolic links as possible directories Richard Henderson
@ 2013-01-12 16:07 ` Blue Swirl
8 siblings, 0 replies; 10+ messages in thread
From: Blue Swirl @ 2013-01-12 16:07 UTC (permalink / raw)
To: Richard Henderson; +Cc: Riku Voipio, qemu-devel
Thanks, applied all.
On Sat, Jan 5, 2013 at 12:39 AM, Richard Henderson <rth@twiddle.net> wrote:
> Version 1 was way back in October,
>
> http://lists.gnu.org/archive/html/qemu-devel/2012-10/msg02854.html
>
> wherein Blue asked me to re-do the unaligned access function part of
> the patch. I've now done that, as patch 3 of this series.
>
> But having a look at <qemu/bswap.h> was frought with ugliness, and
> I've now cleaned up some of that as well.
>
>
> r~
>
>
> Richard Henderson (8):
> fdt: Use bswapN instead of bswap_N
> bswap: Tidy base definitions of bswapN
> bswap: Add host endian unaligned access functions
> bswap: Rewrite all ld<type>_<endian>_p functions
> bswap: Rewrite cpu_to_<endian><type>u with {ld,st}<type>_<endian>_p
> linux-user: Rewrite __get_user/__put_user with __builtin_choose_expr
> alpha-linux-user: Fix sigaction
> user: Consider symbolic links as possible directories
>
> include/libfdt_env.h | 16 +-
> include/qemu/bswap.h | 480 ++++++++++++----------------------------------
> linux-user/qemu.h | 63 +++---
> linux-user/signal.c | 22 +--
> linux-user/syscall_defs.h | 2 +-
> path.c | 5 +-
> 6 files changed, 171 insertions(+), 417 deletions(-)
>
> --
> 1.7.11.7
>
^ permalink raw reply [flat|nested] 10+ messages in thread