1 /* 2 * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab. 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 met: 7 * * 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 Open Source and Linux Lab nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "qemu/osdep.h" 29 #include "qemu/units.h" 30 #include "cpu.h" 31 #include "exec/exec-all.h" 32 #include "exec/gdbstub.h" 33 #include "qemu/host-utils.h" 34 #if !defined(CONFIG_USER_ONLY) 35 #include "hw/loader.h" 36 #endif 37 38 static struct XtensaConfigList *xtensa_cores; 39 40 static void xtensa_core_class_init(ObjectClass *oc, void *data) 41 { 42 CPUClass *cc = CPU_CLASS(oc); 43 XtensaCPUClass *xcc = XTENSA_CPU_CLASS(oc); 44 const XtensaConfig *config = data; 45 46 xcc->config = config; 47 48 /* Use num_core_regs to see only non-privileged registers in an unmodified 49 * gdb. Use num_regs to see all registers. gdb modification is required 50 * for that: reset bit 0 in the 'flags' field of the registers definitions 51 * in the gdb/xtensa-config.c inside gdb source tree or inside gdb overlay. 52 */ 53 cc->gdb_num_core_regs = config->gdb_regmap.num_regs; 54 } 55 56 static void init_libisa(XtensaConfig *config) 57 { 58 unsigned i, j; 59 unsigned opcodes; 60 unsigned formats; 61 62 config->isa = xtensa_isa_init(config->isa_internal, NULL, NULL); 63 assert(xtensa_isa_maxlength(config->isa) <= MAX_INSN_LENGTH); 64 opcodes = xtensa_isa_num_opcodes(config->isa); 65 formats = xtensa_isa_num_formats(config->isa); 66 config->opcode_ops = g_new(XtensaOpcodeOps *, opcodes); 67 68 for (i = 0; i < formats; ++i) { 69 assert(xtensa_format_num_slots(config->isa, i) <= MAX_INSN_SLOTS); 70 } 71 72 for (i = 0; i < opcodes; ++i) { 73 const char *opc_name = xtensa_opcode_name(config->isa, i); 74 XtensaOpcodeOps *ops = NULL; 75 76 assert(xtensa_opcode_num_operands(config->isa, i) <= MAX_OPCODE_ARGS); 77 if (!config->opcode_translators) { 78 ops = xtensa_find_opcode_ops(&xtensa_core_opcodes, opc_name); 79 } else { 80 for (j = 0; !ops && config->opcode_translators[j]; ++j) { 81 ops = xtensa_find_opcode_ops(config->opcode_translators[j], 82 opc_name); 83 } 84 } 85 #ifdef DEBUG 86 if (ops == NULL) { 87 fprintf(stderr, 88 "opcode translator not found for %s's opcode '%s'\n", 89 config->name, opc_name); 90 } 91 #endif 92 config->opcode_ops[i] = ops; 93 } 94 } 95 96 void xtensa_finalize_config(XtensaConfig *config) 97 { 98 if (config->isa_internal) { 99 init_libisa(config); 100 } 101 102 if (config->gdb_regmap.num_regs == 0 || 103 config->gdb_regmap.num_core_regs == 0) { 104 unsigned n_regs = 0; 105 unsigned n_core_regs = 0; 106 107 xtensa_count_regs(config, &n_regs, &n_core_regs); 108 if (config->gdb_regmap.num_regs == 0) { 109 config->gdb_regmap.num_regs = n_regs; 110 } 111 if (config->gdb_regmap.num_core_regs == 0) { 112 config->gdb_regmap.num_core_regs = n_core_regs; 113 } 114 } 115 } 116 117 void xtensa_register_core(XtensaConfigList *node) 118 { 119 TypeInfo type = { 120 .parent = TYPE_XTENSA_CPU, 121 .class_init = xtensa_core_class_init, 122 .class_data = (void *)node->config, 123 }; 124 125 node->next = xtensa_cores; 126 xtensa_cores = node; 127 type.name = g_strdup_printf(XTENSA_CPU_TYPE_NAME("%s"), node->config->name); 128 type_register(&type); 129 g_free((gpointer)type.name); 130 } 131 132 static uint32_t check_hw_breakpoints(CPUXtensaState *env) 133 { 134 unsigned i; 135 136 for (i = 0; i < env->config->ndbreak; ++i) { 137 if (env->cpu_watchpoint[i] && 138 env->cpu_watchpoint[i]->flags & BP_WATCHPOINT_HIT) { 139 return DEBUGCAUSE_DB | (i << DEBUGCAUSE_DBNUM_SHIFT); 140 } 141 } 142 return 0; 143 } 144 145 void xtensa_breakpoint_handler(CPUState *cs) 146 { 147 XtensaCPU *cpu = XTENSA_CPU(cs); 148 CPUXtensaState *env = &cpu->env; 149 150 if (cs->watchpoint_hit) { 151 if (cs->watchpoint_hit->flags & BP_CPU) { 152 uint32_t cause; 153 154 cs->watchpoint_hit = NULL; 155 cause = check_hw_breakpoints(env); 156 if (cause) { 157 debug_exception_env(env, cause); 158 } 159 cpu_loop_exit_noexc(cs); 160 } 161 } 162 } 163 164 void xtensa_cpu_list(FILE *f, fprintf_function cpu_fprintf) 165 { 166 XtensaConfigList *core = xtensa_cores; 167 cpu_fprintf(f, "Available CPUs:\n"); 168 for (; core; core = core->next) { 169 cpu_fprintf(f, " %s\n", core->config->name); 170 } 171 } 172 173 hwaddr xtensa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) 174 { 175 #ifndef CONFIG_USER_ONLY 176 XtensaCPU *cpu = XTENSA_CPU(cs); 177 uint32_t paddr; 178 uint32_t page_size; 179 unsigned access; 180 181 if (xtensa_get_physical_addr(&cpu->env, false, addr, 0, 0, 182 &paddr, &page_size, &access) == 0) { 183 return paddr; 184 } 185 if (xtensa_get_physical_addr(&cpu->env, false, addr, 2, 0, 186 &paddr, &page_size, &access) == 0) { 187 return paddr; 188 } 189 return ~0; 190 #else 191 return addr; 192 #endif 193 } 194 195 #ifndef CONFIG_USER_ONLY 196 197 static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector) 198 { 199 if (xtensa_option_enabled(env->config, 200 XTENSA_OPTION_RELOCATABLE_VECTOR)) { 201 return vector - env->config->vecbase + env->sregs[VECBASE]; 202 } else { 203 return vector; 204 } 205 } 206 207 /*! 208 * Handle penging IRQ. 209 * For the high priority interrupt jump to the corresponding interrupt vector. 210 * For the level-1 interrupt convert it to either user, kernel or double 211 * exception with the 'level-1 interrupt' exception cause. 212 */ 213 static void handle_interrupt(CPUXtensaState *env) 214 { 215 int level = env->pending_irq_level; 216 217 if (level > xtensa_get_cintlevel(env) && 218 level <= env->config->nlevel && 219 (env->config->level_mask[level] & 220 env->sregs[INTSET] & 221 env->sregs[INTENABLE])) { 222 CPUState *cs = CPU(xtensa_env_get_cpu(env)); 223 224 if (level > 1) { 225 env->sregs[EPC1 + level - 1] = env->pc; 226 env->sregs[EPS2 + level - 2] = env->sregs[PS]; 227 env->sregs[PS] = 228 (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM; 229 env->pc = relocated_vector(env, 230 env->config->interrupt_vector[level]); 231 } else { 232 env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE; 233 234 if (env->sregs[PS] & PS_EXCM) { 235 if (env->config->ndepc) { 236 env->sregs[DEPC] = env->pc; 237 } else { 238 env->sregs[EPC1] = env->pc; 239 } 240 cs->exception_index = EXC_DOUBLE; 241 } else { 242 env->sregs[EPC1] = env->pc; 243 cs->exception_index = 244 (env->sregs[PS] & PS_UM) ? EXC_USER : EXC_KERNEL; 245 } 246 env->sregs[PS] |= PS_EXCM; 247 } 248 env->exception_taken = 1; 249 } 250 } 251 252 /* Called from cpu_handle_interrupt with BQL held */ 253 void xtensa_cpu_do_interrupt(CPUState *cs) 254 { 255 XtensaCPU *cpu = XTENSA_CPU(cs); 256 CPUXtensaState *env = &cpu->env; 257 258 if (cs->exception_index == EXC_IRQ) { 259 qemu_log_mask(CPU_LOG_INT, 260 "%s(EXC_IRQ) level = %d, cintlevel = %d, " 261 "pc = %08x, a0 = %08x, ps = %08x, " 262 "intset = %08x, intenable = %08x, " 263 "ccount = %08x\n", 264 __func__, env->pending_irq_level, xtensa_get_cintlevel(env), 265 env->pc, env->regs[0], env->sregs[PS], 266 env->sregs[INTSET], env->sregs[INTENABLE], 267 env->sregs[CCOUNT]); 268 handle_interrupt(env); 269 } 270 271 switch (cs->exception_index) { 272 case EXC_WINDOW_OVERFLOW4: 273 case EXC_WINDOW_UNDERFLOW4: 274 case EXC_WINDOW_OVERFLOW8: 275 case EXC_WINDOW_UNDERFLOW8: 276 case EXC_WINDOW_OVERFLOW12: 277 case EXC_WINDOW_UNDERFLOW12: 278 case EXC_KERNEL: 279 case EXC_USER: 280 case EXC_DOUBLE: 281 case EXC_DEBUG: 282 qemu_log_mask(CPU_LOG_INT, "%s(%d) " 283 "pc = %08x, a0 = %08x, ps = %08x, ccount = %08x\n", 284 __func__, cs->exception_index, 285 env->pc, env->regs[0], env->sregs[PS], env->sregs[CCOUNT]); 286 if (env->config->exception_vector[cs->exception_index]) { 287 env->pc = relocated_vector(env, 288 env->config->exception_vector[cs->exception_index]); 289 env->exception_taken = 1; 290 } else { 291 qemu_log_mask(CPU_LOG_INT, "%s(pc = %08x) bad exception_index: %d\n", 292 __func__, env->pc, cs->exception_index); 293 } 294 break; 295 296 case EXC_IRQ: 297 break; 298 299 default: 300 qemu_log("%s(pc = %08x) unknown exception_index: %d\n", 301 __func__, env->pc, cs->exception_index); 302 break; 303 } 304 check_interrupts(env); 305 } 306 #else 307 void xtensa_cpu_do_interrupt(CPUState *cs) 308 { 309 } 310 #endif 311 312 bool xtensa_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 313 { 314 if (interrupt_request & CPU_INTERRUPT_HARD) { 315 cs->exception_index = EXC_IRQ; 316 xtensa_cpu_do_interrupt(cs); 317 return true; 318 } 319 return false; 320 } 321 322 #ifdef CONFIG_USER_ONLY 323 324 int xtensa_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int size, int rw, 325 int mmu_idx) 326 { 327 XtensaCPU *cpu = XTENSA_CPU(cs); 328 CPUXtensaState *env = &cpu->env; 329 330 qemu_log_mask(CPU_LOG_INT, 331 "%s: rw = %d, address = 0x%08" VADDR_PRIx ", size = %d\n", 332 __func__, rw, address, size); 333 env->sregs[EXCVADDR] = address; 334 env->sregs[EXCCAUSE] = rw ? STORE_PROHIBITED_CAUSE : LOAD_PROHIBITED_CAUSE; 335 cs->exception_index = EXC_USER; 336 return 1; 337 } 338 339 #else 340 341 static void reset_tlb_mmu_all_ways(CPUXtensaState *env, 342 const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE]) 343 { 344 unsigned wi, ei; 345 346 for (wi = 0; wi < tlb->nways; ++wi) { 347 for (ei = 0; ei < tlb->way_size[wi]; ++ei) { 348 entry[wi][ei].asid = 0; 349 entry[wi][ei].variable = true; 350 } 351 } 352 } 353 354 static void reset_tlb_mmu_ways56(CPUXtensaState *env, 355 const xtensa_tlb *tlb, xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE]) 356 { 357 if (!tlb->varway56) { 358 static const xtensa_tlb_entry way5[] = { 359 { 360 .vaddr = 0xd0000000, 361 .paddr = 0, 362 .asid = 1, 363 .attr = 7, 364 .variable = false, 365 }, { 366 .vaddr = 0xd8000000, 367 .paddr = 0, 368 .asid = 1, 369 .attr = 3, 370 .variable = false, 371 } 372 }; 373 static const xtensa_tlb_entry way6[] = { 374 { 375 .vaddr = 0xe0000000, 376 .paddr = 0xf0000000, 377 .asid = 1, 378 .attr = 7, 379 .variable = false, 380 }, { 381 .vaddr = 0xf0000000, 382 .paddr = 0xf0000000, 383 .asid = 1, 384 .attr = 3, 385 .variable = false, 386 } 387 }; 388 memcpy(entry[5], way5, sizeof(way5)); 389 memcpy(entry[6], way6, sizeof(way6)); 390 } else { 391 uint32_t ei; 392 for (ei = 0; ei < 8; ++ei) { 393 entry[6][ei].vaddr = ei << 29; 394 entry[6][ei].paddr = ei << 29; 395 entry[6][ei].asid = 1; 396 entry[6][ei].attr = 3; 397 } 398 } 399 } 400 401 static void reset_tlb_region_way0(CPUXtensaState *env, 402 xtensa_tlb_entry entry[][MAX_TLB_WAY_SIZE]) 403 { 404 unsigned ei; 405 406 for (ei = 0; ei < 8; ++ei) { 407 entry[0][ei].vaddr = ei << 29; 408 entry[0][ei].paddr = ei << 29; 409 entry[0][ei].asid = 1; 410 entry[0][ei].attr = 2; 411 entry[0][ei].variable = true; 412 } 413 } 414 415 void reset_mmu(CPUXtensaState *env) 416 { 417 if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { 418 env->sregs[RASID] = 0x04030201; 419 env->sregs[ITLBCFG] = 0; 420 env->sregs[DTLBCFG] = 0; 421 env->autorefill_idx = 0; 422 reset_tlb_mmu_all_ways(env, &env->config->itlb, env->itlb); 423 reset_tlb_mmu_all_ways(env, &env->config->dtlb, env->dtlb); 424 reset_tlb_mmu_ways56(env, &env->config->itlb, env->itlb); 425 reset_tlb_mmu_ways56(env, &env->config->dtlb, env->dtlb); 426 } else { 427 reset_tlb_region_way0(env, env->itlb); 428 reset_tlb_region_way0(env, env->dtlb); 429 } 430 } 431 432 static unsigned get_ring(const CPUXtensaState *env, uint8_t asid) 433 { 434 unsigned i; 435 for (i = 0; i < 4; ++i) { 436 if (((env->sregs[RASID] >> i * 8) & 0xff) == asid) { 437 return i; 438 } 439 } 440 return 0xff; 441 } 442 443 /*! 444 * Lookup xtensa TLB for the given virtual address. 445 * See ISA, 4.6.2.2 446 * 447 * \param pwi: [out] way index 448 * \param pei: [out] entry index 449 * \param pring: [out] access ring 450 * \return 0 if ok, exception cause code otherwise 451 */ 452 int xtensa_tlb_lookup(const CPUXtensaState *env, uint32_t addr, bool dtlb, 453 uint32_t *pwi, uint32_t *pei, uint8_t *pring) 454 { 455 const xtensa_tlb *tlb = dtlb ? 456 &env->config->dtlb : &env->config->itlb; 457 const xtensa_tlb_entry (*entry)[MAX_TLB_WAY_SIZE] = dtlb ? 458 env->dtlb : env->itlb; 459 460 int nhits = 0; 461 unsigned wi; 462 463 for (wi = 0; wi < tlb->nways; ++wi) { 464 uint32_t vpn; 465 uint32_t ei; 466 split_tlb_entry_spec_way(env, addr, dtlb, &vpn, wi, &ei); 467 if (entry[wi][ei].vaddr == vpn && entry[wi][ei].asid) { 468 unsigned ring = get_ring(env, entry[wi][ei].asid); 469 if (ring < 4) { 470 if (++nhits > 1) { 471 return dtlb ? 472 LOAD_STORE_TLB_MULTI_HIT_CAUSE : 473 INST_TLB_MULTI_HIT_CAUSE; 474 } 475 *pwi = wi; 476 *pei = ei; 477 *pring = ring; 478 } 479 } 480 } 481 return nhits ? 0 : 482 (dtlb ? LOAD_STORE_TLB_MISS_CAUSE : INST_TLB_MISS_CAUSE); 483 } 484 485 /*! 486 * Convert MMU ATTR to PAGE_{READ,WRITE,EXEC} mask. 487 * See ISA, 4.6.5.10 488 */ 489 static unsigned mmu_attr_to_access(uint32_t attr) 490 { 491 unsigned access = 0; 492 493 if (attr < 12) { 494 access |= PAGE_READ; 495 if (attr & 0x1) { 496 access |= PAGE_EXEC; 497 } 498 if (attr & 0x2) { 499 access |= PAGE_WRITE; 500 } 501 502 switch (attr & 0xc) { 503 case 0: 504 access |= PAGE_CACHE_BYPASS; 505 break; 506 507 case 4: 508 access |= PAGE_CACHE_WB; 509 break; 510 511 case 8: 512 access |= PAGE_CACHE_WT; 513 break; 514 } 515 } else if (attr == 13) { 516 access |= PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE; 517 } 518 return access; 519 } 520 521 /*! 522 * Convert region protection ATTR to PAGE_{READ,WRITE,EXEC} mask. 523 * See ISA, 4.6.3.3 524 */ 525 static unsigned region_attr_to_access(uint32_t attr) 526 { 527 static const unsigned access[16] = { 528 [0] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_WT, 529 [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT, 530 [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS, 531 [3] = PAGE_EXEC | PAGE_CACHE_WB, 532 [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB, 533 [5] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB, 534 [14] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE, 535 }; 536 537 return access[attr & 0xf]; 538 } 539 540 /*! 541 * Convert cacheattr to PAGE_{READ,WRITE,EXEC} mask. 542 * See ISA, A.2.14 The Cache Attribute Register 543 */ 544 static unsigned cacheattr_attr_to_access(uint32_t attr) 545 { 546 static const unsigned access[16] = { 547 [0] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_WT, 548 [1] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WT, 549 [2] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_BYPASS, 550 [3] = PAGE_EXEC | PAGE_CACHE_WB, 551 [4] = PAGE_READ | PAGE_WRITE | PAGE_EXEC | PAGE_CACHE_WB, 552 [14] = PAGE_READ | PAGE_WRITE | PAGE_CACHE_ISOLATE, 553 }; 554 555 return access[attr & 0xf]; 556 } 557 558 static bool is_access_granted(unsigned access, int is_write) 559 { 560 switch (is_write) { 561 case 0: 562 return access & PAGE_READ; 563 564 case 1: 565 return access & PAGE_WRITE; 566 567 case 2: 568 return access & PAGE_EXEC; 569 570 default: 571 return 0; 572 } 573 } 574 575 static bool get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte); 576 577 static int get_physical_addr_mmu(CPUXtensaState *env, bool update_tlb, 578 uint32_t vaddr, int is_write, int mmu_idx, 579 uint32_t *paddr, uint32_t *page_size, unsigned *access, 580 bool may_lookup_pt) 581 { 582 bool dtlb = is_write != 2; 583 uint32_t wi; 584 uint32_t ei; 585 uint8_t ring; 586 uint32_t vpn; 587 uint32_t pte; 588 const xtensa_tlb_entry *entry = NULL; 589 xtensa_tlb_entry tmp_entry; 590 int ret = xtensa_tlb_lookup(env, vaddr, dtlb, &wi, &ei, &ring); 591 592 if ((ret == INST_TLB_MISS_CAUSE || ret == LOAD_STORE_TLB_MISS_CAUSE) && 593 may_lookup_pt && get_pte(env, vaddr, &pte)) { 594 ring = (pte >> 4) & 0x3; 595 wi = 0; 596 split_tlb_entry_spec_way(env, vaddr, dtlb, &vpn, wi, &ei); 597 598 if (update_tlb) { 599 wi = ++env->autorefill_idx & 0x3; 600 xtensa_tlb_set_entry(env, dtlb, wi, ei, vpn, pte); 601 env->sregs[EXCVADDR] = vaddr; 602 qemu_log_mask(CPU_LOG_MMU, "%s: autorefill(%08x): %08x -> %08x\n", 603 __func__, vaddr, vpn, pte); 604 } else { 605 xtensa_tlb_set_entry_mmu(env, &tmp_entry, dtlb, wi, ei, vpn, pte); 606 entry = &tmp_entry; 607 } 608 ret = 0; 609 } 610 if (ret != 0) { 611 return ret; 612 } 613 614 if (entry == NULL) { 615 entry = xtensa_tlb_get_entry(env, dtlb, wi, ei); 616 } 617 618 if (ring < mmu_idx) { 619 return dtlb ? 620 LOAD_STORE_PRIVILEGE_CAUSE : 621 INST_FETCH_PRIVILEGE_CAUSE; 622 } 623 624 *access = mmu_attr_to_access(entry->attr) & 625 ~(dtlb ? PAGE_EXEC : PAGE_READ | PAGE_WRITE); 626 if (!is_access_granted(*access, is_write)) { 627 return dtlb ? 628 (is_write ? 629 STORE_PROHIBITED_CAUSE : 630 LOAD_PROHIBITED_CAUSE) : 631 INST_FETCH_PROHIBITED_CAUSE; 632 } 633 634 *paddr = entry->paddr | (vaddr & ~xtensa_tlb_get_addr_mask(env, dtlb, wi)); 635 *page_size = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1; 636 637 return 0; 638 } 639 640 static bool get_pte(CPUXtensaState *env, uint32_t vaddr, uint32_t *pte) 641 { 642 CPUState *cs = CPU(xtensa_env_get_cpu(env)); 643 uint32_t paddr; 644 uint32_t page_size; 645 unsigned access; 646 uint32_t pt_vaddr = 647 (env->sregs[PTEVADDR] | (vaddr >> 10)) & 0xfffffffc; 648 int ret = get_physical_addr_mmu(env, false, pt_vaddr, 0, 0, 649 &paddr, &page_size, &access, false); 650 651 if (ret == 0) { 652 qemu_log_mask(CPU_LOG_MMU, 653 "%s: autorefill(%08x): PTE va = %08x, pa = %08x\n", 654 __func__, vaddr, pt_vaddr, paddr); 655 } else { 656 qemu_log_mask(CPU_LOG_MMU, 657 "%s: autorefill(%08x): PTE va = %08x, failed (%d)\n", 658 __func__, vaddr, pt_vaddr, ret); 659 } 660 661 if (ret == 0) { 662 MemTxResult result; 663 664 *pte = address_space_ldl(cs->as, paddr, MEMTXATTRS_UNSPECIFIED, 665 &result); 666 if (result != MEMTX_OK) { 667 qemu_log_mask(CPU_LOG_MMU, 668 "%s: couldn't load PTE: transaction failed (%u)\n", 669 __func__, (unsigned)result); 670 ret = 1; 671 } 672 } 673 return ret == 0; 674 } 675 676 static int get_physical_addr_region(CPUXtensaState *env, 677 uint32_t vaddr, int is_write, int mmu_idx, 678 uint32_t *paddr, uint32_t *page_size, unsigned *access) 679 { 680 bool dtlb = is_write != 2; 681 uint32_t wi = 0; 682 uint32_t ei = (vaddr >> 29) & 0x7; 683 const xtensa_tlb_entry *entry = 684 xtensa_tlb_get_entry(env, dtlb, wi, ei); 685 686 *access = region_attr_to_access(entry->attr); 687 if (!is_access_granted(*access, is_write)) { 688 return dtlb ? 689 (is_write ? 690 STORE_PROHIBITED_CAUSE : 691 LOAD_PROHIBITED_CAUSE) : 692 INST_FETCH_PROHIBITED_CAUSE; 693 } 694 695 *paddr = entry->paddr | (vaddr & ~REGION_PAGE_MASK); 696 *page_size = ~REGION_PAGE_MASK + 1; 697 698 return 0; 699 } 700 701 /*! 702 * Convert virtual address to physical addr. 703 * MMU may issue pagewalk and change xtensa autorefill TLB way entry. 704 * 705 * \return 0 if ok, exception cause code otherwise 706 */ 707 int xtensa_get_physical_addr(CPUXtensaState *env, bool update_tlb, 708 uint32_t vaddr, int is_write, int mmu_idx, 709 uint32_t *paddr, uint32_t *page_size, unsigned *access) 710 { 711 if (xtensa_option_enabled(env->config, XTENSA_OPTION_MMU)) { 712 return get_physical_addr_mmu(env, update_tlb, 713 vaddr, is_write, mmu_idx, paddr, page_size, access, true); 714 } else if (xtensa_option_bits_enabled(env->config, 715 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | 716 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION))) { 717 return get_physical_addr_region(env, vaddr, is_write, mmu_idx, 718 paddr, page_size, access); 719 } else { 720 *paddr = vaddr; 721 *page_size = TARGET_PAGE_SIZE; 722 *access = cacheattr_attr_to_access( 723 env->sregs[CACHEATTR] >> ((vaddr & 0xe0000000) >> 27)); 724 return 0; 725 } 726 } 727 728 static void dump_tlb(FILE *f, fprintf_function cpu_fprintf, 729 CPUXtensaState *env, bool dtlb) 730 { 731 unsigned wi, ei; 732 const xtensa_tlb *conf = 733 dtlb ? &env->config->dtlb : &env->config->itlb; 734 unsigned (*attr_to_access)(uint32_t) = 735 xtensa_option_enabled(env->config, XTENSA_OPTION_MMU) ? 736 mmu_attr_to_access : region_attr_to_access; 737 738 for (wi = 0; wi < conf->nways; ++wi) { 739 uint32_t sz = ~xtensa_tlb_get_addr_mask(env, dtlb, wi) + 1; 740 const char *sz_text; 741 bool print_header = true; 742 743 if (sz >= 0x100000) { 744 sz /= MiB; 745 sz_text = "MB"; 746 } else { 747 sz /= KiB; 748 sz_text = "KB"; 749 } 750 751 for (ei = 0; ei < conf->way_size[wi]; ++ei) { 752 const xtensa_tlb_entry *entry = 753 xtensa_tlb_get_entry(env, dtlb, wi, ei); 754 755 if (entry->asid) { 756 static const char * const cache_text[8] = { 757 [PAGE_CACHE_BYPASS >> PAGE_CACHE_SHIFT] = "Bypass", 758 [PAGE_CACHE_WT >> PAGE_CACHE_SHIFT] = "WT", 759 [PAGE_CACHE_WB >> PAGE_CACHE_SHIFT] = "WB", 760 [PAGE_CACHE_ISOLATE >> PAGE_CACHE_SHIFT] = "Isolate", 761 }; 762 unsigned access = attr_to_access(entry->attr); 763 unsigned cache_idx = (access & PAGE_CACHE_MASK) >> 764 PAGE_CACHE_SHIFT; 765 766 if (print_header) { 767 print_header = false; 768 cpu_fprintf(f, "Way %u (%d %s)\n", wi, sz, sz_text); 769 cpu_fprintf(f, 770 "\tVaddr Paddr ASID Attr RWX Cache\n" 771 "\t---------- ---------- ---- ---- --- -------\n"); 772 } 773 cpu_fprintf(f, 774 "\t0x%08x 0x%08x 0x%02x 0x%02x %c%c%c %-7s\n", 775 entry->vaddr, 776 entry->paddr, 777 entry->asid, 778 entry->attr, 779 (access & PAGE_READ) ? 'R' : '-', 780 (access & PAGE_WRITE) ? 'W' : '-', 781 (access & PAGE_EXEC) ? 'X' : '-', 782 cache_text[cache_idx] ? cache_text[cache_idx] : 783 "Invalid"); 784 } 785 } 786 } 787 } 788 789 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUXtensaState *env) 790 { 791 if (xtensa_option_bits_enabled(env->config, 792 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_PROTECTION) | 793 XTENSA_OPTION_BIT(XTENSA_OPTION_REGION_TRANSLATION) | 794 XTENSA_OPTION_BIT(XTENSA_OPTION_MMU))) { 795 796 cpu_fprintf(f, "ITLB:\n"); 797 dump_tlb(f, cpu_fprintf, env, false); 798 cpu_fprintf(f, "\nDTLB:\n"); 799 dump_tlb(f, cpu_fprintf, env, true); 800 } else { 801 cpu_fprintf(f, "No TLB for this CPU core\n"); 802 } 803 } 804 805 void xtensa_runstall(CPUXtensaState *env, bool runstall) 806 { 807 CPUState *cpu = CPU(xtensa_env_get_cpu(env)); 808 809 env->runstall = runstall; 810 cpu->halted = runstall; 811 if (runstall) { 812 cpu_interrupt(cpu, CPU_INTERRUPT_HALT); 813 } else { 814 cpu_reset_interrupt(cpu, CPU_INTERRUPT_HALT); 815 } 816 } 817 #endif 818