From 297916273244b8877631027b68a8911b737bb47b Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Tue, 8 Dec 2015 21:54:39 +0000 Subject: [PATCH] [PPC64, TSAN] LLVM basic enablement of thread sanitizer for PPC64 (BE and LE) This patch is by Simone Atzeni with portions by Adhemerval Zanella. This contains the LLVM patches to enable the thread sanitizer for PPC64, both big- and little-endian. Two different virtual memory sizes are supported: Old kernels use a 44-bit address space, while newer kernels require a 46-bit address space. There are two companion patches that will be added shortly. There is a Clang patch to actually turn on the use of the thread sanitizer for PPC64. There is also a patch that I wrote to provide interceptor support for setjmp/longjmp on PPC64. Patch discussion at reviews.llvm.org/D12841. llvm-svn: 255057 --- compiler-rt/cmake/config-ix.cmake | 2 +- .../lib/sanitizer_common/sanitizer_linux.cc | 85 +++++++++++++- compiler-rt/lib/sanitizer_common/sanitizer_linux.h | 3 +- .../sanitizer_stoptheworld_linux_libcdep.cc | 6 +- compiler-rt/lib/tsan/rtl/tsan_interceptors.cc | 6 +- compiler-rt/lib/tsan/rtl/tsan_platform.h | 127 +++++++++++++++++++++ compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc | 8 ++ compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc | 12 ++ compiler-rt/lib/tsan/rtl/tsan_rtl.h | 2 +- compiler-rt/test/tsan/CMakeLists.txt | 2 +- compiler-rt/test/tsan/cond_cancel.c | 8 ++ compiler-rt/test/tsan/java_race_pc.cc | 4 + compiler-rt/test/tsan/map32bit.cc | 1 + compiler-rt/test/tsan/mmap_large.cc | 2 + compiler-rt/test/tsan/race_on_mutex.c | 3 + compiler-rt/test/tsan/signal_errno.cc | 4 + compiler-rt/test/tsan/signal_longjmp.cc | 4 + compiler-rt/test/tsan/test.h | 2 +- 18 files changed, 270 insertions(+), 11 deletions(-) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 50e59c79..f953704 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -278,7 +278,7 @@ set(ALL_LSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC64} ${MIPS32} ${MIPS64}) -set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64}) +set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64}) set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64} ${PPC64}) set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64}) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 2e685ac..9239d1e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -89,7 +89,8 @@ const int FUTEX_WAKE = 1; // Are we using 32-bit or 64-bit Linux syscalls? // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 // but it still needs to use 64-bit syscalls. -#if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64) +#if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \ + SANITIZER_WORDSIZE == 64) # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 #else # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 @@ -983,6 +984,88 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, : "x30", "memory"); return res; } +#elif defined(__powerpc64__) +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + long long res; +/* Stack frame offsets. */ +#if _CALL_ELF != 2 +#define FRAME_MIN_SIZE 112 +#define FRAME_TOC_SAVE 40 +#else +#define FRAME_MIN_SIZE 32 +#define FRAME_TOC_SAVE 24 +#endif + if (!fn || !child_stack) + return -EINVAL; + CHECK_EQ(0, (uptr)child_stack % 16); + child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); + ((unsigned long long *)child_stack)[0] = (uptr)fn; + ((unsigned long long *)child_stack)[1] = (uptr)arg; + + register int (*__fn)(void *) __asm__("r3") = fn; + register void *__cstack __asm__("r4") = child_stack; + register int __flags __asm__("r5") = flags; + register void * __arg __asm__("r6") = arg; + register int * __ptidptr __asm__("r7") = parent_tidptr; + register void * __newtls __asm__("r8") = newtls; + register int * __ctidptr __asm__("r9") = child_tidptr; + + __asm__ __volatile__( + /* fn, arg, child_stack are saved acrVoss the syscall */ + "mr 28, %5\n\t" + "mr 29, %6\n\t" + "mr 27, %8\n\t" + + /* syscall + r3 == flags + r4 == child_stack + r5 == parent_tidptr + r6 == newtls + r7 == child_tidptr */ + "mr 3, %7\n\t" + "mr 5, %9\n\t" + "mr 6, %10\n\t" + "mr 7, %11\n\t" + "li 0, %3\n\t" + "sc\n\t" + + /* Test if syscall was successful */ + "cmpdi cr1, 3, 0\n\t" + "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" + "bne- cr1, 1f\n\t" + + /* Do the function call */ + "std 2, %13(1)\n\t" +#if _CALL_ELF != 2 + "ld 0, 0(28)\n\t" + "ld 2, 8(28)\n\t" + "mtctr 0\n\t" +#else + "mr 12, 28\n\t" + "mtctr 12\n\t" +#endif + "mr 3, 27\n\t" + "bctrl\n\t" + "ld 2, %13(1)\n\t" + + /* Call _exit(r3) */ + "li 0, %4\n\t" + "sc\n\t" + + /* Return to parent */ + "1:\n\t" + "mr %0, 3\n\t" + : "=r" (res) + : "0" (-1), "i" (EINVAL), + "i" (__NR_clone), "i" (__NR_exit), + "r" (__fn), "r" (__cstack), "r" (__flags), + "r" (__arg), "r" (__ptidptr), "r" (__newtls), + "r" (__ctidptr), "i" (FRAME_MIN_SIZE), "i" (FRAME_TOC_SAVE) + : "cr0", "cr1", "memory", "ctr", + "r0", "r29", "r27", "r28"); + return res; +} #endif // defined(__x86_64__) && SANITIZER_LINUX #if SANITIZER_ANDROID diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index d996f8c..77bfbd1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -44,7 +44,8 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); // internal_sigaction instead. int internal_sigaction_norestorer(int signum, const void *act, void *oldact); void internal_sigdelset(__sanitizer_sigset_t *set, int signum); -#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) \ + || defined(__powerpc64__) uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc index 6fd6312..2376ee5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc @@ -15,7 +15,7 @@ #include "sanitizer_platform.h" #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \ - defined(__aarch64__)) + defined(__aarch64__) || defined(__powerpc64__)) #include "sanitizer_stoptheworld.h" @@ -511,5 +511,5 @@ uptr SuspendedThreadsList::RegisterCount() { } } // namespace __sanitizer -#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) - // || defined(__aarch64__) +#endif // SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) + // || defined(__aarch64__) || defined(__powerpc64__) diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc index 57a676f..bc31075 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc @@ -79,9 +79,11 @@ struct ucontext_t { }; #endif -#if defined(__x86_64__) || defined(__mips__) +#if defined(__x86_64__) || defined(__mips__) \ + || (defined(__powerpc64__) && defined(__BIG_ENDIAN__)) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" -#elif defined(__aarch64__) +#elif defined(__aarch64__) || (defined(__powerpc64__) \ + && defined(__LITTLE_ENDIAN__)) #define PTHREAD_ABI_BASE "GLIBC_2.17" #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 254ea79..b6bd8b0 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -161,6 +161,79 @@ struct Mapping42 { // Indicates the runtime will define the memory regions at runtime. #define TSAN_RUNTIME_VMA 1 +#elif defined(__powerpc64__) +// PPC64 supports multiple VMA which leads to multiple address transformation +// functions. To support these multiple VMAS transformations and mappings TSAN +// runtime for PPC64 uses an external memory read (vmaSize) to select which +// mapping to use. Although slower, it make a same instrumented binary run on +// multiple kernels. + +/* +C/C++ on linux/powerpc64 (44-bit VMA) +0000 0000 0100 - 0001 0000 0000: main binary +0001 0000 0000 - 0001 0000 0000: - +0001 0000 0000 - 0b00 0000 0000: shadow +0b00 0000 0000 - 0b00 0000 0000: - +0b00 0000 0000 - 0d00 0000 0000: metainfo (memory blocks and sync objects) +0d00 0000 0000 - 0d00 0000 0000: - +0d00 0000 0000 - 0f00 0000 0000: traces +0f00 0000 0000 - 0f00 0000 0000: - +0f00 0000 0000 - 0f50 0000 0000: heap +0f50 0000 0000 - 0f60 0000 0000: - +0f60 0000 0000 - 1000 0000 0000: modules and main thread stack +*/ +struct Mapping44 { + static const uptr kMetaShadowBeg = 0x0b0000000000ull; + static const uptr kMetaShadowEnd = 0x0d0000000000ull; + static const uptr kTraceMemBeg = 0x0d0000000000ull; + static const uptr kTraceMemEnd = 0x0f0000000000ull; + static const uptr kShadowBeg = 0x000100000000ull; + static const uptr kShadowEnd = 0x0b0000000000ull; + static const uptr kLoAppMemBeg = 0x000000000100ull; + static const uptr kLoAppMemEnd = 0x000100000000ull; + static const uptr kHeapMemBeg = 0x0f0000000000ull; + static const uptr kHeapMemEnd = 0x0f5000000000ull; + static const uptr kHiAppMemBeg = 0x0f6000000000ull; + static const uptr kHiAppMemEnd = 0x100000000000ull; // 44 bits + static const uptr kAppMemMsk = 0x0f0000000000ull; + static const uptr kAppMemXor = 0x002100000000ull; + static const uptr kVdsoBeg = 0x3c0000000000000ull; +}; + +/* +C/C++ on linux/powerpc64 (46-bit VMA) +0000 0000 1000 - 0100 0000 0000: main binary +0100 0000 0000 - 0200 0000 0000: - +0100 0000 0000 - 1000 0000 0000: shadow +1000 0000 0000 - 1000 0000 0000: - +1000 0000 0000 - 2000 0000 0000: metainfo (memory blocks and sync objects) +2000 0000 0000 - 2000 0000 0000: - +2000 0000 0000 - 2200 0000 0000: traces +2200 0000 0000 - 3d00 0000 0000: - +3d00 0000 0000 - 3e00 0000 0000: heap +3e00 0000 0000 - 3e80 0000 0000: - +3e80 0000 0000 - 4000 0000 0000: modules and main thread stack +*/ +struct Mapping46 { + static const uptr kMetaShadowBeg = 0x100000000000ull; + static const uptr kMetaShadowEnd = 0x200000000000ull; + static const uptr kTraceMemBeg = 0x200000000000ull; + static const uptr kTraceMemEnd = 0x220000000000ull; + static const uptr kShadowBeg = 0x010000000000ull; + static const uptr kShadowEnd = 0x100000000000ull; + static const uptr kHeapMemBeg = 0x3d0000000000ull; + static const uptr kHeapMemEnd = 0x3e0000000000ull; + static const uptr kLoAppMemBeg = 0x000000001000ull; + static const uptr kLoAppMemEnd = 0x010000000000ull; + static const uptr kHiAppMemBeg = 0x3e8000000000ull; + static const uptr kHiAppMemEnd = 0x400000000000ull; // 46 bits + static const uptr kAppMemMsk = 0x3c0000000000ull; + static const uptr kAppMemXor = 0x020000000000ull; + static const uptr kVdsoBeg = 0x7800000000000000ull; +}; + +// Indicates the runtime will define the memory regions at runtime. +#define TSAN_RUNTIME_VMA 1 #endif #elif defined(SANITIZER_GO) && !SANITIZER_WINDOWS @@ -274,6 +347,12 @@ uptr MappingArchImpl(void) { else return MappingImpl(); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MappingImpl(); + else + return MappingImpl(); + DCHECK(0); #else return MappingImpl(); #endif @@ -399,6 +478,12 @@ bool IsAppMem(uptr mem) { else return IsAppMemImpl(mem); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsAppMemImpl(mem); + else + return IsAppMemImpl(mem); + DCHECK(0); #else return IsAppMemImpl(mem); #endif @@ -418,6 +503,12 @@ bool IsShadowMem(uptr mem) { else return IsShadowMemImpl(mem); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsShadowMemImpl(mem); + else + return IsShadowMemImpl(mem); + DCHECK(0); #else return IsShadowMemImpl(mem); #endif @@ -437,6 +528,12 @@ bool IsMetaMem(uptr mem) { else return IsMetaMemImpl(mem); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return IsMetaMemImpl(mem); + else + return IsMetaMemImpl(mem); + DCHECK(0); #else return IsMetaMemImpl(mem); #endif @@ -462,6 +559,12 @@ uptr MemToShadow(uptr x) { else return MemToShadowImpl(x); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MemToShadowImpl(x); + else + return MemToShadowImpl(x); + DCHECK(0); #else return MemToShadowImpl(x); #endif @@ -489,6 +592,12 @@ u32 *MemToMeta(uptr x) { else return MemToMetaImpl(x); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return MemToMetaImpl(x); + else + return MemToMetaImpl(x); + DCHECK(0); #else return MemToMetaImpl(x); #endif @@ -522,6 +631,12 @@ uptr ShadowToMem(uptr s) { else return ShadowToMemImpl(s); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return ShadowToMemImpl(s); + else + return ShadowToMemImpl(s); + DCHECK(0); #else return ShadowToMemImpl(s); #endif @@ -549,6 +664,12 @@ uptr GetThreadTrace(int tid) { else return GetThreadTraceImpl(tid); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return GetThreadTraceImpl(tid); + else + return GetThreadTraceImpl(tid); + DCHECK(0); #else return GetThreadTraceImpl(tid); #endif @@ -571,6 +692,12 @@ uptr GetThreadTraceHeader(int tid) { else return GetThreadTraceHeaderImpl(tid); DCHECK(0); +#elif defined(__powerpc64__) + if (vmaSize == 44) + return GetThreadTraceHeaderImpl(tid); + else + return GetThreadTraceHeaderImpl(tid); + DCHECK(0); #else return GetThreadTraceHeaderImpl(tid); #endif diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index a635f4e..ff7a4b9 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -244,11 +244,19 @@ void InitializePlatformEarly() { #ifdef TSAN_RUNTIME_VMA vmaSize = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); +#if defined(__aarch64__) if (vmaSize != 39 && vmaSize != 42) { Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); Printf("FATAL: Found %d - Supported 39 and 42\n", vmaSize); Die(); } +#elif defined(__powerpc64__) + if (vmaSize != 44 && vmaSize != 46) { + Printf("FATAL: ThreadSanitizer: unsupported VMA range\n"); + Printf("FATAL: Found %d - Supported 42 and 46\n", vmaSize); + Die(); + } +#endif #endif } diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc index 968dd40..7c9acf5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc @@ -58,6 +58,18 @@ void InitializeShadowMemory() { } else { DCHECK(0); } +#elif defined(__powerpc64__) + uptr kMadviseRangeBeg = 0; + uptr kMadviseRangeSize = 0; + if (vmaSize == 44) { + kMadviseRangeBeg = 0x0f60000000ull; + kMadviseRangeSize = 0x0010000000ull; + } else if (vmaSize == 46) { + kMadviseRangeBeg = 0x3f0000000000ull; + kMadviseRangeSize = 0x010000000000ull; + } else { + DCHECK(0); + } #endif NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), kMadviseRangeSize * kShadowMultiplier); diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index a709b4f..04104b1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -54,7 +54,7 @@ namespace __tsan { #ifndef SANITIZER_GO struct MapUnmapCallback; -#if defined(__mips64) || defined(__aarch64__) +#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) static const uptr kAllocatorSpace = 0; static const uptr kAllocatorSize = SANITIZER_MMAP_RANGE_SIZE; static const uptr kAllocatorRegionSizeLog = 20; diff --git a/compiler-rt/test/tsan/CMakeLists.txt b/compiler-rt/test/tsan/CMakeLists.txt index d4fed1d..01e8038 100644 --- a/compiler-rt/test/tsan/CMakeLists.txt +++ b/compiler-rt/test/tsan/CMakeLists.txt @@ -1,5 +1,5 @@ set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -if(NOT ${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "mips") +if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "x86_64") list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck) endif() if(NOT COMPILER_RT_STANDALONE_BUILD) diff --git a/compiler-rt/test/tsan/cond_cancel.c b/compiler-rt/test/tsan/cond_cancel.c index ddfb745..ca56e8e 100644 --- a/compiler-rt/test/tsan/cond_cancel.c +++ b/compiler-rt/test/tsan/cond_cancel.c @@ -1,6 +1,14 @@ // RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s // CHECK-NOT: WARNING // CHECK: OK +// This test is failing on powerpc64 (VMA=44). After calling pthread_cancel, +// the Thread-specific data destructors are not called, so the destructor +// "thread_finalize" (defined in tsan_interceptors.cc) can not set the status +// of the thread to "ThreadStatusFinished" failing a check in "SetJoined" +// (defined in sanitizer_thread_registry.cc). It might seem a bug on glibc, +// however the same version GLIBC-2.17 will not make fail the test on +// powerpc64 (VMA=46) +// XFAIL: powerpc64 #include "test.h" diff --git a/compiler-rt/test/tsan/java_race_pc.cc b/compiler-rt/test/tsan/java_race_pc.cc index 015a0b1..0745ade 100644 --- a/compiler-rt/test/tsan/java_race_pc.cc +++ b/compiler-rt/test/tsan/java_race_pc.cc @@ -1,4 +1,8 @@ // RUN: %clangxx_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 on both VMA (44 and 46). +// The Tsan report is returning wrong information about +// the location of the race. +// XFAIL: powerpc64 #include "java.h" void foobar() { diff --git a/compiler-rt/test/tsan/map32bit.cc b/compiler-rt/test/tsan/map32bit.cc index 9f933bc..0411f29 100644 --- a/compiler-rt/test/tsan/map32bit.cc +++ b/compiler-rt/test/tsan/map32bit.cc @@ -10,6 +10,7 @@ // MAP_32BIT flag for mmap is supported only for x86_64. // XFAIL: mips64 // XFAIL: aarch64 +// XFAIL: powerpc64 // MAP_32BIT doesn't exist on OS X. // UNSUPPORTED: darwin diff --git a/compiler-rt/test/tsan/mmap_large.cc b/compiler-rt/test/tsan/mmap_large.cc index de32d91..764e954 100644 --- a/compiler-rt/test/tsan/mmap_large.cc +++ b/compiler-rt/test/tsan/mmap_large.cc @@ -16,6 +16,8 @@ int main() { const size_t kLog2Size = 39; #elif defined(__mips64) || defined(__aarch64__) const size_t kLog2Size = 32; +#elif defined(__powerpc64__) + const size_t kLog2Size = 39; #endif const uintptr_t kLocation = 0x40ULL << kLog2Size; void *p = mmap( diff --git a/compiler-rt/test/tsan/race_on_mutex.c b/compiler-rt/test/tsan/race_on_mutex.c index 7bd461b..ec705dee 100644 --- a/compiler-rt/test/tsan/race_on_mutex.c +++ b/compiler-rt/test/tsan/race_on_mutex.c @@ -1,4 +1,7 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 (VMA=46). +// The size of the write reported by Tsan for T1 is 8 instead of 1. +// XFAIL: powerpc64 #include "test.h" pthread_mutex_t Mtx; diff --git a/compiler-rt/test/tsan/signal_errno.cc b/compiler-rt/test/tsan/signal_errno.cc index 5354cde..ce19950 100644 --- a/compiler-rt/test/tsan/signal_errno.cc +++ b/compiler-rt/test/tsan/signal_errno.cc @@ -1,4 +1,8 @@ // RUN: %clang_tsan -O1 %s -o %t && %deflake %run %t | FileCheck %s +// This test fails on powerpc64 (VMA=44), it does not appear to be +// a functional problem, but the Tsan report is missing some info. +// XFAIL: powerpc64 + #include "test.h" #include #include diff --git a/compiler-rt/test/tsan/signal_longjmp.cc b/compiler-rt/test/tsan/signal_longjmp.cc index 556928a..fb4d278 100644 --- a/compiler-rt/test/tsan/signal_longjmp.cc +++ b/compiler-rt/test/tsan/signal_longjmp.cc @@ -5,6 +5,10 @@ // Longjmp assembly has not been implemented for mips64 yet // XFAIL: mips64 +// This test fails on powerpc64 (VMA=44), a segmentation fault +// error happens at the second assignment +// "((volatile int *volatile)mem)[1] = 1". +// XFAIL: powerpc64 #include #include diff --git a/compiler-rt/test/tsan/test.h b/compiler-rt/test/tsan/test.h index cec7c0d..a681daa 100644 --- a/compiler-rt/test/tsan/test.h +++ b/compiler-rt/test/tsan/test.h @@ -43,7 +43,7 @@ void print_address(const char *str, int n, ...) { va_start(ap, n); while (n--) { void *p = va_arg(ap, void *); -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) // On FreeBSD, the %p conversion specifier works as 0x%x and thus does not // match to the format used in the diagnotic message. fprintf(stderr, "0x%012lx ", (unsigned long) p); -- 2.7.4