isa.hh revision 11768:5b80960dcf08
1/* 2 * Copyright (c) 2010, 2012-2016 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2009 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Gabe Black 41 */ 42 43#ifndef __ARCH_ARM_ISA_HH__ 44#define __ARCH_ARM_ISA_HH__ 45 46#include "arch/arm/isa_device.hh" 47#include "arch/arm/registers.hh" 48#include "arch/arm/system.hh" 49#include "arch/arm/tlb.hh" 50#include "arch/arm/types.hh" 51#include "debug/Checkpoint.hh" 52#include "sim/sim_object.hh" 53#include "enums/DecoderFlavour.hh" 54 55struct ArmISAParams; 56struct DummyArmISADeviceParams; 57class ThreadContext; 58class Checkpoint; 59class EventManager; 60 61namespace ArmISA 62{ 63 class ISA : public SimObject 64 { 65 protected: 66 // Parent system 67 ArmSystem *system; 68 69 // Micro Architecture 70 const Enums::DecoderFlavour _decoderFlavour; 71 72 /** Dummy device for to handle non-existing ISA devices */ 73 DummyISADevice dummyDevice; 74 75 // PMU belonging to this ISA 76 BaseISADevice *pmu; 77 78 // Generic timer interface belonging to this ISA 79 std::unique_ptr<BaseISADevice> timer; 80 81 // Cached copies of system-level properties 82 bool haveSecurity; 83 bool haveLPAE; 84 bool haveVirtualization; 85 bool haveLargeAsid64; 86 uint8_t physAddrRange64; 87 88 /** Register translation entry used in lookUpMiscReg */ 89 struct MiscRegLUTEntry { 90 uint32_t lower; 91 uint32_t upper; 92 }; 93 94 struct MiscRegInitializerEntry { 95 uint32_t index; 96 struct MiscRegLUTEntry entry; 97 }; 98 99 /** Register table noting all translations */ 100 static const struct MiscRegInitializerEntry MiscRegSwitch[]; 101 102 /** Translation table accessible via the value of the register */ 103 std::vector<struct MiscRegLUTEntry> lookUpMiscReg; 104 105 MiscReg miscRegs[NumMiscRegs]; 106 const IntRegIndex *intRegMap; 107 108 void 109 updateRegMap(CPSR cpsr) 110 { 111 if (cpsr.width == 0) { 112 intRegMap = IntReg64Map; 113 } else { 114 switch (cpsr.mode) { 115 case MODE_USER: 116 case MODE_SYSTEM: 117 intRegMap = IntRegUsrMap; 118 break; 119 case MODE_FIQ: 120 intRegMap = IntRegFiqMap; 121 break; 122 case MODE_IRQ: 123 intRegMap = IntRegIrqMap; 124 break; 125 case MODE_SVC: 126 intRegMap = IntRegSvcMap; 127 break; 128 case MODE_MON: 129 intRegMap = IntRegMonMap; 130 break; 131 case MODE_ABORT: 132 intRegMap = IntRegAbtMap; 133 break; 134 case MODE_HYP: 135 intRegMap = IntRegHypMap; 136 break; 137 case MODE_UNDEFINED: 138 intRegMap = IntRegUndMap; 139 break; 140 default: 141 panic("Unrecognized mode setting in CPSR.\n"); 142 } 143 } 144 } 145 146 BaseISADevice &getGenericTimer(ThreadContext *tc); 147 148 149 private: 150 inline void assert32(ThreadContext *tc) { 151 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc); 152 assert(cpsr.width); 153 } 154 155 inline void assert64(ThreadContext *tc) { 156 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc); 157 assert(!cpsr.width); 158 } 159 160 void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid, 161 bool secure_lookup, uint8_t target_el); 162 163 void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el); 164 165 void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el); 166 167 void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup, 168 bool hyp, uint8_t target_el); 169 170 public: 171 void clear(); 172 void clear64(const ArmISAParams *p); 173 174 MiscReg readMiscRegNoEffect(int misc_reg) const; 175 MiscReg readMiscReg(int misc_reg, ThreadContext *tc); 176 void setMiscRegNoEffect(int misc_reg, const MiscReg &val); 177 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc); 178 179 int 180 flattenIntIndex(int reg) const 181 { 182 assert(reg >= 0); 183 if (reg < NUM_ARCH_INTREGS) { 184 return intRegMap[reg]; 185 } else if (reg < NUM_INTREGS) { 186 return reg; 187 } else if (reg == INTREG_SPX) { 188 CPSR cpsr = miscRegs[MISCREG_CPSR]; 189 ExceptionLevel el = opModeToEL( 190 (OperatingMode) (uint8_t) cpsr.mode); 191 if (!cpsr.sp && el != EL0) 192 return INTREG_SP0; 193 switch (el) { 194 case EL3: 195 return INTREG_SP3; 196 case EL2: 197 return INTREG_SP2; 198 case EL1: 199 return INTREG_SP1; 200 case EL0: 201 return INTREG_SP0; 202 default: 203 panic("Invalid exception level"); 204 break; 205 } 206 } else { 207 return flattenIntRegModeIndex(reg); 208 } 209 } 210 211 int 212 flattenFloatIndex(int reg) const 213 { 214 assert(reg >= 0); 215 return reg; 216 } 217 218 int 219 flattenCCIndex(int reg) const 220 { 221 assert(reg >= 0); 222 return reg; 223 } 224 225 int 226 flattenMiscIndex(int reg) const 227 { 228 assert(reg >= 0); 229 int flat_idx = reg; 230 231 if (reg == MISCREG_SPSR) { 232 CPSR cpsr = miscRegs[MISCREG_CPSR]; 233 switch (cpsr.mode) { 234 case MODE_EL0T: 235 warn("User mode does not have SPSR\n"); 236 flat_idx = MISCREG_SPSR; 237 break; 238 case MODE_EL1T: 239 case MODE_EL1H: 240 flat_idx = MISCREG_SPSR_EL1; 241 break; 242 case MODE_EL2T: 243 case MODE_EL2H: 244 flat_idx = MISCREG_SPSR_EL2; 245 break; 246 case MODE_EL3T: 247 case MODE_EL3H: 248 flat_idx = MISCREG_SPSR_EL3; 249 break; 250 case MODE_USER: 251 warn("User mode does not have SPSR\n"); 252 flat_idx = MISCREG_SPSR; 253 break; 254 case MODE_FIQ: 255 flat_idx = MISCREG_SPSR_FIQ; 256 break; 257 case MODE_IRQ: 258 flat_idx = MISCREG_SPSR_IRQ; 259 break; 260 case MODE_SVC: 261 flat_idx = MISCREG_SPSR_SVC; 262 break; 263 case MODE_MON: 264 flat_idx = MISCREG_SPSR_MON; 265 break; 266 case MODE_ABORT: 267 flat_idx = MISCREG_SPSR_ABT; 268 break; 269 case MODE_HYP: 270 flat_idx = MISCREG_SPSR_HYP; 271 break; 272 case MODE_UNDEFINED: 273 flat_idx = MISCREG_SPSR_UND; 274 break; 275 default: 276 warn("Trying to access SPSR in an invalid mode: %d\n", 277 cpsr.mode); 278 flat_idx = MISCREG_SPSR; 279 break; 280 } 281 } else if (miscRegInfo[reg][MISCREG_MUTEX]) { 282 // Mutually exclusive CP15 register 283 switch (reg) { 284 case MISCREG_PRRR_MAIR0: 285 case MISCREG_PRRR_MAIR0_NS: 286 case MISCREG_PRRR_MAIR0_S: 287 { 288 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR); 289 // If the muxed reg has been flattened, work out the 290 // offset and apply it to the unmuxed reg 291 int idxOffset = reg - MISCREG_PRRR_MAIR0; 292 if (ttbcr.eae) 293 flat_idx = flattenMiscIndex(MISCREG_MAIR0 + 294 idxOffset); 295 else 296 flat_idx = flattenMiscIndex(MISCREG_PRRR + 297 idxOffset); 298 } 299 break; 300 case MISCREG_NMRR_MAIR1: 301 case MISCREG_NMRR_MAIR1_NS: 302 case MISCREG_NMRR_MAIR1_S: 303 { 304 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR); 305 // If the muxed reg has been flattened, work out the 306 // offset and apply it to the unmuxed reg 307 int idxOffset = reg - MISCREG_NMRR_MAIR1; 308 if (ttbcr.eae) 309 flat_idx = flattenMiscIndex(MISCREG_MAIR1 + 310 idxOffset); 311 else 312 flat_idx = flattenMiscIndex(MISCREG_NMRR + 313 idxOffset); 314 } 315 break; 316 case MISCREG_PMXEVTYPER_PMCCFILTR: 317 { 318 PMSELR pmselr = miscRegs[MISCREG_PMSELR]; 319 if (pmselr.sel == 31) 320 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR); 321 else 322 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER); 323 } 324 break; 325 default: 326 panic("Unrecognized misc. register.\n"); 327 break; 328 } 329 } else { 330 if (miscRegInfo[reg][MISCREG_BANKED]) { 331 bool secureReg = haveSecurity && 332 inSecureState(miscRegs[MISCREG_SCR], 333 miscRegs[MISCREG_CPSR]); 334 flat_idx += secureReg ? 2 : 1; 335 } 336 } 337 return flat_idx; 338 } 339 340 void serialize(CheckpointOut &cp) const 341 { 342 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n"); 343 SERIALIZE_ARRAY(miscRegs, NumMiscRegs); 344 345 SERIALIZE_SCALAR(haveSecurity); 346 SERIALIZE_SCALAR(haveLPAE); 347 SERIALIZE_SCALAR(haveVirtualization); 348 SERIALIZE_SCALAR(haveLargeAsid64); 349 SERIALIZE_SCALAR(physAddrRange64); 350 } 351 void unserialize(CheckpointIn &cp) 352 { 353 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n"); 354 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs); 355 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR]; 356 updateRegMap(tmp_cpsr); 357 358 UNSERIALIZE_SCALAR(haveSecurity); 359 UNSERIALIZE_SCALAR(haveLPAE); 360 UNSERIALIZE_SCALAR(haveVirtualization); 361 UNSERIALIZE_SCALAR(haveLargeAsid64); 362 UNSERIALIZE_SCALAR(physAddrRange64); 363 } 364 365 void startup(ThreadContext *tc) {} 366 367 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; } 368 369 /// Explicitly import the otherwise hidden startup 370 using SimObject::startup; 371 372 typedef ArmISAParams Params; 373 374 const Params *params() const; 375 376 ISA(Params *p); 377 }; 378} 379 380#endif 381