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"
37 #include "exec/helper-proto.h"
45 /* Software driven TLB helpers */
48 ppc6xx_tlb_t *tlb; in ppc6xx_tlb_invalidate_all() local
49 int nr, max = 2 * env->nb_tlb; in ppc6xx_tlb_invalidate_all()
52 tlb = &env->tlb.tlb6[nr]; in ppc6xx_tlb_invalidate_all()
53 pte_invalidate(&tlb->pte0); in ppc6xx_tlb_invalidate_all()
64 ppc6xx_tlb_t *tlb; in ppc6xx_tlb_invalidate_virt2() local
68 for (way = 0; way < env->nb_ways; way++) { in ppc6xx_tlb_invalidate_virt2()
70 tlb = &env->tlb.tlb6[nr]; in ppc6xx_tlb_invalidate_virt2()
71 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) { in ppc6xx_tlb_invalidate_virt2()
72 qemu_log_mask(CPU_LOG_MMU, "TLB invalidate %d/%d " in ppc6xx_tlb_invalidate_virt2()
73 TARGET_FMT_lx "\n", nr, env->nb_tlb, eaddr); in ppc6xx_tlb_invalidate_virt2()
74 pte_invalidate(&tlb->pte0); in ppc6xx_tlb_invalidate_virt2()
75 tlb_flush_page(cs, tlb->EPN); in ppc6xx_tlb_invalidate_virt2()
93 ppc6xx_tlb_t *tlb; in ppc6xx_tlb_store() local
97 tlb = &env->tlb.tlb6[nr]; in ppc6xx_tlb_store()
98 qemu_log_mask(CPU_LOG_MMU, "Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " in ppc6xx_tlb_store()
99 TARGET_FMT_lx " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, in ppc6xx_tlb_store()
103 tlb->pte0 = pte0; in ppc6xx_tlb_store()
104 tlb->pte1 = pte1; in ppc6xx_tlb_store()
105 tlb->EPN = EPN; in ppc6xx_tlb_store()
107 env->last_way = way; in ppc6xx_tlb_store()
113 ppcemb_tlb_t *tlb; in ppc4xx_tlb_invalidate_all() local
116 for (i = 0; i < env->nb_tlb; i++) { in ppc4xx_tlb_invalidate_all()
117 tlb = &env->tlb.tlbe[i]; in ppc4xx_tlb_invalidate_all()
118 tlb->prot &= ~PAGE_VALID; in ppc4xx_tlb_invalidate_all()
128 ppcmas_tlb_t *tlb = env->tlb.tlbm; in booke206_flush_tlb() local
134 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) { in booke206_flush_tlb()
135 tlb[j].mas1 &= ~MAS1_VALID; in booke206_flush_tlb()
139 tlb += booke206_tlb_size(env, i); in booke206_flush_tlb()
156 if (((end - base) >> TARGET_PAGE_BITS) > 1024) { in do_invalidate_BAT()
176 qemu_log_mask(CPU_LOG_MMU, "Set %cBAT%d%c to " TARGET_FMT_lx " (" in dump_store_bat()
178 value, env->nip); in dump_store_bat()
186 if (env->IBAT[0][nr] != value) { in helper_store_ibatu()
189 do_invalidate_BAT(env, env->IBAT[0][nr], mask); in helper_store_ibatu()
196 env->IBAT[0][nr] = (value & 0x00001FFFUL) | in helper_store_ibatu()
198 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) | in helper_store_ibatu()
199 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask); in helper_store_ibatu()
201 do_invalidate_BAT(env, env->IBAT[0][nr], mask); in helper_store_ibatu()
211 env->IBAT[1][nr] = value; in helper_store_ibatl()
218 dump_store_bat(env, 'D', 0, nr, value); in helper_store_dbatu()
219 if (env->DBAT[0][nr] != value) { in helper_store_dbatu()
226 do_invalidate_BAT(env, env->DBAT[0][nr], mask); in helper_store_dbatu()
229 env->DBAT[0][nr] = (value & 0x00001FFFUL) | in helper_store_dbatu()
231 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) | in helper_store_dbatu()
232 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask); in helper_store_dbatu()
234 do_invalidate_BAT(env, env->DBAT[0][nr], mask); in helper_store_dbatu()
243 dump_store_bat(env, 'D', 1, nr, value); in helper_store_dbatl()
244 env->DBAT[1][nr] = value; in helper_store_dbatl()
248 /* TLB management */
252 if (mmu_is_64bit(env->mmu_model)) { in ppc_tlb_invalidate_all()
253 env->tlb_need_flush = 0; in ppc_tlb_invalidate_all()
257 switch (env->mmu_model) { in ppc_tlb_invalidate_all()
265 cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n"); in ppc_tlb_invalidate_all()
275 booke206_flush_tlb(env, -1, 0); in ppc_tlb_invalidate_all()
278 env->tlb_need_flush = 0; in ppc_tlb_invalidate_all()
283 cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model); in ppc_tlb_invalidate_all()
293 if (mmu_is_64bit(env->mmu_model)) { in ppc_tlb_invalidate_one()
300 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; in ppc_tlb_invalidate_one()
303 switch (env->mmu_model) { in ppc_tlb_invalidate_one()
312 * account, we just mark the TLB to be flushed later (context in ppc_tlb_invalidate_one()
313 * synchronizing event or sync instruction on 32-bit). in ppc_tlb_invalidate_one()
315 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; in ppc_tlb_invalidate_one()
333 if (mmu_is_64bit(env->mmu_model)) { in helper_load_sr()
338 return env->sr[sr_num]; in helper_load_sr()
344 "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, in helper_store_sr()
345 (int)srnum, value, env->sr[srnum]); in helper_store_sr()
347 if (mmu_is_64bit(env->mmu_model)) { in helper_store_sr()
362 if (env->sr[srnum] != value) { in helper_store_sr()
363 env->sr[srnum] = value; in helper_store_sr()
366 * longer than flushing the whole TLB. in helper_store_sr()
379 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; in helper_store_sr()
384 /* TLB management */
426 * PRS is currently ignored, because we don't know if a given TLB entry in helper_tlbie_isa300()
434 unsigned ap; /* actual page size */ in helper_tlbie_isa300()
438 "%s: local=%d addr=" TARGET_FMT_lx " ric=%u prs=%d r=%d is=%u\n", in helper_tlbie_isa300()
441 effR = FIELD_EX64(env->msr, MSR, HV) ? r : env->spr[SPR_LPCR] & LPCR_HR; in helper_tlbie_isa300()
443 /* Partial TLB invalidation is supported for Radix only for now. */ in helper_tlbie_isa300()
454 "%s: invalid instruction form: ric=%u prs=%d r=%d is=%u\n", in helper_tlbie_isa300()
464 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid set: %d\n", in helper_tlbie_isa300()
474 * to full TLB flush in these cases. in helper_tlbie_isa300()
521 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid AP: %d\n", __func__, ap); in helper_tlbie_isa300()
535 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; in helper_tlbie_isa300()
537 env->tlb_need_flush |= TLB_NEED_GLOBAL_FLUSH; in helper_tlbie_isa300()
552 assert(env->mmu_model == POWERPC_MMU_BOOKE); in helper_tlbiva()
558 /* PowerPC 602/603 software TLB load instructions helpers */
564 RPN = env->spr[SPR_RPA]; in do_6xx_tlb()
566 CMP = env->spr[SPR_ICMP]; in do_6xx_tlb()
567 EPN = env->spr[SPR_IMISS]; in do_6xx_tlb()
569 CMP = env->spr[SPR_DCMP]; in do_6xx_tlb()
570 EPN = env->spr[SPR_DMISS]; in do_6xx_tlb()
572 way = (env->spr[SPR_SRR1] >> 17) & 1; in do_6xx_tlb()
575 " PTE0 " TARGET_FMT_lx " PTE1 " TARGET_FMT_lx " way %d\n", in do_6xx_tlb()
577 /* Store this TLB */ in do_6xx_tlb()
592 static inline target_ulong booke_tlb_to_page_size(int size) in booke_tlb_to_page_size() argument
594 return 1024 << (2 * size); in booke_tlb_to_page_size()
599 int size; in booke_page_size_to_tlb() local
603 size = 0x0; in booke_page_size_to_tlb()
606 size = 0x1; in booke_page_size_to_tlb()
609 size = 0x2; in booke_page_size_to_tlb()
612 size = 0x3; in booke_page_size_to_tlb()
615 size = 0x4; in booke_page_size_to_tlb()
618 size = 0x5; in booke_page_size_to_tlb()
621 size = 0x6; in booke_page_size_to_tlb()
624 size = 0x7; in booke_page_size_to_tlb()
627 size = 0x8; in booke_page_size_to_tlb()
630 size = 0x9; in booke_page_size_to_tlb()
633 size = 0xA; in booke_page_size_to_tlb()
637 size = 0xB; in booke_page_size_to_tlb()
640 size = 0xC; in booke_page_size_to_tlb()
643 size = 0xD; in booke_page_size_to_tlb()
646 size = 0xE; in booke_page_size_to_tlb()
649 size = 0xF; in booke_page_size_to_tlb()
653 size = -1; in booke_page_size_to_tlb()
657 return size; in booke_page_size_to_tlb()
660 /* Helpers for 4xx TLB management */
661 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
678 if (env->spr[SPR_40x_PID] != val) { in helper_store_40x_pid()
679 env->spr[SPR_40x_PID] = val; in helper_store_40x_pid()
680 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH; in helper_store_40x_pid()
686 ppcemb_tlb_t *tlb; in helper_4xx_tlbre_hi() local
688 int size; in helper_4xx_tlbre_hi() local
691 tlb = &env->tlb.tlbe[entry]; in helper_4xx_tlbre_hi()
692 ret = tlb->EPN; in helper_4xx_tlbre_hi()
693 if (tlb->prot & PAGE_VALID) { in helper_4xx_tlbre_hi()
696 size = booke_page_size_to_tlb(tlb->size); in helper_4xx_tlbre_hi()
697 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) { in helper_4xx_tlbre_hi()
698 size = PPC4XX_TLBHI_SIZE_DEFAULT; in helper_4xx_tlbre_hi()
700 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; in helper_4xx_tlbre_hi()
701 helper_store_40x_pid(env, tlb->PID); in helper_4xx_tlbre_hi()
707 ppcemb_tlb_t *tlb; in helper_4xx_tlbre_lo() local
711 tlb = &env->tlb.tlbe[entry]; in helper_4xx_tlbre_lo()
712 ret = tlb->RPN; in helper_4xx_tlbre_lo()
713 if (tlb->prot & PAGE_EXEC) { in helper_4xx_tlbre_lo()
716 if (tlb->prot & PAGE_WRITE) { in helper_4xx_tlbre_lo()
722 static void ppcemb_tlb_flush(CPUState *cs, ppcemb_tlb_t *tlb) in ppcemb_tlb_flush() argument
726 if (tlb->prot & 0xf) { in ppcemb_tlb_flush()
729 if ((tlb->prot >> 4) & 0xf) { in ppcemb_tlb_flush()
732 if (tlb->attr & 1) { in ppcemb_tlb_flush()
736 tlb_flush_range_by_mmuidx(cs, tlb->EPN, tlb->size, mmu_idx, in ppcemb_tlb_flush()
744 ppcemb_tlb_t *tlb; in helper_4xx_tlbwe_hi() local
746 qemu_log_mask(CPU_LOG_MMU, "%s entry %d val " TARGET_FMT_lx "\n", in helper_4xx_tlbwe_hi()
750 tlb = &env->tlb.tlbe[entry]; in helper_4xx_tlbwe_hi()
751 /* Invalidate previous TLB (if it's valid) */ in helper_4xx_tlbwe_hi()
752 if ((tlb->prot & PAGE_VALID) && tlb->PID == env->spr[SPR_40x_PID]) { in helper_4xx_tlbwe_hi()
753 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " in helper_4xx_tlbwe_hi()
755 (int)entry, tlb->EPN, tlb->EPN + tlb->size); in helper_4xx_tlbwe_hi()
756 ppcemb_tlb_flush(cs, tlb); in helper_4xx_tlbwe_hi()
758 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT) in helper_4xx_tlbwe_hi()
761 * We cannot handle TLB size < TARGET_PAGE_SIZE. in helper_4xx_tlbwe_hi()
764 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) { in helper_4xx_tlbwe_hi()
765 cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u " in helper_4xx_tlbwe_hi()
766 "are not supported (%d)\n" in helper_4xx_tlbwe_hi()
768 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); in helper_4xx_tlbwe_hi()
770 tlb->EPN = val & ~(tlb->size - 1); in helper_4xx_tlbwe_hi()
772 tlb->prot |= PAGE_VALID; in helper_4xx_tlbwe_hi()
776 "Little-endian TLB entries are not supported by now\n"); in helper_4xx_tlbwe_hi()
779 tlb->prot &= ~PAGE_VALID; in helper_4xx_tlbwe_hi()
781 tlb->PID = env->spr[SPR_40x_PID]; /* PID */ in helper_4xx_tlbwe_hi()
782 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " HWADDR_FMT_plx in helper_4xx_tlbwe_hi()
783 " EPN " TARGET_FMT_lx " size " TARGET_FMT_lx in helper_4xx_tlbwe_hi()
784 " prot %c%c%c%c PID %d\n", __func__, in helper_4xx_tlbwe_hi()
785 (int)entry, tlb->RPN, tlb->EPN, tlb->size, in helper_4xx_tlbwe_hi()
786 tlb->prot & PAGE_READ ? 'r' : '-', in helper_4xx_tlbwe_hi()
787 tlb->prot & PAGE_WRITE ? 'w' : '-', in helper_4xx_tlbwe_hi()
788 tlb->prot & PAGE_EXEC ? 'x' : '-', in helper_4xx_tlbwe_hi()
789 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); in helper_4xx_tlbwe_hi()
796 ppcemb_tlb_t *tlb; in helper_4xx_tlbwe_lo() local
801 tlb = &env->tlb.tlbe[entry]; in helper_4xx_tlbwe_lo()
802 /* Invalidate previous TLB (if it's valid) */ in helper_4xx_tlbwe_lo()
803 if ((tlb->prot & PAGE_VALID) && tlb->PID == env->spr[SPR_40x_PID]) { in helper_4xx_tlbwe_lo()
804 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " in helper_4xx_tlbwe_lo()
806 (int)entry, tlb->EPN, tlb->EPN + tlb->size); in helper_4xx_tlbwe_lo()
807 ppcemb_tlb_flush(cs, tlb); in helper_4xx_tlbwe_lo()
809 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK; in helper_4xx_tlbwe_lo()
810 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK; in helper_4xx_tlbwe_lo()
811 tlb->prot = PAGE_READ; in helper_4xx_tlbwe_lo()
813 tlb->prot |= PAGE_EXEC; in helper_4xx_tlbwe_lo()
816 tlb->prot |= PAGE_WRITE; in helper_4xx_tlbwe_lo()
818 qemu_log_mask(CPU_LOG_MMU, "%s: set up TLB %d RPN " HWADDR_FMT_plx in helper_4xx_tlbwe_lo()
820 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, in helper_4xx_tlbwe_lo()
821 (int)entry, tlb->RPN, tlb->EPN, tlb->size, in helper_4xx_tlbwe_lo()
822 tlb->prot & PAGE_READ ? 'r' : '-', in helper_4xx_tlbwe_lo()
823 tlb->prot & PAGE_WRITE ? 'w' : '-', in helper_4xx_tlbwe_lo()
824 tlb->prot & PAGE_EXEC ? 'x' : '-', in helper_4xx_tlbwe_lo()
825 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID); in helper_4xx_tlbwe_lo()
830 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); in helper_4xx_tlbsx()
833 static bool mmubooke_pid_match(CPUPPCState *env, ppcemb_tlb_t *tlb) in mmubooke_pid_match() argument
835 if (tlb->PID == env->spr[SPR_BOOKE_PID]) { in mmubooke_pid_match()
838 if (!env->nb_pids) { in mmubooke_pid_match()
842 if (env->spr[SPR_BOOKE_PID1] && tlb->PID == env->spr[SPR_BOOKE_PID1]) { in mmubooke_pid_match()
845 if (env->spr[SPR_BOOKE_PID2] && tlb->PID == env->spr[SPR_BOOKE_PID2]) { in mmubooke_pid_match()
852 /* PowerPC 440 TLB management */
856 ppcemb_tlb_t *tlb; in helper_440_tlbwe() local
858 qemu_log_mask(CPU_LOG_MMU, "%s word %d entry %d value " TARGET_FMT_lx "\n", in helper_440_tlbwe()
861 tlb = &env->tlb.tlbe[entry]; in helper_440_tlbwe()
863 /* Invalidate previous TLB (if it's valid) */ in helper_440_tlbwe()
864 if ((tlb->prot & PAGE_VALID) && mmubooke_pid_match(env, tlb)) { in helper_440_tlbwe()
865 qemu_log_mask(CPU_LOG_MMU, "%s: invalidate old TLB %d start " in helper_440_tlbwe()
867 (int)entry, tlb->EPN, tlb->EPN + tlb->size); in helper_440_tlbwe()
868 ppcemb_tlb_flush(env_cpu(env), tlb); in helper_440_tlbwe()
875 tlb->EPN = value & 0xFFFFFC00; in helper_440_tlbwe()
876 tlb->size = booke_tlb_to_page_size((value >> 4) & 0xF); in helper_440_tlbwe()
877 tlb->attr &= ~0x1; in helper_440_tlbwe()
878 tlb->attr |= (value >> 8) & 1; in helper_440_tlbwe()
880 tlb->prot |= PAGE_VALID; in helper_440_tlbwe()
882 tlb->prot &= ~PAGE_VALID; in helper_440_tlbwe()
884 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF; in helper_440_tlbwe()
887 tlb->RPN = value & 0xFFFFFC0F; in helper_440_tlbwe()
890 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00); in helper_440_tlbwe()
891 tlb->prot = tlb->prot & PAGE_VALID; in helper_440_tlbwe()
893 tlb->prot |= PAGE_READ << 4; in helper_440_tlbwe()
896 tlb->prot |= PAGE_WRITE << 4; in helper_440_tlbwe()
899 tlb->prot |= PAGE_EXEC << 4; in helper_440_tlbwe()
902 tlb->prot |= PAGE_READ; in helper_440_tlbwe()
905 tlb->prot |= PAGE_WRITE; in helper_440_tlbwe()
908 tlb->prot |= PAGE_EXEC; in helper_440_tlbwe()
917 ppcemb_tlb_t *tlb; in helper_440_tlbre() local
919 int size; in helper_440_tlbre() local
922 tlb = &env->tlb.tlbe[entry]; in helper_440_tlbre()
927 ret = tlb->EPN; in helper_440_tlbre()
928 size = booke_page_size_to_tlb(tlb->size); in helper_440_tlbre()
929 if (size < 0 || size > 0xF) { in helper_440_tlbre()
930 size = 1; in helper_440_tlbre()
932 ret |= size << 4; in helper_440_tlbre()
933 if (tlb->attr & 0x1) { in helper_440_tlbre()
936 if (tlb->prot & PAGE_VALID) { in helper_440_tlbre()
939 env->spr[SPR_440_MMUCR] &= ~0x000000FF; in helper_440_tlbre()
940 env->spr[SPR_440_MMUCR] |= tlb->PID; in helper_440_tlbre()
943 ret = tlb->RPN; in helper_440_tlbre()
946 ret = tlb->attr & ~0x1; in helper_440_tlbre()
947 if (tlb->prot & (PAGE_READ << 4)) { in helper_440_tlbre()
950 if (tlb->prot & (PAGE_WRITE << 4)) { in helper_440_tlbre()
953 if (tlb->prot & (PAGE_EXEC << 4)) { in helper_440_tlbre()
956 if (tlb->prot & PAGE_READ) { in helper_440_tlbre()
959 if (tlb->prot & PAGE_WRITE) { in helper_440_tlbre()
962 if (tlb->prot & PAGE_EXEC) { in helper_440_tlbre()
972 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); in helper_440_tlbsx()
975 /* PowerPC BookE 2.06 TLB management */
980 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT; in booke206_cur_tlb()
981 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK); in booke206_cur_tlb()
982 int tlb; in booke206_cur_tlb() local
984 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; in booke206_cur_tlb()
985 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb]; in booke206_cur_tlb()
987 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) { in booke206_cur_tlb()
991 return booke206_get_tlbm(env, tlb, ea, esel); in booke206_cur_tlb()
996 env->spr[pidn] = pid; in helper_booke_setpid()
1003 env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK; in helper_booke_set_eplc()
1008 env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK; in helper_booke_set_epsc()
1012 static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb) in flush_page() argument
1014 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) { in flush_page()
1015 tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK); in flush_page()
1024 ppcmas_tlb_t *tlb; in helper_booke206_tlbwe() local
1029 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) { in helper_booke206_tlbwe()
1047 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) && in helper_booke206_tlbwe()
1048 !FIELD_EX64(env->msr, MSR, GS)) { in helper_booke206_tlbwe()
1054 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT; in helper_booke206_tlbwe()
1055 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn]; in helper_booke206_tlbwe()
1057 tlb = booke206_cur_tlb(env); in helper_booke206_tlbwe()
1059 if (!tlb) { in helper_booke206_tlbwe()
1065 /* check that we support the targeted size */ in helper_booke206_tlbwe()
1066 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT; in helper_booke206_tlbwe()
1068 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) && in helper_booke206_tlbwe()
1075 if (FIELD_EX64(env->msr, MSR, GS)) { in helper_booke206_tlbwe()
1079 if (tlb->mas1 & MAS1_VALID) { in helper_booke206_tlbwe()
1081 * Invalidate the page in QEMU TLB if it was a valid entry. in helper_booke206_tlbwe()
1084 * Section "12.4.2 TLB Write Entry (tlbwe) Instruction": in helper_booke206_tlbwe()
1085 * (https://www.nxp.com/docs/en/reference-manual/E500CORERM.pdf) in helper_booke206_tlbwe()
1087 * "Note that when an L2 TLB entry is written, it may be displacing an in helper_booke206_tlbwe()
1088 * already valid entry in the same L2 TLB location (a victim). If a in helper_booke206_tlbwe()
1089 * valid L1 TLB entry corresponds to the L2 MMU victim entry, that L1 in helper_booke206_tlbwe()
1090 * TLB entry is automatically invalidated." in helper_booke206_tlbwe()
1092 flush_page(env, tlb); in helper_booke206_tlbwe()
1095 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) | in helper_booke206_tlbwe()
1096 env->spr[SPR_BOOKE_MAS3]; in helper_booke206_tlbwe()
1097 tlb->mas1 = env->spr[SPR_BOOKE_MAS1]; in helper_booke206_tlbwe()
1099 if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) { in helper_booke206_tlbwe()
1100 /* For TLB which has a fixed size TSIZE is ignored with MAV2 */ in helper_booke206_tlbwe()
1101 booke206_fixed_size_tlbn(env, tlbn, tlb); in helper_booke206_tlbwe()
1104 /* force !AVAIL TLB entries to correct page size */ in helper_booke206_tlbwe()
1105 tlb->mas1 &= ~MAS1_TSIZE_MASK; in helper_booke206_tlbwe()
1107 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12; in helper_booke206_tlbwe()
1111 /* Make a mask from TLB size to discard invalid bits in EPN field */ in helper_booke206_tlbwe()
1112 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); in helper_booke206_tlbwe()
1116 if (!FIELD_EX64(env->msr, MSR, CM)) { in helper_booke206_tlbwe()
1118 * Executing a tlbwe instruction in 32-bit mode will set bits in helper_booke206_tlbwe()
1119 * 0:31 of the TLB EPN field to zero. in helper_booke206_tlbwe()
1124 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask; in helper_booke206_tlbwe()
1127 /* no IPROT supported by TLB */ in helper_booke206_tlbwe()
1128 tlb->mas1 &= ~MAS1_IPROT; in helper_booke206_tlbwe()
1131 flush_page(env, tlb); in helper_booke206_tlbwe()
1134 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb) in booke206_tlb_to_mas() argument
1136 int tlbn = booke206_tlbm_to_tlbn(env, tlb); in booke206_tlb_to_mas()
1137 int way = booke206_tlbm_to_way(env, tlb); in booke206_tlb_to_mas()
1139 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT; in booke206_tlb_to_mas()
1140 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT; in booke206_tlb_to_mas()
1141 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; in booke206_tlb_to_mas()
1143 env->spr[SPR_BOOKE_MAS1] = tlb->mas1; in booke206_tlb_to_mas()
1144 env->spr[SPR_BOOKE_MAS2] = tlb->mas2; in booke206_tlb_to_mas()
1145 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3; in booke206_tlb_to_mas()
1146 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32; in booke206_tlb_to_mas()
1151 ppcmas_tlb_t *tlb = NULL; in helper_booke206_tlbre() local
1153 tlb = booke206_cur_tlb(env); in helper_booke206_tlbre()
1154 if (!tlb) { in helper_booke206_tlbre()
1155 env->spr[SPR_BOOKE_MAS1] = 0; in helper_booke206_tlbre()
1157 booke206_tlb_to_mas(env, tlb); in helper_booke206_tlbre()
1163 ppcmas_tlb_t *tlb = NULL; in helper_booke206_tlbsx() local
1168 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT; in helper_booke206_tlbsx()
1169 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS; in helper_booke206_tlbsx()
1175 tlb = booke206_get_tlbm(env, i, address, j); in helper_booke206_tlbsx()
1177 if (!tlb) { in helper_booke206_tlbsx()
1181 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) { in helper_booke206_tlbsx()
1185 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) { in helper_booke206_tlbsx()
1189 booke206_tlb_to_mas(env, tlb); in helper_booke206_tlbsx()
1195 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK; in helper_booke206_tlbsx()
1196 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK; in helper_booke206_tlbsx()
1197 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK; in helper_booke206_tlbsx()
1198 env->spr[SPR_BOOKE_MAS3] = 0; in helper_booke206_tlbsx()
1199 env->spr[SPR_BOOKE_MAS7] = 0; in helper_booke206_tlbsx()
1201 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) { in helper_booke206_tlbsx()
1202 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS; in helper_booke206_tlbsx()
1205 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16) in helper_booke206_tlbsx()
1209 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT; in helper_booke206_tlbsx()
1210 env->last_way++; in helper_booke206_tlbsx()
1211 env->last_way &= booke206_tlb_ways(env, 0) - 1; in helper_booke206_tlbsx()
1212 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT; in helper_booke206_tlbsx()
1223 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i); in booke206_invalidate_ea_tlb() local
1224 if (!tlb) { in booke206_invalidate_ea_tlb()
1227 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1); in booke206_invalidate_ea_tlb()
1228 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) && in booke206_invalidate_ea_tlb()
1229 !(tlb->mas1 & MAS1_IPROT)) { in booke206_invalidate_ea_tlb()
1230 tlb->mas1 &= ~MAS1_VALID; in booke206_invalidate_ea_tlb()
1269 booke206_flush_tlb(env, -1, 1); in helper_booke206_tlbilx0()
1275 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); in helper_booke206_tlbilx1()
1276 ppcmas_tlb_t *tlb = env->tlb.tlbm; in helper_booke206_tlbilx1() local
1283 if (!(tlb[j].mas1 & MAS1_IPROT) && in helper_booke206_tlbilx1()
1284 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) { in helper_booke206_tlbilx1()
1285 tlb[j].mas1 &= ~MAS1_VALID; in helper_booke206_tlbilx1()
1288 tlb += booke206_tlb_size(env, i); in helper_booke206_tlbilx1()
1296 ppcmas_tlb_t *tlb; in helper_booke206_tlbilx3() local
1297 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID); in helper_booke206_tlbilx3()
1299 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS; in helper_booke206_tlbilx3()
1300 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0; in helper_booke206_tlbilx3()
1302 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK; in helper_booke206_tlbilx3() local
1312 tlb = booke206_get_tlbm(env, i, address, j); in helper_booke206_tlbilx3()
1313 if (!tlb) { in helper_booke206_tlbilx3()
1316 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) || in helper_booke206_tlbilx3()
1317 (tlb->mas1 & MAS1_IPROT) || in helper_booke206_tlbilx3()
1318 ((tlb->mas1 & MAS1_IND) != ind) || in helper_booke206_tlbilx3()
1319 ((tlb->mas8 & MAS8_TGS) != sgs)) { in helper_booke206_tlbilx3()
1322 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) { in helper_booke206_tlbilx3()
1327 tlb->mas1 &= ~MAS1_VALID; in helper_booke206_tlbilx3()
1360 bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size, in ppc_cpu_tlb_fill() argument
1377 raise_exception_err_ra(&cpu->env, cs->exception_index, in ppc_cpu_tlb_fill()
1378 cpu->env.error_code, retaddr); in ppc_cpu_tlb_fill()