v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cpu-arm64.cc
Go to the documentation of this file.
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 // CPU specific code for arm independent of OS goes here.
29 
30 #include "v8.h"
31 
32 #if V8_TARGET_ARCH_ARM64
33 
34 #include "arm64/cpu-arm64.h"
35 #include "arm64/utils-arm64.h"
36 
37 namespace v8 {
38 namespace internal {
39 
40 #ifdef DEBUG
41 bool CpuFeatures::initialized_ = false;
42 #endif
43 unsigned CpuFeatures::supported_ = 0;
44 unsigned CpuFeatures::found_by_runtime_probing_only_ = 0;
45 unsigned CpuFeatures::cross_compile_ = 0;
46 
47 // Initialise to smallest possible cache size.
48 unsigned CpuFeatures::dcache_line_size_ = 1;
49 unsigned CpuFeatures::icache_line_size_ = 1;
50 
51 
52 void CPU::SetUp() {
54 }
55 
56 
57 bool CPU::SupportsCrankshaft() {
58  return true;
59 }
60 
61 
62 void CPU::FlushICache(void* address, size_t length) {
63  if (length == 0) {
64  return;
65  }
66 
67 #ifdef USE_SIMULATOR
68  // TODO(all): consider doing some cache simulation to ensure every address
69  // run has been synced.
70  USE(address);
71  USE(length);
72 #else
73  // The code below assumes user space cache operations are allowed. The goal
74  // of this routine is to make sure the code generated is visible to the I
75  // side of the CPU.
76 
77  uintptr_t start = reinterpret_cast<uintptr_t>(address);
78  // Sizes will be used to generate a mask big enough to cover a pointer.
79  uintptr_t dsize = static_cast<uintptr_t>(CpuFeatures::dcache_line_size());
80  uintptr_t isize = static_cast<uintptr_t>(CpuFeatures::icache_line_size());
81  // Cache line sizes are always a power of 2.
82  ASSERT(CountSetBits(dsize, 64) == 1);
83  ASSERT(CountSetBits(isize, 64) == 1);
84  uintptr_t dstart = start & ~(dsize - 1);
85  uintptr_t istart = start & ~(isize - 1);
86  uintptr_t end = start + length;
87 
88  __asm__ __volatile__ ( // NOLINT
89  // Clean every line of the D cache containing the target data.
90  "0: \n\t"
91  // dc : Data Cache maintenance
92  // c : Clean
93  // va : by (Virtual) Address
94  // u : to the point of Unification
95  // The point of unification for a processor is the point by which the
96  // instruction and data caches are guaranteed to see the same copy of a
97  // memory location. See ARM DDI 0406B page B2-12 for more information.
98  "dc cvau, %[dline] \n\t"
99  "add %[dline], %[dline], %[dsize] \n\t"
100  "cmp %[dline], %[end] \n\t"
101  "b.lt 0b \n\t"
102  // Barrier to make sure the effect of the code above is visible to the rest
103  // of the world.
104  // dsb : Data Synchronisation Barrier
105  // ish : Inner SHareable domain
106  // The point of unification for an Inner Shareable shareability domain is
107  // the point by which the instruction and data caches of all the processors
108  // in that Inner Shareable shareability domain are guaranteed to see the
109  // same copy of a memory location. See ARM DDI 0406B page B2-12 for more
110  // information.
111  "dsb ish \n\t"
112  // Invalidate every line of the I cache containing the target data.
113  "1: \n\t"
114  // ic : instruction cache maintenance
115  // i : invalidate
116  // va : by address
117  // u : to the point of unification
118  "ic ivau, %[iline] \n\t"
119  "add %[iline], %[iline], %[isize] \n\t"
120  "cmp %[iline], %[end] \n\t"
121  "b.lt 1b \n\t"
122  // Barrier to make sure the effect of the code above is visible to the rest
123  // of the world.
124  "dsb ish \n\t"
125  // Barrier to ensure any prefetching which happened before this code is
126  // discarded.
127  // isb : Instruction Synchronisation Barrier
128  "isb \n\t"
129  : [dline] "+r" (dstart),
130  [iline] "+r" (istart)
131  : [dsize] "r" (dsize),
132  [isize] "r" (isize),
133  [end] "r" (end)
134  // This code does not write to memory but without the dependency gcc might
135  // move this code before the code is generated.
136  : "cc", "memory"
137  ); // NOLINT
138 #endif
139 }
140 
141 
142 void CpuFeatures::Probe() {
143  // Compute I and D cache line size. The cache type register holds
144  // information about the caches.
145  uint32_t cache_type_register = GetCacheType();
146 
147  static const int kDCacheLineSizeShift = 16;
148  static const int kICacheLineSizeShift = 0;
149  static const uint32_t kDCacheLineSizeMask = 0xf << kDCacheLineSizeShift;
150  static const uint32_t kICacheLineSizeMask = 0xf << kICacheLineSizeShift;
151 
152  // The cache type register holds the size of the I and D caches as a power of
153  // two.
154  uint32_t dcache_line_size_power_of_two =
155  (cache_type_register & kDCacheLineSizeMask) >> kDCacheLineSizeShift;
156  uint32_t icache_line_size_power_of_two =
157  (cache_type_register & kICacheLineSizeMask) >> kICacheLineSizeShift;
158 
159  dcache_line_size_ = 1 << dcache_line_size_power_of_two;
160  icache_line_size_ = 1 << icache_line_size_power_of_two;
161 
162  // AArch64 has no configuration options, no further probing is required.
163  supported_ = 0;
164 
165 #ifdef DEBUG
166  initialized_ = true;
167 #endif
168 }
169 
170 
172  ASSERT(initialized_);
173  return dcache_line_size_;
174 }
175 
176 
178  ASSERT(initialized_);
179  return icache_line_size_;
180 }
181 
182 
183 uint32_t CpuFeatures::GetCacheType() {
184 #ifdef USE_SIMULATOR
185  // This will lead to a cache with 1 byte long lines, which is fine since the
186  // simulator will not need this information.
187  return 0;
188 #else
189  uint32_t cache_type_register;
190  // Copy the content of the cache type register to a core register.
191  __asm__ __volatile__ ("mrs %[ctr], ctr_el0" // NOLINT
192  : [ctr] "=r" (cache_type_register));
193  return cache_type_register;
194 #endif
195 }
196 
197 } } // namespace v8::internal
198 
199 #endif // V8_TARGET_ARCH_ARM64
#define ASSERT(condition)
Definition: checks.h:329
static unsigned dcache_line_size()
int CountSetBits(uint64_t value, int width)
void USE(T)
Definition: globals.h:341
static unsigned icache_line_size()