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