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