1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "instruction_set.h"
18
19 #include "android-base/logging.h"
20 #include "android-base/properties.h"
21 #include "android-base/stringprintf.h"
22 #include "base/bit_utils.h"
23 #include "base/globals.h"
24
25 namespace art {
26
InstructionSetAbort(InstructionSet isa)27 void InstructionSetAbort(InstructionSet isa) {
28 switch (isa) {
29 case InstructionSet::kArm:
30 case InstructionSet::kThumb2:
31 case InstructionSet::kArm64:
32 case InstructionSet::kRiscv64:
33 case InstructionSet::kX86:
34 case InstructionSet::kX86_64:
35 case InstructionSet::kNone:
36 LOG(FATAL) << "Unsupported instruction set " << isa;
37 UNREACHABLE();
38 }
39 LOG(FATAL) << "Unknown ISA " << isa;
40 UNREACHABLE();
41 }
42
GetInstructionSetString(InstructionSet isa)43 const char* GetInstructionSetString(InstructionSet isa) {
44 switch (isa) {
45 case InstructionSet::kArm:
46 case InstructionSet::kThumb2:
47 return "arm";
48 case InstructionSet::kArm64:
49 return "arm64";
50 case InstructionSet::kRiscv64:
51 return "riscv64";
52 case InstructionSet::kX86:
53 return "x86";
54 case InstructionSet::kX86_64:
55 return "x86_64";
56 case InstructionSet::kNone:
57 return "none";
58 }
59 LOG(FATAL) << "Unknown ISA " << isa;
60 UNREACHABLE();
61 }
62
GetInstructionSetFromString(const char * isa_str)63 InstructionSet GetInstructionSetFromString(const char* isa_str) {
64 CHECK(isa_str != nullptr);
65
66 if (strcmp("arm", isa_str) == 0) {
67 return InstructionSet::kArm;
68 } else if (strcmp("arm64", isa_str) == 0) {
69 return InstructionSet::kArm64;
70 } else if (strcmp("riscv64", isa_str) == 0) {
71 return InstructionSet::kRiscv64;
72 } else if (strcmp("x86", isa_str) == 0) {
73 return InstructionSet::kX86;
74 } else if (strcmp("x86_64", isa_str) == 0) {
75 return InstructionSet::kX86_64;
76 }
77
78 return InstructionSet::kNone;
79 }
80
GetSupportedInstructionSets(std::string * error_msg)81 std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg) {
82 std::string zygote_kinds = android::base::GetProperty("ro.zygote", {});
83 if (zygote_kinds.empty()) {
84 *error_msg = "Unable to get Zygote kinds";
85 return {};
86 }
87
88 switch (kRuntimeISA) {
89 case InstructionSet::kArm:
90 case InstructionSet::kArm64:
91 if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
92 return {InstructionSet::kArm64, InstructionSet::kArm};
93 } else if (zygote_kinds == "zygote64") {
94 return {InstructionSet::kArm64};
95 } else if (zygote_kinds == "zygote32") {
96 return {InstructionSet::kArm};
97 } else {
98 *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
99 return {};
100 }
101 case InstructionSet::kRiscv64:
102 return {InstructionSet::kRiscv64};
103 case InstructionSet::kX86:
104 case InstructionSet::kX86_64:
105 if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
106 return {InstructionSet::kX86_64, InstructionSet::kX86};
107 } else if (zygote_kinds == "zygote64") {
108 return {InstructionSet::kX86_64};
109 } else if (zygote_kinds == "zygote32") {
110 return {InstructionSet::kX86};
111 } else {
112 *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
113 return {};
114 }
115 default:
116 *error_msg = android::base::StringPrintf("Unknown runtime ISA '%s'",
117 GetInstructionSetString(kRuntimeISA));
118 return {};
119 }
120 }
121
122 namespace instruction_set_details {
123
124 static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
125 static_assert(IsAligned<kPageSize>(kArm64StackOverflowReservedBytes), "ARM64 gap not page aligned");
126 static_assert(IsAligned<kPageSize>(kRiscv64StackOverflowReservedBytes),
127 "RISCV64 gap not page aligned");
128 static_assert(IsAligned<kPageSize>(kX86StackOverflowReservedBytes), "X86 gap not page aligned");
129 static_assert(IsAligned<kPageSize>(kX86_64StackOverflowReservedBytes),
130 "X86_64 gap not page aligned");
131
132 #if !defined(ART_FRAME_SIZE_LIMIT)
133 #error "ART frame size limit missing"
134 #endif
135
136 // TODO: Should we require an extra page (RoundUp(SIZE) + kPageSize)?
137 static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
138 static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
139 "Frame size limit too large");
140 static_assert(ART_FRAME_SIZE_LIMIT < kRiscv64StackOverflowReservedBytes,
141 "Frame size limit too large");
142 static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
143 "Frame size limit too large");
144 static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
145 "Frame size limit too large");
146
GetStackOverflowReservedBytesFailure(const char * error_msg)147 NO_RETURN void GetStackOverflowReservedBytesFailure(const char* error_msg) {
148 LOG(FATAL) << error_msg;
149 UNREACHABLE();
150 }
151
152 } // namespace instruction_set_details
153
154 } // namespace art
155