Lines Matching +full:d +full:- +full:tlb +full:- +full:size

2  *  PowerPC MMU, TLB, SLB and BAT emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
25 #include "mmu-hash64.h"
26 #include "mmu-hash32.h"
27 #include "exec/exec-all.h"
28 #include "exec/page-protection.h"
31 #include "qemu/error-report.h"
32 #include "qemu/qemu-print.h"
34 #include "mmu-book3s-v3.h"
35 #include "mmu-radix64.h"
36 #include "mmu-booke.h"
44 assert(!cpu->env.has_hv_mode || !cpu->vhyp); in ppc_store_sdr1()
46 if (mmu_is_64bit(env->mmu_model)) { in ppc_store_sdr1()
62 /* FIXME: Should check for valid HTABMASK values in 32-bit case */ in ppc_store_sdr1()
63 env->spr[SPR_SDR1] = value; in ppc_store_sdr1()
74 /* Select TLB num in a way from address */ in ppc6xx_tlb_getnum()
75 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1); in ppc6xx_tlb_getnum()
76 /* Select TLB way */ in ppc6xx_tlb_getnum()
77 nr += env->tlb_per_way * way; in ppc6xx_tlb_getnum()
80 nr += env->nb_tlb; in ppc6xx_tlb_getnum()
86 /* Software driven TLB helpers */
92 ppc6xx_tlb_t *tlb; in ppc6xx_tlb_check() local
98 *raddr = (hwaddr)-1ULL; in ppc6xx_tlb_check()
99 best = -1; in ppc6xx_tlb_check()
100 ret = -1; /* No TLB found */ in ppc6xx_tlb_check()
101 for (way = 0; way < env->nb_ways; way++) { in ppc6xx_tlb_check()
103 tlb = &env->tlb.tlb6[nr]; in ppc6xx_tlb_check()
105 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) { in ppc6xx_tlb_check()
106 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s [" TARGET_FMT_lx in ppc6xx_tlb_check()
108 nr, env->nb_tlb, in ppc6xx_tlb_check()
109 pte_is_valid(tlb->pte0) ? "valid" : "inval", in ppc6xx_tlb_check()
110 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr); in ppc6xx_tlb_check()
113 qemu_log_mask(CPU_LOG_MMU, "TLB %d/%d %s " TARGET_FMT_lx " <> " in ppc6xx_tlb_check()
115 nr, env->nb_tlb, in ppc6xx_tlb_check()
116 pte_is_valid(tlb->pte0) ? "valid" : "inval", in ppc6xx_tlb_check()
117 tlb->EPN, eaddr, tlb->pte1, in ppc6xx_tlb_check()
119 access_type == MMU_INST_FETCH ? 'I' : 'D'); in ppc6xx_tlb_check()
121 if (!pte_is_valid(tlb->pte0) || ((tlb->pte0 >> 6) & 1) != 0 || in ppc6xx_tlb_check()
122 (tlb->pte0 & PTE_PTEM_MASK) != ptem) { in ppc6xx_tlb_check()
126 if (*raddr != (hwaddr)-1ULL && in ppc6xx_tlb_check()
127 (*raddr & PTE_CHECK_MASK) != (tlb->pte1 & PTE_CHECK_MASK)) { in ppc6xx_tlb_check()
129 /* TLB inconsistency */ in ppc6xx_tlb_check()
134 *raddr = tlb->pte1; in ppc6xx_tlb_check()
135 *prot = ppc_hash32_prot(key, tlb->pte1 & HPTE32_R_PP, nx); in ppc6xx_tlb_check()
142 ret = -2; in ppc6xx_tlb_check()
145 if (best != -1) { in ppc6xx_tlb_check()
146 qemu_log_mask(CPU_LOG_MMU, "found TLB at addr " HWADDR_FMT_plx in ppc6xx_tlb_check()
147 " prot=%01x ret=%d\n", in ppc6xx_tlb_check()
150 pte1p = &env->tlb.tlb6[best].pte1; in ppc6xx_tlb_check()
162 if (ret == -1) { in ppc6xx_tlb_check()
164 env->spr[r] = ptem; in ppc6xx_tlb_check()
176 a0 = ldl_phys(cs->as, curaddr); in ppc6xx_tlb_check()
177 a1 = ldl_phys(cs->as, curaddr + 4); in ppc6xx_tlb_check()
178 a2 = ldl_phys(cs->as, curaddr + 8); in ppc6xx_tlb_check()
179 a3 = ldl_phys(cs->as, curaddr + 12); in ppc6xx_tlb_check()
196 int i, ret = -1; in get_bat_6xx_tlb()
200 ifetch ? 'I' : 'D', eaddr); in get_bat_6xx_tlb()
202 BATlt = env->IBAT[1]; in get_bat_6xx_tlb()
203 BATut = env->IBAT[0]; in get_bat_6xx_tlb()
205 BATlt = env->DBAT[1]; in get_bat_6xx_tlb()
206 BATut = env->DBAT[0]; in get_bat_6xx_tlb()
208 for (i = 0; i < env->nb_BATs; i++) { in get_bat_6xx_tlb()
213 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx " BATu " in get_bat_6xx_tlb()
215 ifetch ? 'I' : 'D', i, eaddr, *BATu, *BATl); in get_bat_6xx_tlb()
227 qemu_log_mask(CPU_LOG_MMU, "BAT %d match: r " HWADDR_FMT_plx in get_bat_6xx_tlb()
229 *prot & PAGE_READ ? 'R' : '-', in get_bat_6xx_tlb()
230 *prot & PAGE_WRITE ? 'W' : '-'); in get_bat_6xx_tlb()
233 ret = -2; in get_bat_6xx_tlb()
249 qemu_log_mask(CPU_LOG_MMU, "%s: %cBAT%d v " TARGET_FMT_lx in get_bat_6xx_tlb()
252 TARGET_FMT_lx "\n", __func__, ifetch ? 'I' : 'D', in get_bat_6xx_tlb()
270 bool pr = FIELD_EX64(env->msr, MSR, PR); in mmu6xx_get_physical_address()
273 if (env->nb_BATs && in mmu6xx_get_physical_address()
279 sr = env->sr[eaddr >> 28]; in mmu6xx_get_physical_address()
286 "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx in mmu6xx_get_physical_address()
288 " ir=%d dr=%d pr=%d %d t=%d\n", in mmu6xx_get_physical_address()
289 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, in mmu6xx_get_physical_address()
290 (int)FIELD_EX64(env->msr, MSR, IR), in mmu6xx_get_physical_address()
291 (int)FIELD_EX64(env->msr, MSR, DR), pr ? 1 : 0, in mmu6xx_get_physical_address()
297 qemu_log_mask(CPU_LOG_MMU, "pte segment: key=%d ds %d nx %d vsid " in mmu6xx_get_physical_address()
303 return -3; in mmu6xx_get_physical_address()
311 /* Software TLB search */ in mmu6xx_get_physical_address()
316 /* Direct-store segment : absolutely *BUGGY* for now */ in mmu6xx_get_physical_address()
326 * Should make the instruction do no-op. As it already do in mmu6xx_get_physical_address()
327 * no-op, it's quite easy :-) in mmu6xx_get_physical_address()
331 case ACCESS_CODE: /* No code fetch is allowed in direct-store areas */ in mmu6xx_get_physical_address()
335 return -4; in mmu6xx_get_physical_address()
342 return -2; in mmu6xx_get_physical_address()
358 if (kvm_enabled() && !env->kvm_sw_tlb) { in mmubooke_dump_mmu()
359 qemu_printf("Cannot access KVM TLB\n"); in mmubooke_dump_mmu()
365 qemu_printf("Effective Physical Size PID Prot " in mmubooke_dump_mmu()
368 entry = &env->tlb.tlbe[0]; in mmubooke_dump_mmu()
369 for (i = 0; i < env->nb_tlb; i++, entry++) { in mmubooke_dump_mmu()
372 uint64_t size = (uint64_t)entry->size; in mmubooke_dump_mmu() local
376 if (!(entry->prot & PAGE_VALID)) { in mmubooke_dump_mmu()
380 mask = ~(entry->size - 1); in mmubooke_dump_mmu()
381 ea = entry->EPN & mask; in mmubooke_dump_mmu()
382 pa = entry->RPN & mask; in mmubooke_dump_mmu()
384 pa |= (hwaddr)(entry->RPN & 0xF) << 32; in mmubooke_dump_mmu()
385 if (size >= 1 * MiB) { in mmubooke_dump_mmu()
386 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB); in mmubooke_dump_mmu()
388 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB); in mmubooke_dump_mmu()
390 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n", in mmubooke_dump_mmu()
391 (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID, in mmubooke_dump_mmu()
392 entry->prot, entry->attr); in mmubooke_dump_mmu()
403 qemu_printf("\nTLB%d:\n", tlbn); in mmubooke206_dump_one_tlb()
404 qemu_printf("Effective Physical Size TID TS SRWX" in mmubooke206_dump_one_tlb()
407 entry = &env->tlb.tlbm[offset]; in mmubooke206_dump_one_tlb()
409 hwaddr ea, pa, size; in mmubooke206_dump_one_tlb() local
412 if (!(entry->mas1 & MAS1_VALID)) { in mmubooke206_dump_one_tlb()
416 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; in mmubooke206_dump_one_tlb()
417 size = 1024ULL << tsize; in mmubooke206_dump_one_tlb()
418 ea = entry->mas2 & ~(size - 1); in mmubooke206_dump_one_tlb()
419 pa = entry->mas7_3 & ~(size - 1); in mmubooke206_dump_one_tlb()
421 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c" in mmubooke206_dump_one_tlb()
425 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT, in mmubooke206_dump_one_tlb()
426 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT, in mmubooke206_dump_one_tlb()
427 entry->mas7_3 & MAS3_SR ? 'R' : '-', in mmubooke206_dump_one_tlb()
428 entry->mas7_3 & MAS3_SW ? 'W' : '-', in mmubooke206_dump_one_tlb()
429 entry->mas7_3 & MAS3_SX ? 'X' : '-', in mmubooke206_dump_one_tlb()
430 entry->mas7_3 & MAS3_UR ? 'R' : '-', in mmubooke206_dump_one_tlb()
431 entry->mas7_3 & MAS3_UW ? 'W' : '-', in mmubooke206_dump_one_tlb()
432 entry->mas7_3 & MAS3_UX ? 'X' : '-', in mmubooke206_dump_one_tlb()
433 entry->mas2 & MAS2_W ? 'W' : '-', in mmubooke206_dump_one_tlb()
434 entry->mas2 & MAS2_I ? 'I' : '-', in mmubooke206_dump_one_tlb()
435 entry->mas2 & MAS2_M ? 'M' : '-', in mmubooke206_dump_one_tlb()
436 entry->mas2 & MAS2_G ? 'G' : '-', in mmubooke206_dump_one_tlb()
437 entry->mas2 & MAS2_E ? 'E' : '-', in mmubooke206_dump_one_tlb()
438 entry->mas7_3 & MAS3_U0 ? '0' : '-', in mmubooke206_dump_one_tlb()
439 entry->mas7_3 & MAS3_U1 ? '1' : '-', in mmubooke206_dump_one_tlb()
440 entry->mas7_3 & MAS3_U2 ? '2' : '-', in mmubooke206_dump_one_tlb()
441 entry->mas7_3 & MAS3_U3 ? '3' : '-'); in mmubooke206_dump_one_tlb()
451 if (kvm_enabled() && !env->kvm_sw_tlb) { in mmubooke206_dump_mmu()
452 qemu_printf("Cannot access KVM TLB\n"); in mmubooke206_dump_mmu()
458 int size = booke206_tlb_size(env, i); in mmubooke206_dump_mmu() local
460 if (size == 0) { in mmubooke206_dump_mmu()
464 mmubooke206_dump_one_tlb(env, i, offset, size); in mmubooke206_dump_mmu()
465 offset += size; in mmubooke206_dump_mmu()
477 BATlt = env->IBAT[1]; in mmu6xx_dump_BATs()
478 BATut = env->IBAT[0]; in mmu6xx_dump_BATs()
481 BATlt = env->DBAT[1]; in mmu6xx_dump_BATs()
482 BATut = env->DBAT[0]; in mmu6xx_dump_BATs()
486 for (i = 0; i < env->nb_BATs; i++) { in mmu6xx_dump_BATs()
492 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx in mmu6xx_dump_BATs()
503 ppc6xx_tlb_t *tlb; in mmu6xx_dump_mmu() local
512 sr = env->sr[i]; in mmu6xx_dump_mmu()
514 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x " in mmu6xx_dump_mmu()
520 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i, in mmu6xx_dump_mmu()
531 qemu_printf("\nTLBs [EPN EPN + SIZE]\n"); in mmu6xx_dump_mmu()
533 for (way = 0; way < env->nb_ways; way++) { in mmu6xx_dump_mmu()
534 for (entry = env->nb_tlb * type + env->tlb_per_way * way; in mmu6xx_dump_mmu()
535 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1)); in mmu6xx_dump_mmu()
538 tlb = &env->tlb.tlb6[entry]; in mmu6xx_dump_mmu()
539 qemu_printf("%s TLB %02d/%02d way:%d %s [" in mmu6xx_dump_mmu()
541 type ? "code" : "data", entry % env->nb_tlb, in mmu6xx_dump_mmu()
542 env->nb_tlb, way, in mmu6xx_dump_mmu()
543 pte_is_valid(tlb->pte0) ? "valid" : "inval", in mmu6xx_dump_mmu()
544 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE); in mmu6xx_dump_mmu()
552 switch (env->mmu_model) { in dump_mmu()
588 CPUPPCState *env = &cpu->env; in ppc_real_mode_xlate()
590 if (access_type == MMU_INST_FETCH ? !FIELD_EX64(env->msr, MSR, IR) in ppc_real_mode_xlate()
591 : !FIELD_EX64(env->msr, MSR, DR)) { in ppc_real_mode_xlate()
596 } else if (env->mmu_model == POWERPC_MMU_REAL) { in ppc_real_mode_xlate()
608 CPUPPCState *env = &cpu->env; in ppc_40x_xlate()
626 case -1: in ppc_40x_xlate()
627 /* No matches in page tables or TLB */ in ppc_40x_xlate()
628 cs->exception_index = POWERPC_EXCP_ITLB; in ppc_40x_xlate()
629 env->error_code = 0; in ppc_40x_xlate()
630 env->spr[SPR_40x_DEAR] = eaddr; in ppc_40x_xlate()
631 env->spr[SPR_40x_ESR] = 0x00000000; in ppc_40x_xlate()
633 case -2: in ppc_40x_xlate()
635 cs->exception_index = POWERPC_EXCP_ISI; in ppc_40x_xlate()
636 env->error_code = 0x08000000; in ppc_40x_xlate()
643 case -1: in ppc_40x_xlate()
644 /* No matches in page tables or TLB */ in ppc_40x_xlate()
645 cs->exception_index = POWERPC_EXCP_DTLB; in ppc_40x_xlate()
646 env->error_code = 0; in ppc_40x_xlate()
647 env->spr[SPR_40x_DEAR] = eaddr; in ppc_40x_xlate()
649 env->spr[SPR_40x_ESR] = 0x00800000; in ppc_40x_xlate()
651 env->spr[SPR_40x_ESR] = 0x00000000; in ppc_40x_xlate()
654 case -2: in ppc_40x_xlate()
656 cs->exception_index = POWERPC_EXCP_DSI; in ppc_40x_xlate()
657 env->error_code = 0; in ppc_40x_xlate()
658 env->spr[SPR_40x_DEAR] = eaddr; in ppc_40x_xlate()
660 env->spr[SPR_40x_ESR] |= 0x00800000; in ppc_40x_xlate()
676 CPUPPCState *env = &cpu->env; in ppc_6xx_xlate()
690 type = env->access_type; in ppc_6xx_xlate()
707 case -1: in ppc_6xx_xlate()
708 /* No matches in page tables or TLB */ in ppc_6xx_xlate()
709 cs->exception_index = POWERPC_EXCP_IFTLB; in ppc_6xx_xlate()
710 env->error_code = 1 << 18; in ppc_6xx_xlate()
711 env->spr[SPR_IMISS] = eaddr; in ppc_6xx_xlate()
712 env->spr[SPR_ICMP] |= 0x80000000; in ppc_6xx_xlate()
714 case -2: in ppc_6xx_xlate()
716 cs->exception_index = POWERPC_EXCP_ISI; in ppc_6xx_xlate()
717 env->error_code = 0x08000000; in ppc_6xx_xlate()
719 case -3: in ppc_6xx_xlate()
721 cs->exception_index = POWERPC_EXCP_ISI; in ppc_6xx_xlate()
722 env->error_code = 0x10000000; in ppc_6xx_xlate()
724 case -4: in ppc_6xx_xlate()
726 /* No code fetch is allowed in direct-store areas */ in ppc_6xx_xlate()
727 cs->exception_index = POWERPC_EXCP_ISI; in ppc_6xx_xlate()
728 env->error_code = 0x10000000; in ppc_6xx_xlate()
733 case -1: in ppc_6xx_xlate()
734 /* No matches in page tables or TLB */ in ppc_6xx_xlate()
736 cs->exception_index = POWERPC_EXCP_DSTLB; in ppc_6xx_xlate()
737 env->error_code = 1 << 16; in ppc_6xx_xlate()
739 cs->exception_index = POWERPC_EXCP_DLTLB; in ppc_6xx_xlate()
740 env->error_code = 0; in ppc_6xx_xlate()
742 env->spr[SPR_DMISS] = eaddr; in ppc_6xx_xlate()
743 env->spr[SPR_DCMP] |= 0x80000000; in ppc_6xx_xlate()
745 env->error_code |= key << 19; in ppc_6xx_xlate()
746 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) + in ppc_6xx_xlate()
748 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) + in ppc_6xx_xlate()
751 case -2: in ppc_6xx_xlate()
753 cs->exception_index = POWERPC_EXCP_DSI; in ppc_6xx_xlate()
754 env->error_code = 0; in ppc_6xx_xlate()
755 env->spr[SPR_DAR] = eaddr; in ppc_6xx_xlate()
757 env->spr[SPR_DSISR] = 0x0A000000; in ppc_6xx_xlate()
759 env->spr[SPR_DSISR] = 0x08000000; in ppc_6xx_xlate()
762 case -4: in ppc_6xx_xlate()
767 cs->exception_index = POWERPC_EXCP_ALIGN; in ppc_6xx_xlate()
768 env->error_code = POWERPC_EXCP_ALIGN_FP; in ppc_6xx_xlate()
769 env->spr[SPR_DAR] = eaddr; in ppc_6xx_xlate()
773 cs->exception_index = POWERPC_EXCP_DSI; in ppc_6xx_xlate()
774 env->error_code = 0; in ppc_6xx_xlate()
775 env->spr[SPR_DAR] = eaddr; in ppc_6xx_xlate()
777 env->spr[SPR_DSISR] = 0x06000000; in ppc_6xx_xlate()
779 env->spr[SPR_DSISR] = 0x04000000; in ppc_6xx_xlate()
784 cs->exception_index = POWERPC_EXCP_DSI; in ppc_6xx_xlate()
785 env->error_code = 0; in ppc_6xx_xlate()
786 env->spr[SPR_DAR] = eaddr; in ppc_6xx_xlate()
788 env->spr[SPR_DSISR] = 0x06100000; in ppc_6xx_xlate()
790 env->spr[SPR_DSISR] = 0x04100000; in ppc_6xx_xlate()
794 printf("DSI: invalid exception (%d)\n", ret); in ppc_6xx_xlate()
795 cs->exception_index = POWERPC_EXCP_PROGRAM; in ppc_6xx_xlate()
796 env->error_code = POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL; in ppc_6xx_xlate()
797 env->spr[SPR_DAR] = eaddr; in ppc_6xx_xlate()
812 switch (cpu->env.mmu_model) { in ppc_xlate()
845 cpu_abort(env_cpu(&cpu->env), "MPC8xx MMU model is not implemented\n"); in ppc_xlate()
863 ppc_env_mmu_index(&cpu->env, false), false) || in ppc_cpu_get_phys_page_debug()
865 ppc_env_mmu_index(&cpu->env, true), false)) { in ppc_cpu_get_phys_page_debug()
868 return -1; in ppc_cpu_get_phys_page_debug()