]> git.proxmox.com Git - qemu.git/blob - target-ppc/mmu_helper.c
target-ppc: Disentangle hash mmu paths for cpu_ppc_handle_mmu_fault
[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_32B:
1314 case POWERPC_MMU_601:
1315 ret = ppc_hash32_get_physical_address(env, ctx, eaddr, rw, access_type);
1316 break;
1317
1318 case POWERPC_MMU_SOFT_6xx:
1319 case POWERPC_MMU_SOFT_74xx:
1320 if (real_mode) {
1321 ret = check_physical(env, ctx, eaddr, rw);
1322 } else {
1323 /* Try to find a BAT */
1324 if (env->nb_BATs != 0) {
1325 ret = get_bat(env, ctx, eaddr, rw, access_type);
1326 }
1327 if (ret < 0) {
1328 /* We didn't match any BAT entry or don't have BATs */
1329 ret = get_segment_6xx_tlb(env, ctx, eaddr, rw, access_type);
1330 }
1331 }
1332 break;
1333
1334 #if defined(TARGET_PPC64)
1335 case POWERPC_MMU_64B:
1336 case POWERPC_MMU_2_06:
1337 case POWERPC_MMU_2_06d:
1338 ret = ppc_hash64_get_physical_address(env, ctx, eaddr, rw, access_type);
1339 break;
1340 #endif
1341
1342 case POWERPC_MMU_SOFT_4xx:
1343 case POWERPC_MMU_SOFT_4xx_Z:
1344 if (real_mode) {
1345 ret = check_physical(env, ctx, eaddr, rw);
1346 } else {
1347 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1348 rw, access_type);
1349 }
1350 break;
1351 case POWERPC_MMU_BOOKE:
1352 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1353 rw, access_type);
1354 break;
1355 case POWERPC_MMU_BOOKE206:
1356 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1357 access_type);
1358 break;
1359 case POWERPC_MMU_MPC8xx:
1360 /* XXX: TODO */
1361 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1362 break;
1363 case POWERPC_MMU_REAL:
1364 if (real_mode) {
1365 ret = check_physical(env, ctx, eaddr, rw);
1366 } else {
1367 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1368 }
1369 return -1;
1370 default:
1371 cpu_abort(env, "Unknown or invalid MMU model\n");
1372 return -1;
1373 }
1374 #if 0
1375 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1376 __func__, eaddr, ret, ctx->raddr);
1377 #endif
1378
1379 return ret;
1380 }
1381
1382 hwaddr cpu_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
1383 {
1384 mmu_ctx_t ctx;
1385
1386 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0)) {
1387 return -1;
1388 }
1389
1390 return ctx.raddr & TARGET_PAGE_MASK;
1391 }
1392
1393 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1394 int rw)
1395 {
1396 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1397 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1398 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1399 env->spr[SPR_BOOKE_MAS3] = 0;
1400 env->spr[SPR_BOOKE_MAS6] = 0;
1401 env->spr[SPR_BOOKE_MAS7] = 0;
1402
1403 /* AS */
1404 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1405 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1406 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1407 }
1408
1409 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1410 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1411
1412 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1413 case MAS4_TIDSELD_PID0:
1414 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1415 break;
1416 case MAS4_TIDSELD_PID1:
1417 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1418 break;
1419 case MAS4_TIDSELD_PID2:
1420 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1421 break;
1422 }
1423
1424 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1425
1426 /* next victim logic */
1427 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1428 env->last_way++;
1429 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1430 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1431 }
1432
1433 /* Perform address translation */
1434 int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rw,
1435 int mmu_idx)
1436 {
1437 mmu_ctx_t ctx;
1438 int access_type;
1439 int ret = 0;
1440
1441 switch (env->mmu_model) {
1442 #if defined(TARGET_PPC64)
1443 case POWERPC_MMU_64B:
1444 case POWERPC_MMU_2_06:
1445 case POWERPC_MMU_2_06d:
1446 return ppc_hash64_handle_mmu_fault(env, address, rw, mmu_idx);
1447 #endif
1448
1449 case POWERPC_MMU_32B:
1450 case POWERPC_MMU_601:
1451 return ppc_hash32_handle_mmu_fault(env, address, rw, mmu_idx);
1452
1453 default:
1454 ; /* Otherwise fall through to the general code below */
1455 }
1456
1457 if (rw == 2) {
1458 /* code access */
1459 rw = 0;
1460 access_type = ACCESS_CODE;
1461 } else {
1462 /* data access */
1463 access_type = env->access_type;
1464 }
1465 ret = get_physical_address(env, &ctx, address, rw, access_type);
1466 if (ret == 0) {
1467 tlb_set_page(env, address & TARGET_PAGE_MASK,
1468 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1469 mmu_idx, TARGET_PAGE_SIZE);
1470 ret = 0;
1471 } else if (ret < 0) {
1472 LOG_MMU_STATE(env);
1473 if (access_type == ACCESS_CODE) {
1474 switch (ret) {
1475 case -1:
1476 /* No matches in page tables or TLB */
1477 switch (env->mmu_model) {
1478 case POWERPC_MMU_SOFT_6xx:
1479 env->exception_index = POWERPC_EXCP_IFTLB;
1480 env->error_code = 1 << 18;
1481 env->spr[SPR_IMISS] = address;
1482 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1483 goto tlb_miss;
1484 case POWERPC_MMU_SOFT_74xx:
1485 env->exception_index = POWERPC_EXCP_IFTLB;
1486 goto tlb_miss_74xx;
1487 case POWERPC_MMU_SOFT_4xx:
1488 case POWERPC_MMU_SOFT_4xx_Z:
1489 env->exception_index = POWERPC_EXCP_ITLB;
1490 env->error_code = 0;
1491 env->spr[SPR_40x_DEAR] = address;
1492 env->spr[SPR_40x_ESR] = 0x00000000;
1493 break;
1494 case POWERPC_MMU_BOOKE206:
1495 booke206_update_mas_tlb_miss(env, address, rw);
1496 /* fall through */
1497 case POWERPC_MMU_BOOKE:
1498 env->exception_index = POWERPC_EXCP_ITLB;
1499 env->error_code = 0;
1500 env->spr[SPR_BOOKE_DEAR] = address;
1501 return -1;
1502 case POWERPC_MMU_MPC8xx:
1503 /* XXX: TODO */
1504 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1505 break;
1506 case POWERPC_MMU_REAL:
1507 cpu_abort(env, "PowerPC in real mode should never raise "
1508 "any MMU exceptions\n");
1509 return -1;
1510 default:
1511 cpu_abort(env, "Unknown or invalid MMU model\n");
1512 return -1;
1513 }
1514 break;
1515 case -2:
1516 /* Access rights violation */
1517 env->exception_index = POWERPC_EXCP_ISI;
1518 env->error_code = 0x08000000;
1519 break;
1520 case -3:
1521 /* No execute protection violation */
1522 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1523 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1524 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1525 }
1526 env->exception_index = POWERPC_EXCP_ISI;
1527 env->error_code = 0x10000000;
1528 break;
1529 case -4:
1530 /* Direct store exception */
1531 /* No code fetch is allowed in direct-store areas */
1532 env->exception_index = POWERPC_EXCP_ISI;
1533 env->error_code = 0x10000000;
1534 break;
1535 }
1536 } else {
1537 switch (ret) {
1538 case -1:
1539 /* No matches in page tables or TLB */
1540 switch (env->mmu_model) {
1541 case POWERPC_MMU_SOFT_6xx:
1542 if (rw == 1) {
1543 env->exception_index = POWERPC_EXCP_DSTLB;
1544 env->error_code = 1 << 16;
1545 } else {
1546 env->exception_index = POWERPC_EXCP_DLTLB;
1547 env->error_code = 0;
1548 }
1549 env->spr[SPR_DMISS] = address;
1550 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1551 tlb_miss:
1552 env->error_code |= ctx.key << 19;
1553 env->spr[SPR_HASH1] = env->htab_base +
1554 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1555 env->spr[SPR_HASH2] = env->htab_base +
1556 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1557 break;
1558 case POWERPC_MMU_SOFT_74xx:
1559 if (rw == 1) {
1560 env->exception_index = POWERPC_EXCP_DSTLB;
1561 } else {
1562 env->exception_index = POWERPC_EXCP_DLTLB;
1563 }
1564 tlb_miss_74xx:
1565 /* Implement LRU algorithm */
1566 env->error_code = ctx.key << 19;
1567 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1568 ((env->last_way + 1) & (env->nb_ways - 1));
1569 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1570 break;
1571 case POWERPC_MMU_SOFT_4xx:
1572 case POWERPC_MMU_SOFT_4xx_Z:
1573 env->exception_index = POWERPC_EXCP_DTLB;
1574 env->error_code = 0;
1575 env->spr[SPR_40x_DEAR] = address;
1576 if (rw) {
1577 env->spr[SPR_40x_ESR] = 0x00800000;
1578 } else {
1579 env->spr[SPR_40x_ESR] = 0x00000000;
1580 }
1581 break;
1582 case POWERPC_MMU_MPC8xx:
1583 /* XXX: TODO */
1584 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1585 break;
1586 case POWERPC_MMU_BOOKE206:
1587 booke206_update_mas_tlb_miss(env, address, rw);
1588 /* fall through */
1589 case POWERPC_MMU_BOOKE:
1590 env->exception_index = POWERPC_EXCP_DTLB;
1591 env->error_code = 0;
1592 env->spr[SPR_BOOKE_DEAR] = address;
1593 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1594 return -1;
1595 case POWERPC_MMU_REAL:
1596 cpu_abort(env, "PowerPC in real mode should never raise "
1597 "any MMU exceptions\n");
1598 return -1;
1599 default:
1600 cpu_abort(env, "Unknown or invalid MMU model\n");
1601 return -1;
1602 }
1603 break;
1604 case -2:
1605 /* Access rights violation */
1606 env->exception_index = POWERPC_EXCP_DSI;
1607 env->error_code = 0;
1608 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1609 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1610 env->spr[SPR_40x_DEAR] = address;
1611 if (rw) {
1612 env->spr[SPR_40x_ESR] |= 0x00800000;
1613 }
1614 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1615 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1616 env->spr[SPR_BOOKE_DEAR] = address;
1617 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1618 } else {
1619 env->spr[SPR_DAR] = address;
1620 if (rw == 1) {
1621 env->spr[SPR_DSISR] = 0x0A000000;
1622 } else {
1623 env->spr[SPR_DSISR] = 0x08000000;
1624 }
1625 }
1626 break;
1627 case -4:
1628 /* Direct store exception */
1629 switch (access_type) {
1630 case ACCESS_FLOAT:
1631 /* Floating point load/store */
1632 env->exception_index = POWERPC_EXCP_ALIGN;
1633 env->error_code = POWERPC_EXCP_ALIGN_FP;
1634 env->spr[SPR_DAR] = address;
1635 break;
1636 case ACCESS_RES:
1637 /* lwarx, ldarx or stwcx. */
1638 env->exception_index = POWERPC_EXCP_DSI;
1639 env->error_code = 0;
1640 env->spr[SPR_DAR] = address;
1641 if (rw == 1) {
1642 env->spr[SPR_DSISR] = 0x06000000;
1643 } else {
1644 env->spr[SPR_DSISR] = 0x04000000;
1645 }
1646 break;
1647 case ACCESS_EXT:
1648 /* eciwx or ecowx */
1649 env->exception_index = POWERPC_EXCP_DSI;
1650 env->error_code = 0;
1651 env->spr[SPR_DAR] = address;
1652 if (rw == 1) {
1653 env->spr[SPR_DSISR] = 0x06100000;
1654 } else {
1655 env->spr[SPR_DSISR] = 0x04100000;
1656 }
1657 break;
1658 default:
1659 printf("DSI: invalid exception (%d)\n", ret);
1660 env->exception_index = POWERPC_EXCP_PROGRAM;
1661 env->error_code =
1662 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1663 env->spr[SPR_DAR] = address;
1664 break;
1665 }
1666 break;
1667 }
1668 }
1669 #if 0
1670 printf("%s: set exception to %d %02x\n", __func__,
1671 env->exception, env->error_code);
1672 #endif
1673 ret = 1;
1674 }
1675
1676 return ret;
1677 }
1678
1679 /*****************************************************************************/
1680 /* BATs management */
1681 #if !defined(FLUSH_ALL_TLBS)
1682 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1683 target_ulong mask)
1684 {
1685 target_ulong base, end, page;
1686
1687 base = BATu & ~0x0001FFFF;
1688 end = base + mask + 0x00020000;
1689 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1690 TARGET_FMT_lx ")\n", base, end, mask);
1691 for (page = base; page != end; page += TARGET_PAGE_SIZE) {
1692 tlb_flush_page(env, page);
1693 }
1694 LOG_BATS("Flush done\n");
1695 }
1696 #endif
1697
1698 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1699 target_ulong value)
1700 {
1701 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1702 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1703 }
1704
1705 void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1706 {
1707 target_ulong mask;
1708
1709 dump_store_bat(env, 'I', 0, nr, value);
1710 if (env->IBAT[0][nr] != value) {
1711 mask = (value << 15) & 0x0FFE0000UL;
1712 #if !defined(FLUSH_ALL_TLBS)
1713 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1714 #endif
1715 /* When storing valid upper BAT, mask BEPI and BRPN
1716 * and invalidate all TLBs covered by this BAT
1717 */
1718 mask = (value << 15) & 0x0FFE0000UL;
1719 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1720 (value & ~0x0001FFFFUL & ~mask);
1721 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1722 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1723 #if !defined(FLUSH_ALL_TLBS)
1724 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1725 #else
1726 tlb_flush(env, 1);
1727 #endif
1728 }
1729 }
1730
1731 void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1732 {
1733 dump_store_bat(env, 'I', 1, nr, value);
1734 env->IBAT[1][nr] = value;
1735 }
1736
1737 void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
1738 {
1739 target_ulong mask;
1740
1741 dump_store_bat(env, 'D', 0, nr, value);
1742 if (env->DBAT[0][nr] != value) {
1743 /* When storing valid upper BAT, mask BEPI and BRPN
1744 * and invalidate all TLBs covered by this BAT
1745 */
1746 mask = (value << 15) & 0x0FFE0000UL;
1747 #if !defined(FLUSH_ALL_TLBS)
1748 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1749 #endif
1750 mask = (value << 15) & 0x0FFE0000UL;
1751 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1752 (value & ~0x0001FFFFUL & ~mask);
1753 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1754 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1755 #if !defined(FLUSH_ALL_TLBS)
1756 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1757 #else
1758 tlb_flush(env, 1);
1759 #endif
1760 }
1761 }
1762
1763 void helper_store_dbatl(CPUPPCState *env, uint32_t nr, target_ulong value)
1764 {
1765 dump_store_bat(env, 'D', 1, nr, value);
1766 env->DBAT[1][nr] = value;
1767 }
1768
1769 void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
1770 {
1771 target_ulong mask;
1772 #if defined(FLUSH_ALL_TLBS)
1773 int do_inval;
1774 #endif
1775
1776 dump_store_bat(env, 'I', 0, nr, value);
1777 if (env->IBAT[0][nr] != value) {
1778 #if defined(FLUSH_ALL_TLBS)
1779 do_inval = 0;
1780 #endif
1781 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1782 if (env->IBAT[1][nr] & 0x40) {
1783 /* Invalidate BAT only if it is valid */
1784 #if !defined(FLUSH_ALL_TLBS)
1785 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1786 #else
1787 do_inval = 1;
1788 #endif
1789 }
1790 /* When storing valid upper BAT, mask BEPI and BRPN
1791 * and invalidate all TLBs covered by this BAT
1792 */
1793 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1794 (value & ~0x0001FFFFUL & ~mask);
1795 env->DBAT[0][nr] = env->IBAT[0][nr];
1796 if (env->IBAT[1][nr] & 0x40) {
1797 #if !defined(FLUSH_ALL_TLBS)
1798 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1799 #else
1800 do_inval = 1;
1801 #endif
1802 }
1803 #if defined(FLUSH_ALL_TLBS)
1804 if (do_inval) {
1805 tlb_flush(env, 1);
1806 }
1807 #endif
1808 }
1809 }
1810
1811 void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
1812 {
1813 #if !defined(FLUSH_ALL_TLBS)
1814 target_ulong mask;
1815 #else
1816 int do_inval;
1817 #endif
1818
1819 dump_store_bat(env, 'I', 1, nr, value);
1820 if (env->IBAT[1][nr] != value) {
1821 #if defined(FLUSH_ALL_TLBS)
1822 do_inval = 0;
1823 #endif
1824 if (env->IBAT[1][nr] & 0x40) {
1825 #if !defined(FLUSH_ALL_TLBS)
1826 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1827 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1828 #else
1829 do_inval = 1;
1830 #endif
1831 }
1832 if (value & 0x40) {
1833 #if !defined(FLUSH_ALL_TLBS)
1834 mask = (value << 17) & 0x0FFE0000UL;
1835 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1836 #else
1837 do_inval = 1;
1838 #endif
1839 }
1840 env->IBAT[1][nr] = value;
1841 env->DBAT[1][nr] = value;
1842 #if defined(FLUSH_ALL_TLBS)
1843 if (do_inval) {
1844 tlb_flush(env, 1);
1845 }
1846 #endif
1847 }
1848 }
1849
1850 /*****************************************************************************/
1851 /* TLB management */
1852 void ppc_tlb_invalidate_all(CPUPPCState *env)
1853 {
1854 switch (env->mmu_model) {
1855 case POWERPC_MMU_SOFT_6xx:
1856 case POWERPC_MMU_SOFT_74xx:
1857 ppc6xx_tlb_invalidate_all(env);
1858 break;
1859 case POWERPC_MMU_SOFT_4xx:
1860 case POWERPC_MMU_SOFT_4xx_Z:
1861 ppc4xx_tlb_invalidate_all(env);
1862 break;
1863 case POWERPC_MMU_REAL:
1864 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1865 break;
1866 case POWERPC_MMU_MPC8xx:
1867 /* XXX: TODO */
1868 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1869 break;
1870 case POWERPC_MMU_BOOKE:
1871 tlb_flush(env, 1);
1872 break;
1873 case POWERPC_MMU_BOOKE206:
1874 booke206_flush_tlb(env, -1, 0);
1875 break;
1876 case POWERPC_MMU_32B:
1877 case POWERPC_MMU_601:
1878 #if defined(TARGET_PPC64)
1879 case POWERPC_MMU_64B:
1880 case POWERPC_MMU_2_06:
1881 case POWERPC_MMU_2_06d:
1882 #endif /* defined(TARGET_PPC64) */
1883 tlb_flush(env, 1);
1884 break;
1885 default:
1886 /* XXX: TODO */
1887 cpu_abort(env, "Unknown MMU model\n");
1888 break;
1889 }
1890 }
1891
1892 void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
1893 {
1894 #if !defined(FLUSH_ALL_TLBS)
1895 addr &= TARGET_PAGE_MASK;
1896 switch (env->mmu_model) {
1897 case POWERPC_MMU_SOFT_6xx:
1898 case POWERPC_MMU_SOFT_74xx:
1899 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1900 if (env->id_tlbs == 1) {
1901 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1902 }
1903 break;
1904 case POWERPC_MMU_SOFT_4xx:
1905 case POWERPC_MMU_SOFT_4xx_Z:
1906 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1907 break;
1908 case POWERPC_MMU_REAL:
1909 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1910 break;
1911 case POWERPC_MMU_MPC8xx:
1912 /* XXX: TODO */
1913 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1914 break;
1915 case POWERPC_MMU_BOOKE:
1916 /* XXX: TODO */
1917 cpu_abort(env, "BookE MMU model is not implemented\n");
1918 break;
1919 case POWERPC_MMU_BOOKE206:
1920 /* XXX: TODO */
1921 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
1922 break;
1923 case POWERPC_MMU_32B:
1924 case POWERPC_MMU_601:
1925 /* tlbie invalidate TLBs for all segments */
1926 addr &= ~((target_ulong)-1ULL << 28);
1927 /* XXX: this case should be optimized,
1928 * giving a mask to tlb_flush_page
1929 */
1930 tlb_flush_page(env, addr | (0x0 << 28));
1931 tlb_flush_page(env, addr | (0x1 << 28));
1932 tlb_flush_page(env, addr | (0x2 << 28));
1933 tlb_flush_page(env, addr | (0x3 << 28));
1934 tlb_flush_page(env, addr | (0x4 << 28));
1935 tlb_flush_page(env, addr | (0x5 << 28));
1936 tlb_flush_page(env, addr | (0x6 << 28));
1937 tlb_flush_page(env, addr | (0x7 << 28));
1938 tlb_flush_page(env, addr | (0x8 << 28));
1939 tlb_flush_page(env, addr | (0x9 << 28));
1940 tlb_flush_page(env, addr | (0xA << 28));
1941 tlb_flush_page(env, addr | (0xB << 28));
1942 tlb_flush_page(env, addr | (0xC << 28));
1943 tlb_flush_page(env, addr | (0xD << 28));
1944 tlb_flush_page(env, addr | (0xE << 28));
1945 tlb_flush_page(env, addr | (0xF << 28));
1946 break;
1947 #if defined(TARGET_PPC64)
1948 case POWERPC_MMU_64B:
1949 case POWERPC_MMU_2_06:
1950 case POWERPC_MMU_2_06d:
1951 /* tlbie invalidate TLBs for all segments */
1952 /* XXX: given the fact that there are too many segments to invalidate,
1953 * and we still don't have a tlb_flush_mask(env, n, mask) in QEMU,
1954 * we just invalidate all TLBs
1955 */
1956 tlb_flush(env, 1);
1957 break;
1958 #endif /* defined(TARGET_PPC64) */
1959 default:
1960 /* XXX: TODO */
1961 cpu_abort(env, "Unknown MMU model\n");
1962 break;
1963 }
1964 #else
1965 ppc_tlb_invalidate_all(env);
1966 #endif
1967 }
1968
1969 /*****************************************************************************/
1970 /* Special registers manipulation */
1971 void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
1972 {
1973 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1974 if (env->spr[SPR_SDR1] != value) {
1975 env->spr[SPR_SDR1] = value;
1976 #if defined(TARGET_PPC64)
1977 if (env->mmu_model & POWERPC_MMU_64) {
1978 target_ulong htabsize = value & SDR_64_HTABSIZE;
1979
1980 if (htabsize > 28) {
1981 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1982 " stored in SDR1\n", htabsize);
1983 htabsize = 28;
1984 }
1985 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1986 env->htab_base = value & SDR_64_HTABORG;
1987 } else
1988 #endif /* defined(TARGET_PPC64) */
1989 {
1990 /* FIXME: Should check for valid HTABMASK values */
1991 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1992 env->htab_base = value & SDR_32_HTABORG;
1993 }
1994 tlb_flush(env, 1);
1995 }
1996 }
1997
1998 /* Segment registers load and store */
1999 target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
2000 {
2001 #if defined(TARGET_PPC64)
2002 if (env->mmu_model & POWERPC_MMU_64) {
2003 /* XXX */
2004 return 0;
2005 }
2006 #endif
2007 return env->sr[sr_num];
2008 }
2009
2010 void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
2011 {
2012 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2013 (int)srnum, value, env->sr[srnum]);
2014 #if defined(TARGET_PPC64)
2015 if (env->mmu_model & POWERPC_MMU_64) {
2016 uint64_t rb = 0, rs = 0;
2017
2018 /* ESID = srnum */
2019 rb |= ((uint32_t)srnum & 0xf) << 28;
2020 /* Set the valid bit */
2021 rb |= 1 << 27;
2022 /* Index = ESID */
2023 rb |= (uint32_t)srnum;
2024
2025 /* VSID = VSID */
2026 rs |= (value & 0xfffffff) << 12;
2027 /* flags = flags */
2028 rs |= ((value >> 27) & 0xf) << 8;
2029
2030 ppc_store_slb(env, rb, rs);
2031 } else
2032 #endif
2033 if (env->sr[srnum] != value) {
2034 env->sr[srnum] = value;
2035 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2036 flusing the whole TLB. */
2037 #if !defined(FLUSH_ALL_TLBS) && 0
2038 {
2039 target_ulong page, end;
2040 /* Invalidate 256 MB of virtual memory */
2041 page = (16 << 20) * srnum;
2042 end = page + (16 << 20);
2043 for (; page != end; page += TARGET_PAGE_SIZE) {
2044 tlb_flush_page(env, page);
2045 }
2046 }
2047 #else
2048 tlb_flush(env, 1);
2049 #endif
2050 }
2051 }
2052 #endif /* !defined(CONFIG_USER_ONLY) */
2053
2054 #if !defined(CONFIG_USER_ONLY)
2055 /* TLB management */
2056 void helper_tlbia(CPUPPCState *env)
2057 {
2058 ppc_tlb_invalidate_all(env);
2059 }
2060
2061 void helper_tlbie(CPUPPCState *env, target_ulong addr)
2062 {
2063 ppc_tlb_invalidate_one(env, addr);
2064 }
2065
2066 /* Software driven TLBs management */
2067 /* PowerPC 602/603 software TLB load instructions helpers */
2068 static void do_6xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2069 {
2070 target_ulong RPN, CMP, EPN;
2071 int way;
2072
2073 RPN = env->spr[SPR_RPA];
2074 if (is_code) {
2075 CMP = env->spr[SPR_ICMP];
2076 EPN = env->spr[SPR_IMISS];
2077 } else {
2078 CMP = env->spr[SPR_DCMP];
2079 EPN = env->spr[SPR_DMISS];
2080 }
2081 way = (env->spr[SPR_SRR1] >> 17) & 1;
2082 (void)EPN; /* avoid a compiler warning */
2083 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2084 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2085 RPN, way);
2086 /* Store this TLB */
2087 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2088 way, is_code, CMP, RPN);
2089 }
2090
2091 void helper_6xx_tlbd(CPUPPCState *env, target_ulong EPN)
2092 {
2093 do_6xx_tlb(env, EPN, 0);
2094 }
2095
2096 void helper_6xx_tlbi(CPUPPCState *env, target_ulong EPN)
2097 {
2098 do_6xx_tlb(env, EPN, 1);
2099 }
2100
2101 /* PowerPC 74xx software TLB load instructions helpers */
2102 static void do_74xx_tlb(CPUPPCState *env, target_ulong new_EPN, int is_code)
2103 {
2104 target_ulong RPN, CMP, EPN;
2105 int way;
2106
2107 RPN = env->spr[SPR_PTELO];
2108 CMP = env->spr[SPR_PTEHI];
2109 EPN = env->spr[SPR_TLBMISS] & ~0x3;
2110 way = env->spr[SPR_TLBMISS] & 0x3;
2111 (void)EPN; /* avoid a compiler warning */
2112 LOG_SWTLB("%s: EPN " TARGET_FMT_lx " " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
2113 " PTE1 " TARGET_FMT_lx " way %d\n", __func__, new_EPN, EPN, CMP,
2114 RPN, way);
2115 /* Store this TLB */
2116 ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
2117 way, is_code, CMP, RPN);
2118 }
2119
2120 void helper_74xx_tlbd(CPUPPCState *env, target_ulong EPN)
2121 {
2122 do_74xx_tlb(env, EPN, 0);
2123 }
2124
2125 void helper_74xx_tlbi(CPUPPCState *env, target_ulong EPN)
2126 {
2127 do_74xx_tlb(env, EPN, 1);
2128 }
2129
2130 /*****************************************************************************/
2131 /* PowerPC 601 specific instructions (POWER bridge) */
2132
2133 target_ulong helper_rac(CPUPPCState *env, target_ulong addr)
2134 {
2135 mmu_ctx_t ctx;
2136 int nb_BATs;
2137 target_ulong ret = 0;
2138
2139 /* We don't have to generate many instances of this instruction,
2140 * as rac is supervisor only.
2141 */
2142 /* XXX: FIX THIS: Pretend we have no BAT */
2143 nb_BATs = env->nb_BATs;
2144 env->nb_BATs = 0;
2145 if (get_physical_address(env, &ctx, addr, 0, ACCESS_INT) == 0) {
2146 ret = ctx.raddr;
2147 }
2148 env->nb_BATs = nb_BATs;
2149 return ret;
2150 }
2151
2152 static inline target_ulong booke_tlb_to_page_size(int size)
2153 {
2154 return 1024 << (2 * size);
2155 }
2156
2157 static inline int booke_page_size_to_tlb(target_ulong page_size)
2158 {
2159 int size;
2160
2161 switch (page_size) {
2162 case 0x00000400UL:
2163 size = 0x0;
2164 break;
2165 case 0x00001000UL:
2166 size = 0x1;
2167 break;
2168 case 0x00004000UL:
2169 size = 0x2;
2170 break;
2171 case 0x00010000UL:
2172 size = 0x3;
2173 break;
2174 case 0x00040000UL:
2175 size = 0x4;
2176 break;
2177 case 0x00100000UL:
2178 size = 0x5;
2179 break;
2180 case 0x00400000UL:
2181 size = 0x6;
2182 break;
2183 case 0x01000000UL:
2184 size = 0x7;
2185 break;
2186 case 0x04000000UL:
2187 size = 0x8;
2188 break;
2189 case 0x10000000UL:
2190 size = 0x9;
2191 break;
2192 case 0x40000000UL:
2193 size = 0xA;
2194 break;
2195 #if defined(TARGET_PPC64)
2196 case 0x000100000000ULL:
2197 size = 0xB;
2198 break;
2199 case 0x000400000000ULL:
2200 size = 0xC;
2201 break;
2202 case 0x001000000000ULL:
2203 size = 0xD;
2204 break;
2205 case 0x004000000000ULL:
2206 size = 0xE;
2207 break;
2208 case 0x010000000000ULL:
2209 size = 0xF;
2210 break;
2211 #endif
2212 default:
2213 size = -1;
2214 break;
2215 }
2216
2217 return size;
2218 }
2219
2220 /* Helpers for 4xx TLB management */
2221 #define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */
2222
2223 #define PPC4XX_TLBHI_V 0x00000040
2224 #define PPC4XX_TLBHI_E 0x00000020
2225 #define PPC4XX_TLBHI_SIZE_MIN 0
2226 #define PPC4XX_TLBHI_SIZE_MAX 7
2227 #define PPC4XX_TLBHI_SIZE_DEFAULT 1
2228 #define PPC4XX_TLBHI_SIZE_SHIFT 7
2229 #define PPC4XX_TLBHI_SIZE_MASK 0x00000007
2230
2231 #define PPC4XX_TLBLO_EX 0x00000200
2232 #define PPC4XX_TLBLO_WR 0x00000100
2233 #define PPC4XX_TLBLO_ATTR_MASK 0x000000FF
2234 #define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00
2235
2236 target_ulong helper_4xx_tlbre_hi(CPUPPCState *env, target_ulong entry)
2237 {
2238 ppcemb_tlb_t *tlb;
2239 target_ulong ret;
2240 int size;
2241
2242 entry &= PPC4XX_TLB_ENTRY_MASK;
2243 tlb = &env->tlb.tlbe[entry];
2244 ret = tlb->EPN;
2245 if (tlb->prot & PAGE_VALID) {
2246 ret |= PPC4XX_TLBHI_V;
2247 }
2248 size = booke_page_size_to_tlb(tlb->size);
2249 if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) {
2250 size = PPC4XX_TLBHI_SIZE_DEFAULT;
2251 }
2252 ret |= size << PPC4XX_TLBHI_SIZE_SHIFT;
2253 env->spr[SPR_40x_PID] = tlb->PID;
2254 return ret;
2255 }
2256
2257 target_ulong helper_4xx_tlbre_lo(CPUPPCState *env, target_ulong entry)
2258 {
2259 ppcemb_tlb_t *tlb;
2260 target_ulong ret;
2261
2262 entry &= PPC4XX_TLB_ENTRY_MASK;
2263 tlb = &env->tlb.tlbe[entry];
2264 ret = tlb->RPN;
2265 if (tlb->prot & PAGE_EXEC) {
2266 ret |= PPC4XX_TLBLO_EX;
2267 }
2268 if (tlb->prot & PAGE_WRITE) {
2269 ret |= PPC4XX_TLBLO_WR;
2270 }
2271 return ret;
2272 }
2273
2274 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
2275 target_ulong val)
2276 {
2277 ppcemb_tlb_t *tlb;
2278 target_ulong page, end;
2279
2280 LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry,
2281 val);
2282 entry &= PPC4XX_TLB_ENTRY_MASK;
2283 tlb = &env->tlb.tlbe[entry];
2284 /* Invalidate previous TLB (if it's valid) */
2285 if (tlb->prot & PAGE_VALID) {
2286 end = tlb->EPN + tlb->size;
2287 LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end "
2288 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2289 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2290 tlb_flush_page(env, page);
2291 }
2292 }
2293 tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT)
2294 & PPC4XX_TLBHI_SIZE_MASK);
2295 /* We cannot handle TLB size < TARGET_PAGE_SIZE.
2296 * If this ever occurs, one should use the ppcemb target instead
2297 * of the ppc or ppc64 one
2298 */
2299 if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
2300 cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u "
2301 "are not supported (%d)\n",
2302 tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
2303 }
2304 tlb->EPN = val & ~(tlb->size - 1);
2305 if (val & PPC4XX_TLBHI_V) {
2306 tlb->prot |= PAGE_VALID;
2307 if (val & PPC4XX_TLBHI_E) {
2308 /* XXX: TO BE FIXED */
2309 cpu_abort(env,
2310 "Little-endian TLB entries are not supported by now\n");
2311 }
2312 } else {
2313 tlb->prot &= ~PAGE_VALID;
2314 }
2315 tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2316 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2317 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2318 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2319 tlb->prot & PAGE_READ ? 'r' : '-',
2320 tlb->prot & PAGE_WRITE ? 'w' : '-',
2321 tlb->prot & PAGE_EXEC ? 'x' : '-',
2322 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2323 /* Invalidate new TLB (if valid) */
2324 if (tlb->prot & PAGE_VALID) {
2325 end = tlb->EPN + tlb->size;
2326 LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end "
2327 TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end);
2328 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
2329 tlb_flush_page(env, page);
2330 }
2331 }
2332 }
2333
2334 void helper_4xx_tlbwe_lo(CPUPPCState *env, target_ulong entry,
2335 target_ulong val)
2336 {
2337 ppcemb_tlb_t *tlb;
2338
2339 LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry,
2340 val);
2341 entry &= PPC4XX_TLB_ENTRY_MASK;
2342 tlb = &env->tlb.tlbe[entry];
2343 tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
2344 tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
2345 tlb->prot = PAGE_READ;
2346 if (val & PPC4XX_TLBLO_EX) {
2347 tlb->prot |= PAGE_EXEC;
2348 }
2349 if (val & PPC4XX_TLBLO_WR) {
2350 tlb->prot |= PAGE_WRITE;
2351 }
2352 LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx
2353 " size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__,
2354 (int)entry, tlb->RPN, tlb->EPN, tlb->size,
2355 tlb->prot & PAGE_READ ? 'r' : '-',
2356 tlb->prot & PAGE_WRITE ? 'w' : '-',
2357 tlb->prot & PAGE_EXEC ? 'x' : '-',
2358 tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
2359 }
2360
2361 target_ulong helper_4xx_tlbsx(CPUPPCState *env, target_ulong address)
2362 {
2363 return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]);
2364 }
2365
2366 /* PowerPC 440 TLB management */
2367 void helper_440_tlbwe(CPUPPCState *env, uint32_t word, target_ulong entry,
2368 target_ulong value)
2369 {
2370 ppcemb_tlb_t *tlb;
2371 target_ulong EPN, RPN, size;
2372 int do_flush_tlbs;
2373
2374 LOG_SWTLB("%s word %d entry %d value " TARGET_FMT_lx "\n",
2375 __func__, word, (int)entry, value);
2376 do_flush_tlbs = 0;
2377 entry &= 0x3F;
2378 tlb = &env->tlb.tlbe[entry];
2379 switch (word) {
2380 default:
2381 /* Just here to please gcc */
2382 case 0:
2383 EPN = value & 0xFFFFFC00;
2384 if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) {
2385 do_flush_tlbs = 1;
2386 }
2387 tlb->EPN = EPN;
2388 size = booke_tlb_to_page_size((value >> 4) & 0xF);
2389 if ((tlb->prot & PAGE_VALID) && tlb->size < size) {
2390 do_flush_tlbs = 1;
2391 }
2392 tlb->size = size;
2393 tlb->attr &= ~0x1;
2394 tlb->attr |= (value >> 8) & 1;
2395 if (value & 0x200) {
2396 tlb->prot |= PAGE_VALID;
2397 } else {
2398 if (tlb->prot & PAGE_VALID) {
2399 tlb->prot &= ~PAGE_VALID;
2400 do_flush_tlbs = 1;
2401 }
2402 }
2403 tlb->PID = env->spr[SPR_440_MMUCR] & 0x000000FF;
2404 if (do_flush_tlbs) {
2405 tlb_flush(env, 1);
2406 }
2407 break;
2408 case 1:
2409 RPN = value & 0xFFFFFC0F;
2410 if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) {
2411 tlb_flush(env, 1);
2412 }
2413 tlb->RPN = RPN;
2414 break;
2415 case 2:
2416 tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
2417 tlb->prot = tlb->prot & PAGE_VALID;
2418 if (value & 0x1) {
2419 tlb->prot |= PAGE_READ << 4;
2420 }
2421 if (value & 0x2) {
2422 tlb->prot |= PAGE_WRITE << 4;
2423 }
2424 if (value & 0x4) {
2425 tlb->prot |= PAGE_EXEC << 4;
2426 }
2427 if (value & 0x8) {
2428 tlb->prot |= PAGE_READ;
2429 }
2430 if (value & 0x10) {
2431 tlb->prot |= PAGE_WRITE;
2432 }
2433 if (value & 0x20) {
2434 tlb->prot |= PAGE_EXEC;
2435 }
2436 break;
2437 }
2438 }
2439
2440 target_ulong helper_440_tlbre(CPUPPCState *env, uint32_t word,
2441 target_ulong entry)
2442 {
2443 ppcemb_tlb_t *tlb;
2444 target_ulong ret;
2445 int size;
2446
2447 entry &= 0x3F;
2448 tlb = &env->tlb.tlbe[entry];
2449 switch (word) {
2450 default:
2451 /* Just here to please gcc */
2452 case 0:
2453 ret = tlb->EPN;
2454 size = booke_page_size_to_tlb(tlb->size);
2455 if (size < 0 || size > 0xF) {
2456 size = 1;
2457 }
2458 ret |= size << 4;
2459 if (tlb->attr & 0x1) {
2460 ret |= 0x100;
2461 }
2462 if (tlb->prot & PAGE_VALID) {
2463 ret |= 0x200;
2464 }
2465 env->spr[SPR_440_MMUCR] &= ~0x000000FF;
2466 env->spr[SPR_440_MMUCR] |= tlb->PID;
2467 break;
2468 case 1:
2469 ret = tlb->RPN;
2470 break;
2471 case 2:
2472 ret = tlb->attr & ~0x1;
2473 if (tlb->prot & (PAGE_READ << 4)) {
2474 ret |= 0x1;
2475 }
2476 if (tlb->prot & (PAGE_WRITE << 4)) {
2477 ret |= 0x2;
2478 }
2479 if (tlb->prot & (PAGE_EXEC << 4)) {
2480 ret |= 0x4;
2481 }
2482 if (tlb->prot & PAGE_READ) {
2483 ret |= 0x8;
2484 }
2485 if (tlb->prot & PAGE_WRITE) {
2486 ret |= 0x10;
2487 }
2488 if (tlb->prot & PAGE_EXEC) {
2489 ret |= 0x20;
2490 }
2491 break;
2492 }
2493 return ret;
2494 }
2495
2496 target_ulong helper_440_tlbsx(CPUPPCState *env, target_ulong address)
2497 {
2498 return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF);
2499 }
2500
2501 /* PowerPC BookE 2.06 TLB management */
2502
2503 static ppcmas_tlb_t *booke206_cur_tlb(CPUPPCState *env)
2504 {
2505 uint32_t tlbncfg = 0;
2506 int esel = (env->spr[SPR_BOOKE_MAS0] & MAS0_ESEL_MASK) >> MAS0_ESEL_SHIFT;
2507 int ea = (env->spr[SPR_BOOKE_MAS2] & MAS2_EPN_MASK);
2508 int tlb;
2509
2510 tlb = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2511 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlb];
2512
2513 if ((tlbncfg & TLBnCFG_HES) && (env->spr[SPR_BOOKE_MAS0] & MAS0_HES)) {
2514 cpu_abort(env, "we don't support HES yet\n");
2515 }
2516
2517 return booke206_get_tlbm(env, tlb, ea, esel);
2518 }
2519
2520 void helper_booke_setpid(CPUPPCState *env, uint32_t pidn, target_ulong pid)
2521 {
2522 env->spr[pidn] = pid;
2523 /* changing PIDs mean we're in a different address space now */
2524 tlb_flush(env, 1);
2525 }
2526
2527 void helper_booke206_tlbwe(CPUPPCState *env)
2528 {
2529 uint32_t tlbncfg, tlbn;
2530 ppcmas_tlb_t *tlb;
2531 uint32_t size_tlb, size_ps;
2532 target_ulong mask;
2533
2534
2535 switch (env->spr[SPR_BOOKE_MAS0] & MAS0_WQ_MASK) {
2536 case MAS0_WQ_ALWAYS:
2537 /* good to go, write that entry */
2538 break;
2539 case MAS0_WQ_COND:
2540 /* XXX check if reserved */
2541 if (0) {
2542 return;
2543 }
2544 break;
2545 case MAS0_WQ_CLR_RSRV:
2546 /* XXX clear entry */
2547 return;
2548 default:
2549 /* no idea what to do */
2550 return;
2551 }
2552
2553 if (((env->spr[SPR_BOOKE_MAS0] & MAS0_ATSEL) == MAS0_ATSEL_LRAT) &&
2554 !msr_gs) {
2555 /* XXX we don't support direct LRAT setting yet */
2556 fprintf(stderr, "cpu: don't support LRAT setting yet\n");
2557 return;
2558 }
2559
2560 tlbn = (env->spr[SPR_BOOKE_MAS0] & MAS0_TLBSEL_MASK) >> MAS0_TLBSEL_SHIFT;
2561 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
2562
2563 tlb = booke206_cur_tlb(env);
2564
2565 if (!tlb) {
2566 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2567 POWERPC_EXCP_INVAL |
2568 POWERPC_EXCP_INVAL_INVAL);
2569 }
2570
2571 /* check that we support the targeted size */
2572 size_tlb = (env->spr[SPR_BOOKE_MAS1] & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
2573 size_ps = booke206_tlbnps(env, tlbn);
2574 if ((env->spr[SPR_BOOKE_MAS1] & MAS1_VALID) && (tlbncfg & TLBnCFG_AVAIL) &&
2575 !(size_ps & (1 << size_tlb))) {
2576 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2577 POWERPC_EXCP_INVAL |
2578 POWERPC_EXCP_INVAL_INVAL);
2579 }
2580
2581 if (msr_gs) {
2582 cpu_abort(env, "missing HV implementation\n");
2583 }
2584 tlb->mas7_3 = ((uint64_t)env->spr[SPR_BOOKE_MAS7] << 32) |
2585 env->spr[SPR_BOOKE_MAS3];
2586 tlb->mas1 = env->spr[SPR_BOOKE_MAS1];
2587
2588 /* MAV 1.0 only */
2589 if (!(tlbncfg & TLBnCFG_AVAIL)) {
2590 /* force !AVAIL TLB entries to correct page size */
2591 tlb->mas1 &= ~MAS1_TSIZE_MASK;
2592 /* XXX can be configured in MMUCSR0 */
2593 tlb->mas1 |= (tlbncfg & TLBnCFG_MINSIZE) >> 12;
2594 }
2595
2596 /* Make a mask from TLB size to discard invalid bits in EPN field */
2597 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2598 /* Add a mask for page attributes */
2599 mask |= MAS2_ACM | MAS2_VLE | MAS2_W | MAS2_I | MAS2_M | MAS2_G | MAS2_E;
2600
2601 if (!msr_cm) {
2602 /* Executing a tlbwe instruction in 32-bit mode will set
2603 * bits 0:31 of the TLB EPN field to zero.
2604 */
2605 mask &= 0xffffffff;
2606 }
2607
2608 tlb->mas2 = env->spr[SPR_BOOKE_MAS2] & mask;
2609
2610 if (!(tlbncfg & TLBnCFG_IPROT)) {
2611 /* no IPROT supported by TLB */
2612 tlb->mas1 &= ~MAS1_IPROT;
2613 }
2614
2615 if (booke206_tlb_to_page_size(env, tlb) == TARGET_PAGE_SIZE) {
2616 tlb_flush_page(env, tlb->mas2 & MAS2_EPN_MASK);
2617 } else {
2618 tlb_flush(env, 1);
2619 }
2620 }
2621
2622 static inline void booke206_tlb_to_mas(CPUPPCState *env, ppcmas_tlb_t *tlb)
2623 {
2624 int tlbn = booke206_tlbm_to_tlbn(env, tlb);
2625 int way = booke206_tlbm_to_way(env, tlb);
2626
2627 env->spr[SPR_BOOKE_MAS0] = tlbn << MAS0_TLBSEL_SHIFT;
2628 env->spr[SPR_BOOKE_MAS0] |= way << MAS0_ESEL_SHIFT;
2629 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2630
2631 env->spr[SPR_BOOKE_MAS1] = tlb->mas1;
2632 env->spr[SPR_BOOKE_MAS2] = tlb->mas2;
2633 env->spr[SPR_BOOKE_MAS3] = tlb->mas7_3;
2634 env->spr[SPR_BOOKE_MAS7] = tlb->mas7_3 >> 32;
2635 }
2636
2637 void helper_booke206_tlbre(CPUPPCState *env)
2638 {
2639 ppcmas_tlb_t *tlb = NULL;
2640
2641 tlb = booke206_cur_tlb(env);
2642 if (!tlb) {
2643 env->spr[SPR_BOOKE_MAS1] = 0;
2644 } else {
2645 booke206_tlb_to_mas(env, tlb);
2646 }
2647 }
2648
2649 void helper_booke206_tlbsx(CPUPPCState *env, target_ulong address)
2650 {
2651 ppcmas_tlb_t *tlb = NULL;
2652 int i, j;
2653 hwaddr raddr;
2654 uint32_t spid, sas;
2655
2656 spid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID_MASK) >> MAS6_SPID_SHIFT;
2657 sas = env->spr[SPR_BOOKE_MAS6] & MAS6_SAS;
2658
2659 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2660 int ways = booke206_tlb_ways(env, i);
2661
2662 for (j = 0; j < ways; j++) {
2663 tlb = booke206_get_tlbm(env, i, address, j);
2664
2665 if (!tlb) {
2666 continue;
2667 }
2668
2669 if (ppcmas_tlb_check(env, tlb, &raddr, address, spid)) {
2670 continue;
2671 }
2672
2673 if (sas != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
2674 continue;
2675 }
2676
2677 booke206_tlb_to_mas(env, tlb);
2678 return;
2679 }
2680 }
2681
2682 /* no entry found, fill with defaults */
2683 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
2684 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
2685 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
2686 env->spr[SPR_BOOKE_MAS3] = 0;
2687 env->spr[SPR_BOOKE_MAS7] = 0;
2688
2689 if (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) {
2690 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
2691 }
2692
2693 env->spr[SPR_BOOKE_MAS1] |= (env->spr[SPR_BOOKE_MAS6] >> 16)
2694 << MAS1_TID_SHIFT;
2695
2696 /* next victim logic */
2697 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
2698 env->last_way++;
2699 env->last_way &= booke206_tlb_ways(env, 0) - 1;
2700 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
2701 }
2702
2703 static inline void booke206_invalidate_ea_tlb(CPUPPCState *env, int tlbn,
2704 uint32_t ea)
2705 {
2706 int i;
2707 int ways = booke206_tlb_ways(env, tlbn);
2708 target_ulong mask;
2709
2710 for (i = 0; i < ways; i++) {
2711 ppcmas_tlb_t *tlb = booke206_get_tlbm(env, tlbn, ea, i);
2712 if (!tlb) {
2713 continue;
2714 }
2715 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
2716 if (((tlb->mas2 & MAS2_EPN_MASK) == (ea & mask)) &&
2717 !(tlb->mas1 & MAS1_IPROT)) {
2718 tlb->mas1 &= ~MAS1_VALID;
2719 }
2720 }
2721 }
2722
2723 void helper_booke206_tlbivax(CPUPPCState *env, target_ulong address)
2724 {
2725 if (address & 0x4) {
2726 /* flush all entries */
2727 if (address & 0x8) {
2728 /* flush all of TLB1 */
2729 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB1, 1);
2730 } else {
2731 /* flush all of TLB0 */
2732 booke206_flush_tlb(env, BOOKE206_FLUSH_TLB0, 0);
2733 }
2734 return;
2735 }
2736
2737 if (address & 0x8) {
2738 /* flush TLB1 entries */
2739 booke206_invalidate_ea_tlb(env, 1, address);
2740 tlb_flush(env, 1);
2741 } else {
2742 /* flush TLB0 entries */
2743 booke206_invalidate_ea_tlb(env, 0, address);
2744 tlb_flush_page(env, address & MAS2_EPN_MASK);
2745 }
2746 }
2747
2748 void helper_booke206_tlbilx0(CPUPPCState *env, target_ulong address)
2749 {
2750 /* XXX missing LPID handling */
2751 booke206_flush_tlb(env, -1, 1);
2752 }
2753
2754 void helper_booke206_tlbilx1(CPUPPCState *env, target_ulong address)
2755 {
2756 int i, j;
2757 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2758 ppcmas_tlb_t *tlb = env->tlb.tlbm;
2759 int tlb_size;
2760
2761 /* XXX missing LPID handling */
2762 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2763 tlb_size = booke206_tlb_size(env, i);
2764 for (j = 0; j < tlb_size; j++) {
2765 if (!(tlb[j].mas1 & MAS1_IPROT) &&
2766 ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
2767 tlb[j].mas1 &= ~MAS1_VALID;
2768 }
2769 }
2770 tlb += booke206_tlb_size(env, i);
2771 }
2772 tlb_flush(env, 1);
2773 }
2774
2775 void helper_booke206_tlbilx3(CPUPPCState *env, target_ulong address)
2776 {
2777 int i, j;
2778 ppcmas_tlb_t *tlb;
2779 int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
2780 int pid = tid >> MAS6_SPID_SHIFT;
2781 int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
2782 int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
2783 /* XXX check for unsupported isize and raise an invalid opcode then */
2784 int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
2785 /* XXX implement MAV2 handling */
2786 bool mav2 = false;
2787
2788 /* XXX missing LPID handling */
2789 /* flush by pid and ea */
2790 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
2791 int ways = booke206_tlb_ways(env, i);
2792
2793 for (j = 0; j < ways; j++) {
2794 tlb = booke206_get_tlbm(env, i, address, j);
2795 if (!tlb) {
2796 continue;
2797 }
2798 if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
2799 (tlb->mas1 & MAS1_IPROT) ||
2800 ((tlb->mas1 & MAS1_IND) != ind) ||
2801 ((tlb->mas8 & MAS8_TGS) != sgs)) {
2802 continue;
2803 }
2804 if (mav2 && ((tlb->mas1 & MAS1_TSIZE_MASK) != size)) {
2805 /* XXX only check when MMUCFG[TWC] || TLBnCFG[HES] */
2806 continue;
2807 }
2808 /* XXX e500mc doesn't match SAS, but other cores might */
2809 tlb->mas1 &= ~MAS1_VALID;
2810 }
2811 }
2812 tlb_flush(env, 1);
2813 }
2814
2815 void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type)
2816 {
2817 int flags = 0;
2818
2819 if (type & 2) {
2820 flags |= BOOKE206_FLUSH_TLB1;
2821 }
2822
2823 if (type & 4) {
2824 flags |= BOOKE206_FLUSH_TLB0;
2825 }
2826
2827 booke206_flush_tlb(env, flags, 1);
2828 }
2829 #endif