1 /* 2 * MIPS TLB (Translation lookaside buffer) helpers. 3 * 4 * Copyright (c) 2004-2005 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include "qemu/osdep.h" 20 #include "qemu/bitops.h" 21 22 #include "cpu.h" 23 #include "internal.h" 24 #include "exec/cputlb.h" 25 #include "exec/exec-all.h" 26 #include "exec/page-protection.h" 27 #include "exec/cpu_ldst.h" 28 #include "exec/log.h" 29 #include "exec/helper-proto.h" 30 31 /* TLB management */ 32 static void r4k_mips_tlb_flush_extra(CPUMIPSState *env, int first) 33 { 34 /* Discard entries from env->tlb[first] onwards. */ 35 while (env->tlb->tlb_in_use > first) { 36 r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0); 37 } 38 } 39 40 static inline uint64_t get_tlb_pfn_from_entrylo(uint64_t entrylo) 41 { 42 #if defined(TARGET_MIPS64) 43 return extract64(entrylo, 6, 54); 44 #else 45 return extract64(entrylo, 6, 24) | /* PFN */ 46 (extract64(entrylo, 32, 32) << 24); /* PFNX */ 47 #endif 48 } 49 50 static void r4k_fill_tlb(CPUMIPSState *env, int idx) 51 { 52 r4k_tlb_t *tlb; 53 uint64_t mask = env->CP0_PageMask >> (TARGET_PAGE_BITS + 1); 54 55 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ 56 tlb = &env->tlb->mmu.r4k.tlb[idx]; 57 if (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) { 58 tlb->EHINV = 1; 59 return; 60 } 61 tlb->EHINV = 0; 62 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); 63 #if defined(TARGET_MIPS64) 64 tlb->VPN &= env->SEGMask; 65 #endif 66 tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 67 tlb->MMID = env->CP0_MemoryMapID; 68 tlb->PageMask = env->CP0_PageMask; 69 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 70 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; 71 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; 72 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; 73 tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; 74 tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; 75 tlb->PFN[0] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo0) & ~mask) << 12; 76 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; 77 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; 78 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; 79 tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; 80 tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; 81 tlb->PFN[1] = (get_tlb_pfn_from_entrylo(env->CP0_EntryLo1) & ~mask) << 12; 82 } 83 84 static void r4k_helper_tlbinv(CPUMIPSState *env) 85 { 86 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 87 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 88 uint32_t MMID = env->CP0_MemoryMapID; 89 uint32_t tlb_mmid; 90 r4k_tlb_t *tlb; 91 int idx; 92 93 MMID = mi ? MMID : (uint32_t) ASID; 94 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 95 tlb = &env->tlb->mmu.r4k.tlb[idx]; 96 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 97 if (!tlb->G && tlb_mmid == MMID) { 98 tlb->EHINV = 1; 99 } 100 } 101 cpu_mips_tlb_flush(env); 102 } 103 104 static void r4k_helper_tlbinvf(CPUMIPSState *env) 105 { 106 int idx; 107 108 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 109 env->tlb->mmu.r4k.tlb[idx].EHINV = 1; 110 } 111 cpu_mips_tlb_flush(env); 112 } 113 114 static void r4k_helper_tlbwi(CPUMIPSState *env) 115 { 116 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 117 target_ulong VPN; 118 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 119 uint32_t MMID = env->CP0_MemoryMapID; 120 uint32_t tlb_mmid; 121 bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1; 122 r4k_tlb_t *tlb; 123 int idx; 124 125 MMID = mi ? MMID : (uint32_t) ASID; 126 127 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; 128 tlb = &env->tlb->mmu.r4k.tlb[idx]; 129 VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1); 130 #if defined(TARGET_MIPS64) 131 VPN &= env->SEGMask; 132 #endif 133 EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0; 134 G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1; 135 V0 = (env->CP0_EntryLo0 & 2) != 0; 136 D0 = (env->CP0_EntryLo0 & 4) != 0; 137 XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) &1; 138 RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) &1; 139 V1 = (env->CP0_EntryLo1 & 2) != 0; 140 D1 = (env->CP0_EntryLo1 & 4) != 0; 141 XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) &1; 142 RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) &1; 143 144 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 145 /* 146 * Discard cached TLB entries, unless tlbwi is just upgrading access 147 * permissions on the current entry. 148 */ 149 if (tlb->VPN != VPN || tlb_mmid != MMID || tlb->G != G || 150 (!tlb->EHINV && EHINV) || 151 (tlb->V0 && !V0) || (tlb->D0 && !D0) || 152 (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) || 153 (tlb->V1 && !V1) || (tlb->D1 && !D1) || 154 (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) { 155 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); 156 } 157 158 r4k_invalidate_tlb(env, idx, 0); 159 r4k_fill_tlb(env, idx); 160 } 161 162 static void r4k_helper_tlbwr(CPUMIPSState *env) 163 { 164 int r = cpu_mips_get_random(env); 165 166 r4k_invalidate_tlb(env, r, 1); 167 r4k_fill_tlb(env, r); 168 } 169 170 static void r4k_helper_tlbp(CPUMIPSState *env) 171 { 172 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 173 r4k_tlb_t *tlb; 174 target_ulong mask; 175 target_ulong tag; 176 target_ulong VPN; 177 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 178 uint32_t MMID = env->CP0_MemoryMapID; 179 uint32_t tlb_mmid; 180 int i; 181 182 MMID = mi ? MMID : (uint32_t) ASID; 183 for (i = 0; i < env->tlb->nb_tlb; i++) { 184 tlb = &env->tlb->mmu.r4k.tlb[i]; 185 /* 1k pages are not supported. */ 186 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 187 tag = env->CP0_EntryHi & ~mask; 188 VPN = tlb->VPN & ~mask; 189 #if defined(TARGET_MIPS64) 190 tag &= env->SEGMask; 191 #endif 192 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 193 /* Check ASID/MMID, virtual page number & size */ 194 if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) { 195 /* TLB match */ 196 env->CP0_Index = i; 197 break; 198 } 199 } 200 if (i == env->tlb->nb_tlb) { 201 /* No match. Discard any shadow entries, if any of them match. */ 202 for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) { 203 tlb = &env->tlb->mmu.r4k.tlb[i]; 204 /* 1k pages are not supported. */ 205 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 206 tag = env->CP0_EntryHi & ~mask; 207 VPN = tlb->VPN & ~mask; 208 #if defined(TARGET_MIPS64) 209 tag &= env->SEGMask; 210 #endif 211 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 212 /* Check ASID/MMID, virtual page number & size */ 213 if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag) { 214 r4k_mips_tlb_flush_extra(env, i); 215 break; 216 } 217 } 218 219 env->CP0_Index |= 0x80000000; 220 } 221 } 222 223 static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn) 224 { 225 #if defined(TARGET_MIPS64) 226 return tlb_pfn << 6; 227 #else 228 return (extract64(tlb_pfn, 0, 24) << 6) | /* PFN */ 229 (extract64(tlb_pfn, 24, 32) << 32); /* PFNX */ 230 #endif 231 } 232 233 static void r4k_helper_tlbr(CPUMIPSState *env) 234 { 235 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 236 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 237 uint32_t MMID = env->CP0_MemoryMapID; 238 uint32_t tlb_mmid; 239 r4k_tlb_t *tlb; 240 int idx; 241 242 MMID = mi ? MMID : (uint32_t) ASID; 243 idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb; 244 tlb = &env->tlb->mmu.r4k.tlb[idx]; 245 246 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 247 /* If this will change the current ASID/MMID, flush qemu's TLB. */ 248 if (MMID != tlb_mmid) { 249 cpu_mips_tlb_flush(env); 250 } 251 252 r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb); 253 254 if (tlb->EHINV) { 255 env->CP0_EntryHi = 1 << CP0EnHi_EHINV; 256 env->CP0_PageMask = 0; 257 env->CP0_EntryLo0 = 0; 258 env->CP0_EntryLo1 = 0; 259 } else { 260 env->CP0_EntryHi = mi ? tlb->VPN : tlb->VPN | tlb->ASID; 261 env->CP0_MemoryMapID = tlb->MMID; 262 env->CP0_PageMask = tlb->PageMask; 263 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | 264 ((uint64_t)tlb->RI0 << CP0EnLo_RI) | 265 ((uint64_t)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) | 266 get_entrylo_pfn_from_tlb(tlb->PFN[0] >> 12); 267 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | 268 ((uint64_t)tlb->RI1 << CP0EnLo_RI) | 269 ((uint64_t)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) | 270 get_entrylo_pfn_from_tlb(tlb->PFN[1] >> 12); 271 } 272 } 273 274 void helper_tlbwi(CPUMIPSState *env) 275 { 276 env->tlb->helper_tlbwi(env); 277 } 278 279 void helper_tlbwr(CPUMIPSState *env) 280 { 281 env->tlb->helper_tlbwr(env); 282 } 283 284 void helper_tlbp(CPUMIPSState *env) 285 { 286 env->tlb->helper_tlbp(env); 287 } 288 289 void helper_tlbr(CPUMIPSState *env) 290 { 291 env->tlb->helper_tlbr(env); 292 } 293 294 void helper_tlbinv(CPUMIPSState *env) 295 { 296 env->tlb->helper_tlbinv(env); 297 } 298 299 void helper_tlbinvf(CPUMIPSState *env) 300 { 301 env->tlb->helper_tlbinvf(env); 302 } 303 304 static void global_invalidate_tlb(CPUMIPSState *env, 305 uint32_t invMsgVPN2, 306 uint8_t invMsgR, 307 uint32_t invMsgMMid, 308 bool invAll, 309 bool invVAMMid, 310 bool invMMid, 311 bool invVA) 312 { 313 314 int idx; 315 r4k_tlb_t *tlb; 316 bool VAMatch; 317 bool MMidMatch; 318 319 for (idx = 0; idx < env->tlb->nb_tlb; idx++) { 320 tlb = &env->tlb->mmu.r4k.tlb[idx]; 321 VAMatch = 322 (((tlb->VPN & ~tlb->PageMask) == (invMsgVPN2 & ~tlb->PageMask)) 323 #ifdef TARGET_MIPS64 324 && 325 (extract64(env->CP0_EntryHi, 62, 2) == invMsgR) 326 #endif 327 ); 328 MMidMatch = tlb->MMID == invMsgMMid; 329 if ((invAll && (idx > env->CP0_Wired)) || 330 (VAMatch && invVAMMid && (tlb->G || MMidMatch)) || 331 (VAMatch && invVA) || 332 (MMidMatch && !(tlb->G) && invMMid)) { 333 tlb->EHINV = 1; 334 } 335 } 336 cpu_mips_tlb_flush(env); 337 } 338 339 void helper_ginvt(CPUMIPSState *env, target_ulong arg, uint32_t type) 340 { 341 bool invAll = type == 0; 342 bool invVA = type == 1; 343 bool invMMid = type == 2; 344 bool invVAMMid = type == 3; 345 uint32_t invMsgVPN2 = arg & (TARGET_PAGE_MASK << 1); 346 uint8_t invMsgR = 0; 347 uint32_t invMsgMMid = env->CP0_MemoryMapID; 348 CPUState *other_cs = first_cpu; 349 350 #ifdef TARGET_MIPS64 351 invMsgR = extract64(arg, 62, 2); 352 #endif 353 354 CPU_FOREACH(other_cs) { 355 MIPSCPU *other_cpu = MIPS_CPU(other_cs); 356 global_invalidate_tlb(&other_cpu->env, invMsgVPN2, invMsgR, invMsgMMid, 357 invAll, invVAMMid, invMMid, invVA); 358 } 359 } 360 361 /* no MMU emulation */ 362 static int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, 363 target_ulong address, MMUAccessType access_type) 364 { 365 *physical = address; 366 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 367 return TLBRET_MATCH; 368 } 369 370 /* fixed mapping MMU emulation */ 371 static int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, 372 int *prot, target_ulong address, 373 MMUAccessType access_type) 374 { 375 if (address <= (int32_t)0x7FFFFFFFUL) { 376 if (!(env->CP0_Status & (1 << CP0St_ERL))) { 377 *physical = address + 0x40000000UL; 378 } else { 379 *physical = address; 380 } 381 } else if (address <= (int32_t)0xBFFFFFFFUL) { 382 *physical = address & 0x1FFFFFFF; 383 } else { 384 *physical = address; 385 } 386 387 *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; 388 return TLBRET_MATCH; 389 } 390 391 /* MIPS32/MIPS64 R4000-style MMU emulation */ 392 static int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, 393 target_ulong address, MMUAccessType access_type) 394 { 395 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 396 uint32_t MMID = env->CP0_MemoryMapID; 397 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 398 uint32_t tlb_mmid; 399 int i; 400 401 MMID = mi ? MMID : (uint32_t) ASID; 402 403 for (i = 0; i < env->tlb->tlb_in_use; i++) { 404 r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i]; 405 /* 1k pages are not supported. */ 406 target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 407 target_ulong tag = address & ~mask; 408 target_ulong VPN = tlb->VPN & ~mask; 409 #if defined(TARGET_MIPS64) 410 tag &= env->SEGMask; 411 #endif 412 413 /* Check ASID/MMID, virtual page number & size */ 414 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 415 if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) { 416 /* TLB match */ 417 int n = !!(address & mask & ~(mask >> 1)); 418 /* Check access rights */ 419 if (!(n ? tlb->V1 : tlb->V0)) { 420 return TLBRET_INVALID; 421 } 422 if (access_type == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { 423 return TLBRET_XI; 424 } 425 if (access_type == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { 426 return TLBRET_RI; 427 } 428 if (access_type != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { 429 *physical = tlb->PFN[n] | (address & (mask >> 1)); 430 *prot = PAGE_READ; 431 if (n ? tlb->D1 : tlb->D0) { 432 *prot |= PAGE_WRITE; 433 } 434 if (!(n ? tlb->XI1 : tlb->XI0)) { 435 *prot |= PAGE_EXEC; 436 } 437 return TLBRET_MATCH; 438 } 439 return TLBRET_DIRTY; 440 } 441 } 442 return TLBRET_NOMATCH; 443 } 444 445 static void no_mmu_init(CPUMIPSState *env, const mips_def_t *def) 446 { 447 env->tlb->nb_tlb = 1; 448 env->tlb->map_address = &no_mmu_map_address; 449 } 450 451 static void fixed_mmu_init(CPUMIPSState *env, const mips_def_t *def) 452 { 453 env->tlb->nb_tlb = 1; 454 env->tlb->map_address = &fixed_mmu_map_address; 455 } 456 457 static void r4k_mmu_init(CPUMIPSState *env, const mips_def_t *def) 458 { 459 env->tlb->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63); 460 env->tlb->map_address = &r4k_map_address; 461 env->tlb->helper_tlbwi = r4k_helper_tlbwi; 462 env->tlb->helper_tlbwr = r4k_helper_tlbwr; 463 env->tlb->helper_tlbp = r4k_helper_tlbp; 464 env->tlb->helper_tlbr = r4k_helper_tlbr; 465 env->tlb->helper_tlbinv = r4k_helper_tlbinv; 466 env->tlb->helper_tlbinvf = r4k_helper_tlbinvf; 467 } 468 469 void mmu_init(CPUMIPSState *env, const mips_def_t *def) 470 { 471 env->tlb = g_malloc0(sizeof(CPUMIPSTLBContext)); 472 473 switch (def->mmu_type) { 474 case MMU_TYPE_NONE: 475 no_mmu_init(env, def); 476 break; 477 case MMU_TYPE_R4000: 478 r4k_mmu_init(env, def); 479 break; 480 case MMU_TYPE_FMT: 481 fixed_mmu_init(env, def); 482 break; 483 case MMU_TYPE_R3000: 484 case MMU_TYPE_R6000: 485 case MMU_TYPE_R8000: 486 default: 487 cpu_abort(env_cpu(env), "MMU type not supported\n"); 488 } 489 } 490 491 void cpu_mips_tlb_flush(CPUMIPSState *env) 492 { 493 /* Flush qemu's TLB and discard all shadowed entries. */ 494 tlb_flush(env_cpu(env)); 495 env->tlb->tlb_in_use = env->tlb->nb_tlb; 496 } 497 498 static void raise_mmu_exception(CPUMIPSState *env, target_ulong address, 499 MMUAccessType access_type, int tlb_error) 500 { 501 CPUState *cs = env_cpu(env); 502 int exception = 0, error_code = 0; 503 504 if (access_type == MMU_INST_FETCH) { 505 error_code |= EXCP_INST_NOTAVAIL; 506 } 507 508 switch (tlb_error) { 509 default: 510 case TLBRET_BADADDR: 511 /* Reference to kernel address from user mode or supervisor mode */ 512 /* Reference to supervisor address from user mode */ 513 if (access_type == MMU_DATA_STORE) { 514 exception = EXCP_AdES; 515 } else { 516 exception = EXCP_AdEL; 517 } 518 break; 519 case TLBRET_NOMATCH: 520 /* No TLB match for a mapped address */ 521 if (access_type == MMU_DATA_STORE) { 522 exception = EXCP_TLBS; 523 } else { 524 exception = EXCP_TLBL; 525 } 526 error_code |= EXCP_TLB_NOMATCH; 527 break; 528 case TLBRET_INVALID: 529 /* TLB match with no valid bit */ 530 if (access_type == MMU_DATA_STORE) { 531 exception = EXCP_TLBS; 532 } else { 533 exception = EXCP_TLBL; 534 } 535 break; 536 case TLBRET_DIRTY: 537 /* TLB match but 'D' bit is cleared */ 538 exception = EXCP_LTLBL; 539 break; 540 case TLBRET_XI: 541 /* Execute-Inhibit Exception */ 542 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { 543 exception = EXCP_TLBXI; 544 } else { 545 exception = EXCP_TLBL; 546 } 547 break; 548 case TLBRET_RI: 549 /* Read-Inhibit Exception */ 550 if (env->CP0_PageGrain & (1 << CP0PG_IEC)) { 551 exception = EXCP_TLBRI; 552 } else { 553 exception = EXCP_TLBL; 554 } 555 break; 556 } 557 /* Raise exception */ 558 if (!(env->hflags & MIPS_HFLAG_DM)) { 559 env->CP0_BadVAddr = address; 560 } 561 env->CP0_Context = (env->CP0_Context & ~0x007fffff) | 562 ((address >> 9) & 0x007ffff0); 563 env->CP0_EntryHi = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) | 564 (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) | 565 (address & (TARGET_PAGE_MASK << 1)); 566 #if defined(TARGET_MIPS64) 567 env->CP0_EntryHi &= env->SEGMask; 568 env->CP0_XContext = 569 (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) | /* PTEBase */ 570 (extract64(address, 62, 2) << (env->SEGBITS - 9)) | /* R */ 571 (extract64(address, 13, env->SEGBITS - 13) << 4); /* BadVPN2 */ 572 #endif 573 cs->exception_index = exception; 574 env->error_code = error_code; 575 } 576 577 #if !defined(TARGET_MIPS64) 578 579 /* 580 * Perform hardware page table walk 581 * 582 * Memory accesses are performed using the KERNEL privilege level. 583 * Synchronous exceptions detected on memory accesses cause a silent exit 584 * from page table walking, resulting in a TLB or XTLB Refill exception. 585 * 586 * Implementations are not required to support page table walk memory 587 * accesses from mapped memory regions. When an unsupported access is 588 * attempted, a silent exit is taken, resulting in a TLB or XTLB Refill 589 * exception. 590 * 591 * Note that if an exception is caused by AddressTranslation or LoadMemory 592 * functions, the exception is not taken, a silent exit is taken, 593 * resulting in a TLB or XTLB Refill exception. 594 */ 595 596 static bool get_pte(CPUMIPSState *env, uint64_t vaddr, MemOp op, 597 uint64_t *pte, unsigned ptw_mmu_idx) 598 { 599 MemOpIdx oi; 600 601 if ((vaddr & (memop_size(op) - 1)) != 0) { 602 return false; 603 } 604 605 oi = make_memop_idx(op | mo_endian_env(env), ptw_mmu_idx); 606 if (op == MO_64) { 607 *pte = cpu_ldq_mmu(env, vaddr, oi, 0); 608 } else { 609 *pte = cpu_ldl_mmu(env, vaddr, oi, 0); 610 } 611 612 return true; 613 } 614 615 static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry, 616 MemOp op, int ptei) 617 { 618 unsigned entry_size = memop_size(op) << 3; 619 uint64_t result = entry; 620 uint64_t rixi; 621 if (ptei > entry_size) { 622 ptei -= 32; 623 } 624 result >>= (ptei - 2); 625 rixi = result & 3; 626 result >>= 2; 627 result |= rixi << CP0EnLo_XI; 628 return result; 629 } 630 631 static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, 632 int directory_index, bool *huge_page, bool *hgpg_directory_hit, 633 uint64_t *pw_entrylo0, uint64_t *pw_entrylo1, 634 MemOp directory_mop, MemOp leaf_mop, int ptw_mmu_idx) 635 { 636 int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1; 637 int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F; 638 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; 639 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; 640 uint64_t entry; 641 uint64_t paddr; 642 int prot; 643 uint64_t lsb = 0; 644 uint64_t w = 0; 645 646 if (get_physical_address(env, &paddr, &prot, *vaddr, MMU_DATA_LOAD, 647 ptw_mmu_idx) != TLBRET_MATCH) { 648 /* wrong base address */ 649 return 0; 650 } 651 if (!get_pte(env, *vaddr, directory_mop, &entry, ptw_mmu_idx)) { 652 return 0; 653 } 654 655 if ((entry & (1 << psn)) && hugepg) { 656 *huge_page = true; 657 *hgpg_directory_hit = true; 658 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); 659 w = directory_index - 1; 660 if (directory_index & 0x1) { 661 /* Generate adjacent page from same PTE for odd TLB page */ 662 lsb = BIT_ULL(w) >> 6; 663 *pw_entrylo0 = entry & ~lsb; /* even page */ 664 *pw_entrylo1 = entry | lsb; /* odd page */ 665 } else if (dph) { 666 int oddpagebit = 1 << leaf_mop; 667 uint64_t vaddr2 = *vaddr ^ oddpagebit; 668 if (*vaddr & oddpagebit) { 669 *pw_entrylo1 = entry; 670 } else { 671 *pw_entrylo0 = entry; 672 } 673 if (get_physical_address(env, &paddr, &prot, vaddr2, MMU_DATA_LOAD, 674 ptw_mmu_idx) != TLBRET_MATCH) { 675 return 0; 676 } 677 if (!get_pte(env, vaddr2, leaf_mop, &entry, ptw_mmu_idx)) { 678 return 0; 679 } 680 entry = get_tlb_entry_layout(env, entry, leaf_mop, pf_ptew); 681 if (*vaddr & oddpagebit) { 682 *pw_entrylo0 = entry; 683 } else { 684 *pw_entrylo1 = entry; 685 } 686 } else { 687 return 0; 688 } 689 return 1; 690 } else { 691 *vaddr = entry; 692 return 2; 693 } 694 } 695 696 static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, 697 int ptw_mmu_idx) 698 { 699 int gdw = (env->CP0_PWSize >> CP0PS_GDW) & 0x3F; 700 int udw = (env->CP0_PWSize >> CP0PS_UDW) & 0x3F; 701 int mdw = (env->CP0_PWSize >> CP0PS_MDW) & 0x3F; 702 int ptw = (env->CP0_PWSize >> CP0PS_PTW) & 0x3F; 703 int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F; 704 705 /* Initial values */ 706 bool huge_page = false; 707 bool hgpg_bdhit = false; 708 bool hgpg_gdhit = false; 709 bool hgpg_udhit = false; 710 bool hgpg_mdhit = false; 711 712 int32_t pw_pagemask = 0; 713 target_ulong pw_entryhi = 0; 714 uint64_t pw_entrylo0 = 0; 715 uint64_t pw_entrylo1 = 0; 716 717 /* Native pointer size */ 718 /*For the 32-bit architectures, this bit is fixed to 0.*/ 719 MemOp native_op = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? MO_32 : MO_64; 720 721 /* Indices from PWField */ 722 int pf_gdw = (env->CP0_PWField >> CP0PF_GDW) & 0x3F; 723 int pf_udw = (env->CP0_PWField >> CP0PF_UDW) & 0x3F; 724 int pf_mdw = (env->CP0_PWField >> CP0PF_MDW) & 0x3F; 725 int pf_ptw = (env->CP0_PWField >> CP0PF_PTW) & 0x3F; 726 int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; 727 728 /* Indices computed from faulting address */ 729 int gindex = (address >> pf_gdw) & ((1 << gdw) - 1); 730 int uindex = (address >> pf_udw) & ((1 << udw) - 1); 731 int mindex = (address >> pf_mdw) & ((1 << mdw) - 1); 732 int ptindex = (address >> pf_ptw) & ((1 << ptw) - 1); 733 734 /* Other HTW configs */ 735 int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; 736 MemOp directory_mop, leaf_mop; 737 738 /* Offsets into tables */ 739 unsigned goffset, uoffset, moffset, ptoffset0, ptoffset1; 740 741 /* Starting address - Page Table Base */ 742 uint64_t vaddr = env->CP0_PWBase; 743 744 uint64_t dir_entry; 745 uint64_t paddr; 746 int prot; 747 int m; 748 749 if (!(env->CP0_Config3 & (1 << CP0C3_PW))) { 750 /* walker is unimplemented */ 751 return false; 752 } 753 if (!(env->CP0_PWCtl & (1 << CP0PC_PWEN))) { 754 /* walker is disabled */ 755 return false; 756 } 757 if (!(gdw > 0 || udw > 0 || mdw > 0)) { 758 /* no structure to walk */ 759 return false; 760 } 761 if (ptew > 1) { 762 return false; 763 } 764 765 /* HTW Shift values (depend on entry size) */ 766 directory_mop = (hugepg && (ptew == 1)) ? native_op + 1 : native_op; 767 leaf_mop = (ptew == 1) ? native_op + 1 : native_op; 768 769 goffset = gindex << directory_mop; 770 uoffset = uindex << directory_mop; 771 moffset = mindex << directory_mop; 772 ptoffset0 = (ptindex >> 1) << (leaf_mop + 1); 773 ptoffset1 = ptoffset0 | (1 << (leaf_mop)); 774 775 /* Global Directory */ 776 if (gdw > 0) { 777 vaddr |= goffset; 778 switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit, 779 &pw_entrylo0, &pw_entrylo1, 780 directory_mop, leaf_mop, ptw_mmu_idx)) 781 { 782 case 0: 783 return false; 784 case 1: 785 goto refill; 786 case 2: 787 default: 788 break; 789 } 790 } 791 792 /* Upper directory */ 793 if (udw > 0) { 794 vaddr |= uoffset; 795 switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit, 796 &pw_entrylo0, &pw_entrylo1, 797 directory_mop, leaf_mop, ptw_mmu_idx)) 798 { 799 case 0: 800 return false; 801 case 1: 802 goto refill; 803 case 2: 804 default: 805 break; 806 } 807 } 808 809 /* Middle directory */ 810 if (mdw > 0) { 811 vaddr |= moffset; 812 switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit, 813 &pw_entrylo0, &pw_entrylo1, 814 directory_mop, leaf_mop, ptw_mmu_idx)) 815 { 816 case 0: 817 return false; 818 case 1: 819 goto refill; 820 case 2: 821 default: 822 break; 823 } 824 } 825 826 /* Leaf Level Page Table - First half of PTE pair */ 827 vaddr |= ptoffset0; 828 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, 829 ptw_mmu_idx) != TLBRET_MATCH) { 830 return false; 831 } 832 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { 833 return false; 834 } 835 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); 836 pw_entrylo0 = dir_entry; 837 838 /* Leaf Level Page Table - Second half of PTE pair */ 839 vaddr |= ptoffset1; 840 if (get_physical_address(env, &paddr, &prot, vaddr, MMU_DATA_LOAD, 841 ptw_mmu_idx) != TLBRET_MATCH) { 842 return false; 843 } 844 if (!get_pte(env, vaddr, leaf_mop, &dir_entry, ptw_mmu_idx)) { 845 return false; 846 } 847 dir_entry = get_tlb_entry_layout(env, dir_entry, leaf_mop, pf_ptew); 848 pw_entrylo1 = dir_entry; 849 850 refill: 851 852 m = (1 << pf_ptw) - 1; 853 854 if (huge_page) { 855 switch (hgpg_bdhit << 3 | hgpg_gdhit << 2 | hgpg_udhit << 1 | 856 hgpg_mdhit) 857 { 858 case 4: 859 m = (1 << pf_gdw) - 1; 860 if (pf_gdw & 1) { 861 m >>= 1; 862 } 863 break; 864 case 2: 865 m = (1 << pf_udw) - 1; 866 if (pf_udw & 1) { 867 m >>= 1; 868 } 869 break; 870 case 1: 871 m = (1 << pf_mdw) - 1; 872 if (pf_mdw & 1) { 873 m >>= 1; 874 } 875 break; 876 } 877 } 878 pw_pagemask = m >> TARGET_PAGE_BITS_MIN; 879 update_pagemask(env, pw_pagemask << CP0PM_MASK, &pw_pagemask); 880 pw_entryhi = (address & ~0x1fff) | (env->CP0_EntryHi & 0xFF); 881 { 882 target_ulong tmp_entryhi = env->CP0_EntryHi; 883 int32_t tmp_pagemask = env->CP0_PageMask; 884 uint64_t tmp_entrylo0 = env->CP0_EntryLo0; 885 uint64_t tmp_entrylo1 = env->CP0_EntryLo1; 886 887 env->CP0_EntryHi = pw_entryhi; 888 env->CP0_PageMask = pw_pagemask; 889 env->CP0_EntryLo0 = pw_entrylo0; 890 env->CP0_EntryLo1 = pw_entrylo1; 891 892 /* 893 * The hardware page walker inserts a page into the TLB in a manner 894 * identical to a TLBWR instruction as executed by the software refill 895 * handler. 896 */ 897 r4k_helper_tlbwr(env); 898 899 env->CP0_EntryHi = tmp_entryhi; 900 env->CP0_PageMask = tmp_pagemask; 901 env->CP0_EntryLo0 = tmp_entrylo0; 902 env->CP0_EntryLo1 = tmp_entrylo1; 903 } 904 return true; 905 } 906 #endif 907 908 bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, 909 MMUAccessType access_type, int mmu_idx, 910 bool probe, uintptr_t retaddr) 911 { 912 CPUMIPSState *env = cpu_env(cs); 913 hwaddr physical; 914 int prot; 915 int ret = TLBRET_BADADDR; 916 917 /* data access */ 918 /* XXX: put correct access by using cpu_restore_state() correctly */ 919 ret = get_physical_address(env, &physical, &prot, address, 920 access_type, mmu_idx); 921 switch (ret) { 922 case TLBRET_MATCH: 923 qemu_log_mask(CPU_LOG_MMU, 924 "%s address=%" VADDR_PRIx " physical " HWADDR_FMT_plx 925 " prot %d\n", __func__, address, physical, prot); 926 break; 927 default: 928 qemu_log_mask(CPU_LOG_MMU, 929 "%s address=%" VADDR_PRIx " ret %d\n", __func__, address, 930 ret); 931 break; 932 } 933 if (ret == TLBRET_MATCH) { 934 tlb_set_page(cs, address & TARGET_PAGE_MASK, 935 physical & TARGET_PAGE_MASK, prot, 936 mmu_idx, TARGET_PAGE_SIZE); 937 return true; 938 } 939 #if !defined(TARGET_MIPS64) 940 if ((ret == TLBRET_NOMATCH) && (env->tlb->nb_tlb > 1)) { 941 /* 942 * Memory reads during hardware page table walking are performed 943 * as if they were kernel-mode load instructions. 944 */ 945 int ptw_mmu_idx = (env->hflags & MIPS_HFLAG_ERL ? 946 MMU_ERL_IDX : MMU_KERNEL_IDX); 947 948 if (page_table_walk_refill(env, address, ptw_mmu_idx)) { 949 ret = get_physical_address(env, &physical, &prot, address, 950 access_type, mmu_idx); 951 if (ret == TLBRET_MATCH) { 952 tlb_set_page(cs, address & TARGET_PAGE_MASK, 953 physical & TARGET_PAGE_MASK, prot, 954 mmu_idx, TARGET_PAGE_SIZE); 955 return true; 956 } 957 } 958 } 959 #endif 960 if (probe) { 961 return false; 962 } 963 964 raise_mmu_exception(env, address, access_type, ret); 965 do_raise_exception_err(env, cs->exception_index, env->error_code, retaddr); 966 } 967 968 hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, 969 MMUAccessType access_type, uintptr_t retaddr) 970 { 971 hwaddr physical; 972 int prot; 973 int ret = 0; 974 CPUState *cs = env_cpu(env); 975 976 /* data access */ 977 ret = get_physical_address(env, &physical, &prot, address, access_type, 978 mips_env_mmu_index(env)); 979 if (ret == TLBRET_MATCH) { 980 return physical; 981 } 982 983 raise_mmu_exception(env, address, access_type, ret); 984 cpu_loop_exit_restore(cs, retaddr); 985 } 986 987 static void set_hflags_for_handler(CPUMIPSState *env) 988 { 989 /* Exception handlers are entered in 32-bit mode. */ 990 env->hflags &= ~(MIPS_HFLAG_M16); 991 /* ...except that microMIPS lets you choose. */ 992 if (env->insn_flags & ASE_MICROMIPS) { 993 env->hflags |= (!!(env->CP0_Config3 & 994 (1 << CP0C3_ISA_ON_EXC)) 995 << MIPS_HFLAG_M16_SHIFT); 996 } 997 } 998 999 static inline void set_badinstr_registers(CPUMIPSState *env) 1000 { 1001 if (env->insn_flags & ISA_NANOMIPS32) { 1002 if (env->CP0_Config3 & (1 << CP0C3_BI)) { 1003 uint32_t instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16; 1004 if ((instr & 0x10000000) == 0) { 1005 instr |= cpu_lduw_code(env, env->active_tc.PC + 2); 1006 } 1007 env->CP0_BadInstr = instr; 1008 1009 if ((instr & 0xFC000000) == 0x60000000) { 1010 instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16; 1011 env->CP0_BadInstrX = instr; 1012 } 1013 } 1014 return; 1015 } 1016 1017 if (env->hflags & MIPS_HFLAG_M16) { 1018 /* TODO: add BadInstr support for microMIPS */ 1019 return; 1020 } 1021 if (env->CP0_Config3 & (1 << CP0C3_BI)) { 1022 env->CP0_BadInstr = cpu_ldl_code(env, env->active_tc.PC); 1023 } 1024 if ((env->CP0_Config3 & (1 << CP0C3_BP)) && 1025 (env->hflags & MIPS_HFLAG_BMASK)) { 1026 env->CP0_BadInstrP = cpu_ldl_code(env, env->active_tc.PC - 4); 1027 } 1028 } 1029 1030 void mips_cpu_do_interrupt(CPUState *cs) 1031 { 1032 MIPSCPU *cpu = MIPS_CPU(cs); 1033 CPUMIPSState *env = &cpu->env; 1034 bool update_badinstr = 0; 1035 target_ulong offset; 1036 int cause = -1; 1037 1038 if (qemu_loglevel_mask(CPU_LOG_INT) 1039 && cs->exception_index != EXCP_EXT_INTERRUPT) { 1040 qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx 1041 " %s exception\n", 1042 __func__, env->active_tc.PC, env->CP0_EPC, 1043 mips_exception_name(cs->exception_index)); 1044 } 1045 if (cs->exception_index == EXCP_EXT_INTERRUPT && 1046 (env->hflags & MIPS_HFLAG_DM)) { 1047 cs->exception_index = EXCP_DINT; 1048 } 1049 offset = 0x180; 1050 switch (cs->exception_index) { 1051 case EXCP_SEMIHOST: 1052 cs->exception_index = EXCP_NONE; 1053 mips_semihosting(env); 1054 env->active_tc.PC += env->error_code; 1055 return; 1056 case EXCP_DSS: 1057 env->CP0_Debug |= 1 << CP0DB_DSS; 1058 /* 1059 * Debug single step cannot be raised inside a delay slot and 1060 * resume will always occur on the next instruction 1061 * (but we assume the pc has always been updated during 1062 * code translation). 1063 */ 1064 env->CP0_DEPC = env->active_tc.PC | !!(env->hflags & MIPS_HFLAG_M16); 1065 goto enter_debug_mode; 1066 case EXCP_DINT: 1067 env->CP0_Debug |= 1 << CP0DB_DINT; 1068 goto set_DEPC; 1069 case EXCP_DIB: 1070 env->CP0_Debug |= 1 << CP0DB_DIB; 1071 goto set_DEPC; 1072 case EXCP_DBp: 1073 env->CP0_Debug |= 1 << CP0DB_DBp; 1074 /* Setup DExcCode - SDBBP instruction */ 1075 env->CP0_Debug = (env->CP0_Debug & ~(0x1fULL << CP0DB_DEC)) | 1076 (9 << CP0DB_DEC); 1077 goto set_DEPC; 1078 case EXCP_DDBS: 1079 env->CP0_Debug |= 1 << CP0DB_DDBS; 1080 goto set_DEPC; 1081 case EXCP_DDBL: 1082 env->CP0_Debug |= 1 << CP0DB_DDBL; 1083 set_DEPC: 1084 env->CP0_DEPC = exception_resume_pc(env); 1085 env->hflags &= ~MIPS_HFLAG_BMASK; 1086 enter_debug_mode: 1087 if (env->insn_flags & ISA_MIPS3) { 1088 env->hflags |= MIPS_HFLAG_64; 1089 if (!(env->insn_flags & ISA_MIPS_R6) || 1090 env->CP0_Status & (1 << CP0St_KX)) { 1091 env->hflags &= ~MIPS_HFLAG_AWRAP; 1092 } 1093 } 1094 env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_CP0; 1095 env->hflags &= ~(MIPS_HFLAG_KSU); 1096 /* EJTAG probe trap enable is not implemented... */ 1097 if (!(env->CP0_Status & (1 << CP0St_EXL))) { 1098 env->CP0_Cause &= ~(1U << CP0Ca_BD); 1099 } 1100 env->active_tc.PC = env->exception_base + 0x480; 1101 set_hflags_for_handler(env); 1102 break; 1103 case EXCP_RESET: 1104 cpu_reset(CPU(cpu)); 1105 break; 1106 case EXCP_SRESET: 1107 env->CP0_Status |= (1 << CP0St_SR); 1108 memset(env->CP0_WatchLo, 0, sizeof(env->CP0_WatchLo)); 1109 goto set_error_EPC; 1110 case EXCP_NMI: 1111 env->CP0_Status |= (1 << CP0St_NMI); 1112 set_error_EPC: 1113 env->CP0_ErrorEPC = exception_resume_pc(env); 1114 env->hflags &= ~MIPS_HFLAG_BMASK; 1115 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); 1116 if (env->insn_flags & ISA_MIPS3) { 1117 env->hflags |= MIPS_HFLAG_64; 1118 if (!(env->insn_flags & ISA_MIPS_R6) || 1119 env->CP0_Status & (1 << CP0St_KX)) { 1120 env->hflags &= ~MIPS_HFLAG_AWRAP; 1121 } 1122 } 1123 env->hflags |= MIPS_HFLAG_CP0; 1124 env->hflags &= ~(MIPS_HFLAG_KSU); 1125 if (!(env->CP0_Status & (1 << CP0St_EXL))) { 1126 env->CP0_Cause &= ~(1U << CP0Ca_BD); 1127 } 1128 env->active_tc.PC = env->exception_base; 1129 set_hflags_for_handler(env); 1130 break; 1131 case EXCP_EXT_INTERRUPT: 1132 cause = 0; 1133 if (env->CP0_Cause & (1 << CP0Ca_IV)) { 1134 uint32_t spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & 0x1f; 1135 1136 if ((env->CP0_Status & (1 << CP0St_BEV)) || spacing == 0) { 1137 offset = 0x200; 1138 } else { 1139 uint32_t vector = 0; 1140 uint32_t pending = (env->CP0_Cause & CP0Ca_IP_mask) >> CP0Ca_IP; 1141 1142 if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { 1143 /* 1144 * For VEIC mode, the external interrupt controller feeds 1145 * the vector through the CP0Cause IP lines. 1146 */ 1147 vector = pending; 1148 } else { 1149 /* 1150 * Vectored Interrupts 1151 * Mask with Status.IM7-IM0 to get enabled interrupts. 1152 */ 1153 pending &= (env->CP0_Status >> CP0St_IM) & 0xff; 1154 /* Find the highest-priority interrupt. */ 1155 while (pending >>= 1) { 1156 vector++; 1157 } 1158 } 1159 offset = 0x200 + (vector * (spacing << 5)); 1160 } 1161 } 1162 goto set_EPC; 1163 case EXCP_LTLBL: 1164 cause = 1; 1165 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); 1166 goto set_EPC; 1167 case EXCP_TLBL: 1168 cause = 2; 1169 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); 1170 if ((env->error_code & EXCP_TLB_NOMATCH) && 1171 !(env->CP0_Status & (1 << CP0St_EXL))) { 1172 #if defined(TARGET_MIPS64) 1173 int R = env->CP0_BadVAddr >> 62; 1174 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; 1175 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; 1176 1177 if ((R != 0 || UX) && (R != 3 || KX) && 1178 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { 1179 offset = 0x080; 1180 } else { 1181 #endif 1182 offset = 0x000; 1183 #if defined(TARGET_MIPS64) 1184 } 1185 #endif 1186 } 1187 goto set_EPC; 1188 case EXCP_TLBS: 1189 cause = 3; 1190 update_badinstr = 1; 1191 if ((env->error_code & EXCP_TLB_NOMATCH) && 1192 !(env->CP0_Status & (1 << CP0St_EXL))) { 1193 #if defined(TARGET_MIPS64) 1194 int R = env->CP0_BadVAddr >> 62; 1195 int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0; 1196 int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0; 1197 1198 if ((R != 0 || UX) && (R != 3 || KX) && 1199 (!(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)))) { 1200 offset = 0x080; 1201 } else { 1202 #endif 1203 offset = 0x000; 1204 #if defined(TARGET_MIPS64) 1205 } 1206 #endif 1207 } 1208 goto set_EPC; 1209 case EXCP_AdEL: 1210 cause = 4; 1211 update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL); 1212 goto set_EPC; 1213 case EXCP_AdES: 1214 cause = 5; 1215 update_badinstr = 1; 1216 goto set_EPC; 1217 case EXCP_IBE: 1218 cause = 6; 1219 goto set_EPC; 1220 case EXCP_DBE: 1221 cause = 7; 1222 goto set_EPC; 1223 case EXCP_SYSCALL: 1224 cause = 8; 1225 update_badinstr = 1; 1226 goto set_EPC; 1227 case EXCP_BREAK: 1228 cause = 9; 1229 update_badinstr = 1; 1230 goto set_EPC; 1231 case EXCP_RI: 1232 cause = 10; 1233 update_badinstr = 1; 1234 goto set_EPC; 1235 case EXCP_CpU: 1236 cause = 11; 1237 update_badinstr = 1; 1238 env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) | 1239 (env->error_code << CP0Ca_CE); 1240 goto set_EPC; 1241 case EXCP_OVERFLOW: 1242 cause = 12; 1243 update_badinstr = 1; 1244 goto set_EPC; 1245 case EXCP_TRAP: 1246 cause = 13; 1247 update_badinstr = 1; 1248 goto set_EPC; 1249 case EXCP_MSAFPE: 1250 cause = 14; 1251 update_badinstr = 1; 1252 goto set_EPC; 1253 case EXCP_FPE: 1254 cause = 15; 1255 update_badinstr = 1; 1256 goto set_EPC; 1257 case EXCP_C2E: 1258 cause = 18; 1259 goto set_EPC; 1260 case EXCP_TLBRI: 1261 cause = 19; 1262 update_badinstr = 1; 1263 goto set_EPC; 1264 case EXCP_TLBXI: 1265 cause = 20; 1266 goto set_EPC; 1267 case EXCP_MSADIS: 1268 cause = 21; 1269 update_badinstr = 1; 1270 goto set_EPC; 1271 case EXCP_MDMX: 1272 cause = 22; 1273 goto set_EPC; 1274 case EXCP_DWATCH: 1275 cause = 23; 1276 /* XXX: TODO: manage deferred watch exceptions */ 1277 goto set_EPC; 1278 case EXCP_MCHECK: 1279 cause = 24; 1280 goto set_EPC; 1281 case EXCP_THREAD: 1282 cause = 25; 1283 goto set_EPC; 1284 case EXCP_DSPDIS: 1285 cause = 26; 1286 goto set_EPC; 1287 case EXCP_CACHE: 1288 cause = 30; 1289 offset = 0x100; 1290 set_EPC: 1291 if (!(env->CP0_Status & (1 << CP0St_EXL))) { 1292 env->CP0_EPC = exception_resume_pc(env); 1293 if (update_badinstr) { 1294 set_badinstr_registers(env); 1295 } 1296 if (env->hflags & MIPS_HFLAG_BMASK) { 1297 env->CP0_Cause |= (1U << CP0Ca_BD); 1298 } else { 1299 env->CP0_Cause &= ~(1U << CP0Ca_BD); 1300 } 1301 env->CP0_Status |= (1 << CP0St_EXL); 1302 if (env->insn_flags & ISA_MIPS3) { 1303 env->hflags |= MIPS_HFLAG_64; 1304 if (!(env->insn_flags & ISA_MIPS_R6) || 1305 env->CP0_Status & (1 << CP0St_KX)) { 1306 env->hflags &= ~MIPS_HFLAG_AWRAP; 1307 } 1308 } 1309 env->hflags |= MIPS_HFLAG_CP0; 1310 env->hflags &= ~(MIPS_HFLAG_KSU); 1311 } 1312 env->hflags &= ~MIPS_HFLAG_BMASK; 1313 if (env->CP0_Status & (1 << CP0St_BEV)) { 1314 env->active_tc.PC = env->exception_base + 0x200; 1315 } else if (cause == 30 && !(env->CP0_Config3 & (1 << CP0C3_SC) && 1316 env->CP0_Config5 & (1 << CP0C5_CV))) { 1317 /* Force KSeg1 for cache errors */ 1318 env->active_tc.PC = KSEG1_BASE | (env->CP0_EBase & 0x1FFFF000); 1319 } else { 1320 env->active_tc.PC = env->CP0_EBase & ~0xfff; 1321 } 1322 1323 env->active_tc.PC += offset; 1324 set_hflags_for_handler(env); 1325 env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | 1326 (cause << CP0Ca_EC); 1327 break; 1328 default: 1329 abort(); 1330 } 1331 if (qemu_loglevel_mask(CPU_LOG_INT) 1332 && cs->exception_index != EXCP_EXT_INTERRUPT) { 1333 qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" 1334 " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", 1335 __func__, env->active_tc.PC, env->CP0_EPC, cause, 1336 env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr, 1337 env->CP0_DEPC); 1338 } 1339 cs->exception_index = EXCP_NONE; 1340 } 1341 1342 bool mips_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 1343 { 1344 if (interrupt_request & CPU_INTERRUPT_HARD) { 1345 CPUMIPSState *env = cpu_env(cs); 1346 1347 if (cpu_mips_hw_interrupts_enabled(env) && 1348 cpu_mips_hw_interrupts_pending(env)) { 1349 /* Raise it */ 1350 cs->exception_index = EXCP_EXT_INTERRUPT; 1351 env->error_code = 0; 1352 mips_cpu_do_interrupt(cs); 1353 return true; 1354 } 1355 } 1356 return false; 1357 } 1358 1359 void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra) 1360 { 1361 CPUState *cs = env_cpu(env); 1362 r4k_tlb_t *tlb; 1363 target_ulong addr; 1364 target_ulong end; 1365 uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask; 1366 uint32_t MMID = env->CP0_MemoryMapID; 1367 bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1); 1368 uint32_t tlb_mmid; 1369 target_ulong mask; 1370 1371 MMID = mi ? MMID : (uint32_t) ASID; 1372 1373 tlb = &env->tlb->mmu.r4k.tlb[idx]; 1374 /* 1375 * The qemu TLB is flushed when the ASID/MMID changes, so no need to 1376 * flush these entries again. 1377 */ 1378 tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID; 1379 if (tlb->G == 0 && tlb_mmid != MMID) { 1380 return; 1381 } 1382 1383 if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) { 1384 /* 1385 * For tlbwr, we can shadow the discarded entry into 1386 * a new (fake) TLB entry, as long as the guest can not 1387 * tell that it's there. 1388 */ 1389 env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb; 1390 env->tlb->tlb_in_use++; 1391 return; 1392 } 1393 1394 /* 1k pages are not supported. */ 1395 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1); 1396 if (tlb->V0) { 1397 addr = tlb->VPN & ~mask; 1398 #if defined(TARGET_MIPS64) 1399 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { 1400 addr |= 0x3FFFFF0000000000ULL; 1401 } 1402 #endif 1403 end = addr | (mask >> 1); 1404 while (addr < end) { 1405 tlb_flush_page(cs, addr); 1406 addr += TARGET_PAGE_SIZE; 1407 } 1408 } 1409 if (tlb->V1) { 1410 addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1); 1411 #if defined(TARGET_MIPS64) 1412 if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) { 1413 addr |= 0x3FFFFF0000000000ULL; 1414 } 1415 #endif 1416 end = addr | mask; 1417 while (addr - 1 < end) { 1418 tlb_flush_page(cs, addr); 1419 addr += TARGET_PAGE_SIZE; 1420 } 1421 } 1422 } 1423