From: VMware, Inc <> Date: Thu, 18 Nov 2010 22:40:48 +0000 (-0800) Subject: Prohibit use of Atomic_Read64() and Atomic_Write64() on misaligned vars. X-Git-Tag: 2010.11.17-327185~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e14efb67b0f1420e373d6b546ed971eb2e2d24e2;p=thirdparty%2Fopen-vm-tools.git Prohibit use of Atomic_Read64() and Atomic_Write64() on misaligned vars. This is necessary since the functions do not provide any atomicity guarantees in the misaligned case. Add new functions, Atomic_ReadUnaligned64() and Atomic_WriteUnaligned64(), and use these instead. For the time being this change applies just to the VMM. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/lib/include/vm_atomic.h b/open-vm-tools/lib/include/vm_atomic.h index dbaafd687..a8615fa9f 100644 --- a/open-vm-tools/lib/include/vm_atomic.h +++ b/open-vm-tools/lib/include/vm_atomic.h @@ -1780,10 +1780,11 @@ Atomic_Read64(Atomic_uint64 const *var) // IN #elif defined(__GNUC__) && defined(__x86_64__) uint64 value; +#ifdef VMM + ASSERT((uintptr_t)var % 8 == 0); +#endif /* - * We have no evidence that suggests GCC will split this read into - * two move instructions. However, we prefer to be defensive in - * light of errors seen in Atomic_Write64. + * Use asm to ensure we emit a single load. */ __asm__ __volatile__( "movq %1, %0" @@ -1838,6 +1839,35 @@ Atomic_Read64(Atomic_uint64 const *var) // IN } +/* + *---------------------------------------------------------------------- + * + * Atomic_ReadUnaligned64 -- + * + * Atomically read a 64 bit integer, possibly misaligned. + * This function can be *very* expensive, costing over 50 kcycles + * on Nehalem. + * + * Note that "var" needs to be writable, even though it will not + * be modified. + * + * Results: + * The value of the atomic variable. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +#if defined(__x86_64__) +static INLINE uint64 +Atomic_ReadUnaligned64(Atomic_uint64 const *var) +{ + return Atomic_ReadIfEqualWrite64((Atomic_uint64*)var, 0, 0); +} +#endif + + /* *---------------------------------------------------------------------- * @@ -2070,6 +2100,10 @@ Atomic_Write64(Atomic_uint64 *var, // IN { #if defined(__x86_64__) #if defined(__GNUC__) + +#ifdef VMM + ASSERT((uintptr_t)var % 8 == 0); +#endif /* * There is no move instruction for 64-bit immediate to memory, so unless * the immediate value fits in 32-bit (i.e. can be sign-extended), GCC