1// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(TARGET_ARCH_ARM64)
7
8#include "vm/cpu.h"
9#include "vm/cpu_arm64.h"
10
11#include "vm/cpuinfo.h"
12#include "vm/simulator.h"
13
14#if !defined(USING_SIMULATOR)
15#if !defined(HOST_OS_FUCHSIA)
16#include <sys/syscall.h>
17#else
18#include <zircon/syscalls.h>
19#endif
20#include <unistd.h>
21#endif
22
23#if defined(HOST_OS_IOS)
24#include <libkern/OSCacheControl.h>
25#endif
26
27namespace dart {
28
29void CPU::FlushICache(uword start, uword size) {
30#if defined(DART_PRECOMPILED_RUNTIME)
31 UNREACHABLE();
32#elif !defined(USING_SIMULATOR)
33 // Nothing to do. Flushing no instructions.
34 if (size == 0) {
35 return;
36 }
37
38// ARM recommends using the gcc intrinsic __clear_cache on Linux and Android.
39//
40// https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/caches-and-self-modifying-code
41//
42// On iOS we use sys_icache_invalidate from Darwin. See:
43//
44// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
45#if defined(HOST_OS_IOS)
46 sys_icache_invalidate(reinterpret_cast<void*>(start), size);
47#elif defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
48 extern void __clear_cache(char*, char*);
49 char* beg = reinterpret_cast<char*>(start);
50 char* end = reinterpret_cast<char*>(start + size);
51 ::__clear_cache(beg, end);
52#elif defined(HOST_OS_FUCHSIA)
53 zx_status_t result = zx_cache_flush(reinterpret_cast<const void*>(start),
54 size, ZX_CACHE_FLUSH_INSN);
55 ASSERT(result == ZX_OK);
56#else
57#error FlushICache only tested/supported on Android, Fuchsia, Linux and iOS
58#endif
59
60#endif
61}
62
63const char* CPU::Id() {
64 return
65#if defined(USING_SIMULATOR)
66 "sim"
67#endif // !defined(HOST_ARCH_ARM64)
68 "arm64";
69}
70
71const char* HostCPUFeatures::hardware_ = NULL;
72#if defined(DEBUG)
73bool HostCPUFeatures::initialized_ = false;
74#endif
75
76#if !defined(USING_SIMULATOR)
77void HostCPUFeatures::Init() {
78 CpuInfo::Init();
79 hardware_ = CpuInfo::GetCpuModel();
80#if defined(DEBUG)
81 initialized_ = true;
82#endif
83}
84
85void HostCPUFeatures::Cleanup() {
86 DEBUG_ASSERT(initialized_);
87#if defined(DEBUG)
88 initialized_ = false;
89#endif
90 ASSERT(hardware_ != NULL);
91 free(const_cast<char*>(hardware_));
92 hardware_ = NULL;
93 CpuInfo::Cleanup();
94}
95
96#else // !defined(USING_SIMULATOR)
97
98void HostCPUFeatures::Init() {
99 CpuInfo::Init();
100 hardware_ = CpuInfo::GetCpuModel();
101#if defined(DEBUG)
102 initialized_ = true;
103#endif
104}
105
106void HostCPUFeatures::Cleanup() {
107 DEBUG_ASSERT(initialized_);
108#if defined(DEBUG)
109 initialized_ = false;
110#endif
111 ASSERT(hardware_ != NULL);
112 free(const_cast<char*>(hardware_));
113 hardware_ = NULL;
114 CpuInfo::Cleanup();
115}
116#endif // !defined(USING_SIMULATOR)
117
118} // namespace dart
119
120#endif // defined TARGET_ARCH_ARM64
121