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