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