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