From 8a0da0b040a743677f20f29548ff3380ffb9a5ed Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Thu, 12 Jul 2012 18:51:00 +0200 Subject: Android ucontext refinements (upstream backport). This is a forward-compatible patch to avoid naming/type conflicts in the near future, when the Android C library will be updated to provide mcontext_t/ucontext_t properly. Note that this changes the naming convention used to access the register values from mcontext_t, to follow current ARM GLibc (this is also the convention being adopted by Android). + Android provides gettid() (all API levels) so use it instead of relying on syscall(). This is a backport of http://code.google.com/p/v8/source/detail?r=12250 See http://code.google.com/p/android/issues/detail?id=34784 for more context. Change-Id: Id1fe5489eea8a51d0210858bf91132191f967822 --- src/platform-linux.cc | 62 ++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 9781407e..14011340 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -938,32 +938,32 @@ Semaphore* OS::CreateSemaphore(int count) { } -#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) -// Android runs a fairly new Linux kernel, so signal info is there, -// but the C library doesn't have the structs defined. +#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) -struct sigcontext { - uint32_t trap_no; - uint32_t error_code; - uint32_t oldmask; - uint32_t gregs[16]; - uint32_t arm_cpsr; - uint32_t fault_address; -}; -typedef uint32_t __sigset_t; +// Not all versions of the Android C library headers provide ucontext_t. +// Provide custom but compatible declarations if this is the case here. + +// Follow the modern ARM GLibc convention of defining mcontext_t as a typedef +// for 'struct sigcontext'. This means that register values are accessed +// by individual fields like arm_r0, arm_r1, arm_pc, instead of a gregs[] +// array. +#if !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) +#include +#endif + +typedef uint32_t kernel_sigset_t[2]; // ARM kernel uses 64-bit signal masks typedef struct sigcontext mcontext_t; typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - __sigset_t uc_sigmask; + kernel_sigset_t uc_sigmask; } ucontext_t; -enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; #elif !defined(__GLIBC__) && defined(__mips__) -// MIPS version of sigcontext, for Android bionic. -struct sigcontext { +// MIPS version of mcontext_t for Android bionic. +typedef struct { uint32_t regmask; uint32_t status; uint64_t pc; @@ -982,44 +982,43 @@ struct sigcontext { uint32_t lo2; uint32_t hi3; uint32_t lo3; -}; -typedef uint32_t __sigset_t; -typedef struct sigcontext mcontext_t; +} mcontext_t; +typedef uint32_t kernel_sigset_t[4]; // Mips kernel uses 128-bit signal masks. typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - __sigset_t uc_sigmask; + kernel_sigset_t uc_sigmask; } ucontext_t; #elif !defined(__GLIBC__) && defined(__i386__) // x86 version for Android. -struct sigcontext { +typedef struct { uint32_t gregs[19]; void* fpregs; uint32_t oldmask; uint32_t cr2; -}; +} mcontext_t; -typedef uint32_t __sigset_t; -typedef struct sigcontext mcontext_t; +typedef uint32_t kernel_sigset_t[2]; // i386 kernel uses 64-bit signal masks typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - __sigset_t uc_sigmask; + kernel_sigset_t uc_sigmask; } ucontext_t; enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; #endif static int GetThreadID() { - // Glibc doesn't provide a wrapper for gettid(2). -#if defined(ANDROID) - return syscall(__NR_gettid); +#if defined(__ANDROID__) + // Android's C library provides gettid(2). + return gettid(); #else + // Glibc doesn't provide a wrapper for gettid(2). return syscall(SYS_gettid); #endif } @@ -1059,15 +1058,18 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { sample->fp = reinterpret_cast
(mcontext.gregs[REG_RBP]); #elif V8_HOST_ARCH_ARM // An undefined macro evaluates to 0, so this applies to Android's Bionic also. -#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) +#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ + (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) + // Obsolete ARM GLibc convention to access register values. sample->pc = reinterpret_cast
(mcontext.gregs[R15]); sample->sp = reinterpret_cast
(mcontext.gregs[R13]); sample->fp = reinterpret_cast
(mcontext.gregs[R11]); #else + // Modern ARM GLibc convention. Also followed by UCLibc and Android. sample->pc = reinterpret_cast
(mcontext.arm_pc); sample->sp = reinterpret_cast
(mcontext.arm_sp); sample->fp = reinterpret_cast
(mcontext.arm_fp); -#endif // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) +#endif // .... (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) #elif V8_HOST_ARCH_MIPS sample->pc = reinterpret_cast
(mcontext.pc); sample->sp = reinterpret_cast
(mcontext.gregs[29]); -- cgit v1.2.3 From 1bbccaca327b1fed6859a62f6d3ed75a75e4856a Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Wed, 17 Oct 2012 19:01:49 +0200 Subject: Revert "Android ucontext refinements (upstream backport)". This creates build breakages in the internal Android tree. Will investigate later. Original patch: https://android-review.googlesource.com/#/c/38852/ Change-Id: I902021fa56b959f1f035f4d448a43483328debd8 --- src/platform-linux.cc | 62 +++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 14011340..9781407e 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -938,32 +938,32 @@ Semaphore* OS::CreateSemaphore(int count) { } -#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) +#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) +// Android runs a fairly new Linux kernel, so signal info is there, +// but the C library doesn't have the structs defined. -// Not all versions of the Android C library headers provide ucontext_t. -// Provide custom but compatible declarations if this is the case here. - -// Follow the modern ARM GLibc convention of defining mcontext_t as a typedef -// for 'struct sigcontext'. This means that register values are accessed -// by individual fields like arm_r0, arm_r1, arm_pc, instead of a gregs[] -// array. -#if !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) -#include -#endif - -typedef uint32_t kernel_sigset_t[2]; // ARM kernel uses 64-bit signal masks +struct sigcontext { + uint32_t trap_no; + uint32_t error_code; + uint32_t oldmask; + uint32_t gregs[16]; + uint32_t arm_cpsr; + uint32_t fault_address; +}; +typedef uint32_t __sigset_t; typedef struct sigcontext mcontext_t; typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - kernel_sigset_t uc_sigmask; + __sigset_t uc_sigmask; } ucontext_t; +enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; #elif !defined(__GLIBC__) && defined(__mips__) -// MIPS version of mcontext_t for Android bionic. -typedef struct { +// MIPS version of sigcontext, for Android bionic. +struct sigcontext { uint32_t regmask; uint32_t status; uint64_t pc; @@ -982,43 +982,44 @@ typedef struct { uint32_t lo2; uint32_t hi3; uint32_t lo3; -} mcontext_t; -typedef uint32_t kernel_sigset_t[4]; // Mips kernel uses 128-bit signal masks. +}; +typedef uint32_t __sigset_t; +typedef struct sigcontext mcontext_t; typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - kernel_sigset_t uc_sigmask; + __sigset_t uc_sigmask; } ucontext_t; #elif !defined(__GLIBC__) && defined(__i386__) // x86 version for Android. -typedef struct { +struct sigcontext { uint32_t gregs[19]; void* fpregs; uint32_t oldmask; uint32_t cr2; -} mcontext_t; +}; -typedef uint32_t kernel_sigset_t[2]; // i386 kernel uses 64-bit signal masks +typedef uint32_t __sigset_t; +typedef struct sigcontext mcontext_t; typedef struct ucontext { uint32_t uc_flags; struct ucontext* uc_link; stack_t uc_stack; mcontext_t uc_mcontext; - kernel_sigset_t uc_sigmask; + __sigset_t uc_sigmask; } ucontext_t; enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; #endif static int GetThreadID() { -#if defined(__ANDROID__) - // Android's C library provides gettid(2). - return gettid(); -#else // Glibc doesn't provide a wrapper for gettid(2). +#if defined(ANDROID) + return syscall(__NR_gettid); +#else return syscall(SYS_gettid); #endif } @@ -1058,18 +1059,15 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { sample->fp = reinterpret_cast
(mcontext.gregs[REG_RBP]); #elif V8_HOST_ARCH_ARM // An undefined macro evaluates to 0, so this applies to Android's Bionic also. -#if defined(__GLIBC__) && !defined(__UCLIBC__) && \ - (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) - // Obsolete ARM GLibc convention to access register values. +#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) sample->pc = reinterpret_cast
(mcontext.gregs[R15]); sample->sp = reinterpret_cast
(mcontext.gregs[R13]); sample->fp = reinterpret_cast
(mcontext.gregs[R11]); #else - // Modern ARM GLibc convention. Also followed by UCLibc and Android. sample->pc = reinterpret_cast
(mcontext.arm_pc); sample->sp = reinterpret_cast
(mcontext.arm_sp); sample->fp = reinterpret_cast
(mcontext.arm_fp); -#endif // .... (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) +#endif // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) #elif V8_HOST_ARCH_MIPS sample->pc = reinterpret_cast
(mcontext.pc); sample->sp = reinterpret_cast
(mcontext.gregs[29]); -- cgit v1.2.3 From af537b8206a515f942e5ee0338113bd485b55eb7 Mon Sep 17 00:00:00 2001 From: Andrew Hsieh Date: Fri, 2 Nov 2012 21:54:11 -0700 Subject: Fix ARM hardfloat detection in linux See http://code.google.com/p/v8/issues/detail?id=2140 https://chromiumcodereview.appspot.com/10713009 The original code fails to detect at run-time when compiled with GCC 4.7, because the undefined behavior of casting void to double, and the r0/r1 clobbered in assembly code isn't reaching the use when compared to 1.0 in VFP reg. In summary, the old code is incorrect and overkill, and the new code fix it. Change-Id: I6b63a4f9789e08089368e431a5553f482400725a --- src/platform-linux.cc | 71 ++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 38 deletions(-) diff --git a/src/platform-linux.cc b/src/platform-linux.cc index 9781407e..6c4a549c 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -190,48 +190,43 @@ bool OS::ArmCpuHasFeature(CpuFeature feature) { } -// Simple helper function to detect whether the C code is compiled with -// option -mfloat-abi=hard. The register d0 is loaded with 1.0 and the register -// pair r0, r1 is loaded with 0.0. If -mfloat-abi=hard is pased to GCC then -// calling this will return 1.0 and otherwise 0.0. -static void ArmUsingHardFloatHelper() { - asm("mov r0, #0":::"r0"); -#if defined(__VFP_FP__) && !defined(__SOFTFP__) - // Load 0x3ff00000 into r1 using instructions available in both ARM - // and Thumb mode. - asm("mov r1, #3":::"r1"); - asm("mov r2, #255":::"r2"); - asm("lsl r1, r1, #8":::"r1"); - asm("orr r1, r1, r2":::"r1"); - asm("lsl r1, r1, #20":::"r1"); - // For vmov d0, r0, r1 use ARM mode. -#ifdef __thumb__ - asm volatile( - "@ Enter ARM Mode \n\t" - " adr r3, 1f \n\t" - " bx r3 \n\t" - " .ALIGN 4 \n\t" - " .ARM \n" - "1: vmov d0, r0, r1 \n\t" - "@ Enter THUMB Mode\n\t" - " adr r3, 2f+1 \n\t" - " bx r3 \n\t" - " .THUMB \n" - "2: \n\t":::"r3"); +bool OS::ArmUsingHardFloat() { + // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify + // the Floating Point ABI used (PCS stands for Procedure Call Standard). + // We use these as well as a couple of other defines to statically determine + // what FP ABI used. + // GCC versions 4.4 and below don't support hard-fp. + // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or + // __ARM_PCS_VFP. + +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +#if GCC_VERSION >= 40600 +#if defined(__ARM_PCS_VFP) + return true; #else - asm("vmov d0, r0, r1"); -#endif // __thumb__ -#endif // defined(__VFP_FP__) && !defined(__SOFTFP__) - asm("mov r1, #0":::"r1"); -} + return false; +#endif +#elif GCC_VERSION < 40500 + return false; -bool OS::ArmUsingHardFloat() { - // Cast helper function from returning void to returning double. - typedef double (*F)(); - F f = FUNCTION_CAST(FUNCTION_ADDR(ArmUsingHardFloatHelper)); - return f() == 1.0; +#else +#if defined(__ARM_PCS_VFP) + return true; +#elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__) + return false; +#else +#error "Your version of GCC does not report the FP ABI compiled for." \ + "Please report it on this issue" \ + "http://code.google.com/p/v8/issues/detail?id=2140" + +#endif +#endif +#undef GCC_VERSION } + #endif // def __arm__ -- cgit v1.2.3 From eb8b6a4f5e8e39c8a9c3e4e19a558e52081dfd8a Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Mon, 28 Jan 2013 11:04:51 -0800 Subject: Use target-specific PRIVATE_CLEAN_FILES Change-Id: Idb8136a0dc887538e2ee857a60e60ab6aa358883 --- Android.libv8.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Android.libv8.mk b/Android.libv8.mk index 35e5e5f1..fdbac236 100644 --- a/Android.libv8.mk +++ b/Android.libv8.mk @@ -15,7 +15,8 @@ LOCAL_MODULE := libv8 LOCAL_MODULE_CLASS := STATIC_LIBRARIES intermediates := $(call local-intermediates-dir) -PRIVATE_CLEAN_FILES := $(HOST_OUT)/bin/mksnapshot.$(TARGET_ARCH) \ +# clean-$(LOCAL_MODULE) is a target defined build/core/base_rules.mk. +clean-$(LOCAL_MODULE): PRIVATE_CLEAN_FILES := $(HOST_OUT)/bin/mksnapshot.$(TARGET_ARCH) \ $(HOST_OUT)/obj/EXECUTABLES/mksnapshot.$(TARGET_ARCH)_intermediates # Android.v8common.mk defines common V8_LOCAL_SRC_FILES -- cgit v1.2.3 From 1af9b71e17f270a19572a9b8606a1ef93a55be6c Mon Sep 17 00:00:00 2001 From: Ying Wang Date: Fri, 22 Mar 2013 18:54:46 -0700 Subject: Remove the unnecessary PRIVATE_CLEAN_FILES If you want to clean those files, you should run "make clean-mksnapshot.$(TARGET_ARCH)" instead. Change-Id: I45a35903126225a54f8d942ed38c5cea70fd2664 --- Android.libv8.mk | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Android.libv8.mk b/Android.libv8.mk index fdbac236..4b99a137 100644 --- a/Android.libv8.mk +++ b/Android.libv8.mk @@ -15,10 +15,6 @@ LOCAL_MODULE := libv8 LOCAL_MODULE_CLASS := STATIC_LIBRARIES intermediates := $(call local-intermediates-dir) -# clean-$(LOCAL_MODULE) is a target defined build/core/base_rules.mk. -clean-$(LOCAL_MODULE): PRIVATE_CLEAN_FILES := $(HOST_OUT)/bin/mksnapshot.$(TARGET_ARCH) \ - $(HOST_OUT)/obj/EXECUTABLES/mksnapshot.$(TARGET_ARCH)_intermediates - # Android.v8common.mk defines common V8_LOCAL_SRC_FILES # and V8_LOCAL_JS_LIBRARY_FILES V8_LOCAL_SRC_FILES := -- cgit v1.2.3 From 8c7c06b5cdac575f2288290cbad8c757ca078635 Mon Sep 17 00:00:00 2001 From: Paul Lind Date: Mon, 6 May 2013 16:09:29 -0700 Subject: Use kernel cacheflush for large sizes on MIPS. This is a workaround to a deserializer bug. The bug was exposed with a recent optimization to use user-mode cache-flushing on MIPS. To reduce risk, we're doing a workaround in mips-specific code so that other arch's cannot be affected. The deserializer does this FlushICache: CPU::FlushICache(last_object_address_, Page::kPageSize); However, that region includes OS guard-pages with no access privilege. The MIPS kernel cacheflush routines work OK in this case, but the Bionic cacheflush recently enabled user-mode flushing using the synci instruction, which causes a segfault on MIPS when the guard pages are reached. (change I48fd6f2b0cbe80c3cd90f453ced97a2f154f7ad3) The workaround just reverts to the kernel flush when the size is Page::kPageSize or bigger. A better fix would be to alter the deserializer so that only the executable pages are flushed: CPU::FlushICache(last_object_address_, isolate_->memory_allocator()->CodePageAreaSize()); However, that changes common code for all supported architectures. There is no evidence that this bug affects the other arch's, so we are doing a MIPS-specific workaround. (cherry-pick from AOSP) bug: 8851838 Change-Id: I30b62eb579feab1453d3ae85a5fb9b408f91756b Signed-off-by: Paul Lind --- src/mips/cpu-mips.cc | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/mips/cpu-mips.cc b/src/mips/cpu-mips.cc index 93ebeda8..b8200007 100644 --- a/src/mips/cpu-mips.cc +++ b/src/mips/cpu-mips.cc @@ -65,10 +65,23 @@ void CPU::FlushICache(void* start, size_t size) { #if !defined (USE_SIMULATOR) #if defined(ANDROID) - // Bionic cacheflush can typically run in userland, avoiding kernel call. - char *end = reinterpret_cast(start) + size; - cacheflush( - reinterpret_cast(start), reinterpret_cast(end), 0); + // Workaround for a deserializer bug. Bionic usermode cacheflush + // fails in deserializer for a size of Page::kPageSize (1MB), + // because that region contains protected pages. Switch to kernel + // cacheflush in this case. + if (size >= static_cast(Page::kPageSize)) { + int res; + // See http://www.linux-mips.org/wiki/Cacheflush_Syscall. + res = syscall(__NR_cacheflush, start, size, ICACHE); + if (res) { + V8_Fatal(__FILE__, __LINE__, "Failed to flush the instruction cache"); + } + } else { + // Bionic cacheflush can typically run in userland, avoiding kernel call. + char *end = reinterpret_cast(start) + size; + cacheflush( + reinterpret_cast(start), reinterpret_cast(end), 0); + } #else // ANDROID int res; // See http://www.linux-mips.org/wiki/Cacheflush_Syscall. -- cgit v1.2.3