Don't use timestamp counters on ARM32
Not all arm32 have access to timestamp counters. Even on ARMV8
processors where timestamp counters are available, they are not
accessible from user space always when running in 32-bit mode. There is
no easy way to check if the timestamp counters are supported. So for now
just fallback to clock_gettime.
Bug: 289178149
Test: art/test.py --trace --32
Change-Id: I8406f3a99a178e6806e2dc762662a7f5f0e538ea
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 9ab2683..08ae4c2 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -91,10 +91,14 @@
uint64_t GetTimestamp() {
uint64_t t = 0;
#if defined(__arm__)
- // See Architecture Reference Manual ARMv7-A and ARMv7-R edition section B4.1.34
- // Q and R specify that they should be written to lower and upper halves of 64-bit value.
- // See: https://llvm.org/docs/LangRef.html#asm-template-argument-modifiers
- asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r"(t));
+ // On ARM 32 bit, we don't always have access to the timestamp counters from user space. There is
+ // no easy way to check if it is safe to read the timestamp counters. There is HWCAP_EVTSTRM which
+ // is set when generic timer is available but not necessarily from the user space. Kernel disables
+ // access to generic timer when there are known problems on the target CPUs. Sometimes access is
+ // disabled only for 32-bit processes even when 64-bit processes can accesses the timer from user
+ // space. These are not reflected in the HWCAP_EVTSTRM capability.So just fallback to
+ // clock_gettime on these processes. See b/289178149 for more discussion.
+ t = MicroTime();
#elif defined(__aarch64__)
// See Arm Architecture Registers Armv8 section System Registers
asm volatile("mrs %0, cntvct_el0" : "=r"(t));
@@ -173,11 +177,9 @@
}
#if defined(__arm__)
- double seconds_to_microseconds = 1000 * 1000;
- uint64_t freq = 0;
- // See Architecture Reference Manual ARMv7-A and ARMv7-R edition section B4.1.21
- asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq));
- tsc_to_microsec_scaling_factor = seconds_to_microseconds / static_cast<double>(freq);
+ // On ARM 32 bit, we don't always have access to the timestamp counters from
+ // user space. Seem comment in GetTimestamp for more details.
+ tsc_to_microsec_scaling_factor = 1.0;
#elif defined(__aarch64__)
double seconds_to_microseconds = 1000 * 1000;
uint64_t freq = 0;
@@ -545,6 +547,11 @@
// For thread cpu clocks, we need to make a kernel call and hence we call into c++ to
// support them.
bool is_fast_trace = !the_trace_->UseThreadCpuClock();
+#if defined(__arm__)
+ // On ARM 32 bit, we don't always have access to the timestamp counters from
+ // user space. Seem comment in GetTimestamp for more details.
+ is_fast_trace = false;
+#endif
runtime->GetInstrumentation()->AddListener(
the_trace_,
instrumentation::Instrumentation::kMethodEntered |
@@ -604,6 +611,11 @@
// For thread cpu clocks, we need to make a kernel call and hence we call into c++ to support
// them.
bool is_fast_trace = !the_trace_->UseThreadCpuClock();
+#if defined(__arm__)
+ // On ARM 32 bit, we don't always have access to the timestamp counters from
+ // user space. Seem comment in GetTimestamp for more details.
+ is_fast_trace = false;
+#endif
runtime->GetInstrumentation()->RemoveListener(
the_trace,
instrumentation::Instrumentation::kMethodEntered |