1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "context_arm64.h"
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils_iterator.h"
23*795d594fSAndroid Build Coastguard Worker #include "quick/quick_method_frame_info.h"
24*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #if defined(__aarch64__) && defined(__BIONIC__)
28*795d594fSAndroid Build Coastguard Worker #include <bionic/malloc.h>
29*795d594fSAndroid Build Coastguard Worker #endif
30*795d594fSAndroid Build Coastguard Worker
31*795d594fSAndroid Build Coastguard Worker extern "C" __attribute__((weak)) void __hwasan_handle_longjmp(const void* sp_dst);
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
34*795d594fSAndroid Build Coastguard Worker namespace arm64 {
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker static constexpr uint64_t gZero = 0;
37*795d594fSAndroid Build Coastguard Worker
Reset()38*795d594fSAndroid Build Coastguard Worker void Arm64Context::Reset() {
39*795d594fSAndroid Build Coastguard Worker std::fill_n(gprs_, arraysize(gprs_), nullptr);
40*795d594fSAndroid Build Coastguard Worker std::fill_n(fprs_, arraysize(fprs_), nullptr);
41*795d594fSAndroid Build Coastguard Worker gprs_[SP] = &sp_;
42*795d594fSAndroid Build Coastguard Worker gprs_[kPC] = &pc_;
43*795d594fSAndroid Build Coastguard Worker gprs_[X0] = &arg0_;
44*795d594fSAndroid Build Coastguard Worker // Initialize registers with easy to spot debug values.
45*795d594fSAndroid Build Coastguard Worker sp_ = kBadGprBase + SP;
46*795d594fSAndroid Build Coastguard Worker pc_ = kBadGprBase + kPC;
47*795d594fSAndroid Build Coastguard Worker arg0_ = 0;
48*795d594fSAndroid Build Coastguard Worker }
49*795d594fSAndroid Build Coastguard Worker
FillCalleeSaves(uint8_t * frame,const QuickMethodFrameInfo & frame_info)50*795d594fSAndroid Build Coastguard Worker void Arm64Context::FillCalleeSaves(uint8_t* frame, const QuickMethodFrameInfo& frame_info) {
51*795d594fSAndroid Build Coastguard Worker const size_t frame_size = frame_info.FrameSizeInBytes();
52*795d594fSAndroid Build Coastguard Worker int spill_pos = 0;
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker // Core registers come first, from the highest down to the lowest.
55*795d594fSAndroid Build Coastguard Worker for (uint32_t core_reg : HighToLowBits(frame_info.CoreSpillMask())) {
56*795d594fSAndroid Build Coastguard Worker gprs_[core_reg] = CalleeSaveAddress<InstructionSet::kArm64>(frame, spill_pos, frame_size);
57*795d594fSAndroid Build Coastguard Worker ++spill_pos;
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()));
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker // FP registers come second, from the highest down to the lowest.
62*795d594fSAndroid Build Coastguard Worker for (uint32_t fp_reg : HighToLowBits(frame_info.FpSpillMask())) {
63*795d594fSAndroid Build Coastguard Worker fprs_[fp_reg] = CalleeSaveAddress<InstructionSet::kArm64>(frame, spill_pos, frame_size);
64*795d594fSAndroid Build Coastguard Worker ++spill_pos;
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(spill_pos, POPCOUNT(frame_info.CoreSpillMask()) + POPCOUNT(frame_info.FpSpillMask()));
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker
SetGPR(uint32_t reg,uintptr_t value)69*795d594fSAndroid Build Coastguard Worker void Arm64Context::SetGPR(uint32_t reg, uintptr_t value) {
70*795d594fSAndroid Build Coastguard Worker DCHECK_LT(reg, arraysize(gprs_));
71*795d594fSAndroid Build Coastguard Worker // Note: we use kPC == XZR, so do not ensure that reg != XZR.
72*795d594fSAndroid Build Coastguard Worker DCHECK(IsAccessibleGPR(reg));
73*795d594fSAndroid Build Coastguard Worker DCHECK_NE(gprs_[reg], &gZero); // Can't overwrite this static value since they are never reset.
74*795d594fSAndroid Build Coastguard Worker *gprs_[reg] = value;
75*795d594fSAndroid Build Coastguard Worker }
76*795d594fSAndroid Build Coastguard Worker
SetFPR(uint32_t reg,uintptr_t value)77*795d594fSAndroid Build Coastguard Worker void Arm64Context::SetFPR(uint32_t reg, uintptr_t value) {
78*795d594fSAndroid Build Coastguard Worker DCHECK_LT(reg, static_cast<uint32_t>(kNumberOfDRegisters));
79*795d594fSAndroid Build Coastguard Worker DCHECK(IsAccessibleFPR(reg));
80*795d594fSAndroid Build Coastguard Worker DCHECK_NE(fprs_[reg], &gZero); // Can't overwrite this static value since they are never reset.
81*795d594fSAndroid Build Coastguard Worker *fprs_[reg] = value;
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker
SmashCallerSaves()84*795d594fSAndroid Build Coastguard Worker void Arm64Context::SmashCallerSaves() {
85*795d594fSAndroid Build Coastguard Worker // This needs to be 0 because we want a null/zero return value.
86*795d594fSAndroid Build Coastguard Worker gprs_[X0] = const_cast<uint64_t*>(&gZero);
87*795d594fSAndroid Build Coastguard Worker gprs_[X1] = nullptr;
88*795d594fSAndroid Build Coastguard Worker gprs_[X2] = nullptr;
89*795d594fSAndroid Build Coastguard Worker gprs_[X3] = nullptr;
90*795d594fSAndroid Build Coastguard Worker gprs_[X4] = nullptr;
91*795d594fSAndroid Build Coastguard Worker gprs_[X5] = nullptr;
92*795d594fSAndroid Build Coastguard Worker gprs_[X6] = nullptr;
93*795d594fSAndroid Build Coastguard Worker gprs_[X7] = nullptr;
94*795d594fSAndroid Build Coastguard Worker gprs_[X8] = nullptr;
95*795d594fSAndroid Build Coastguard Worker gprs_[X9] = nullptr;
96*795d594fSAndroid Build Coastguard Worker gprs_[X10] = nullptr;
97*795d594fSAndroid Build Coastguard Worker gprs_[X11] = nullptr;
98*795d594fSAndroid Build Coastguard Worker gprs_[X12] = nullptr;
99*795d594fSAndroid Build Coastguard Worker gprs_[X13] = nullptr;
100*795d594fSAndroid Build Coastguard Worker gprs_[X14] = nullptr;
101*795d594fSAndroid Build Coastguard Worker gprs_[X15] = nullptr;
102*795d594fSAndroid Build Coastguard Worker gprs_[X18] = nullptr;
103*795d594fSAndroid Build Coastguard Worker
104*795d594fSAndroid Build Coastguard Worker // d0-d7, d16-d31 are caller-saved; d8-d15 are callee-saved.
105*795d594fSAndroid Build Coastguard Worker
106*795d594fSAndroid Build Coastguard Worker fprs_[D0] = nullptr;
107*795d594fSAndroid Build Coastguard Worker fprs_[D1] = nullptr;
108*795d594fSAndroid Build Coastguard Worker fprs_[D2] = nullptr;
109*795d594fSAndroid Build Coastguard Worker fprs_[D3] = nullptr;
110*795d594fSAndroid Build Coastguard Worker fprs_[D4] = nullptr;
111*795d594fSAndroid Build Coastguard Worker fprs_[D5] = nullptr;
112*795d594fSAndroid Build Coastguard Worker fprs_[D6] = nullptr;
113*795d594fSAndroid Build Coastguard Worker fprs_[D7] = nullptr;
114*795d594fSAndroid Build Coastguard Worker
115*795d594fSAndroid Build Coastguard Worker fprs_[D16] = nullptr;
116*795d594fSAndroid Build Coastguard Worker fprs_[D17] = nullptr;
117*795d594fSAndroid Build Coastguard Worker fprs_[D18] = nullptr;
118*795d594fSAndroid Build Coastguard Worker fprs_[D19] = nullptr;
119*795d594fSAndroid Build Coastguard Worker fprs_[D20] = nullptr;
120*795d594fSAndroid Build Coastguard Worker fprs_[D21] = nullptr;
121*795d594fSAndroid Build Coastguard Worker fprs_[D22] = nullptr;
122*795d594fSAndroid Build Coastguard Worker fprs_[D23] = nullptr;
123*795d594fSAndroid Build Coastguard Worker fprs_[D24] = nullptr;
124*795d594fSAndroid Build Coastguard Worker fprs_[D25] = nullptr;
125*795d594fSAndroid Build Coastguard Worker fprs_[D26] = nullptr;
126*795d594fSAndroid Build Coastguard Worker fprs_[D27] = nullptr;
127*795d594fSAndroid Build Coastguard Worker fprs_[D28] = nullptr;
128*795d594fSAndroid Build Coastguard Worker fprs_[D29] = nullptr;
129*795d594fSAndroid Build Coastguard Worker fprs_[D30] = nullptr;
130*795d594fSAndroid Build Coastguard Worker fprs_[D31] = nullptr;
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker
133*795d594fSAndroid Build Coastguard Worker #if defined(__aarch64__) && defined(__BIONIC__) && defined(M_MEMTAG_STACK_IS_ON)
untag_memory(void * from,void * to)134*795d594fSAndroid Build Coastguard Worker static inline __attribute__((no_sanitize("memtag"))) void untag_memory(void* from, void* to) {
135*795d594fSAndroid Build Coastguard Worker __asm__ __volatile__(
136*795d594fSAndroid Build Coastguard Worker ".arch_extension mte\n"
137*795d594fSAndroid Build Coastguard Worker "1:\n"
138*795d594fSAndroid Build Coastguard Worker "stg %[Ptr], [%[Ptr]], #16\n"
139*795d594fSAndroid Build Coastguard Worker "cmp %[Ptr], %[End]\n"
140*795d594fSAndroid Build Coastguard Worker "b.lt 1b\n"
141*795d594fSAndroid Build Coastguard Worker : [Ptr] "+&r"(from)
142*795d594fSAndroid Build Coastguard Worker : [End] "r"(to)
143*795d594fSAndroid Build Coastguard Worker : "memory");
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker #endif
146*795d594fSAndroid Build Coastguard Worker
CopyContextTo(uintptr_t * gprs,uintptr_t * fprs)147*795d594fSAndroid Build Coastguard Worker void Arm64Context::CopyContextTo(uintptr_t* gprs, uintptr_t* fprs) {
148*795d594fSAndroid Build Coastguard Worker // The long jump routine called below expects to find the value for SP at index 31.
149*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(SP, 31);
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < arraysize(gprs_); ++i) {
152*795d594fSAndroid Build Coastguard Worker gprs[i] = gprs_[i] != nullptr ? *gprs_[i] : kBadGprBase + i;
153*795d594fSAndroid Build Coastguard Worker }
154*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumberOfDRegisters; ++i) {
155*795d594fSAndroid Build Coastguard Worker fprs[i] = fprs_[i] != nullptr ? *fprs_[i] : kBadFprBase + i;
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker // Ensure the Thread Register contains the address of the current thread.
158*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(reinterpret_cast<uintptr_t>(Thread::Current()), gprs[TR]);
159*795d594fSAndroid Build Coastguard Worker #if defined(__aarch64__) && defined(__BIONIC__) && defined(M_MEMTAG_STACK_IS_ON)
160*795d594fSAndroid Build Coastguard Worker bool memtag_stack;
161*795d594fSAndroid Build Coastguard Worker // This works fine because versions of Android that did not support M_MEMTAG_STACK_ON did not
162*795d594fSAndroid Build Coastguard Worker // support stack tagging either.
163*795d594fSAndroid Build Coastguard Worker if (android_mallopt(M_MEMTAG_STACK_IS_ON, &memtag_stack, sizeof(memtag_stack)) && memtag_stack)
164*795d594fSAndroid Build Coastguard Worker untag_memory(__builtin_frame_address(0), reinterpret_cast<void*>(gprs[SP]));
165*795d594fSAndroid Build Coastguard Worker #endif
166*795d594fSAndroid Build Coastguard Worker // Tell HWASan about the new stack top.
167*795d594fSAndroid Build Coastguard Worker if (__hwasan_handle_longjmp != nullptr)
168*795d594fSAndroid Build Coastguard Worker __hwasan_handle_longjmp(reinterpret_cast<void*>(gprs[SP]));
169*795d594fSAndroid Build Coastguard Worker // The Marking Register will be updated after return by art_quick_do_long_jump.
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker
172*795d594fSAndroid Build Coastguard Worker } // namespace arm64
173*795d594fSAndroid Build Coastguard Worker } // namespace art
174