Home | History | Annotate | Download | only in arch
      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 // Explicitly include our own elf.h to avoid Linux and other dependencies.
     20 #include "../elf.h"
     21 #include "android-base/logging.h"
     22 #include "base/bit_utils.h"
     23 #include "globals.h"
     24 
     25 namespace art {
     26 
     27 void InstructionSetAbort(InstructionSet isa) {
     28   switch (isa) {
     29     case InstructionSet::kArm:
     30     case InstructionSet::kThumb2:
     31     case InstructionSet::kArm64:
     32     case InstructionSet::kX86:
     33     case InstructionSet::kX86_64:
     34     case InstructionSet::kMips:
     35     case InstructionSet::kMips64:
     36     case InstructionSet::kNone:
     37       LOG(FATAL) << "Unsupported instruction set " << isa;
     38       UNREACHABLE();
     39   }
     40   LOG(FATAL) << "Unknown ISA " << isa;
     41   UNREACHABLE();
     42 }
     43 
     44 const char* GetInstructionSetString(InstructionSet isa) {
     45   switch (isa) {
     46     case InstructionSet::kArm:
     47     case InstructionSet::kThumb2:
     48       return "arm";
     49     case InstructionSet::kArm64:
     50       return "arm64";
     51     case InstructionSet::kX86:
     52       return "x86";
     53     case InstructionSet::kX86_64:
     54       return "x86_64";
     55     case InstructionSet::kMips:
     56       return "mips";
     57     case InstructionSet::kMips64:
     58       return "mips64";
     59     case InstructionSet::kNone:
     60       return "none";
     61   }
     62   LOG(FATAL) << "Unknown ISA " << isa;
     63   UNREACHABLE();
     64 }
     65 
     66 InstructionSet GetInstructionSetFromString(const char* isa_str) {
     67   CHECK(isa_str != nullptr);
     68 
     69   if (strcmp("arm", isa_str) == 0) {
     70     return InstructionSet::kArm;
     71   } else if (strcmp("arm64", isa_str) == 0) {
     72     return InstructionSet::kArm64;
     73   } else if (strcmp("x86", isa_str) == 0) {
     74     return InstructionSet::kX86;
     75   } else if (strcmp("x86_64", isa_str) == 0) {
     76     return InstructionSet::kX86_64;
     77   } else if (strcmp("mips", isa_str) == 0) {
     78     return InstructionSet::kMips;
     79   } else if (strcmp("mips64", isa_str) == 0) {
     80     return InstructionSet::kMips64;
     81   }
     82 
     83   return InstructionSet::kNone;
     84 }
     85 
     86 InstructionSet GetInstructionSetFromELF(uint16_t e_machine, uint32_t e_flags) {
     87   switch (e_machine) {
     88     case EM_ARM:
     89       return InstructionSet::kArm;
     90     case EM_AARCH64:
     91       return InstructionSet::kArm64;
     92     case EM_386:
     93       return InstructionSet::kX86;
     94     case EM_X86_64:
     95       return InstructionSet::kX86_64;
     96     case EM_MIPS: {
     97       if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R2 ||
     98           (e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_32R6) {
     99         return InstructionSet::kMips;
    100       } else if ((e_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_64R6) {
    101         return InstructionSet::kMips64;
    102       }
    103       break;
    104     }
    105   }
    106   return InstructionSet::kNone;
    107 }
    108 
    109 size_t GetInstructionSetAlignment(InstructionSet isa) {
    110   switch (isa) {
    111     case InstructionSet::kArm:
    112       // Fall-through.
    113     case InstructionSet::kThumb2:
    114       return kArmAlignment;
    115     case InstructionSet::kArm64:
    116       return kArm64Alignment;
    117     case InstructionSet::kX86:
    118       // Fall-through.
    119     case InstructionSet::kX86_64:
    120       return kX86Alignment;
    121     case InstructionSet::kMips:
    122       // Fall-through.
    123     case InstructionSet::kMips64:
    124       return kMipsAlignment;
    125     case InstructionSet::kNone:
    126       LOG(FATAL) << "ISA kNone does not have alignment.";
    127       UNREACHABLE();
    128   }
    129   LOG(FATAL) << "Unknown ISA " << isa;
    130   UNREACHABLE();
    131 }
    132 
    133 #if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
    134     !defined(ART_STACK_OVERFLOW_GAP_mips) || !defined(ART_STACK_OVERFLOW_GAP_mips64) || \
    135     !defined(ART_STACK_OVERFLOW_GAP_x86) || !defined(ART_STACK_OVERFLOW_GAP_x86_64)
    136 #error "Missing defines for stack overflow gap"
    137 #endif
    138 
    139 static constexpr size_t kArmStackOverflowReservedBytes    = ART_STACK_OVERFLOW_GAP_arm;
    140 static constexpr size_t kArm64StackOverflowReservedBytes  = ART_STACK_OVERFLOW_GAP_arm64;
    141 static constexpr size_t kMipsStackOverflowReservedBytes   = ART_STACK_OVERFLOW_GAP_mips;
    142 static constexpr size_t kMips64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_mips64;
    143 static constexpr size_t kX86StackOverflowReservedBytes    = ART_STACK_OVERFLOW_GAP_x86;
    144 static constexpr size_t kX86_64StackOverflowReservedBytes = ART_STACK_OVERFLOW_GAP_x86_64;
    145 
    146 static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
    147 static_assert(IsAligned<kPageSize>(kArm64StackOverflowReservedBytes), "ARM64 gap not page aligned");
    148 static_assert(IsAligned<kPageSize>(kMipsStackOverflowReservedBytes), "Mips gap not page aligned");
    149 static_assert(IsAligned<kPageSize>(kMips64StackOverflowReservedBytes),
    150               "Mips64 gap not page aligned");
    151 static_assert(IsAligned<kPageSize>(kX86StackOverflowReservedBytes), "X86 gap not page aligned");
    152 static_assert(IsAligned<kPageSize>(kX86_64StackOverflowReservedBytes),
    153               "X86_64 gap not page aligned");
    154 
    155 #if !defined(ART_FRAME_SIZE_LIMIT)
    156 #error "ART frame size limit missing"
    157 #endif
    158 
    159 // TODO: Should we require an extra page (RoundUp(SIZE) + kPageSize)?
    160 static_assert(ART_FRAME_SIZE_LIMIT < kArmStackOverflowReservedBytes, "Frame size limit too large");
    161 static_assert(ART_FRAME_SIZE_LIMIT < kArm64StackOverflowReservedBytes,
    162               "Frame size limit too large");
    163 static_assert(ART_FRAME_SIZE_LIMIT < kMipsStackOverflowReservedBytes,
    164               "Frame size limit too large");
    165 static_assert(ART_FRAME_SIZE_LIMIT < kMips64StackOverflowReservedBytes,
    166               "Frame size limit too large");
    167 static_assert(ART_FRAME_SIZE_LIMIT < kX86StackOverflowReservedBytes,
    168               "Frame size limit too large");
    169 static_assert(ART_FRAME_SIZE_LIMIT < kX86_64StackOverflowReservedBytes,
    170               "Frame size limit too large");
    171 
    172 size_t GetStackOverflowReservedBytes(InstructionSet isa) {
    173   switch (isa) {
    174     case InstructionSet::kArm:      // Intentional fall-through.
    175     case InstructionSet::kThumb2:
    176       return kArmStackOverflowReservedBytes;
    177 
    178     case InstructionSet::kArm64:
    179       return kArm64StackOverflowReservedBytes;
    180 
    181     case InstructionSet::kMips:
    182       return kMipsStackOverflowReservedBytes;
    183 
    184     case InstructionSet::kMips64:
    185       return kMips64StackOverflowReservedBytes;
    186 
    187     case InstructionSet::kX86:
    188       return kX86StackOverflowReservedBytes;
    189 
    190     case InstructionSet::kX86_64:
    191       return kX86_64StackOverflowReservedBytes;
    192 
    193     case InstructionSet::kNone:
    194       LOG(FATAL) << "kNone has no stack overflow size";
    195       UNREACHABLE();
    196   }
    197   LOG(FATAL) << "Unknown instruction set" << isa;
    198   UNREACHABLE();
    199 }
    200 
    201 }  // namespace art
    202