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 #if !defined(ART_FRAME_SIZE_LIMIT)
125 #error "ART frame size limit missing"
126 #endif
127
128 // TODO: Should we require an extra page (RoundUp(SIZE) + gPageSize)?
129 static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
130 static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
131 "Frame size limit too large");
132 static_assert(ART_FRAME_SIZE_LIMIT < kRiscv64StackOverflowReservedBytes,
133 "Frame size limit too large");
134 static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
135 "Frame size limit too large");
136 static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
137 "Frame size limit too large");
138
GetStackOverflowReservedBytesFailure(const char * error_msg)139 NO_RETURN void GetStackOverflowReservedBytesFailure(const char* error_msg) {
140 LOG(FATAL) << error_msg;
141 UNREACHABLE();
142 }
143
144 } // namespace instruction_set_details
145
146 } // namespace art
147