1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "qemu/osdep.h"
21#include "qemu/units.h"
22#include "cpu.h"
23#include "sysemu/kvm.h"
24#include "kvm_ppc.h"
25#include "mmu-hash64.h"
26#include "mmu-hash32.h"
27#include "exec/exec-all.h"
28#include "exec/log.h"
29#include "helper_regs.h"
30#include "qemu/error-report.h"
31#include "qemu/main-loop.h"
32#include "qemu/qemu-print.h"
33#include "internal.h"
34#include "mmu-book3s-v3.h"
35#include "mmu-radix64.h"
36
37#ifdef CONFIG_TCG
38#include "exec/helper-proto.h"
39#include "exec/cpu_ldst.h"
40#endif
41
42
43
44
45
46
47#ifdef DEBUG_MMU
48# define LOG_MMU_STATE(cpu) log_cpu_state_mask(CPU_LOG_MMU, (cpu), 0)
49#else
50# define LOG_MMU_STATE(cpu) do { } while (0)
51#endif
52
53#ifdef DEBUG_SOFTWARE_TLB
54# define LOG_SWTLB(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
55#else
56# define LOG_SWTLB(...) do { } while (0)
57#endif
58
59#ifdef DEBUG_BATS
60# define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
61#else
62# define LOG_BATS(...) do { } while (0)
63#endif
64
65
66
67
68
69typedef struct mmu_ctx_t mmu_ctx_t;
70struct mmu_ctx_t {
71 hwaddr raddr;
72 hwaddr eaddr;
73 int prot;
74 hwaddr hash[2];
75 target_ulong ptem;
76 int key;
77 int nx;
78};
79
80
81static inline int pte_is_valid(target_ulong pte0)
82{
83 return pte0 & 0x80000000 ? 1 : 0;
84}
85
86static inline void pte_invalidate(target_ulong *pte0)
87{
88 *pte0 &= ~0x80000000;
89}
90
91#define PTE_PTEM_MASK 0x7FFFFFBF
92#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
93
94static int pp_check(int key, int pp, int nx)
95{
96 int access;
97
98
99 access = 0;
100 if (key == 0) {
101 switch (pp) {
102 case 0x0:
103 case 0x1:
104 case 0x2:
105 access |= PAGE_WRITE;
106
107 case 0x3:
108 access |= PAGE_READ;
109 break;
110 }
111 } else {
112 switch (pp) {
113 case 0x0:
114 access = 0;
115 break;
116 case 0x1:
117 case 0x3:
118 access = PAGE_READ;
119 break;
120 case 0x2:
121 access = PAGE_READ | PAGE_WRITE;
122 break;
123 }
124 }
125 if (nx == 0) {
126 access |= PAGE_EXEC;
127 }
128
129 return access;
130}
131
132static int check_prot(int prot, MMUAccessType access_type)
133{
134 return prot & prot_for_access_type(access_type) ? 0 : -2;
135}
136
137static int ppc6xx_tlb_pte_check(mmu_ctx_t *ctx, target_ulong pte0,
138 target_ulong pte1, int h,
139 MMUAccessType access_type)
140{
141 target_ulong ptem, mmask;
142 int access, ret, pteh, ptev, pp;
143
144 ret = -1;
145
146 ptev = pte_is_valid(pte0);
147 pteh = (pte0 >> 6) & 1;
148 if (ptev && h == pteh) {
149
150 ptem = pte0 & PTE_PTEM_MASK;
151 mmask = PTE_CHECK_MASK;
152 pp = pte1 & 0x00000003;
153 if (ptem == ctx->ptem) {
154 if (ctx->raddr != (hwaddr)-1ULL) {
155
156 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
157 qemu_log_mask(CPU_LOG_MMU, "Bad RPN/WIMG/PP\n");
158 return -3;
159 }
160 }
161
162 access = pp_check(ctx->key, pp, ctx->nx);
163
164 ctx->raddr = pte1;
165 ctx->prot = access;
166 ret = check_prot(ctx->prot, access_type);
167 if (ret == 0) {
168
169 qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
170 } else {
171
172 qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
173 }
174 }
175 }
176
177 return ret;
178}
179
180static int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
181 int ret, MMUAccessType access_type)
182{
183 int store = 0;
184
185
186 if (!(*pte1p & 0x00000100)) {
187
188 *pte1p |= 0x00000100;
189 store = 1;
190 }
191 if (!(*pte1p & 0x00000080)) {
192 if (access_type == MMU_DATA_STORE && ret == 0) {
193
194 *pte1p |= 0x00000080;
195 store = 1;
196 } else {
197
198 ctx->prot &= ~PAGE_WRITE;
199 }
200 }
201
202 return store;
203}
204
205
206static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
207 int way, int is_code)
208{
209 int nr;
210
211
212 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
213
214 nr += env->tlb_per_way * way;
215
216 if (is_code && env->id_tlbs == 1) {
217 nr += env->nb_tlb;
218 }
219
220 return nr;
221}
222
223static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
224{
225 ppc6xx_tlb_t *tlb;
226 int nr, max;
227
228
229
230 max = env->nb_tlb;
231 if (env->id_tlbs == 1) {
232 max *= 2;
233 }
234 for (nr = 0; nr < max; nr++) {
235 tlb = &env->tlb.tlb6[nr];
236 pte_invalidate(&tlb->pte0);
237 }
238 tlb_flush(env_cpu(env));
239}
240
241static inline void ppc6xx_tlb_invalidate_virt2(CPUPPCState *env,
242 target_ulong eaddr,
243 int is_code, int match_epn)
244{
245#if !defined(FLUSH_ALL_TLBS)
246 CPUState *cs = env_cpu(env);
247 ppc6xx_tlb_t *tlb;
248 int way, nr;
249
250
251 for (way = 0; way < env->nb_ways; way++) {
252 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
253 tlb = &env->tlb.tlb6[nr];
254 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
255 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
256 env->nb_tlb, eaddr);
257 pte_invalidate(&tlb->pte0);
258 tlb_flush_page(cs, tlb->EPN);
259 }
260 }
261#else
262
263 ppc6xx_tlb_invalidate_all(env);
264#endif
265}
266
267static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
268 target_ulong eaddr, int is_code)
269{
270 ppc6xx_tlb_invalidate_virt2(env, eaddr, is_code, 0);
271}
272
273#ifdef CONFIG_TCG
274static void ppc6xx_tlb_store(CPUPPCState *env, target_ulong EPN, int way,
275 int is_code, target_ulong pte0, target_ulong pte1)
276{
277 ppc6xx_tlb_t *tlb;
278 int nr;
279
280 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
281 tlb = &env->tlb.tlb6[nr];
282 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
283 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
284
285 ppc6xx_tlb_invalidate_virt2(env, EPN, is_code, 1);
286 tlb->pte0 = pte0;
287 tlb->pte1 = pte1;
288 tlb->EPN = EPN;
289
290 env->last_way = way;
291}
292#endif
293
294static int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
295 target_ulong eaddr, MMUAccessType access_type)
296{
297 ppc6xx_tlb_t *tlb;
298 int nr, best, way;
299 int ret;
300
301 best = -1;
302 ret = -1;
303 for (way = 0; way < env->nb_ways; way++) {
304 nr = ppc6xx_tlb_getnum(env, eaddr, way, access_type == MMU_INST_FETCH);
305 tlb = &env->tlb.tlb6[nr];
306
307 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
308 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
309 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
310 pte_is_valid(tlb->pte0) ? "valid" : "inval",
311 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
312 continue;
313 }
314 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
315 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
316 pte_is_valid(tlb->pte0) ? "valid" : "inval",
317 tlb->EPN, eaddr, tlb->pte1,
318 access_type == MMU_DATA_STORE ? 'S' : 'L',
319 access_type == MMU_INST_FETCH ? 'I' : 'D');
320 switch (ppc6xx_tlb_pte_check(ctx, tlb->pte0, tlb->pte1,
321 0, access_type)) {
322 case -3:
323
324 return -1;
325 case -2:
326
327 ret = -2;
328 best = nr;
329 break;
330 case -1:
331 default:
332
333 break;
334 case 0:
335
336
337
338
339
340
341
342 ret = 0;
343 best = nr;
344 goto done;
345 }
346 }
347 if (best != -1) {
348 done:
349 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
350 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
351
352 pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, access_type);
353 }
354
355 return ret;
356}
357
358
359static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp,
360 int *validp, int *protp, target_ulong *BATu,
361 target_ulong *BATl)
362{
363 target_ulong bl;
364 int pp, valid, prot;
365
366 bl = (*BATu & 0x00001FFC) << 15;
367 valid = 0;
368 prot = 0;
369 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
370 ((msr_pr != 0) && (*BATu & 0x00000001))) {
371 valid = 1;
372 pp = *BATl & 0x00000003;
373 if (pp != 0) {
374 prot = PAGE_READ | PAGE_EXEC;
375 if (pp == 0x2) {
376 prot |= PAGE_WRITE;
377 }
378 }
379 }
380 *blp = bl;
381 *validp = valid;
382 *protp = prot;
383}
384
385static int get_bat_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
386 target_ulong virtual, MMUAccessType access_type)
387{
388 target_ulong *BATlt, *BATut, *BATu, *BATl;
389 target_ulong BEPIl, BEPIu, bl;
390 int i, valid, prot;
391 int ret = -1;
392 bool ifetch = access_type == MMU_INST_FETCH;
393
394 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
395 ifetch ? 'I' : 'D', virtual);
396 if (ifetch) {
397 BATlt = env->IBAT[1];
398 BATut = env->IBAT[0];
399 } else {
400 BATlt = env->DBAT[1];
401 BATut = env->DBAT[0];
402 }
403 for (i = 0; i < env->nb_BATs; i++) {
404 BATu = &BATut[i];
405 BATl = &BATlt[i];
406 BEPIu = *BATu & 0xF0000000;
407 BEPIl = *BATu & 0x0FFE0000;
408 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
409 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
410 " BATl " TARGET_FMT_lx "\n", __func__,
411 ifetch ? 'I' : 'D', i, virtual, *BATu, *BATl);
412 if ((virtual & 0xF0000000) == BEPIu &&
413 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
414
415 if (valid != 0) {
416
417 ctx->raddr = (*BATl & 0xF0000000) |
418 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
419 (virtual & 0x0001F000);
420
421 ctx->prot = prot;
422 ret = check_prot(ctx->prot, access_type);
423 if (ret == 0) {
424 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
425 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
426 ctx->prot & PAGE_WRITE ? 'W' : '-');
427 }
428 break;
429 }
430 }
431 }
432 if (ret < 0) {
433#if defined(DEBUG_BATS)
434 if (qemu_log_enabled()) {
435 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
436 for (i = 0; i < 4; i++) {
437 BATu = &BATut[i];
438 BATl = &BATlt[i];
439 BEPIu = *BATu & 0xF0000000;
440 BEPIl = *BATu & 0x0FFE0000;
441 bl = (*BATu & 0x00001FFC) << 15;
442 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
443 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
444 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
445 __func__, ifetch ? 'I' : 'D', i, virtual,
446 *BATu, *BATl, BEPIu, BEPIl, bl);
447 }
448 }
449#endif
450 }
451
452 return ret;
453}
454
455
456static int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
457 target_ulong eaddr, MMUAccessType access_type,
458 int type)
459{
460 PowerPCCPU *cpu = env_archcpu(env);
461 hwaddr hash;
462 target_ulong vsid;
463 int ds, pr, target_page_bits;
464 int ret;
465 target_ulong sr, pgidx;
466
467 pr = msr_pr;
468 ctx->eaddr = eaddr;
469
470 sr = env->sr[eaddr >> 28];
471 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
472 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
473 ds = sr & 0x80000000 ? 1 : 0;
474 ctx->nx = sr & 0x10000000 ? 1 : 0;
475 vsid = sr & 0x00FFFFFF;
476 target_page_bits = TARGET_PAGE_BITS;
477 qemu_log_mask(CPU_LOG_MMU,
478 "Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx
479 " nip=" TARGET_FMT_lx " lr=" TARGET_FMT_lx
480 " ir=%d dr=%d pr=%d %d t=%d\n",
481 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
482 (int)msr_dr, pr != 0 ? 1 : 0, access_type == MMU_DATA_STORE, type);
483 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
484 hash = vsid ^ pgidx;
485 ctx->ptem = (vsid << 7) | (pgidx >> 10);
486
487 qemu_log_mask(CPU_LOG_MMU,
488 "pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
489 ctx->key, ds, ctx->nx, vsid);
490 ret = -1;
491 if (!ds) {
492
493 if (type != ACCESS_CODE || ctx->nx == 0) {
494
495 qemu_log_mask(CPU_LOG_MMU, "htab_base " TARGET_FMT_plx
496 " htab_mask " TARGET_FMT_plx
497 " hash " TARGET_FMT_plx "\n",
498 ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
499 ctx->hash[0] = hash;
500 ctx->hash[1] = ~hash;
501
502
503 ctx->raddr = (hwaddr)-1ULL;
504
505 ret = ppc6xx_tlb_check(env, ctx, eaddr, access_type);
506#if defined(DUMP_PAGE_TABLES)
507 if (qemu_loglevel_mask(CPU_LOG_MMU)) {
508 CPUState *cs = env_cpu(env);
509 hwaddr curaddr;
510 uint32_t a0, a1, a2, a3;
511
512 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
513 "\n", ppc_hash32_hpt_base(cpu),
514 ppc_hash32_hpt_mask(cpu) + 0x80);
515 for (curaddr = ppc_hash32_hpt_base(cpu);
516 curaddr < (ppc_hash32_hpt_base(cpu)
517 + ppc_hash32_hpt_mask(cpu) + 0x80);
518 curaddr += 16) {
519 a0 = ldl_phys(cs->as, curaddr);
520 a1 = ldl_phys(cs->as, curaddr + 4);
521 a2 = ldl_phys(cs->as, curaddr + 8);
522 a3 = ldl_phys(cs->as, curaddr + 12);
523 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
524 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
525 curaddr, a0, a1, a2, a3);
526 }
527 }
528 }
529#endif
530 } else {
531 qemu_log_mask(CPU_LOG_MMU, "No access allowed\n");
532 ret = -3;
533 }
534 } else {
535 target_ulong sr;
536
537 qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
538
539
540
541
542
543
544 sr = env->sr[eaddr >> 28];
545 if ((sr & 0x1FF00000) >> 20 == 0x07f) {
546
547
548
549
550
551
552
553 ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
554 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
555 return 0;
556 }
557
558 switch (type) {
559 case ACCESS_INT:
560
561 break;
562 case ACCESS_CODE:
563
564 return -4;
565 case ACCESS_FLOAT:
566
567 return -4;
568 case ACCESS_RES:
569
570 return -4;
571 case ACCESS_CACHE:
572
573
574
575
576
577
578 ctx->raddr = eaddr;
579 return 0;
580 case ACCESS_EXT:
581
582 return -4;
583 default:
584 qemu_log_mask(CPU_LOG_MMU, "ERROR: instruction should not need "
585 "address translation\n");
586 return -4;
587 }
588 if ((access_type == MMU_DATA_STORE || ctx->key != 1) &&
589 (access_type == MMU_DATA_LOAD || ctx->key != 0)) {
590 ctx->raddr = eaddr;
591 ret = 2;
592 } else {
593 ret = -2;
594 }
595 }
596
597 return ret;
598}
599
600
601static int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
602 hwaddr *raddrp,
603 target_ulong address, uint32_t pid, int ext,
604 int i)
605{
606 target_ulong mask;
607
608
609 if (!(tlb->prot & PAGE_VALID)) {
610 return -1;
611 }
612 mask = ~(tlb->size - 1);
613 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
614 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
615 mask, (uint32_t)tlb->PID, tlb->prot);
616
617 if (tlb->PID != 0 && tlb->PID != pid) {
618 return -1;
619 }
620
621 if ((address & mask) != tlb->EPN) {
622 return -1;
623 }
624 *raddrp = (tlb->RPN & mask) | (address & ~mask);
625 if (ext) {
626
627 *raddrp |= (uint64_t)(tlb->RPN & 0xF) << 32;
628 }
629
630 return 0;
631}
632
633#ifdef CONFIG_TCG
634
635static int ppcemb_tlb_search(CPUPPCState *env, target_ulong address,
636 uint32_t pid)
637{
638 ppcemb_tlb_t *tlb;
639 hwaddr raddr;
640 int i, ret;
641
642
643 ret = -1;
644 for (i = 0; i < env->nb_tlb; i++) {
645 tlb = &env->tlb.tlbe[i];
646 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
647 ret = i;
648 break;
649 }
650 }
651
652 return ret;
653}
654#endif
655
656
657static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
658{
659 ppcemb_tlb_t *tlb;
660 int i;
661
662 for (i = 0; i < env->nb_tlb; i++) {
663 tlb = &env->tlb.tlbe[i];
664 tlb->prot &= ~PAGE_VALID;
665 }
666 tlb_flush(env_cpu(env));
667}
668
669static int mmu40x_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
670 target_ulong address,
671 MMUAccessType access_type)
672{
673 ppcemb_tlb_t *tlb;
674 hwaddr raddr;
675 int i, ret, zsel, zpr, pr;
676
677 ret = -1;
678 raddr = (hwaddr)-1ULL;
679 pr = msr_pr;
680 for (i = 0; i < env->nb_tlb; i++) {
681 tlb = &env->tlb.tlbe[i];
682 if (ppcemb_tlb_check(env, tlb, &raddr, address,
683 env->spr[SPR_40x_PID], 0, i) < 0) {
684 continue;
685 }
686 zsel = (tlb->attr >> 4) & 0xF;
687 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
688 LOG_SWTLB("%s: TLB %d zsel %d zpr %d ty %d attr %08x\n",
689 __func__, i, zsel, zpr, access_type, tlb->attr);
690
691 switch (zpr) {
692 case 0x2:
693 if (pr != 0) {
694 goto check_perms;
695 }
696
697 case 0x3:
698
699 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
700 ret = 0;
701 break;
702 case 0x0:
703 if (pr != 0) {
704
705 env->spr[SPR_40x_ESR] = 1 << 22;
706 ctx->prot = 0;
707 ret = -2;
708 break;
709 }
710
711 case 0x1:
712 check_perms:
713
714 ctx->prot = tlb->prot;
715 ret = check_prot(ctx->prot, access_type);
716 if (ret == -2) {
717 env->spr[SPR_40x_ESR] = 0;
718 }
719 break;
720 }
721 if (ret >= 0) {
722 ctx->raddr = raddr;
723 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
724 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
725 ret);
726 return 0;
727 }
728 }
729 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
730 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
731
732 return ret;
733}
734
735void store_40x_sler(CPUPPCState *env, uint32_t val)
736{
737
738 if (val != 0x00000000) {
739 cpu_abort(env_cpu(env),
740 "Little-endian regions are not supported by now\n");
741 }
742 env->spr[SPR_405_SLER] = val;
743}
744
745static int mmubooke_check_tlb(CPUPPCState *env, ppcemb_tlb_t *tlb,
746 hwaddr *raddr, int *prot, target_ulong address,
747 MMUAccessType access_type, int i)
748{
749 int prot2;
750
751 if (ppcemb_tlb_check(env, tlb, raddr, address,
752 env->spr[SPR_BOOKE_PID],
753 !env->nb_pids, i) >= 0) {
754 goto found_tlb;
755 }
756
757 if (env->spr[SPR_BOOKE_PID1] &&
758 ppcemb_tlb_check(env, tlb, raddr, address,
759 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
760 goto found_tlb;
761 }
762
763 if (env->spr[SPR_BOOKE_PID2] &&
764 ppcemb_tlb_check(env, tlb, raddr, address,
765 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
766 goto found_tlb;
767 }
768
769 LOG_SWTLB("%s: TLB entry not found\n", __func__);
770 return -1;
771
772found_tlb:
773
774 if (msr_pr != 0) {
775 prot2 = tlb->prot & 0xF;
776 } else {
777 prot2 = (tlb->prot >> 4) & 0xF;
778 }
779
780
781 if ((access_type == MMU_INST_FETCH ? msr_ir : msr_dr) != (tlb->attr & 1)) {
782 LOG_SWTLB("%s: AS doesn't match\n", __func__);
783 return -1;
784 }
785
786 *prot = prot2;
787 if (prot2 & prot_for_access_type(access_type)) {
788 LOG_SWTLB("%s: good TLB!\n", __func__);
789 return 0;
790 }
791
792 LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2);
793 return access_type == MMU_INST_FETCH ? -3 : -2;
794}
795
796static int mmubooke_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
797 target_ulong address,
798 MMUAccessType access_type)
799{
800 ppcemb_tlb_t *tlb;
801 hwaddr raddr;
802 int i, ret;
803
804 ret = -1;
805 raddr = (hwaddr)-1ULL;
806 for (i = 0; i < env->nb_tlb; i++) {
807 tlb = &env->tlb.tlbe[i];
808 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address,
809 access_type, i);
810 if (ret != -1) {
811 break;
812 }
813 }
814
815 if (ret >= 0) {
816 ctx->raddr = raddr;
817 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
818 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
819 ret);
820 } else {
821 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
822 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
823 }
824
825 return ret;
826}
827
828#ifdef CONFIG_TCG
829static void booke206_flush_tlb(CPUPPCState *env, int flags,
830 const int check_iprot)
831{
832 int tlb_size;
833 int i, j;
834 ppcmas_tlb_t *tlb = env->tlb.tlbm;
835
836 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
837 if (flags & (1 << i)) {
838 tlb_size = booke206_tlb_size(env, i);
839 for (j = 0; j < tlb_size; j++) {
840 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
841 tlb[j].mas1 &= ~MAS1_VALID;
842 }
843 }
844 }
845 tlb += booke206_tlb_size(env, i);
846 }
847
848 tlb_flush(env_cpu(env));
849}
850#endif
851
852static hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
853 ppcmas_tlb_t *tlb)
854{
855 int tlbm_size;
856
857 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
858
859 return 1024ULL << tlbm_size;
860}
861
862
863static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
864 hwaddr *raddrp, target_ulong address,
865 uint32_t pid)
866{
867 hwaddr mask;
868 uint32_t tlb_pid;
869
870 if (!msr_cm) {
871
872 address = (uint32_t)address;
873 }
874
875
876 if (!(tlb->mas1 & MAS1_VALID)) {
877 return -1;
878 }
879
880 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
881 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
882 PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
883 PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
884 tlb->mas7_3, tlb->mas8);
885
886
887 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
888 if (tlb_pid != 0 && tlb_pid != pid) {
889 return -1;
890 }
891
892
893 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
894 return -1;
895 }
896
897 if (raddrp) {
898 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
899 }
900
901 return 0;
902}
903
904static bool is_epid_mmu(int mmu_idx)
905{
906 return mmu_idx == PPC_TLB_EPID_STORE || mmu_idx == PPC_TLB_EPID_LOAD;
907}
908
909static uint32_t mmubooke206_esr(int mmu_idx, MMUAccessType access_type)
910{
911 uint32_t esr = 0;
912 if (access_type == MMU_DATA_STORE) {
913 esr |= ESR_ST;
914 }
915 if (is_epid_mmu(mmu_idx)) {
916 esr |= ESR_EPID;
917 }
918 return esr;
919}
920
921
922
923
924
925
926
927
928
929static bool mmubooke206_get_as(CPUPPCState *env,
930 int mmu_idx, uint32_t *epid_out,
931 bool *as_out, bool *pr_out)
932{
933 if (is_epid_mmu(mmu_idx)) {
934 uint32_t epidr;
935 if (mmu_idx == PPC_TLB_EPID_STORE) {
936 epidr = env->spr[SPR_BOOKE_EPSC];
937 } else {
938 epidr = env->spr[SPR_BOOKE_EPLC];
939 }
940 *epid_out = (epidr & EPID_EPID) >> EPID_EPID_SHIFT;
941 *as_out = !!(epidr & EPID_EAS);
942 *pr_out = !!(epidr & EPID_EPR);
943 return true;
944 } else {
945 *as_out = msr_ds;
946 *pr_out = msr_pr;
947 return false;
948 }
949}
950
951
952static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
953 hwaddr *raddr, int *prot,
954 target_ulong address,
955 MMUAccessType access_type, int mmu_idx)
956{
957 int prot2 = 0;
958 uint32_t epid;
959 bool as, pr;
960 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
961
962 if (!use_epid) {
963 if (ppcmas_tlb_check(env, tlb, raddr, address,
964 env->spr[SPR_BOOKE_PID]) >= 0) {
965 goto found_tlb;
966 }
967
968 if (env->spr[SPR_BOOKE_PID1] &&
969 ppcmas_tlb_check(env, tlb, raddr, address,
970 env->spr[SPR_BOOKE_PID1]) >= 0) {
971 goto found_tlb;
972 }
973
974 if (env->spr[SPR_BOOKE_PID2] &&
975 ppcmas_tlb_check(env, tlb, raddr, address,
976 env->spr[SPR_BOOKE_PID2]) >= 0) {
977 goto found_tlb;
978 }
979 } else {
980 if (ppcmas_tlb_check(env, tlb, raddr, address, epid) >= 0) {
981 goto found_tlb;
982 }
983 }
984
985 LOG_SWTLB("%s: TLB entry not found\n", __func__);
986 return -1;
987
988found_tlb:
989
990 if (pr) {
991 if (tlb->mas7_3 & MAS3_UR) {
992 prot2 |= PAGE_READ;
993 }
994 if (tlb->mas7_3 & MAS3_UW) {
995 prot2 |= PAGE_WRITE;
996 }
997 if (tlb->mas7_3 & MAS3_UX) {
998 prot2 |= PAGE_EXEC;
999 }
1000 } else {
1001 if (tlb->mas7_3 & MAS3_SR) {
1002 prot2 |= PAGE_READ;
1003 }
1004 if (tlb->mas7_3 & MAS3_SW) {
1005 prot2 |= PAGE_WRITE;
1006 }
1007 if (tlb->mas7_3 & MAS3_SX) {
1008 prot2 |= PAGE_EXEC;
1009 }
1010 }
1011
1012
1013 if (access_type == MMU_INST_FETCH) {
1014
1015 assert(!use_epid);
1016 as = msr_ir;
1017 }
1018
1019 if (as != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1020 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1021 return -1;
1022 }
1023
1024 *prot = prot2;
1025 if (prot2 & prot_for_access_type(access_type)) {
1026 LOG_SWTLB("%s: good TLB!\n", __func__);
1027 return 0;
1028 }
1029
1030 LOG_SWTLB("%s: no prot match: %x\n", __func__, prot2);
1031 return access_type == MMU_INST_FETCH ? -3 : -2;
1032}
1033
1034static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1035 target_ulong address,
1036 MMUAccessType access_type,
1037 int mmu_idx)
1038{
1039 ppcmas_tlb_t *tlb;
1040 hwaddr raddr;
1041 int i, j, ret;
1042
1043 ret = -1;
1044 raddr = (hwaddr)-1ULL;
1045
1046 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1047 int ways = booke206_tlb_ways(env, i);
1048
1049 for (j = 0; j < ways; j++) {
1050 tlb = booke206_get_tlbm(env, i, address, j);
1051 if (!tlb) {
1052 continue;
1053 }
1054 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1055 access_type, mmu_idx);
1056 if (ret != -1) {
1057 goto found_tlb;
1058 }
1059 }
1060 }
1061
1062found_tlb:
1063
1064 if (ret >= 0) {
1065 ctx->raddr = raddr;
1066 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1067 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1068 ret);
1069 } else {
1070 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1071 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1072 }
1073
1074 return ret;
1075}
1076
1077static const char *book3e_tsize_to_str[32] = {
1078 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1079 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1080 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1081 "1T", "2T"
1082};
1083
1084static void mmubooke_dump_mmu(CPUPPCState *env)
1085{
1086 ppcemb_tlb_t *entry;
1087 int i;
1088
1089 if (kvm_enabled() && !env->kvm_sw_tlb) {
1090 qemu_printf("Cannot access KVM TLB\n");
1091 return;
1092 }
1093
1094 qemu_printf("\nTLB:\n");
1095 qemu_printf("Effective Physical Size PID Prot "
1096 "Attr\n");
1097
1098 entry = &env->tlb.tlbe[0];
1099 for (i = 0; i < env->nb_tlb; i++, entry++) {
1100 hwaddr ea, pa;
1101 target_ulong mask;
1102 uint64_t size = (uint64_t)entry->size;
1103 char size_buf[20];
1104
1105
1106 if (!(entry->prot & PAGE_VALID)) {
1107 continue;
1108 }
1109
1110 mask = ~(entry->size - 1);
1111 ea = entry->EPN & mask;
1112 pa = entry->RPN & mask;
1113
1114 pa |= (hwaddr)(entry->RPN & 0xF) << 32;
1115 if (size >= 1 * MiB) {
1116 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "M", size / MiB);
1117 } else {
1118 snprintf(size_buf, sizeof(size_buf), "%3" PRId64 "k", size / KiB);
1119 }
1120 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %s %-5u %08x %08x\n",
1121 (uint64_t)ea, (uint64_t)pa, size_buf, (uint32_t)entry->PID,
1122 entry->prot, entry->attr);
1123 }
1124
1125}
1126
1127static void mmubooke206_dump_one_tlb(CPUPPCState *env, int tlbn, int offset,
1128 int tlbsize)
1129{
1130 ppcmas_tlb_t *entry;
1131 int i;
1132
1133 qemu_printf("\nTLB%d:\n", tlbn);
1134 qemu_printf("Effective Physical Size TID TS SRWX"
1135 " URWX WIMGE U0123\n");
1136
1137 entry = &env->tlb.tlbm[offset];
1138 for (i = 0; i < tlbsize; i++, entry++) {
1139 hwaddr ea, pa, size;
1140 int tsize;
1141
1142 if (!(entry->mas1 & MAS1_VALID)) {
1143 continue;
1144 }
1145
1146 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1147 size = 1024ULL << tsize;
1148 ea = entry->mas2 & ~(size - 1);
1149 pa = entry->mas7_3 & ~(size - 1);
1150
1151 qemu_printf("0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c"
1152 "U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1153 (uint64_t)ea, (uint64_t)pa,
1154 book3e_tsize_to_str[tsize],
1155 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1156 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1157 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1158 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1159 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1160 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1161 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1162 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1163 entry->mas2 & MAS2_W ? 'W' : '-',
1164 entry->mas2 & MAS2_I ? 'I' : '-',
1165 entry->mas2 & MAS2_M ? 'M' : '-',
1166 entry->mas2 & MAS2_G ? 'G' : '-',
1167 entry->mas2 & MAS2_E ? 'E' : '-',
1168 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1169 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1170 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1171 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1172 }
1173}
1174
1175static void mmubooke206_dump_mmu(CPUPPCState *env)
1176{
1177 int offset = 0;
1178 int i;
1179
1180 if (kvm_enabled() && !env->kvm_sw_tlb) {
1181 qemu_printf("Cannot access KVM TLB\n");
1182 return;
1183 }
1184
1185 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1186 int size = booke206_tlb_size(env, i);
1187
1188 if (size == 0) {
1189 continue;
1190 }
1191
1192 mmubooke206_dump_one_tlb(env, i, offset, size);
1193 offset += size;
1194 }
1195}
1196
1197static void mmu6xx_dump_BATs(CPUPPCState *env, int type)
1198{
1199 target_ulong *BATlt, *BATut, *BATu, *BATl;
1200 target_ulong BEPIl, BEPIu, bl;
1201 int i;
1202
1203 switch (type) {
1204 case ACCESS_CODE:
1205 BATlt = env->IBAT[1];
1206 BATut = env->IBAT[0];
1207 break;
1208 default:
1209 BATlt = env->DBAT[1];
1210 BATut = env->DBAT[0];
1211 break;
1212 }
1213
1214 for (i = 0; i < env->nb_BATs; i++) {
1215 BATu = &BATut[i];
1216 BATl = &BATlt[i];
1217 BEPIu = *BATu & 0xF0000000;
1218 BEPIl = *BATu & 0x0FFE0000;
1219 bl = (*BATu & 0x00001FFC) << 15;
1220 qemu_printf("%s BAT%d BATu " TARGET_FMT_lx
1221 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
1222 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
1223 type == ACCESS_CODE ? "code" : "data", i,
1224 *BATu, *BATl, BEPIu, BEPIl, bl);
1225 }
1226}
1227
1228static void mmu6xx_dump_mmu(CPUPPCState *env)
1229{
1230 PowerPCCPU *cpu = env_archcpu(env);
1231 ppc6xx_tlb_t *tlb;
1232 target_ulong sr;
1233 int type, way, entry, i;
1234
1235 qemu_printf("HTAB base = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_base(cpu));
1236 qemu_printf("HTAB mask = 0x%"HWADDR_PRIx"\n", ppc_hash32_hpt_mask(cpu));
1237
1238 qemu_printf("\nSegment registers:\n");
1239 for (i = 0; i < 32; i++) {
1240 sr = env->sr[i];
1241 if (sr & 0x80000000) {
1242 qemu_printf("%02d T=%d Ks=%d Kp=%d BUID=0x%03x "
1243 "CNTLR_SPEC=0x%05x\n", i,
1244 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1245 sr & 0x20000000 ? 1 : 0, (uint32_t)((sr >> 20) & 0x1FF),
1246 (uint32_t)(sr & 0xFFFFF));
1247 } else {
1248 qemu_printf("%02d T=%d Ks=%d Kp=%d N=%d VSID=0x%06x\n", i,
1249 sr & 0x80000000 ? 1 : 0, sr & 0x40000000 ? 1 : 0,
1250 sr & 0x20000000 ? 1 : 0, sr & 0x10000000 ? 1 : 0,
1251 (uint32_t)(sr & 0x00FFFFFF));
1252 }
1253 }
1254
1255 qemu_printf("\nBATs:\n");
1256 mmu6xx_dump_BATs(env, ACCESS_INT);
1257 mmu6xx_dump_BATs(env, ACCESS_CODE);
1258
1259 if (env->id_tlbs != 1) {
1260 qemu_printf("ERROR: 6xx MMU should have separated TLB"
1261 " for code and data\n");
1262 }
1263
1264 qemu_printf("\nTLBs [EPN EPN + SIZE]\n");
1265
1266 for (type = 0; type < 2; type++) {
1267 for (way = 0; way < env->nb_ways; way++) {
1268 for (entry = env->nb_tlb * type + env->tlb_per_way * way;
1269 entry < (env->nb_tlb * type + env->tlb_per_way * (way + 1));
1270 entry++) {
1271
1272 tlb = &env->tlb.tlb6[entry];
1273 qemu_printf("%s TLB %02d/%02d way:%d %s ["
1274 TARGET_FMT_lx " " TARGET_FMT_lx "]\n",
1275 type ? "code" : "data", entry % env->nb_tlb,
1276 env->nb_tlb, way,
1277 pte_is_valid(tlb->pte0) ? "valid" : "inval",
1278 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE);
1279 }
1280 }
1281 }
1282}
1283
1284void dump_mmu(CPUPPCState *env)
1285{
1286 switch (env->mmu_model) {
1287 case POWERPC_MMU_BOOKE:
1288 mmubooke_dump_mmu(env);
1289 break;
1290 case POWERPC_MMU_BOOKE206:
1291 mmubooke206_dump_mmu(env);
1292 break;
1293 case POWERPC_MMU_SOFT_6xx:
1294 case POWERPC_MMU_SOFT_74xx:
1295 mmu6xx_dump_mmu(env);
1296 break;
1297#if defined(TARGET_PPC64)
1298 case POWERPC_MMU_64B:
1299 case POWERPC_MMU_2_03:
1300 case POWERPC_MMU_2_06:
1301 case POWERPC_MMU_2_07:
1302 dump_slb(env_archcpu(env));
1303 break;
1304 case POWERPC_MMU_3_00:
1305 if (ppc64_v3_radix(env_archcpu(env))) {
1306 qemu_log_mask(LOG_UNIMP, "%s: the PPC64 MMU is unsupported\n",
1307 __func__);
1308 } else {
1309 dump_slb(env_archcpu(env));
1310 }
1311 break;
1312#endif
1313 default:
1314 qemu_log_mask(LOG_UNIMP, "%s: unimplemented\n", __func__);
1315 }
1316}
1317
1318static int check_physical(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1319 MMUAccessType access_type)
1320{
1321 int in_plb, ret;
1322
1323 ctx->raddr = eaddr;
1324 ctx->prot = PAGE_READ | PAGE_EXEC;
1325 ret = 0;
1326 switch (env->mmu_model) {
1327 case POWERPC_MMU_SOFT_6xx:
1328 case POWERPC_MMU_SOFT_74xx:
1329 case POWERPC_MMU_SOFT_4xx:
1330 case POWERPC_MMU_REAL:
1331 case POWERPC_MMU_BOOKE:
1332 ctx->prot |= PAGE_WRITE;
1333 break;
1334
1335 case POWERPC_MMU_SOFT_4xx_Z:
1336 if (unlikely(msr_pe != 0)) {
1337
1338
1339
1340
1341 in_plb =
1342
1343 (env->pb[0] < env->pb[1] &&
1344
1345 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1346 (env->pb[2] < env->pb[3] &&
1347 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1348 if (in_plb ^ msr_px) {
1349
1350 if (access_type == MMU_DATA_STORE) {
1351
1352 ret = -2;
1353 }
1354 } else {
1355
1356 ctx->prot |= PAGE_WRITE;
1357 }
1358 }
1359 break;
1360
1361 default:
1362
1363 abort();
1364 return -1;
1365 }
1366
1367 return ret;
1368}
1369
1370static int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
1371 target_ulong eaddr,
1372 MMUAccessType access_type, int type,
1373 int mmu_idx)
1374{
1375 int ret = -1;
1376 bool real_mode = (type == ACCESS_CODE && msr_ir == 0)
1377 || (type != ACCESS_CODE && msr_dr == 0);
1378
1379 switch (env->mmu_model) {
1380 case POWERPC_MMU_SOFT_6xx:
1381 case POWERPC_MMU_SOFT_74xx:
1382 if (real_mode) {
1383 ret = check_physical(env, ctx, eaddr, access_type);
1384 } else {
1385
1386 if (env->nb_BATs != 0) {
1387 ret = get_bat_6xx_tlb(env, ctx, eaddr, access_type);
1388 }
1389 if (ret < 0) {
1390
1391 ret = get_segment_6xx_tlb(env, ctx, eaddr, access_type, type);
1392 }
1393 }
1394 break;
1395
1396 case POWERPC_MMU_SOFT_4xx:
1397 case POWERPC_MMU_SOFT_4xx_Z:
1398 if (real_mode) {
1399 ret = check_physical(env, ctx, eaddr, access_type);
1400 } else {
1401 ret = mmu40x_get_physical_address(env, ctx, eaddr, access_type);
1402 }
1403 break;
1404 case POWERPC_MMU_BOOKE:
1405 ret = mmubooke_get_physical_address(env, ctx, eaddr, access_type);
1406 break;
1407 case POWERPC_MMU_BOOKE206:
1408 ret = mmubooke206_get_physical_address(env, ctx, eaddr, access_type,
1409 mmu_idx);
1410 break;
1411 case POWERPC_MMU_MPC8xx:
1412
1413 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1414 break;
1415 case POWERPC_MMU_REAL:
1416 if (real_mode) {
1417 ret = check_physical(env, ctx, eaddr, access_type);
1418 } else {
1419 cpu_abort(env_cpu(env),
1420 "PowerPC in real mode do not do any translation\n");
1421 }
1422 return -1;
1423 default:
1424 cpu_abort(env_cpu(env), "Unknown or invalid MMU model\n");
1425 return -1;
1426 }
1427
1428 return ret;
1429}
1430
1431#ifdef CONFIG_TCG
1432static int get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1433 target_ulong eaddr, MMUAccessType access_type,
1434 int type)
1435{
1436 return get_physical_address_wtlb(env, ctx, eaddr, access_type, type, 0);
1437}
1438#endif
1439
1440static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1441 MMUAccessType access_type, int mmu_idx)
1442{
1443 uint32_t epid;
1444 bool as, pr;
1445 uint32_t missed_tid = 0;
1446 bool use_epid = mmubooke206_get_as(env, mmu_idx, &epid, &as, &pr);
1447
1448 if (access_type == MMU_INST_FETCH) {
1449 as = msr_ir;
1450 }
1451 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1452 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1453 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1454 env->spr[SPR_BOOKE_MAS3] = 0;
1455 env->spr[SPR_BOOKE_MAS6] = 0;
1456 env->spr[SPR_BOOKE_MAS7] = 0;
1457
1458
1459 if (as) {
1460 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1461 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1462 }
1463
1464 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1465 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1466
1467 if (!use_epid) {
1468 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1469 case MAS4_TIDSELD_PID0:
1470 missed_tid = env->spr[SPR_BOOKE_PID];
1471 break;
1472 case MAS4_TIDSELD_PID1:
1473 missed_tid = env->spr[SPR_BOOKE_PID1];
1474 break;
1475 case MAS4_TIDSELD_PID2:
1476 missed_tid = env->spr[SPR_BOOKE_PID2];
1477 break;
1478 }
1479 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1480 } else {
1481 missed_tid = epid;
1482 env->spr[SPR_BOOKE_MAS6] |= missed_tid << 16;
1483 }
1484 env->spr[SPR_BOOKE_MAS1] |= (missed_tid << MAS1_TID_SHIFT);
1485
1486
1487
1488 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1489 env->last_way++;
1490 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1491 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1492}
1493
1494
1495
1496static bool ppc_jumbo_xlate(PowerPCCPU *cpu, vaddr eaddr,
1497 MMUAccessType access_type,
1498 hwaddr *raddrp, int *psizep, int *protp,
1499 int mmu_idx, bool guest_visible)
1500{
1501 CPUState *cs = CPU(cpu);
1502 CPUPPCState *env = &cpu->env;
1503 mmu_ctx_t ctx;
1504 int type;
1505 int ret;
1506
1507 if (access_type == MMU_INST_FETCH) {
1508
1509 type = ACCESS_CODE;
1510 } else if (guest_visible) {
1511
1512 type = env->access_type;
1513 } else {
1514 type = ACCESS_INT;
1515 }
1516
1517 ret = get_physical_address_wtlb(env, &ctx, eaddr, access_type,
1518 type, mmu_idx);
1519 if (ret == 0) {
1520 *raddrp = ctx.raddr;
1521 *protp = ctx.prot;
1522 *psizep = TARGET_PAGE_BITS;
1523 return true;
1524 }
1525
1526 if (guest_visible) {
1527 LOG_MMU_STATE(cs);
1528 if (type == ACCESS_CODE) {
1529 switch (ret) {
1530 case -1:
1531
1532 switch (env->mmu_model) {
1533 case POWERPC_MMU_SOFT_6xx:
1534 cs->exception_index = POWERPC_EXCP_IFTLB;
1535 env->error_code = 1 << 18;
1536 env->spr[SPR_IMISS] = eaddr;
1537 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1538 goto tlb_miss;
1539 case POWERPC_MMU_SOFT_74xx:
1540 cs->exception_index = POWERPC_EXCP_IFTLB;
1541 goto tlb_miss_74xx;
1542 case POWERPC_MMU_SOFT_4xx:
1543 case POWERPC_MMU_SOFT_4xx_Z:
1544 cs->exception_index = POWERPC_EXCP_ITLB;
1545 env->error_code = 0;
1546 env->spr[SPR_40x_DEAR] = eaddr;
1547 env->spr[SPR_40x_ESR] = 0x00000000;
1548 break;
1549 case POWERPC_MMU_BOOKE206:
1550 booke206_update_mas_tlb_miss(env, eaddr, 2, mmu_idx);
1551
1552 case POWERPC_MMU_BOOKE:
1553 cs->exception_index = POWERPC_EXCP_ITLB;
1554 env->error_code = 0;
1555 env->spr[SPR_BOOKE_DEAR] = eaddr;
1556 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, MMU_DATA_LOAD);
1557 break;
1558 case POWERPC_MMU_MPC8xx:
1559 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1560 case POWERPC_MMU_REAL:
1561 cpu_abort(cs, "PowerPC in real mode should never raise "
1562 "any MMU exceptions\n");
1563 default:
1564 cpu_abort(cs, "Unknown or invalid MMU model\n");
1565 }
1566 break;
1567 case -2:
1568
1569 cs->exception_index = POWERPC_EXCP_ISI;
1570 env->error_code = 0x08000000;
1571 break;
1572 case -3:
1573
1574 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1575 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1576 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1577 }
1578 cs->exception_index = POWERPC_EXCP_ISI;
1579 env->error_code = 0x10000000;
1580 break;
1581 case -4:
1582
1583
1584 cs->exception_index = POWERPC_EXCP_ISI;
1585 env->error_code = 0x10000000;
1586 break;
1587 }
1588 } else {
1589 switch (ret) {
1590 case -1:
1591
1592 switch (env->mmu_model) {
1593 case POWERPC_MMU_SOFT_6xx:
1594 if (access_type == MMU_DATA_STORE) {
1595 cs->exception_index = POWERPC_EXCP_DSTLB;
1596 env->error_code = 1 << 16;
1597 } else {
1598 cs->exception_index = POWERPC_EXCP_DLTLB;
1599 env->error_code = 0;
1600 }
1601 env->spr[SPR_DMISS] = eaddr;
1602 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1603 tlb_miss:
1604 env->error_code |= ctx.key << 19;
1605 env->spr[SPR_HASH1] = ppc_hash32_hpt_base(cpu) +
1606 get_pteg_offset32(cpu, ctx.hash[0]);
1607 env->spr[SPR_HASH2] = ppc_hash32_hpt_base(cpu) +
1608 get_pteg_offset32(cpu, ctx.hash[1]);
1609 break;
1610 case POWERPC_MMU_SOFT_74xx:
1611 if (access_type == MMU_DATA_STORE) {
1612 cs->exception_index = POWERPC_EXCP_DSTLB;
1613 } else {
1614 cs->exception_index = POWERPC_EXCP_DLTLB;
1615 }
1616 tlb_miss_74xx:
1617
1618 env->error_code = ctx.key << 19;
1619 env->spr[SPR_TLBMISS] = (eaddr & ~((target_ulong)0x3)) |
1620 ((env->last_way + 1) & (env->nb_ways - 1));
1621 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1622 break;
1623 case POWERPC_MMU_SOFT_4xx:
1624 case POWERPC_MMU_SOFT_4xx_Z:
1625 cs->exception_index = POWERPC_EXCP_DTLB;
1626 env->error_code = 0;
1627 env->spr[SPR_40x_DEAR] = eaddr;
1628 if (access_type == MMU_DATA_STORE) {
1629 env->spr[SPR_40x_ESR] = 0x00800000;
1630 } else {
1631 env->spr[SPR_40x_ESR] = 0x00000000;
1632 }
1633 break;
1634 case POWERPC_MMU_MPC8xx:
1635
1636 cpu_abort(cs, "MPC8xx MMU model is not implemented\n");
1637 case POWERPC_MMU_BOOKE206:
1638 booke206_update_mas_tlb_miss(env, eaddr, access_type, mmu_idx);
1639
1640 case POWERPC_MMU_BOOKE:
1641 cs->exception_index = POWERPC_EXCP_DTLB;
1642 env->error_code = 0;
1643 env->spr[SPR_BOOKE_DEAR] = eaddr;
1644 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1645 break;
1646 case POWERPC_MMU_REAL:
1647 cpu_abort(cs, "PowerPC in real mode should never raise "
1648 "any MMU exceptions\n");
1649 default:
1650 cpu_abort(cs, "Unknown or invalid MMU model\n");
1651 }
1652 break;
1653 case -2:
1654
1655 cs->exception_index = POWERPC_EXCP_DSI;
1656 env->error_code = 0;
1657 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1658 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1659 env->spr[SPR_40x_DEAR] = eaddr;
1660 if (access_type == MMU_DATA_STORE) {
1661 env->spr[SPR_40x_ESR] |= 0x00800000;
1662 }
1663 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1664 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1665 env->spr[SPR_BOOKE_DEAR] = eaddr;
1666 env->spr[SPR_BOOKE_ESR] = mmubooke206_esr(mmu_idx, access_type);
1667 } else {
1668 env->spr[SPR_DAR] = eaddr;
1669 if (access_type == MMU_DATA_STORE) {
1670 env->spr[SPR_DSISR] = 0x0A000000;
1671 } else {
1672 env->spr[SPR_DSISR] = 0x08000000;
1673 }
1674 }
1675 break;
1676 case -4:
1677
1678 switch (type) {
1679 case ACCESS_FLOAT:
1680
1681 cs->exception_index = POWERPC_EXCP_ALIGN;
1682 env->error_code = POWERPC_EXCP_ALIGN_FP;
1683 env->spr[SPR_DAR] = eaddr;
1684 break;
1685 case ACCESS_RES:
1686
1687 cs->exception_index = POWERPC_EXCP_DSI;
1688 env->error_code = 0;
1689 env->spr[SPR_DAR] = eaddr;
1690 if (access_type == MMU_DATA_STORE) {
1691 env->spr[SPR_DSISR] = 0x06000000;
1692 } else {
1693 env->spr[SPR_DSISR] = 0x04000000;
1694 }
1695 break;
1696 case ACCESS_EXT:
1697
1698 cs->exception_index = POWERPC_EXCP_DSI;
1699 env->error_code = 0;
1700 env->spr[SPR_DAR] = eaddr;
1701 if (access_type == MMU_DATA_STORE) {
1702 env->spr[SPR_DSISR] = 0x06100000;
1703 } else {
1704 env->spr[SPR_DSISR] = 0x04100000;
1705 }
1706 break;
1707 default:
1708 printf("DSI: invalid exception (%d)\n", ret);
1709 cs->exception_index = POWERPC_EXCP_PROGRAM;
1710 env->error_code =
1711 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1712 env->spr[SPR_DAR] = eaddr;
1713 break;
1714 }
1715 break;
1716 }
1717 }
1718 }
1719 return false;
1720}
1721
1722#ifdef CONFIG_TCG
1723
1724
1725#if !defined(FLUSH_ALL_TLBS)
1726static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1727 target_ulong mask)
1728{
1729 CPUState *cs = env_cpu(env);
1730 target_ulong base, end, page;
1731
1732 base = BATu & ~0x0001FFFF;
1733 end = base + mask + 0x00020000;
1734 if (((end - base) >> TARGET_PAGE_BITS) > 1024) {
1735
1736 LOG_BATS("Flush all BATs\n");
1737 tlb_flush(cs);
1738 LOG_BATS("Flush done\n");
1739 return;
1740 }
1741 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1742 TARGET_FMT_lx ")\n", base, end, mask);
1743 for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1744 tlb_flush_page(cs, page);
1745 }
1746 LOG_BATS("Flush done\n");
1747}
1748#endif
1749
1750static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1751 target_ulong value)
1752{
1753 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1754 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1755}
1756
1757void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1758{
1759 target_ulong mask;
1760
1761 dump_store_bat(env, 'I', 0, nr, value);
1762 if (env->IBAT[0][nr] != value) {
1763 mask = (value << 15) & 0x0FFE0000UL;
1764#if !defined(FLUSH_ALL_TLBS)
1765 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1766#endif
1767
1768
1769
1770
1771 mask = (value << 15) & 0x0FFE0000UL;
1772 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1773 (value & ~0x0001FFFFUL & ~mask);
1774 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1775 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1776#if !defined(FLUSH_ALL_TLBS)
1777 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1778#else
1779 tlb_flush(env_cpu(env));
1780#endif
1781 }
1782}
1783
1784void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1785{
1786 dump_store_bat(env, 'I', 1, nr, value);
1787 env->IBAT[1][nr] = value;
1788}
1789
1790void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1791{
1792 target_ulong mask;
1793
1794 dump_store_bat(env, 'D', 0, nr, value);
1795 if (env->DBAT[0][nr] != value) {
1796
1797
1798
1799
1800 mask = (value << 15) & 0x0FFE0000UL;
1801#if !defined(FLUSH_ALL_TLBS)
1802 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1803#endif
1804 mask = (value << 15) & 0x0FFE0000UL;
1805 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1806 (value & ~0x0001FFFFUL & ~mask);
1807 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1808 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1809#if !defined(FLUSH_ALL_TLBS)
1810 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1811#else
1812 tlb_flush(env_cpu(env));
1813#endif
1814 }
1815}
1816
1817void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1818{
1819 dump_store_bat(env, 'D', 1, nr, value);
1820 env->DBAT[1][nr] = value;
1821}
1822
1823void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1824{
1825 target_ulong mask;
1826#if defined(FLUSH_ALL_TLBS)
1827 int do_inval;
1828#endif
1829
1830 dump_store_bat(env, 'I', 0, nr, value);
1831 if (env->IBAT[0][nr] != value) {
1832#if defined(FLUSH_ALL_TLBS)
1833 do_inval = 0;
1834#endif
1835 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1836 if (env->IBAT[1][nr] & 0x40) {
1837
1838#if !defined(FLUSH_ALL_TLBS)
1839 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1840#else
1841 do_inval = 1;
1842#endif
1843 }
1844
1845
1846
1847
1848 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1849 (value & ~0x0001FFFFUL & ~mask);
1850 env->DBAT[0][nr] = env->IBAT[0][nr];
1851 if (env->IBAT[1][nr] & 0x40) {
1852#if !defined(FLUSH_ALL_TLBS)
1853 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1854#else
1855 do_inval = 1;
1856#endif
1857 }
1858#if defined(FLUSH_ALL_TLBS)
1859 if (do_inval) {
1860 tlb_flush(env_cpu(env));
1861 }
1862#endif
1863 }
1864}
1865
1866void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1867{
1868#if !defined(FLUSH_ALL_TLBS)
1869 target_ulong mask;
1870#else
1871 int do_inval;
1872#endif
1873
1874 dump_store_bat(env, 'I', 1, nr, value);
1875 if (env->IBAT[1][nr] != value) {
1876#if defined(FLUSH_ALL_TLBS)
1877 do_inval = 0;
1878#endif
1879 if (env->IBAT[1][nr] & 0x40) {
1880#if !defined(FLUSH_ALL_TLBS)
1881 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1882 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1883#else
1884 do_inval = 1;
1885#endif
1886 }
1887 if (value & 0x40) {
1888#if !defined(FLUSH_ALL_TLBS)
1889 mask = (value << 17) & 0x0FFE0000UL;
1890 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1891#else
1892 do_inval = 1;
1893#endif
1894 }
1895 env->IBAT[1][nr] = value;
1896 env->DBAT[1][nr] = value;
1897#if defined(FLUSH_ALL_TLBS)
1898 if (do_inval) {
1899 tlb_flush(env_cpu(env));
1900 }
1901#endif
1902 }
1903}
1904#endif
1905
1906#ifdef CONFIG_TCG
1907
1908
1909void ppc_tlb_invalidate_all(CPUPPCState *env)
1910{
1911#if defined(TARGET_PPC64)
1912 if (mmu_is_64bit(env->mmu_model)) {
1913 env->tlb_need_flush = 0;
1914 tlb_flush(env_cpu(env));
1915 } else
1916#endif
1917 switch (env->mmu_model) {
1918 case POWERPC_MMU_SOFT_6xx:
1919 case POWERPC_MMU_SOFT_74xx:
1920 ppc6xx_tlb_invalidate_all(env);
1921 break;
1922 case POWERPC_MMU_SOFT_4xx:
1923 case POWERPC_MMU_SOFT_4xx_Z:
1924 ppc4xx_tlb_invalidate_all(env);
1925 break;
1926 case POWERPC_MMU_REAL:
1927 cpu_abort(env_cpu(env), "No TLB for PowerPC 4xx in real mode\n");
1928 break;
1929 case POWERPC_MMU_MPC8xx:
1930
1931 cpu_abort(env_cpu(env), "MPC8xx MMU model is not implemented\n");
1932 break;
1933 case POWERPC_MMU_BOOKE:
1934 tlb_flush(env_cpu(env));
1935 break;
1936 case POWERPC_MMU_BOOKE206:
1937 booke206_flush_tlb(env, -1, 0);
1938 break;
1939 case POWERPC_MMU_32B:
1940 case POWERPC_MMU_601:
1941 env->tlb_need_flush = 0;
1942 tlb_flush(env_cpu(env));
1943 break;
1944 default:
1945
1946 cpu_abort(env_cpu(env), "Unknown MMU model %x\n", env->mmu_model);
1947 break;
1948 }
1949}
1950#endif
1951
1952#ifdef CONFIG_TCG
1953void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
1954{
1955#if !defined(FLUSH_ALL_TLBS)
1956 addr &= TARGET_PAGE_MASK;
1957#if defined(TARGET_PPC64)
1958 if (mmu_is_64bit(env->mmu_model)) {
1959
1960
1961
1962
1963
1964
1965 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
1966 } else
1967#endif
1968 switch (env->mmu_model) {
1969 case POWERPC_MMU_SOFT_6xx:
1970 case POWERPC_MMU_SOFT_74xx:
1971 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1972 if (env->id_tlbs == 1) {
1973 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1974 }
1975 break;
1976 case POWERPC_MMU_32B:
1977 case POWERPC_MMU_601:
1978
1979
1980
1981
1982
1983
1984 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
1985 break;
1986 default:
1987
1988 assert(0);
1989 }
1990#else
1991 ppc_tlb_invalidate_all(env);
1992#endif
1993}
1994
1995
1996
1997
1998
1999target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2000{
2001#if defined(TARGET_PPC64)
2002 if (mmu_is_64bit(env->mmu_model)) {
2003
2004 return 0;
2005 }
2006#endif
2007 return env->sr[sr_num];
2008}
2009
2010void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2011{
2012 qemu_log_mask(CPU_LOG_MMU,
2013 "%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2014 (int)srnum, value, env->sr[srnum]);
2015#if defined(TARGET_PPC64)
2016 if (mmu_is_64bit(env->mmu_model)) {
2017 PowerPCCPU *cpu = env_archcpu(env);
2018 uint64_t esid, vsid;
2019
2020
2021 esid = ((uint64_t)(srnum & 0xf) << 28) | SLB_ESID_V;
2022
2023
2024 vsid = (value & 0xfffffff) << 12;
2025
2026 vsid |= ((value >> 27) & 0xf) << 8;
2027
2028 ppc_store_slb(cpu, srnum, esid, vsid);
2029 } else
2030#endif
2031 if (env->sr[srnum] != value) {
2032 env->sr[srnum] = value;
2033
2034
2035
2036
2037#if !defined(FLUSH_ALL_TLBS) && 0
2038 {
2039 target_ulong page, end;
2040
2041 page = (16 << 20) * srnum;
2042 end = page + (16 << 20);
2043 for (; page != end; page += TARGET_PAGE_SIZE) {
2044 tlb_flush_page(env_cpu(env), page);
2045 }
2046 }
2047#else
2048 env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
2049#endif
2050 }
2051}
2052
2053
2054void helper_tlbia(CPUPPCState *env)
2055{
2056 ppc_tlb_invalidate_all(env);
2057}
2058
2059void helper_tlbie(CPUPPCState *env, target_ulong addr)
2060{
2061 ppc_tlb_invalidate_one(env, addr);
2062}
2063
2064void helper_tlbiva(CPUPPCState *env, target_ulong addr)
2065{
2066
2067 assert(env->mmu_model == POWERPC_MMU_BOOKE);
2068
2069 cpu_abort(env_cpu(env), "BookE MMU model is not implemented\n");
2070}
2071
2072
2073
2074static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2075{
2076 target_ulong RPN, CMP, EPN;
2077 int way;
2078
2079 RPN = env->spr[SPR_RPA];
2080 if (is_code) {
2081 CMP = env->spr[SPR_ICMP];
2082 EPN = env->spr[SPR_IMISS];
2083 } else {
2084 CMP = env->spr[SPR_DCMP];
2085 EPN = env->spr[SPR_DMISS];
2086 }
2087 way = (env->spr[SPR_SRR1] >> 17) & 1;
2088 (void)EPN;
2089 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2090 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2091 RPN, way);
2092
2093 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2094 way, is_code, CMP, RPN);
2095}
2096
2097void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2098{
2099 do_6xx_tlb(env, EPN, 0);
2100}
2101
2102void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2103{
2104 do_6xx_tlb(env, EPN, 1);
2105}
2106
2107
2108static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2109{
2110 target_ulong RPN, CMP, EPN;
2111 int way;
2112
2113 RPN = env->spr[SPR_PTELO];
2114 CMP = env->spr[SPR_PTEHI];
2115 EPN = env->spr[SPR_TLBMISS] & ~0x3;
2116 way = env->spr[SPR_TLBMISS] & 0x3;
2117 (void)EPN;
2118 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2119 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2120 RPN, way);
2121
2122 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2123 way, is_code, CMP, RPN);
2124}
2125
2126void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2127{
2128 do_74xx_tlb(env, EPN, 0);
2129}
2130
2131void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2132{
2133 do_74xx_tlb(env, EPN, 1);
2134}
2135
2136
2137
2138
2139target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2140{
2141 mmu_ctx_t ctx;
2142 int nb_BATs;
2143 target_ulong ret = 0;
2144
2145
2146
2147
2148
2149
2150
2151 nb_BATs = env->nb_BATs;
2152 env->nb_BATs = 0;
2153 if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2154 ret = ctx.raddr;
2155 }
2156 env->nb_BATs = nb_BATs;
2157 return ret;
2158}
2159
2160static inline target_ulong booke_tlb_to_page_size(int size)
2161{
2162 return 1024 << (2 * size);
2163}
2164
2165static inline int booke_page_size_to_tlb(target_ulong page_size)
2166{
2167 int size;
2168
2169 switch (page_size) {
2170 case 0x00000400UL:
2171 size = 0x0;
2172 break;
2173 case 0x00001000UL:
2174 size = 0x1;
2175 break;
2176 case 0x00004000UL:
2177 size = 0x2;
2178 break;
2179 case 0x00010000UL:
2180 size = 0x3;
2181 break;
2182 case 0x00040000UL:
2183 size = 0x4;
2184 break;
2185 case 0x00100000UL:
2186 size = 0x5;
2187 break;
2188 case 0x00400000UL:
2189 size = 0x6;
2190 break;
2191 case 0x01000000UL:
2192 size = 0x7;
2193 break;
2194 case 0x04000000UL:
2195 size = 0x8;
2196 break;
2197 case 0x10000000UL:
2198 size = 0x9;
2199 break;
2200 case 0x40000000UL:
2201 size = 0xA;
2202 break;
2203#if defined(TARGET_PPC64)
2204 case 0x000100000000ULL:
2205 size = 0xB;
2206 break;
2207 case 0x000400000000ULL:
2208 size = 0xC;
2209 break;
2210 case 0x001000000000ULL:
2211 size = 0xD;
2212 break;
2213 case 0x004000000000ULL:
2214 size = 0xE;
2215 break;
2216 case 0x010000000000ULL:
2217 size = 0xF;
2218 break;
2219#endif
2220 default:
2221 size = -1;
2222 break;
2223 }
2224
2225 return size;
2226}
2227
2228
2229#define PPC4XX_TLB_ENTRY_MASK 0x0000003f
2230
2231#define PPC4XX_TLBHI_V 0x00000040
2232#define PPC4XX_TLBHI_E 0x00000020
2233#define PPC4XX_TLBHI_SIZE_MIN 0
2234#define PPC4XX_TLBHI_SIZE_MAX 7
2235#define PPC4XX_TLBHI_SIZE_DEFAULT 1
2236#define PPC4XX_TLBHI_SIZE_SHIFT 7
2237#define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2238
2239#define PPC4XX_TLBLO_EX 0x00000200
2240#define PPC4XX_TLBLO_WR 0x00000100
2241#define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2242#define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2243
2244target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2245{
2246 ppcemb_tlb_t *tlb;
2247 target_ulong ret;
2248 int size;
2249
2250 entry &= PPC4XX_TLB_ENTRY_MASK;
2251 tlb = &env->tlb.tlbe[entry];
2252 ret = tlb->EPN;
2253 if (tlb->prot & PAGE_VALID) {
2254 ret |= PPC4XX_TLBHI_V;
2255 }
2256 size = booke_page_size_to_tlb(tlb->size);
2257 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2258 size = PPC4XX_TLBHI_SIZE_DEFAULT;
2259 }
2260 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2261 env->spr[SPR_40x_PID] = tlb->PID;
2262 return ret;
2263}
2264
2265target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2266{
2267 ppcemb_tlb_t *tlb;
2268 target_ulong ret;
2269
2270 entry &= PPC4XX_TLB_ENTRY_MASK;
2271 tlb = &env->tlb.tlbe[entry];
2272 ret = tlb->RPN;
2273 if (tlb->prot & PAGE_EXEC) {
2274 ret |= PPC4XX_TLBLO_EX;
2275 }
2276 if (tlb->prot & PAGE_WRITE) {
2277 ret |= PPC4XX_TLBLO_WR;
2278 }
2279 return ret;
2280}
2281
2282void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2283 target_ulong val)
2284{
2285 CPUState *cs = env_cpu(env);
2286 ppcemb_tlb_t *tlb;
2287 target_ulong page, end;
2288
2289 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2290 val);
2291 entry &= PPC4XX_TLB_ENTRY_MASK;
2292 tlb = &env->tlb.tlbe[entry];
2293
2294 if (tlb->prot & PAGE_VALID) {
2295 end = tlb->EPN + tlb->size;
2296 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2297 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2298 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2299 tlb_flush_page(cs, page);
2300 }
2301 }
2302 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2303 & PPC4XX_TLBHI_SIZE_MASK);
2304
2305
2306
2307
2308 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2309 cpu_abort(cs, "TLB size " TARGET_FMT_lu " < %u "
2310 "are not supported (%d)\n"
2311 "Please implement TARGET_PAGE_BITS_VARY\n",
2312 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2313 }
2314 tlb->EPN = val & ~(tlb->size - 1);
2315 if (val & PPC4XX_TLBHI_V) {
2316 tlb->prot |= PAGE_VALID;
2317 if (val & PPC4XX_TLBHI_E) {
2318
2319 cpu_abort(cs,
2320 "Little-endian TLB entries are not supported by now\n");
2321 }
2322 } else {
2323 tlb->prot &= ~PAGE_VALID;
2324 }
2325 tlb->PID = env->spr[SPR_40x_PID];
2326 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2327 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2328 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2329 tlb->prot & PAGE_READ ? 'r' : '-',
2330 tlb->prot & PAGE_WRITE ? 'w' : '-',
2331 tlb->prot & PAGE_EXEC ? 'x' : '-',
2332 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2333
2334 if (tlb->prot & PAGE_VALID) {
2335 end = tlb->EPN + tlb->size;
2336 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2337 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2338 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2339 tlb_flush_page(cs, page);
2340 }
2341 }
2342}
2343
2344void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2345 target_ulong val)
2346{
2347 ppcemb_tlb_t *tlb;
2348
2349 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2350 val);
2351 entry &= PPC4XX_TLB_ENTRY_MASK;
2352 tlb = &env->tlb.tlbe[entry];
2353 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2354 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2355 tlb->prot = PAGE_READ;
2356 if (val & PPC4XX_TLBLO_EX) {
2357 tlb->prot |= PAGE_EXEC;
2358 }
2359 if (val & PPC4XX_TLBLO_WR) {
2360 tlb->prot |= PAGE_WRITE;
2361 }
2362 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2363 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2364 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2365 tlb->prot & PAGE_READ ? 'r' : '-',
2366 tlb->prot & PAGE_WRITE ? 'w' : '-',
2367 tlb->prot & PAGE_EXEC ? 'x' : '-',
2368 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2369}
2370
2371target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2372{
2373 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2374}
2375
2376
2377void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2378 target_ulong value)
2379{
2380 ppcemb_tlb_t *tlb;
2381 target_ulong EPN, RPN, size;
2382 int do_flush_tlbs;
2383
2384 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2385 __func__, word, (int)entry, value);
2386 do_flush_tlbs = 0;
2387 entry &= 0x3F;
2388 tlb = &env->tlb.tlbe[entry];
2389 switch (word) {
2390 default:
2391
2392 case 0:
2393 EPN = value & 0xFFFFFC00;
2394 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2395 do_flush_tlbs = 1;
2396 }
2397 tlb->EPN = EPN;
2398 size = booke_tlb_to_page_size((value >> 4) & 0xF);
2399 if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2400 do_flush_tlbs = 1;
2401 }
2402 tlb->size = size;
2403 tlb->attr &= ~0x1;
2404 tlb->attr |= (value >> 8) & 1;
2405 if (value & 0x200) {
2406 tlb->prot |= PAGE_VALID;
2407 } else {
2408 if (tlb->prot & PAGE_VALID) {
2409 tlb->prot &= ~PAGE_VALID;
2410 do_flush_tlbs = 1;
2411 }
2412 }
2413 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2414 if (do_flush_tlbs) {
2415 tlb_flush(env_cpu(env));
2416 }
2417 break;
2418 case 1:
2419 RPN = value & 0xFFFFFC0F;
2420 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2421 tlb_flush(env_cpu(env));
2422 }
2423 tlb->RPN = RPN;
2424 break;
2425 case 2:
2426 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2427 tlb->prot = tlb->prot & PAGE_VALID;
2428 if (value & 0x1) {
2429 tlb->prot |= PAGE_READ << 4;
2430 }
2431 if (value & 0x2) {
2432 tlb->prot |= PAGE_WRITE << 4;
2433 }
2434 if (value & 0x4) {
2435 tlb->prot |= PAGE_EXEC << 4;
2436 }
2437 if (value & 0x8) {
2438 tlb->prot |= PAGE_READ;
2439 }
2440 if (value & 0x10) {
2441 tlb->prot |= PAGE_WRITE;
2442 }
2443 if (value & 0x20) {
2444 tlb->prot |= PAGE_EXEC;
2445 }
2446 break;
2447 }
2448}
2449
2450target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2451 target_ulong entry)
2452{
2453 ppcemb_tlb_t *tlb;
2454 target_ulong ret;
2455 int size;
2456
2457 entry &= 0x3F;
2458 tlb = &env->tlb.tlbe[entry];
2459 switch (word) {
2460 default:
2461
2462 case 0:
2463 ret = tlb->EPN;
2464 size = booke_page_size_to_tlb(tlb->size);
2465 if (size < 0 || size > 0xF) {
2466 size = 1;
2467 }
2468 ret |= size << 4;
2469 if (tlb->attr & 0x1) {
2470 ret |= 0x100;
2471 }
2472 if (tlb->prot & PAGE_VALID) {
2473 ret |= 0x200;
2474 }
2475 env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2476 env->spr[SPR_440_MMUCR] |= tlb->PID;
2477 break;
2478 case 1:
2479 ret = tlb->RPN;
2480 break;
2481 case 2:
2482 ret = tlb->attr & ~0x1;
2483 if (tlb->prot & (PAGE_READ << 4)) {
2484 ret |= 0x1;
2485 }
2486 if (tlb->prot & (PAGE_WRITE << 4)) {
2487 ret |= 0x2;
2488 }
2489 if (tlb->prot & (PAGE_EXEC << 4)) {
2490 ret |= 0x4;
2491 }
2492 if (tlb->prot & PAGE_READ) {
2493 ret |= 0x8;
2494 }
2495 if (tlb->prot & PAGE_WRITE) {
2496 ret |= 0x10;
2497 }
2498 if (tlb->prot & PAGE_EXEC) {
2499 ret |= 0x20;
2500 }
2501 break;
2502 }
2503 return ret;
2504}
2505
2506target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2507{
2508 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2509}
2510
2511
2512
2513static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2514{
2515 uint32_t tlbncfg = 0;
2516 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2517 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2518 int tlb;
2519
2520 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2521 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2522
2523 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2524 cpu_abort(env_cpu(env), "we don't support HES yet\n");
2525 }
2526
2527 return booke206_get_tlbm(env, tlb, ea, esel);
2528}
2529
2530void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2531{
2532 env->spr[pidn] = pid;
2533
2534 tlb_flush(env_cpu(env));
2535}
2536
2537void helper_booke_set_eplc(CPUPPCState *env, target_ulong val)
2538{
2539 env->spr[SPR_BOOKE_EPLC] = val & EPID_MASK;
2540 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_LOAD);
2541}
2542void helper_booke_set_epsc(CPUPPCState *env, target_ulong val)
2543{
2544 env->spr[SPR_BOOKE_EPSC] = val & EPID_MASK;
2545 tlb_flush_by_mmuidx(env_cpu(env), 1 << PPC_TLB_EPID_STORE);
2546}
2547
2548static inline void flush_page(CPUPPCState *env, ppcmas_tlb_t *tlb)
2549{
2550 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2551 tlb_flush_page(env_cpu(env), tlb->mas2 & MAS2_EPN_MASK);
2552 } else {
2553 tlb_flush(env_cpu(env));
2554 }
2555}
2556
2557void helper_booke206_tlbwe(CPUPPCState *env)
2558{
2559 uint32_t tlbncfg, tlbn;
2560 ppcmas_tlb_t *tlb;
2561 uint32_t size_tlb, size_ps;
2562 target_ulong mask;
2563
2564
2565 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2566 case MAS0_WQ_ALWAYS:
2567
2568 break;
2569 case MAS0_WQ_COND:
2570
2571 if (0) {
2572 return;
2573 }
2574 break;
2575 case MAS0_WQ_CLR_RSRV:
2576
2577 return;
2578 default:
2579
2580 return;
2581 }
2582
2583 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2584 !msr_gs) {
2585
2586 fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2587 return;
2588 }
2589
2590 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2591 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2592
2593 tlb = booke206_cur_tlb(env);
2594
2595 if (!tlb) {
2596 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2597 POWERPC_EXCP_INVAL |
2598 POWERPC_EXCP_INVAL_INVAL, GETPC());
2599 }
2600
2601
2602 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2603 size_ps = booke206_tlbnps(env, tlbn);
2604 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2605 !(size_ps & (1 << size_tlb))) {
2606 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2607 POWERPC_EXCP_INVAL |
2608 POWERPC_EXCP_INVAL_INVAL, GETPC());
2609 }
2610
2611 if (msr_gs) {
2612 cpu_abort(env_cpu(env), "missing HV implementation\n");
2613 }
2614
2615 if (tlb->mas1 & MAS1_VALID) {
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628 flush_page(env, tlb);
2629 }
2630
2631 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2632 env->spr[SPR_BOOKE_MAS3];
2633 tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2634
2635 if ((env->spr[SPR_MMUCFG] & MMUCFG_MAVN) == MMUCFG_MAVN_V2) {
2636
2637 booke206_fixed_size_tlbn(env, tlbn, tlb);
2638 } else {
2639 if (!(tlbncfg & TLBnCFG_AVAIL)) {
2640
2641 tlb->mas1 &= ~MAS1_TSIZE_MASK;
2642
2643 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2644 }
2645 }
2646
2647
2648 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2649
2650 mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2651
2652 if (!msr_cm) {
2653
2654
2655
2656
2657 mask &= 0xffffffff;
2658 }
2659
2660 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2661
2662 if (!(tlbncfg & TLBnCFG_IPROT)) {
2663
2664 tlb->mas1 &= ~MAS1_IPROT;
2665 }
2666
2667 flush_page(env, tlb);
2668}
2669
2670static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2671{
2672 int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2673 int way = booke206_tlbm_to_way(env, tlb);
2674
2675 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2676 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2677 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2678
2679 env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2680 env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2681 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2682 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2683}
2684
2685void helper_booke206_tlbre(CPUPPCState *env)
2686{
2687 ppcmas_tlb_t *tlb = NULL;
2688
2689 tlb = booke206_cur_tlb(env);
2690 if (!tlb) {
2691 env->spr[SPR_BOOKE_MAS1] = 0;
2692 } else {
2693 booke206_tlb_to_mas(env, tlb);
2694 }
2695}
2696
2697void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2698{
2699 ppcmas_tlb_t *tlb = NULL;
2700 int i, j;
2701 hwaddr raddr;
2702 uint32_t spid, sas;
2703
2704 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2705 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2706
2707 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2708 int ways = booke206_tlb_ways(env, i);
2709
2710 for (j = 0; j < ways; j++) {
2711 tlb = booke206_get_tlbm(env, i, address, j);
2712
2713 if (!tlb) {
2714 continue;
2715 }
2716
2717 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2718 continue;
2719 }
2720
2721 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2722 continue;
2723 }
2724
2725 booke206_tlb_to_mas(env, tlb);
2726 return;
2727 }
2728 }
2729
2730
2731 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2732 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2733 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2734 env->spr[SPR_BOOKE_MAS3] = 0;
2735 env->spr[SPR_BOOKE_MAS7] = 0;
2736
2737 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2738 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2739 }
2740
2741 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2742 << MAS1_TID_SHIFT;
2743
2744
2745 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2746 env->last_way++;
2747 env->last_way &= booke206_tlb_ways(env, 0) - 1;
2748 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2749}
2750
2751static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2752 uint32_t ea)
2753{
2754 int i;
2755 int ways = booke206_tlb_ways(env, tlbn);
2756 target_ulong mask;
2757
2758 for (i = 0; i < ways; i++) {
2759 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2760 if (!tlb) {
2761 continue;
2762 }
2763 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2764 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2765 !(tlb->mas1 & MAS1_IPROT)) {
2766 tlb->mas1 &= ~MAS1_VALID;
2767 }
2768 }
2769}
2770
2771void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2772{
2773 CPUState *cs;
2774
2775 if (address & 0x4) {
2776
2777 if (address & 0x8) {
2778
2779 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2780 } else {
2781
2782 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2783 }
2784 return;
2785 }
2786
2787 if (address & 0x8) {
2788
2789 booke206_invalidate_ea_tlb(env, 1, address);
2790 CPU_FOREACH(cs) {
2791 tlb_flush(cs);
2792 }
2793 } else {
2794
2795 booke206_invalidate_ea_tlb(env, 0, address);
2796 CPU_FOREACH(cs) {
2797 tlb_flush_page(cs, address & MAS2_EPN_MASK);
2798 }
2799 }
2800}
2801
2802void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2803{
2804
2805 booke206_flush_tlb(env, -1, 1);
2806}
2807
2808void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2809{
2810 int i, j;
2811 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2812 ppcmas_tlb_t *tlb = env->tlb.tlbm;
2813 int tlb_size;
2814
2815
2816 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2817 tlb_size = booke206_tlb_size(env, i);
2818 for (j = 0; j < tlb_size; j++) {
2819 if (!(tlb[j].mas1 & MAS1_IPROT) &&
2820 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2821 tlb[j].mas1 &= ~MAS1_VALID;
2822 }
2823 }
2824 tlb += booke206_tlb_size(env, i);
2825 }
2826 tlb_flush(env_cpu(env));
2827}
2828
2829void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2830{
2831 int i, j;
2832 ppcmas_tlb_t *tlb;
2833 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2834 int pid = tid >> MAS6_SPID_SHIFT;
2835 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2836 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2837
2838 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2839
2840 bool mav2 = false;
2841
2842
2843
2844 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2845 int ways = booke206_tlb_ways(env, i);
2846
2847 for (j = 0; j < ways; j++) {
2848 tlb = booke206_get_tlbm(env, i, address, j);
2849 if (!tlb) {
2850 continue;
2851 }
2852 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2853 (tlb->mas1 & MAS1_IPROT) ||
2854 ((tlb->mas1 & MAS1_IND) != ind) ||
2855 ((tlb->mas8 & MAS8_TGS) != sgs)) {
2856 continue;
2857 }
2858 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2859
2860 continue;
2861 }
2862
2863 tlb->mas1 &= ~MAS1_VALID;
2864 }
2865 }
2866 tlb_flush(env_cpu(env));
2867}
2868
2869void helper_booke206_tlbflush(CPUPPCState *env, target_ulong type)
2870{
2871 int flags = 0;
2872
2873 if (type & 2) {
2874 flags |= BOOKE206_FLUSH_TLB1;
2875 }
2876
2877 if (type & 4) {
2878 flags |= BOOKE206_FLUSH_TLB0;
2879 }
2880
2881 booke206_flush_tlb(env, flags, 1);
2882}
2883
2884
2885void helper_check_tlb_flush_local(CPUPPCState *env)
2886{
2887 check_tlb_flush(env, false);
2888}
2889
2890void helper_check_tlb_flush_global(CPUPPCState *env)
2891{
2892 check_tlb_flush(env, true);
2893}
2894#endif
2895
2896
2897
2898static bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
2899 hwaddr *raddrp, int *psizep, int *protp,
2900 int mmu_idx, bool guest_visible)
2901{
2902 switch (cpu->env.mmu_model) {
2903#if defined(TARGET_PPC64)
2904 case POWERPC_MMU_3_00:
2905 if (ppc64_v3_radix(cpu)) {
2906 return ppc_radix64_xlate(cpu, eaddr, access_type,
2907 raddrp, psizep, protp, mmu_idx, guest_visible);
2908 }
2909
2910 case POWERPC_MMU_64B:
2911 case POWERPC_MMU_2_03:
2912 case POWERPC_MMU_2_06:
2913 case POWERPC_MMU_2_07:
2914 return ppc_hash64_xlate(cpu, eaddr, access_type,
2915 raddrp, psizep, protp, mmu_idx, guest_visible);
2916#endif
2917
2918 case POWERPC_MMU_32B:
2919 case POWERPC_MMU_601:
2920 return ppc_hash32_xlate(cpu, eaddr, access_type,
2921 raddrp, psizep, protp, mmu_idx, guest_visible);
2922
2923 default:
2924 return ppc_jumbo_xlate(cpu, eaddr, access_type, raddrp,
2925 psizep, protp, mmu_idx, guest_visible);
2926 }
2927}
2928
2929hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
2930{
2931 PowerPCCPU *cpu = POWERPC_CPU(cs);
2932 hwaddr raddr;
2933 int s, p;
2934
2935
2936
2937
2938
2939
2940 if (ppc_xlate(cpu, addr, MMU_DATA_LOAD, &raddr, &s, &p,
2941 cpu_mmu_index(&cpu->env, false), false) ||
2942 ppc_xlate(cpu, addr, MMU_INST_FETCH, &raddr, &s, &p,
2943 cpu_mmu_index(&cpu->env, true), false)) {
2944 return raddr & TARGET_PAGE_MASK;
2945 }
2946 return -1;
2947}
2948
2949#ifdef CONFIG_TCG
2950bool ppc_cpu_tlb_fill(CPUState *cs, vaddr eaddr, int size,
2951 MMUAccessType access_type, int mmu_idx,
2952 bool probe, uintptr_t retaddr)
2953{
2954 PowerPCCPU *cpu = POWERPC_CPU(cs);
2955 hwaddr raddr;
2956 int page_size, prot;
2957
2958 if (ppc_xlate(cpu, eaddr, access_type, &raddr,
2959 &page_size, &prot, mmu_idx, !probe)) {
2960 tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
2961 prot, mmu_idx, 1UL << page_size);
2962 return true;
2963 }
2964 if (probe) {
2965 return false;
2966 }
2967 raise_exception_err_ra(&cpu->env, cs->exception_index,
2968 cpu->env.error_code, retaddr);
2969}
2970#endif
2971