1/* 2 * Copyright (c) 2009 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Gabe Black 29 */ 30 31#include "arch/x86/isa.hh" 32 33#include "arch/x86/decoder.hh" 34#include "arch/x86/tlb.hh" 35#include "cpu/base.hh" 36#include "cpu/thread_context.hh" 37#include "params/X86ISA.hh" 38#include "sim/serialize.hh" 39 40namespace X86ISA 41{ 42 43void 44ISA::updateHandyM5Reg(Efer efer, CR0 cr0, 45 SegAttr csAttr, SegAttr ssAttr, RFLAGS rflags, 46 ThreadContext *tc) 47{ 48 HandyM5Reg m5reg = 0; 49 if (efer.lma) { 50 m5reg.mode = LongMode; 51 if (csAttr.longMode) 52 m5reg.submode = SixtyFourBitMode; 53 else 54 m5reg.submode = CompatabilityMode; 55 } else { 56 m5reg.mode = LegacyMode; 57 if (cr0.pe) { 58 if (rflags.vm) 59 m5reg.submode = Virtual8086Mode; 60 else 61 m5reg.submode = ProtectedMode; 62 } else { 63 m5reg.submode = RealMode; 64 } 65 } 66 m5reg.cpl = csAttr.dpl; 67 m5reg.paging = cr0.pg; 68 m5reg.prot = cr0.pe; 69 70 // Compute the default and alternate operand size. 71 if (m5reg.submode == SixtyFourBitMode || csAttr.defaultSize) { 72 m5reg.defOp = 2; 73 m5reg.altOp = 1; 74 } else { 75 m5reg.defOp = 1; 76 m5reg.altOp = 2; 77 } 78 79 // Compute the default and alternate address size. 80 if (m5reg.submode == SixtyFourBitMode) { 81 m5reg.defAddr = 3; 82 m5reg.altAddr = 2; 83 } else if (csAttr.defaultSize) { 84 m5reg.defAddr = 2; 85 m5reg.altAddr = 1; 86 } else { 87 m5reg.defAddr = 1; 88 m5reg.altAddr = 2; 89 } 90 91 // Compute the stack size 92 if (m5reg.submode == SixtyFourBitMode) { 93 m5reg.stack = 3; 94 } else if (ssAttr.defaultSize) { 95 m5reg.stack = 2; 96 } else { 97 m5reg.stack = 1; 98 } 99 100 regVal[MISCREG_M5_REG] = m5reg; 101 if (tc) 102 tc->getDecoderPtr()->setM5Reg(m5reg); 103} 104 105void 106ISA::clear() 107{ 108 // Blank everything. 0 might not be an appropriate value for some things, 109 // but it is for most. 110 memset(regVal, 0, NumMiscRegs * sizeof(RegVal)); 111 regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16); 112 regVal[MISCREG_DR7] = 1 << 10; 113} 114 115ISA::ISA(Params *p) 116 : SimObject(p) 117{ 118 clear(); 119} 120 121const X86ISAParams * 122ISA::params() const 123{ 124 return dynamic_cast<const Params *>(_params); 125} 126 127RegVal 128ISA::readMiscRegNoEffect(int miscReg) const 129{ 130 // Make sure we're not dealing with an illegal control register. 131 // Instructions should filter out these indexes, and nothing else should 132 // attempt to read them directly. 133 assert(isValidMiscReg(miscReg)); 134 135 return regVal[miscReg]; 136} 137 138RegVal 139ISA::readMiscReg(int miscReg, ThreadContext * tc) 140{ 141 if (miscReg == MISCREG_TSC) { 142 return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle(); 143 } 144 145 if (miscReg == MISCREG_FSW) { 146 RegVal fsw = regVal[MISCREG_FSW]; 147 RegVal top = regVal[MISCREG_X87_TOP]; 148 return insertBits(fsw, 13, 11, top); 149 } 150 151 return readMiscRegNoEffect(miscReg); 152} 153 154void 155ISA::setMiscRegNoEffect(int miscReg, RegVal val) 156{ 157 // Make sure we're not dealing with an illegal control register. 158 // Instructions should filter out these indexes, and nothing else should 159 // attempt to write to them directly. 160 assert(isValidMiscReg(miscReg)); 161 162 HandyM5Reg m5Reg = regVal[MISCREG_M5_REG]; 163 int reg_width = 64; 164 switch (miscReg) { 165 case MISCREG_X87_TOP: 166 reg_width = 3; 167 break; 168 case MISCREG_FTW: 169 reg_width = 8; 170 break; 171 case MISCREG_FSW: 172 case MISCREG_FCW: 173 case MISCREG_FOP: 174 reg_width = 16; 175 break; 176 case MISCREG_MXCSR: 177 reg_width = 32; 178 break; 179 case MISCREG_FISEG: 180 case MISCREG_FOSEG: 181 if (m5Reg.submode != SixtyFourBitMode) 182 reg_width = 16; 183 break; 184 case MISCREG_FIOFF: 185 case MISCREG_FOOFF: 186 if (m5Reg.submode != SixtyFourBitMode) 187 reg_width = 32; 188 break; 189 default: 190 break; 191 } 192 193 regVal[miscReg] = val & mask(reg_width); 194} 195 196void 197ISA::setMiscReg(int miscReg, RegVal val, ThreadContext * tc) 198{ 199 RegVal newVal = val; 200 switch(miscReg) 201 { 202 case MISCREG_CR0: 203 { 204 CR0 toggled = regVal[miscReg] ^ val; 205 CR0 newCR0 = val; 206 Efer efer = regVal[MISCREG_EFER]; 207 if (toggled.pg && efer.lme) { 208 if (newCR0.pg) { 209 //Turning on long mode 210 efer.lma = 1; 211 regVal[MISCREG_EFER] = efer; 212 } else { 213 //Turning off long mode 214 efer.lma = 0; 215 regVal[MISCREG_EFER] = efer; 216 } 217 } 218 if (toggled.pg) { 219 dynamic_cast<TLB *>(tc->getITBPtr())->flushAll(); 220 dynamic_cast<TLB *>(tc->getDTBPtr())->flushAll(); 221 } 222 //This must always be 1. 223 newCR0.et = 1; 224 newVal = newCR0; 225 updateHandyM5Reg(regVal[MISCREG_EFER], 226 newCR0, 227 regVal[MISCREG_CS_ATTR], 228 regVal[MISCREG_SS_ATTR], 229 regVal[MISCREG_RFLAGS], 230 tc); 231 } 232 break; 233 case MISCREG_CR2: 234 break; 235 case MISCREG_CR3: 236 dynamic_cast<TLB *>(tc->getITBPtr())->flushNonGlobal(); 237 dynamic_cast<TLB *>(tc->getDTBPtr())->flushNonGlobal(); 238 break; 239 case MISCREG_CR4: 240 { 241 CR4 toggled = regVal[miscReg] ^ val; 242 if (toggled.pae || toggled.pse || toggled.pge) { 243 dynamic_cast<TLB *>(tc->getITBPtr())->flushAll(); 244 dynamic_cast<TLB *>(tc->getDTBPtr())->flushAll(); 245 } 246 } 247 break; 248 case MISCREG_CR8: 249 break; 250 case MISCREG_CS_ATTR: 251 { 252 SegAttr toggled = regVal[miscReg] ^ val; 253 SegAttr newCSAttr = val; 254 if (toggled.longMode) { 255 if (newCSAttr.longMode) { 256 regVal[MISCREG_ES_EFF_BASE] = 0; 257 regVal[MISCREG_CS_EFF_BASE] = 0; 258 regVal[MISCREG_SS_EFF_BASE] = 0; 259 regVal[MISCREG_DS_EFF_BASE] = 0; 260 } else { 261 regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE]; 262 regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE]; 263 regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE]; 264 regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE]; 265 } 266 } 267 updateHandyM5Reg(regVal[MISCREG_EFER], 268 regVal[MISCREG_CR0], 269 newCSAttr, 270 regVal[MISCREG_SS_ATTR], 271 regVal[MISCREG_RFLAGS], 272 tc); 273 } 274 break; 275 case MISCREG_SS_ATTR: 276 updateHandyM5Reg(regVal[MISCREG_EFER], 277 regVal[MISCREG_CR0], 278 regVal[MISCREG_CS_ATTR], 279 val, 280 regVal[MISCREG_RFLAGS], 281 tc); 282 break; 283 // These segments always actually use their bases, or in other words 284 // their effective bases must stay equal to their actual bases. 285 case MISCREG_FS_BASE: 286 case MISCREG_GS_BASE: 287 case MISCREG_HS_BASE: 288 case MISCREG_TSL_BASE: 289 case MISCREG_TSG_BASE: 290 case MISCREG_TR_BASE: 291 case MISCREG_IDTR_BASE: 292 regVal[MISCREG_SEG_EFF_BASE(miscReg - MISCREG_SEG_BASE_BASE)] = val; 293 break; 294 // These segments ignore their bases in 64 bit mode. 295 // their effective bases must stay equal to their actual bases. 296 case MISCREG_ES_BASE: 297 case MISCREG_CS_BASE: 298 case MISCREG_SS_BASE: 299 case MISCREG_DS_BASE: 300 { 301 Efer efer = regVal[MISCREG_EFER]; 302 SegAttr csAttr = regVal[MISCREG_CS_ATTR]; 303 if (!efer.lma || !csAttr.longMode) // Check for non 64 bit mode. 304 regVal[MISCREG_SEG_EFF_BASE(miscReg - 305 MISCREG_SEG_BASE_BASE)] = val; 306 } 307 break; 308 case MISCREG_TSC: 309 regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle(); 310 return; 311 case MISCREG_DR0: 312 case MISCREG_DR1: 313 case MISCREG_DR2: 314 case MISCREG_DR3: 315 /* These should eventually set up breakpoints. */ 316 break; 317 case MISCREG_DR4: 318 miscReg = MISCREG_DR6; 319 M5_FALLTHROUGH; 320 case MISCREG_DR6: 321 { 322 DR6 dr6 = regVal[MISCREG_DR6]; 323 DR6 newDR6 = val; 324 dr6.b0 = newDR6.b0; 325 dr6.b1 = newDR6.b1; 326 dr6.b2 = newDR6.b2; 327 dr6.b3 = newDR6.b3; 328 dr6.bd = newDR6.bd; 329 dr6.bs = newDR6.bs; 330 dr6.bt = newDR6.bt; 331 newVal = dr6; 332 } 333 break; 334 case MISCREG_DR5: 335 miscReg = MISCREG_DR7; 336 M5_FALLTHROUGH; 337 case MISCREG_DR7: 338 { 339 DR7 dr7 = regVal[MISCREG_DR7]; 340 DR7 newDR7 = val; 341 dr7.l0 = newDR7.l0; 342 dr7.g0 = newDR7.g0; 343 if (dr7.l0 || dr7.g0) { 344 panic("Debug register breakpoints not implemented.\n"); 345 } else { 346 /* Disable breakpoint 0. */ 347 } 348 dr7.l1 = newDR7.l1; 349 dr7.g1 = newDR7.g1; 350 if (dr7.l1 || dr7.g1) { 351 panic("Debug register breakpoints not implemented.\n"); 352 } else { 353 /* Disable breakpoint 1. */ 354 } 355 dr7.l2 = newDR7.l2; 356 dr7.g2 = newDR7.g2; 357 if (dr7.l2 || dr7.g2) { 358 panic("Debug register breakpoints not implemented.\n"); 359 } else { 360 /* Disable breakpoint 2. */ 361 } 362 dr7.l3 = newDR7.l3; 363 dr7.g3 = newDR7.g3; 364 if (dr7.l3 || dr7.g3) { 365 panic("Debug register breakpoints not implemented.\n"); 366 } else { 367 /* Disable breakpoint 3. */ 368 } 369 dr7.gd = newDR7.gd; 370 dr7.rw0 = newDR7.rw0; 371 dr7.len0 = newDR7.len0; 372 dr7.rw1 = newDR7.rw1; 373 dr7.len1 = newDR7.len1; 374 dr7.rw2 = newDR7.rw2; 375 dr7.len2 = newDR7.len2; 376 dr7.rw3 = newDR7.rw3; 377 dr7.len3 = newDR7.len3; 378 } 379 break; 380 case MISCREG_M5_REG: 381 // Writing anything to the m5reg with side effects makes it update 382 // based on the current values of the relevant registers. The actual 383 // value written is discarded. 384 updateHandyM5Reg(regVal[MISCREG_EFER], 385 regVal[MISCREG_CR0], 386 regVal[MISCREG_CS_ATTR], 387 regVal[MISCREG_SS_ATTR], 388 regVal[MISCREG_RFLAGS], 389 tc); 390 return; 391 default: 392 break; 393 } 394 setMiscRegNoEffect(miscReg, newVal); 395} 396 397void 398ISA::serialize(CheckpointOut &cp) const 399{ 400 SERIALIZE_ARRAY(regVal, NumMiscRegs); 401} 402 403void 404ISA::unserialize(CheckpointIn &cp) 405{ 406 UNSERIALIZE_ARRAY(regVal, NumMiscRegs); 407 updateHandyM5Reg(regVal[MISCREG_EFER], 408 regVal[MISCREG_CR0], 409 regVal[MISCREG_CS_ATTR], 410 regVal[MISCREG_SS_ATTR], 411 regVal[MISCREG_RFLAGS], 412 NULL); 413} 414 415void 416ISA::startup(ThreadContext *tc) 417{ 418 tc->getDecoderPtr()->setM5Reg(regVal[MISCREG_M5_REG]); 419} 420 421} 422 423X86ISA::ISA * 424X86ISAParams::create() 425{ 426 return new X86ISA::ISA(this); 427} 428