• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // CPU specific code for arm independent of OS goes here.
6 
7 #if V8_TARGET_ARCH_ARM64
8 
9 #include "src/codegen/arm64/utils-arm64.h"
10 #include "src/codegen/cpu-features.h"
11 
12 #if V8_OS_DARWIN
13 #include <libkern/OSCacheControl.h>
14 #endif
15 
16 #if V8_OS_WIN
17 #include <windows.h>
18 #endif
19 
20 namespace v8 {
21 namespace internal {
22 
23 class CacheLineSizes {
24  public:
CacheLineSizes()25   CacheLineSizes() {
26 #if !defined(V8_HOST_ARCH_ARM64) || defined(V8_OS_WIN) || defined(__APPLE__)
27     cache_type_register_ = 0;
28 #else
29     // Copy the content of the cache type register to a core register.
30     __asm__ __volatile__("mrs %x[ctr], ctr_el0"
31                          : [ctr] "=r"(cache_type_register_));
32 #endif
33   }
34 
icache_line_size() const35   uint32_t icache_line_size() const { return ExtractCacheLineSize(0); }
dcache_line_size() const36   uint32_t dcache_line_size() const { return ExtractCacheLineSize(16); }
37 
38  private:
ExtractCacheLineSize(int cache_line_size_shift) const39   uint32_t ExtractCacheLineSize(int cache_line_size_shift) const {
40     // The cache type register holds the size of cache lines in words as a
41     // power of two.
42     return 4 << ((cache_type_register_ >> cache_line_size_shift) & 0xF);
43   }
44 
45   uint32_t cache_type_register_;
46 };
47 
FlushICache(void * address,size_t length)48 void CpuFeatures::FlushICache(void* address, size_t length) {
49 #if defined(V8_HOST_ARCH_ARM64)
50 #if defined(V8_OS_WIN)
51   ::FlushInstructionCache(GetCurrentProcess(), address, length);
52 #elif defined(V8_OS_DARWIN)
53   sys_icache_invalidate(address, length);
54 #else
55   // The code below assumes user space cache operations are allowed. The goal
56   // of this routine is to make sure the code generated is visible to the I
57   // side of the CPU.
58 
59   uintptr_t start = reinterpret_cast<uintptr_t>(address);
60   // Sizes will be used to generate a mask big enough to cover a pointer.
61   CacheLineSizes sizes;
62   uintptr_t dsize = sizes.dcache_line_size();
63   uintptr_t isize = sizes.icache_line_size();
64   // Cache line sizes are always a power of 2.
65   DCHECK_EQ(CountSetBits(dsize, 64), 1);
66   DCHECK_EQ(CountSetBits(isize, 64), 1);
67   uintptr_t dstart = start & ~(dsize - 1);
68   uintptr_t istart = start & ~(isize - 1);
69   uintptr_t end = start + length;
70 
71   __asm__ __volatile__(
72       // Clean every line of the D cache containing the target data.
73       "0:                                \n\t"
74       // dc       : Data Cache maintenance
75       //    c     : Clean
76       //     i    : Invalidate
77       //      va  : by (Virtual) Address
78       //        c : to the point of Coherency
79       // See ARM DDI 0406B page B2-12 for more information.
80       // We would prefer to use "cvau" (clean to the point of unification) here
81       // but we use "civac" to work around Cortex-A53 errata 819472, 826319,
82       // 827319 and 824069.
83       "dc   civac, %[dline]               \n\t"
84       "add  %[dline], %[dline], %[dsize]  \n\t"
85       "cmp  %[dline], %[end]              \n\t"
86       "b.lt 0b                            \n\t"
87       // Barrier to make sure the effect of the code above is visible to the
88       // rest of the world. dsb    : Data Synchronisation Barrier
89       //    ish : Inner SHareable domain
90       // The point of unification for an Inner Shareable shareability domain is
91       // the point by which the instruction and data caches of all the
92       // processors in that Inner Shareable shareability domain are guaranteed
93       // to see the same copy of a memory location.  See ARM DDI 0406B page
94       // B2-12 for more information.
95       "dsb  ish                           \n\t"
96       // Invalidate every line of the I cache containing the target data.
97       "1:                                 \n\t"
98       // ic      : instruction cache maintenance
99       //    i    : invalidate
100       //     va  : by address
101       //       u : to the point of unification
102       "ic   ivau, %[iline]                \n\t"
103       "add  %[iline], %[iline], %[isize]  \n\t"
104       "cmp  %[iline], %[end]              \n\t"
105       "b.lt 1b                            \n\t"
106       // Barrier to make sure the effect of the code above is visible to the
107       // rest of the world.
108       "dsb  ish                           \n\t"
109       // Barrier to ensure any prefetching which happened before this code is
110       // discarded.
111       // isb : Instruction Synchronisation Barrier
112       "isb                                \n\t"
113       : [dline] "+r"(dstart), [iline] "+r"(istart)
114       : [dsize] "r"(dsize), [isize] "r"(isize), [end] "r"(end)
115       // This code does not write to memory but without the dependency gcc might
116       // move this code before the code is generated.
117       : "cc", "memory");
118 #endif  // V8_OS_WIN
119 #endif  // V8_HOST_ARCH_ARM64
120 }
121 
122 }  // namespace internal
123 }  // namespace v8
124 
125 #endif  // V8_TARGET_ARCH_ARM64
126