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