Fix regression introduced by -machine accel=
[qemu.git] / target-ppc / helper.c
blob47006329319fff9e0b32e2abcda96797bf2035c8
1 /*
2 * PowerPC emulation helpers for qemu.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24 #include <signal.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "helper_regs.h"
29 #include "qemu-common.h"
30 #include "kvm.h"
32 //#define DEBUG_MMU
33 //#define DEBUG_BATS
34 //#define DEBUG_SLB
35 //#define DEBUG_SOFTWARE_TLB
36 //#define DUMP_PAGE_TABLES
37 //#define DEBUG_EXCEPTIONS
38 //#define FLUSH_ALL_TLBS
40 #ifdef DEBUG_MMU
41 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
42 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
43 #else
44 # define LOG_MMU(...) do { } while (0)
45 # define LOG_MMU_STATE(...) do { } while (0)
46 #endif
49 #ifdef DEBUG_SOFTWARE_TLB
50 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
51 #else
52 # define LOG_SWTLB(...) do { } while (0)
53 #endif
55 #ifdef DEBUG_BATS
56 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
57 #else
58 # define LOG_BATS(...) do { } while (0)
59 #endif
61 #ifdef DEBUG_SLB
62 # define LOG_SLB(...) qemu_log(__VA_ARGS__)
63 #else
64 # define LOG_SLB(...) do { } while (0)
65 #endif
67 #ifdef DEBUG_EXCEPTIONS
68 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
69 #else
70 # define LOG_EXCP(...) do { } while (0)
71 #endif
73 /*****************************************************************************/
74 /* PowerPC Hypercall emulation */
76 void (*cpu_ppc_hypercall)(CPUState *);
78 /*****************************************************************************/
79 /* PowerPC MMU emulation */
81 #if defined(CONFIG_USER_ONLY)
82 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
83 int mmu_idx, int is_softmmu)
85 int exception, error_code;
87 if (rw == 2) {
88 exception = POWERPC_EXCP_ISI;
89 error_code = 0x40000000;
90 } else {
91 exception = POWERPC_EXCP_DSI;
92 error_code = 0x40000000;
93 if (rw)
94 error_code |= 0x02000000;
95 env->spr[SPR_DAR] = address;
96 env->spr[SPR_DSISR] = error_code;
98 env->exception_index = exception;
99 env->error_code = error_code;
101 return 1;
104 #else
105 /* Common routines used by software and hardware TLBs emulation */
106 static inline int pte_is_valid(target_ulong pte0)
108 return pte0 & 0x80000000 ? 1 : 0;
111 static inline void pte_invalidate(target_ulong *pte0)
113 *pte0 &= ~0x80000000;
116 #if defined(TARGET_PPC64)
117 static inline int pte64_is_valid(target_ulong pte0)
119 return pte0 & 0x0000000000000001ULL ? 1 : 0;
122 static inline void pte64_invalidate(target_ulong *pte0)
124 *pte0 &= ~0x0000000000000001ULL;
126 #endif
128 #define PTE_PTEM_MASK 0x7FFFFFBF
129 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
130 #if defined(TARGET_PPC64)
131 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
132 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
133 #endif
135 static inline int pp_check(int key, int pp, int nx)
137 int access;
139 /* Compute access rights */
140 /* When pp is 3/7, the result is undefined. Set it to noaccess */
141 access = 0;
142 if (key == 0) {
143 switch (pp) {
144 case 0x0:
145 case 0x1:
146 case 0x2:
147 access |= PAGE_WRITE;
148 /* No break here */
149 case 0x3:
150 case 0x6:
151 access |= PAGE_READ;
152 break;
154 } else {
155 switch (pp) {
156 case 0x0:
157 case 0x6:
158 access = 0;
159 break;
160 case 0x1:
161 case 0x3:
162 access = PAGE_READ;
163 break;
164 case 0x2:
165 access = PAGE_READ | PAGE_WRITE;
166 break;
169 if (nx == 0)
170 access |= PAGE_EXEC;
172 return access;
175 static inline int check_prot(int prot, int rw, int access_type)
177 int ret;
179 if (access_type == ACCESS_CODE) {
180 if (prot & PAGE_EXEC)
181 ret = 0;
182 else
183 ret = -2;
184 } else if (rw) {
185 if (prot & PAGE_WRITE)
186 ret = 0;
187 else
188 ret = -2;
189 } else {
190 if (prot & PAGE_READ)
191 ret = 0;
192 else
193 ret = -2;
196 return ret;
199 static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
200 target_ulong pte1, int h, int rw, int type)
202 target_ulong ptem, mmask;
203 int access, ret, pteh, ptev, pp;
205 ret = -1;
206 /* Check validity and table match */
207 #if defined(TARGET_PPC64)
208 if (is_64b) {
209 ptev = pte64_is_valid(pte0);
210 pteh = (pte0 >> 1) & 1;
211 } else
212 #endif
214 ptev = pte_is_valid(pte0);
215 pteh = (pte0 >> 6) & 1;
217 if (ptev && h == pteh) {
218 /* Check vsid & api */
219 #if defined(TARGET_PPC64)
220 if (is_64b) {
221 ptem = pte0 & PTE64_PTEM_MASK;
222 mmask = PTE64_CHECK_MASK;
223 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
224 ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
225 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
226 } else
227 #endif
229 ptem = pte0 & PTE_PTEM_MASK;
230 mmask = PTE_CHECK_MASK;
231 pp = pte1 & 0x00000003;
233 if (ptem == ctx->ptem) {
234 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
235 /* all matches should have equal RPN, WIMG & PP */
236 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
237 qemu_log("Bad RPN/WIMG/PP\n");
238 return -3;
241 /* Compute access rights */
242 access = pp_check(ctx->key, pp, ctx->nx);
243 /* Keep the matching PTE informations */
244 ctx->raddr = pte1;
245 ctx->prot = access;
246 ret = check_prot(ctx->prot, rw, type);
247 if (ret == 0) {
248 /* Access granted */
249 LOG_MMU("PTE access granted !\n");
250 } else {
251 /* Access right violation */
252 LOG_MMU("PTE access rejected\n");
257 return ret;
260 static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
261 target_ulong pte1, int h, int rw, int type)
263 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
266 #if defined(TARGET_PPC64)
267 static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
268 target_ulong pte1, int h, int rw, int type)
270 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
272 #endif
274 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
275 int ret, int rw)
277 int store = 0;
279 /* Update page flags */
280 if (!(*pte1p & 0x00000100)) {
281 /* Update accessed flag */
282 *pte1p |= 0x00000100;
283 store = 1;
285 if (!(*pte1p & 0x00000080)) {
286 if (rw == 1 && ret == 0) {
287 /* Update changed flag */
288 *pte1p |= 0x00000080;
289 store = 1;
290 } else {
291 /* Force page fault for first write access */
292 ctx->prot &= ~PAGE_WRITE;
296 return store;
299 /* Software driven TLB helpers */
300 static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
301 int is_code)
303 int nr;
305 /* Select TLB num in a way from address */
306 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
307 /* Select TLB way */
308 nr += env->tlb_per_way * way;
309 /* 6xx have separate TLBs for instructions and data */
310 if (is_code && env->id_tlbs == 1)
311 nr += env->nb_tlb;
313 return nr;
316 static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
318 ppc6xx_tlb_t *tlb;
319 int nr, max;
321 //LOG_SWTLB("Invalidate all TLBs\n");
322 /* Invalidate all defined software TLB */
323 max = env->nb_tlb;
324 if (env->id_tlbs == 1)
325 max *= 2;
326 for (nr = 0; nr < max; nr++) {
327 tlb = &env->tlb[nr].tlb6;
328 pte_invalidate(&tlb->pte0);
330 tlb_flush(env, 1);
333 static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
334 target_ulong eaddr,
335 int is_code, int match_epn)
337 #if !defined(FLUSH_ALL_TLBS)
338 ppc6xx_tlb_t *tlb;
339 int way, nr;
341 /* Invalidate ITLB + DTLB, all ways */
342 for (way = 0; way < env->nb_ways; way++) {
343 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
344 tlb = &env->tlb[nr].tlb6;
345 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
346 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
347 env->nb_tlb, eaddr);
348 pte_invalidate(&tlb->pte0);
349 tlb_flush_page(env, tlb->EPN);
352 #else
353 /* XXX: PowerPC specification say this is valid as well */
354 ppc6xx_tlb_invalidate_all(env);
355 #endif
358 static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
359 target_ulong eaddr, int is_code)
361 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
364 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
365 target_ulong pte0, target_ulong pte1)
367 ppc6xx_tlb_t *tlb;
368 int nr;
370 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
371 tlb = &env->tlb[nr].tlb6;
372 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
373 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
374 /* Invalidate any pending reference in Qemu for this virtual address */
375 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
376 tlb->pte0 = pte0;
377 tlb->pte1 = pte1;
378 tlb->EPN = EPN;
379 /* Store last way for LRU mechanism */
380 env->last_way = way;
383 static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
384 target_ulong eaddr, int rw, int access_type)
386 ppc6xx_tlb_t *tlb;
387 int nr, best, way;
388 int ret;
390 best = -1;
391 ret = -1; /* No TLB found */
392 for (way = 0; way < env->nb_ways; way++) {
393 nr = ppc6xx_tlb_getnum(env, eaddr, way,
394 access_type == ACCESS_CODE ? 1 : 0);
395 tlb = &env->tlb[nr].tlb6;
396 /* This test "emulates" the PTE index match for hardware TLBs */
397 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
398 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
399 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
400 pte_is_valid(tlb->pte0) ? "valid" : "inval",
401 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
402 continue;
404 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
405 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
406 pte_is_valid(tlb->pte0) ? "valid" : "inval",
407 tlb->EPN, eaddr, tlb->pte1,
408 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
409 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
410 case -3:
411 /* TLB inconsistency */
412 return -1;
413 case -2:
414 /* Access violation */
415 ret = -2;
416 best = nr;
417 break;
418 case -1:
419 default:
420 /* No match */
421 break;
422 case 0:
423 /* access granted */
424 /* XXX: we should go on looping to check all TLBs consistency
425 * but we can speed-up the whole thing as the
426 * result would be undefined if TLBs are not consistent.
428 ret = 0;
429 best = nr;
430 goto done;
433 if (best != -1) {
434 done:
435 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
436 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
437 /* Update page flags */
438 pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
441 return ret;
444 /* Perform BAT hit & translation */
445 static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
446 int *protp, target_ulong *BATu,
447 target_ulong *BATl)
449 target_ulong bl;
450 int pp, valid, prot;
452 bl = (*BATu & 0x00001FFC) << 15;
453 valid = 0;
454 prot = 0;
455 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
456 ((msr_pr != 0) && (*BATu & 0x00000001))) {
457 valid = 1;
458 pp = *BATl & 0x00000003;
459 if (pp != 0) {
460 prot = PAGE_READ | PAGE_EXEC;
461 if (pp == 0x2)
462 prot |= PAGE_WRITE;
465 *blp = bl;
466 *validp = valid;
467 *protp = prot;
470 static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
471 int *validp, int *protp,
472 target_ulong *BATu, target_ulong *BATl)
474 target_ulong bl;
475 int key, pp, valid, prot;
477 bl = (*BATl & 0x0000003F) << 17;
478 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
479 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
480 prot = 0;
481 valid = (*BATl >> 6) & 1;
482 if (valid) {
483 pp = *BATu & 0x00000003;
484 if (msr_pr == 0)
485 key = (*BATu >> 3) & 1;
486 else
487 key = (*BATu >> 2) & 1;
488 prot = pp_check(key, pp, 0);
490 *blp = bl;
491 *validp = valid;
492 *protp = prot;
495 static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
496 int rw, int type)
498 target_ulong *BATlt, *BATut, *BATu, *BATl;
499 target_ulong BEPIl, BEPIu, bl;
500 int i, valid, prot;
501 int ret = -1;
503 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
504 type == ACCESS_CODE ? 'I' : 'D', virtual);
505 switch (type) {
506 case ACCESS_CODE:
507 BATlt = env->IBAT[1];
508 BATut = env->IBAT[0];
509 break;
510 default:
511 BATlt = env->DBAT[1];
512 BATut = env->DBAT[0];
513 break;
515 for (i = 0; i < env->nb_BATs; i++) {
516 BATu = &BATut[i];
517 BATl = &BATlt[i];
518 BEPIu = *BATu & 0xF0000000;
519 BEPIl = *BATu & 0x0FFE0000;
520 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
521 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
522 } else {
523 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
525 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
526 " BATl " TARGET_FMT_lx "\n", __func__,
527 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
528 if ((virtual & 0xF0000000) == BEPIu &&
529 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
530 /* BAT matches */
531 if (valid != 0) {
532 /* Get physical address */
533 ctx->raddr = (*BATl & 0xF0000000) |
534 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
535 (virtual & 0x0001F000);
536 /* Compute access rights */
537 ctx->prot = prot;
538 ret = check_prot(ctx->prot, rw, type);
539 if (ret == 0)
540 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
541 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
542 ctx->prot & PAGE_WRITE ? 'W' : '-');
543 break;
547 if (ret < 0) {
548 #if defined(DEBUG_BATS)
549 if (qemu_log_enabled()) {
550 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
551 for (i = 0; i < 4; i++) {
552 BATu = &BATut[i];
553 BATl = &BATlt[i];
554 BEPIu = *BATu & 0xF0000000;
555 BEPIl = *BATu & 0x0FFE0000;
556 bl = (*BATu & 0x00001FFC) << 15;
557 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
558 " BATl " TARGET_FMT_lx " \n\t" TARGET_FMT_lx " "
559 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
560 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
561 *BATu, *BATl, BEPIu, BEPIl, bl);
564 #endif
566 /* No hit */
567 return ret;
570 static inline target_phys_addr_t get_pteg_offset(CPUState *env,
571 target_phys_addr_t hash,
572 int pte_size)
574 return (hash * pte_size * 8) & env->htab_mask;
577 /* PTE table lookup */
578 static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
579 int rw, int type, int target_page_bits)
581 target_phys_addr_t pteg_off;
582 target_ulong pte0, pte1;
583 int i, good = -1;
584 int ret, r;
586 ret = -1; /* No entry found */
587 pteg_off = get_pteg_offset(env, ctx->hash[h],
588 is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
589 for (i = 0; i < 8; i++) {
590 #if defined(TARGET_PPC64)
591 if (is_64b) {
592 if (env->external_htab) {
593 pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
594 pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
595 } else {
596 pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
597 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
600 /* We have a TLB that saves 4K pages, so let's
601 * split a huge page to 4k chunks */
602 if (target_page_bits != TARGET_PAGE_BITS)
603 pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
604 & TARGET_PAGE_MASK;
606 r = pte64_check(ctx, pte0, pte1, h, rw, type);
607 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
608 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
609 pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
610 (int)((pte0 >> 1) & 1), ctx->ptem);
611 } else
612 #endif
614 if (env->external_htab) {
615 pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
616 pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
617 } else {
618 pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
619 pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
621 r = pte32_check(ctx, pte0, pte1, h, rw, type);
622 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
623 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
624 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
625 (int)((pte0 >> 6) & 1), ctx->ptem);
627 switch (r) {
628 case -3:
629 /* PTE inconsistency */
630 return -1;
631 case -2:
632 /* Access violation */
633 ret = -2;
634 good = i;
635 break;
636 case -1:
637 default:
638 /* No PTE match */
639 break;
640 case 0:
641 /* access granted */
642 /* XXX: we should go on looping to check all PTEs consistency
643 * but if we can speed-up the whole thing as the
644 * result would be undefined if PTEs are not consistent.
646 ret = 0;
647 good = i;
648 goto done;
651 if (good != -1) {
652 done:
653 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
654 ctx->raddr, ctx->prot, ret);
655 /* Update page flags */
656 pte1 = ctx->raddr;
657 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
658 #if defined(TARGET_PPC64)
659 if (is_64b) {
660 if (env->external_htab) {
661 stq_p(env->external_htab + pteg_off + (good * 16) + 8,
662 pte1);
663 } else {
664 stq_phys_notdirty(env->htab_base + pteg_off +
665 (good * 16) + 8, pte1);
667 } else
668 #endif
670 if (env->external_htab) {
671 stl_p(env->external_htab + pteg_off + (good * 8) + 4,
672 pte1);
673 } else {
674 stl_phys_notdirty(env->htab_base + pteg_off +
675 (good * 8) + 4, pte1);
681 return ret;
684 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
685 int type, int target_page_bits)
687 #if defined(TARGET_PPC64)
688 if (env->mmu_model & POWERPC_MMU_64)
689 return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
690 #endif
692 return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
695 #if defined(TARGET_PPC64)
696 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
698 uint64_t esid_256M, esid_1T;
699 int n;
701 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
703 esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
704 esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
706 for (n = 0; n < env->slb_nr; n++) {
707 ppc_slb_t *slb = &env->slb[n];
709 LOG_SLB("%s: slot %d %016" PRIx64 " %016"
710 PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
711 /* We check for 1T matches on all MMUs here - if the MMU
712 * doesn't have 1T segment support, we will have prevented 1T
713 * entries from being inserted in the slbmte code. */
714 if (((slb->esid == esid_256M) &&
715 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
716 || ((slb->esid == esid_1T) &&
717 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
718 return slb;
722 return NULL;
725 void ppc_slb_invalidate_all (CPUPPCState *env)
727 int n, do_invalidate;
729 do_invalidate = 0;
730 /* XXX: Warning: slbia never invalidates the first segment */
731 for (n = 1; n < env->slb_nr; n++) {
732 ppc_slb_t *slb = &env->slb[n];
734 if (slb->esid & SLB_ESID_V) {
735 slb->esid &= ~SLB_ESID_V;
736 /* XXX: given the fact that segment size is 256 MB or 1TB,
737 * and we still don't have a tlb_flush_mask(env, n, mask)
738 * in Qemu, we just invalidate all TLBs
740 do_invalidate = 1;
743 if (do_invalidate)
744 tlb_flush(env, 1);
747 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
749 ppc_slb_t *slb;
751 slb = slb_lookup(env, T0);
752 if (!slb) {
753 return;
756 if (slb->esid & SLB_ESID_V) {
757 slb->esid &= ~SLB_ESID_V;
759 /* XXX: given the fact that segment size is 256 MB or 1TB,
760 * and we still don't have a tlb_flush_mask(env, n, mask)
761 * in Qemu, we just invalidate all TLBs
763 tlb_flush(env, 1);
767 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
769 int slot = rb & 0xfff;
770 ppc_slb_t *slb = &env->slb[slot];
772 if (rb & (0x1000 - env->slb_nr)) {
773 return -1; /* Reserved bits set or slot too high */
775 if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
776 return -1; /* Bad segment size */
778 if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
779 return -1; /* 1T segment on MMU that doesn't support it */
782 /* Mask out the slot number as we store the entry */
783 slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
784 slb->vsid = rs;
786 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
787 " %016" PRIx64 "\n", __func__, slot, rb, rs,
788 slb->esid, slb->vsid);
790 return 0;
793 int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
795 int slot = rb & 0xfff;
796 ppc_slb_t *slb = &env->slb[slot];
798 if (slot >= env->slb_nr) {
799 return -1;
802 *rt = slb->esid;
803 return 0;
806 int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
808 int slot = rb & 0xfff;
809 ppc_slb_t *slb = &env->slb[slot];
811 if (slot >= env->slb_nr) {
812 return -1;
815 *rt = slb->vsid;
816 return 0;
818 #endif /* defined(TARGET_PPC64) */
820 /* Perform segment based translation */
821 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
822 target_ulong eaddr, int rw, int type)
824 target_phys_addr_t hash;
825 target_ulong vsid;
826 int ds, pr, target_page_bits;
827 int ret, ret2;
829 pr = msr_pr;
830 ctx->eaddr = eaddr;
831 #if defined(TARGET_PPC64)
832 if (env->mmu_model & POWERPC_MMU_64) {
833 ppc_slb_t *slb;
834 target_ulong pageaddr;
835 int segment_bits;
837 LOG_MMU("Check SLBs\n");
838 slb = slb_lookup(env, eaddr);
839 if (!slb) {
840 return -5;
843 if (slb->vsid & SLB_VSID_B) {
844 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
845 segment_bits = 40;
846 } else {
847 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
848 segment_bits = 28;
851 target_page_bits = (slb->vsid & SLB_VSID_L)
852 ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
853 ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
854 : (slb->vsid & SLB_VSID_KS));
855 ds = 0;
856 ctx->nx = !!(slb->vsid & SLB_VSID_N);
858 pageaddr = eaddr & ((1ULL << segment_bits)
859 - (1ULL << target_page_bits));
860 if (slb->vsid & SLB_VSID_B) {
861 hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
862 } else {
863 hash = vsid ^ (pageaddr >> target_page_bits);
865 /* Only 5 bits of the page index are used in the AVPN */
866 ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
867 ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
868 } else
869 #endif /* defined(TARGET_PPC64) */
871 target_ulong sr, pgidx;
873 sr = env->sr[eaddr >> 28];
874 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
875 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
876 ds = sr & 0x80000000 ? 1 : 0;
877 ctx->nx = sr & 0x10000000 ? 1 : 0;
878 vsid = sr & 0x00FFFFFF;
879 target_page_bits = TARGET_PAGE_BITS;
880 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
881 TARGET_FMT_lx " lr=" TARGET_FMT_lx
882 " ir=%d dr=%d pr=%d %d t=%d\n",
883 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
884 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
885 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
886 hash = vsid ^ pgidx;
887 ctx->ptem = (vsid << 7) | (pgidx >> 10);
889 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
890 ctx->key, ds, ctx->nx, vsid);
891 ret = -1;
892 if (!ds) {
893 /* Check if instruction fetch is allowed, if needed */
894 if (type != ACCESS_CODE || ctx->nx == 0) {
895 /* Page address translation */
896 LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
897 " hash " TARGET_FMT_plx "\n",
898 env->htab_base, env->htab_mask, hash);
899 ctx->hash[0] = hash;
900 ctx->hash[1] = ~hash;
902 /* Initialize real address with an invalid value */
903 ctx->raddr = (target_phys_addr_t)-1ULL;
904 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
905 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
906 /* Software TLB search */
907 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
908 } else {
909 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
910 " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
911 " hash=" TARGET_FMT_plx "\n",
912 env->htab_base, env->htab_mask, vsid, ctx->ptem,
913 ctx->hash[0]);
914 /* Primary table lookup */
915 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
916 if (ret < 0) {
917 /* Secondary table lookup */
918 if (eaddr != 0xEFFFFFFF)
919 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
920 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
921 " hash=" TARGET_FMT_plx "\n", env->htab_base,
922 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
923 ret2 = find_pte(env, ctx, 1, rw, type,
924 target_page_bits);
925 if (ret2 != -1)
926 ret = ret2;
929 #if defined (DUMP_PAGE_TABLES)
930 if (qemu_log_enabled()) {
931 target_phys_addr_t curaddr;
932 uint32_t a0, a1, a2, a3;
933 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
934 "\n", sdr, mask + 0x80);
935 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
936 curaddr += 16) {
937 a0 = ldl_phys(curaddr);
938 a1 = ldl_phys(curaddr + 4);
939 a2 = ldl_phys(curaddr + 8);
940 a3 = ldl_phys(curaddr + 12);
941 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
942 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
943 curaddr, a0, a1, a2, a3);
947 #endif
948 } else {
949 LOG_MMU("No access allowed\n");
950 ret = -3;
952 } else {
953 LOG_MMU("direct store...\n");
954 /* Direct-store segment : absolutely *BUGGY* for now */
955 switch (type) {
956 case ACCESS_INT:
957 /* Integer load/store : only access allowed */
958 break;
959 case ACCESS_CODE:
960 /* No code fetch is allowed in direct-store areas */
961 return -4;
962 case ACCESS_FLOAT:
963 /* Floating point load/store */
964 return -4;
965 case ACCESS_RES:
966 /* lwarx, ldarx or srwcx. */
967 return -4;
968 case ACCESS_CACHE:
969 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
970 /* Should make the instruction do no-op.
971 * As it already do no-op, it's quite easy :-)
973 ctx->raddr = eaddr;
974 return 0;
975 case ACCESS_EXT:
976 /* eciwx or ecowx */
977 return -4;
978 default:
979 qemu_log("ERROR: instruction should not need "
980 "address translation\n");
981 return -4;
983 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
984 ctx->raddr = eaddr;
985 ret = 2;
986 } else {
987 ret = -2;
991 return ret;
994 /* Generic TLB check function for embedded PowerPC implementations */
995 int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
996 target_phys_addr_t *raddrp,
997 target_ulong address, uint32_t pid, int ext,
998 int i)
1000 target_ulong mask;
1002 /* Check valid flag */
1003 if (!(tlb->prot & PAGE_VALID)) {
1004 return -1;
1006 mask = ~(tlb->size - 1);
1007 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1008 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1009 mask, (uint32_t)tlb->PID, tlb->prot);
1010 /* Check PID */
1011 if (tlb->PID != 0 && tlb->PID != pid)
1012 return -1;
1013 /* Check effective address */
1014 if ((address & mask) != tlb->EPN)
1015 return -1;
1016 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1017 #if (TARGET_PHYS_ADDR_BITS >= 36)
1018 if (ext) {
1019 /* Extend the physical address to 36 bits */
1020 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1022 #endif
1024 return 0;
1027 /* Generic TLB search function for PowerPC embedded implementations */
1028 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1030 ppcemb_tlb_t *tlb;
1031 target_phys_addr_t raddr;
1032 int i, ret;
1034 /* Default return value is no match */
1035 ret = -1;
1036 for (i = 0; i < env->nb_tlb; i++) {
1037 tlb = &env->tlb[i].tlbe;
1038 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1039 ret = i;
1040 break;
1044 return ret;
1047 /* Helpers specific to PowerPC 40x implementations */
1048 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1050 ppcemb_tlb_t *tlb;
1051 int i;
1053 for (i = 0; i < env->nb_tlb; i++) {
1054 tlb = &env->tlb[i].tlbe;
1055 tlb->prot &= ~PAGE_VALID;
1057 tlb_flush(env, 1);
1060 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1061 target_ulong eaddr, uint32_t pid)
1063 #if !defined(FLUSH_ALL_TLBS)
1064 ppcemb_tlb_t *tlb;
1065 target_phys_addr_t raddr;
1066 target_ulong page, end;
1067 int i;
1069 for (i = 0; i < env->nb_tlb; i++) {
1070 tlb = &env->tlb[i].tlbe;
1071 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1072 end = tlb->EPN + tlb->size;
1073 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1074 tlb_flush_page(env, page);
1075 tlb->prot &= ~PAGE_VALID;
1076 break;
1079 #else
1080 ppc4xx_tlb_invalidate_all(env);
1081 #endif
1084 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1085 target_ulong address, int rw, int access_type)
1087 ppcemb_tlb_t *tlb;
1088 target_phys_addr_t raddr;
1089 int i, ret, zsel, zpr, pr;
1091 ret = -1;
1092 raddr = (target_phys_addr_t)-1ULL;
1093 pr = msr_pr;
1094 for (i = 0; i < env->nb_tlb; i++) {
1095 tlb = &env->tlb[i].tlbe;
1096 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1097 env->spr[SPR_40x_PID], 0, i) < 0)
1098 continue;
1099 zsel = (tlb->attr >> 4) & 0xF;
1100 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1101 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1102 __func__, i, zsel, zpr, rw, tlb->attr);
1103 /* Check execute enable bit */
1104 switch (zpr) {
1105 case 0x2:
1106 if (pr != 0)
1107 goto check_perms;
1108 /* No break here */
1109 case 0x3:
1110 /* All accesses granted */
1111 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1112 ret = 0;
1113 break;
1114 case 0x0:
1115 if (pr != 0) {
1116 /* Raise Zone protection fault. */
1117 env->spr[SPR_40x_ESR] = 1 << 22;
1118 ctx->prot = 0;
1119 ret = -2;
1120 break;
1122 /* No break here */
1123 case 0x1:
1124 check_perms:
1125 /* Check from TLB entry */
1126 ctx->prot = tlb->prot;
1127 ret = check_prot(ctx->prot, rw, access_type);
1128 if (ret == -2)
1129 env->spr[SPR_40x_ESR] = 0;
1130 break;
1132 if (ret >= 0) {
1133 ctx->raddr = raddr;
1134 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1135 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1136 ret);
1137 return 0;
1140 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1141 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1143 return ret;
1146 void store_40x_sler (CPUPPCState *env, uint32_t val)
1148 /* XXX: TO BE FIXED */
1149 if (val != 0x00000000) {
1150 cpu_abort(env, "Little-endian regions are not supported by now\n");
1152 env->spr[SPR_405_SLER] = val;
1155 static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1156 target_phys_addr_t *raddr, int *prot,
1157 target_ulong address, int rw,
1158 int access_type, int i)
1160 int ret, _prot;
1162 if (ppcemb_tlb_check(env, tlb, raddr, address,
1163 env->spr[SPR_BOOKE_PID],
1164 !env->nb_pids, i) >= 0) {
1165 goto found_tlb;
1168 if (env->spr[SPR_BOOKE_PID1] &&
1169 ppcemb_tlb_check(env, tlb, raddr, address,
1170 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1171 goto found_tlb;
1174 if (env->spr[SPR_BOOKE_PID2] &&
1175 ppcemb_tlb_check(env, tlb, raddr, address,
1176 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1177 goto found_tlb;
1180 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1181 return -1;
1183 found_tlb:
1185 if (msr_pr != 0) {
1186 _prot = tlb->prot & 0xF;
1187 } else {
1188 _prot = (tlb->prot >> 4) & 0xF;
1191 /* Check the address space */
1192 if (access_type == ACCESS_CODE) {
1193 if (msr_ir != (tlb->attr & 1)) {
1194 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1195 return -1;
1198 *prot = _prot;
1199 if (_prot & PAGE_EXEC) {
1200 LOG_SWTLB("%s: good TLB!\n", __func__);
1201 return 0;
1204 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1205 ret = -3;
1206 } else {
1207 if (msr_dr != (tlb->attr & 1)) {
1208 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1209 return -1;
1212 *prot = _prot;
1213 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1214 LOG_SWTLB("%s: found TLB!\n", __func__);
1215 return 0;
1218 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1219 ret = -2;
1222 return ret;
1225 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1226 target_ulong address, int rw,
1227 int access_type)
1229 ppcemb_tlb_t *tlb;
1230 target_phys_addr_t raddr;
1231 int i, ret;
1233 ret = -1;
1234 raddr = (target_phys_addr_t)-1ULL;
1235 for (i = 0; i < env->nb_tlb; i++) {
1236 tlb = &env->tlb[i].tlbe;
1237 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1238 access_type, i);
1239 if (!ret) {
1240 break;
1244 if (ret >= 0) {
1245 ctx->raddr = raddr;
1246 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1247 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1248 ret);
1249 } else {
1250 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1251 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1254 return ret;
1257 void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1259 int tlb_size;
1260 int i, j;
1261 ppc_tlb_t *tlb = env->tlb;
1263 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1264 if (flags & (1 << i)) {
1265 tlb_size = booke206_tlb_size(env, i);
1266 for (j = 0; j < tlb_size; j++) {
1267 if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
1268 tlb[j].tlbe.prot = 0;
1272 tlb += booke206_tlb_size(env, i);
1275 tlb_flush(env, 1);
1278 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1279 target_ulong address, int rw,
1280 int access_type)
1282 ppcemb_tlb_t *tlb;
1283 target_phys_addr_t raddr;
1284 int i, j, ret;
1286 ret = -1;
1287 raddr = (target_phys_addr_t)-1ULL;
1289 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1290 int ways = booke206_tlb_ways(env, i);
1292 for (j = 0; j < ways; j++) {
1293 tlb = booke206_get_tlbe(env, i, address, j);
1294 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1295 access_type, j);
1296 if (ret != -1) {
1297 goto found_tlb;
1302 found_tlb:
1304 if (ret >= 0) {
1305 ctx->raddr = raddr;
1306 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1307 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1308 ret);
1309 } else {
1310 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1311 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1314 return ret;
1317 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1318 target_ulong eaddr, int rw)
1320 int in_plb, ret;
1322 ctx->raddr = eaddr;
1323 ctx->prot = PAGE_READ | PAGE_EXEC;
1324 ret = 0;
1325 switch (env->mmu_model) {
1326 case POWERPC_MMU_32B:
1327 case POWERPC_MMU_601:
1328 case POWERPC_MMU_SOFT_6xx:
1329 case POWERPC_MMU_SOFT_74xx:
1330 case POWERPC_MMU_SOFT_4xx:
1331 case POWERPC_MMU_REAL:
1332 case POWERPC_MMU_BOOKE:
1333 ctx->prot |= PAGE_WRITE;
1334 break;
1335 #if defined(TARGET_PPC64)
1336 case POWERPC_MMU_620:
1337 case POWERPC_MMU_64B:
1338 case POWERPC_MMU_2_06:
1339 /* Real address are 60 bits long */
1340 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1341 ctx->prot |= PAGE_WRITE;
1342 break;
1343 #endif
1344 case POWERPC_MMU_SOFT_4xx_Z:
1345 if (unlikely(msr_pe != 0)) {
1346 /* 403 family add some particular protections,
1347 * using PBL/PBU registers for accesses with no translation.
1349 in_plb =
1350 /* Check PLB validity */
1351 (env->pb[0] < env->pb[1] &&
1352 /* and address in plb area */
1353 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1354 (env->pb[2] < env->pb[3] &&
1355 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1356 if (in_plb ^ msr_px) {
1357 /* Access in protected area */
1358 if (rw == 1) {
1359 /* Access is not allowed */
1360 ret = -2;
1362 } else {
1363 /* Read-write access is allowed */
1364 ctx->prot |= PAGE_WRITE;
1367 break;
1368 case POWERPC_MMU_MPC8xx:
1369 /* XXX: TODO */
1370 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1371 break;
1372 case POWERPC_MMU_BOOKE206:
1373 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1374 break;
1375 default:
1376 cpu_abort(env, "Unknown or invalid MMU model\n");
1377 return -1;
1380 return ret;
1383 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1384 int rw, int access_type)
1386 int ret;
1388 #if 0
1389 qemu_log("%s\n", __func__);
1390 #endif
1391 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1392 (access_type != ACCESS_CODE && msr_dr == 0)) {
1393 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1394 /* The BookE MMU always performs address translation. The
1395 IS and DS bits only affect the address space. */
1396 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1397 rw, access_type);
1398 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1399 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1400 access_type);
1401 } else {
1402 /* No address translation. */
1403 ret = check_physical(env, ctx, eaddr, rw);
1405 } else {
1406 ret = -1;
1407 switch (env->mmu_model) {
1408 case POWERPC_MMU_32B:
1409 case POWERPC_MMU_601:
1410 case POWERPC_MMU_SOFT_6xx:
1411 case POWERPC_MMU_SOFT_74xx:
1412 /* Try to find a BAT */
1413 if (env->nb_BATs != 0)
1414 ret = get_bat(env, ctx, eaddr, rw, access_type);
1415 #if defined(TARGET_PPC64)
1416 case POWERPC_MMU_620:
1417 case POWERPC_MMU_64B:
1418 case POWERPC_MMU_2_06:
1419 #endif
1420 if (ret < 0) {
1421 /* We didn't match any BAT entry or don't have BATs */
1422 ret = get_segment(env, ctx, eaddr, rw, access_type);
1424 break;
1425 case POWERPC_MMU_SOFT_4xx:
1426 case POWERPC_MMU_SOFT_4xx_Z:
1427 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1428 rw, access_type);
1429 break;
1430 case POWERPC_MMU_BOOKE:
1431 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1432 rw, access_type);
1433 break;
1434 case POWERPC_MMU_BOOKE206:
1435 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1436 access_type);
1437 break;
1438 case POWERPC_MMU_MPC8xx:
1439 /* XXX: TODO */
1440 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1441 break;
1442 case POWERPC_MMU_REAL:
1443 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1444 return -1;
1445 default:
1446 cpu_abort(env, "Unknown or invalid MMU model\n");
1447 return -1;
1450 #if 0
1451 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1452 __func__, eaddr, ret, ctx->raddr);
1453 #endif
1455 return ret;
1458 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1460 mmu_ctx_t ctx;
1462 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1463 return -1;
1465 return ctx.raddr & TARGET_PAGE_MASK;
1468 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1469 int rw)
1471 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1472 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1473 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1474 env->spr[SPR_BOOKE_MAS3] = 0;
1475 env->spr[SPR_BOOKE_MAS6] = 0;
1476 env->spr[SPR_BOOKE_MAS7] = 0;
1478 /* AS */
1479 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1480 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1481 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1484 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1485 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1487 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1488 case MAS4_TIDSELD_PID0:
1489 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1490 break;
1491 case MAS4_TIDSELD_PID1:
1492 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1493 break;
1494 case MAS4_TIDSELD_PID2:
1495 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1496 break;
1499 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1501 /* next victim logic */
1502 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1503 env->last_way++;
1504 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1505 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1508 /* Perform address translation */
1509 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1510 int mmu_idx, int is_softmmu)
1512 mmu_ctx_t ctx;
1513 int access_type;
1514 int ret = 0;
1516 if (rw == 2) {
1517 /* code access */
1518 rw = 0;
1519 access_type = ACCESS_CODE;
1520 } else {
1521 /* data access */
1522 access_type = env->access_type;
1524 ret = get_physical_address(env, &ctx, address, rw, access_type);
1525 if (ret == 0) {
1526 tlb_set_page(env, address & TARGET_PAGE_MASK,
1527 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1528 mmu_idx, TARGET_PAGE_SIZE);
1529 ret = 0;
1530 } else if (ret < 0) {
1531 LOG_MMU_STATE(env);
1532 if (access_type == ACCESS_CODE) {
1533 switch (ret) {
1534 case -1:
1535 /* No matches in page tables or TLB */
1536 switch (env->mmu_model) {
1537 case POWERPC_MMU_SOFT_6xx:
1538 env->exception_index = POWERPC_EXCP_IFTLB;
1539 env->error_code = 1 << 18;
1540 env->spr[SPR_IMISS] = address;
1541 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1542 goto tlb_miss;
1543 case POWERPC_MMU_SOFT_74xx:
1544 env->exception_index = POWERPC_EXCP_IFTLB;
1545 goto tlb_miss_74xx;
1546 case POWERPC_MMU_SOFT_4xx:
1547 case POWERPC_MMU_SOFT_4xx_Z:
1548 env->exception_index = POWERPC_EXCP_ITLB;
1549 env->error_code = 0;
1550 env->spr[SPR_40x_DEAR] = address;
1551 env->spr[SPR_40x_ESR] = 0x00000000;
1552 break;
1553 case POWERPC_MMU_32B:
1554 case POWERPC_MMU_601:
1555 #if defined(TARGET_PPC64)
1556 case POWERPC_MMU_620:
1557 case POWERPC_MMU_64B:
1558 case POWERPC_MMU_2_06:
1559 #endif
1560 env->exception_index = POWERPC_EXCP_ISI;
1561 env->error_code = 0x40000000;
1562 break;
1563 case POWERPC_MMU_BOOKE206:
1564 booke206_update_mas_tlb_miss(env, address, rw);
1565 /* fall through */
1566 case POWERPC_MMU_BOOKE:
1567 env->exception_index = POWERPC_EXCP_ITLB;
1568 env->error_code = 0;
1569 env->spr[SPR_BOOKE_DEAR] = address;
1570 return -1;
1571 case POWERPC_MMU_MPC8xx:
1572 /* XXX: TODO */
1573 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1574 break;
1575 case POWERPC_MMU_REAL:
1576 cpu_abort(env, "PowerPC in real mode should never raise "
1577 "any MMU exceptions\n");
1578 return -1;
1579 default:
1580 cpu_abort(env, "Unknown or invalid MMU model\n");
1581 return -1;
1583 break;
1584 case -2:
1585 /* Access rights violation */
1586 env->exception_index = POWERPC_EXCP_ISI;
1587 env->error_code = 0x08000000;
1588 break;
1589 case -3:
1590 /* No execute protection violation */
1591 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1592 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1593 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1595 env->exception_index = POWERPC_EXCP_ISI;
1596 env->error_code = 0x10000000;
1597 break;
1598 case -4:
1599 /* Direct store exception */
1600 /* No code fetch is allowed in direct-store areas */
1601 env->exception_index = POWERPC_EXCP_ISI;
1602 env->error_code = 0x10000000;
1603 break;
1604 #if defined(TARGET_PPC64)
1605 case -5:
1606 /* No match in segment table */
1607 if (env->mmu_model == POWERPC_MMU_620) {
1608 env->exception_index = POWERPC_EXCP_ISI;
1609 /* XXX: this might be incorrect */
1610 env->error_code = 0x40000000;
1611 } else {
1612 env->exception_index = POWERPC_EXCP_ISEG;
1613 env->error_code = 0;
1615 break;
1616 #endif
1618 } else {
1619 switch (ret) {
1620 case -1:
1621 /* No matches in page tables or TLB */
1622 switch (env->mmu_model) {
1623 case POWERPC_MMU_SOFT_6xx:
1624 if (rw == 1) {
1625 env->exception_index = POWERPC_EXCP_DSTLB;
1626 env->error_code = 1 << 16;
1627 } else {
1628 env->exception_index = POWERPC_EXCP_DLTLB;
1629 env->error_code = 0;
1631 env->spr[SPR_DMISS] = address;
1632 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1633 tlb_miss:
1634 env->error_code |= ctx.key << 19;
1635 env->spr[SPR_HASH1] = env->htab_base +
1636 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1637 env->spr[SPR_HASH2] = env->htab_base +
1638 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1639 break;
1640 case POWERPC_MMU_SOFT_74xx:
1641 if (rw == 1) {
1642 env->exception_index = POWERPC_EXCP_DSTLB;
1643 } else {
1644 env->exception_index = POWERPC_EXCP_DLTLB;
1646 tlb_miss_74xx:
1647 /* Implement LRU algorithm */
1648 env->error_code = ctx.key << 19;
1649 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1650 ((env->last_way + 1) & (env->nb_ways - 1));
1651 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1652 break;
1653 case POWERPC_MMU_SOFT_4xx:
1654 case POWERPC_MMU_SOFT_4xx_Z:
1655 env->exception_index = POWERPC_EXCP_DTLB;
1656 env->error_code = 0;
1657 env->spr[SPR_40x_DEAR] = address;
1658 if (rw)
1659 env->spr[SPR_40x_ESR] = 0x00800000;
1660 else
1661 env->spr[SPR_40x_ESR] = 0x00000000;
1662 break;
1663 case POWERPC_MMU_32B:
1664 case POWERPC_MMU_601:
1665 #if defined(TARGET_PPC64)
1666 case POWERPC_MMU_620:
1667 case POWERPC_MMU_64B:
1668 case POWERPC_MMU_2_06:
1669 #endif
1670 env->exception_index = POWERPC_EXCP_DSI;
1671 env->error_code = 0;
1672 env->spr[SPR_DAR] = address;
1673 if (rw == 1)
1674 env->spr[SPR_DSISR] = 0x42000000;
1675 else
1676 env->spr[SPR_DSISR] = 0x40000000;
1677 break;
1678 case POWERPC_MMU_MPC8xx:
1679 /* XXX: TODO */
1680 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1681 break;
1682 case POWERPC_MMU_BOOKE206:
1683 booke206_update_mas_tlb_miss(env, address, rw);
1684 /* fall through */
1685 case POWERPC_MMU_BOOKE:
1686 env->exception_index = POWERPC_EXCP_DTLB;
1687 env->error_code = 0;
1688 env->spr[SPR_BOOKE_DEAR] = address;
1689 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1690 return -1;
1691 case POWERPC_MMU_REAL:
1692 cpu_abort(env, "PowerPC in real mode should never raise "
1693 "any MMU exceptions\n");
1694 return -1;
1695 default:
1696 cpu_abort(env, "Unknown or invalid MMU model\n");
1697 return -1;
1699 break;
1700 case -2:
1701 /* Access rights violation */
1702 env->exception_index = POWERPC_EXCP_DSI;
1703 env->error_code = 0;
1704 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1705 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1706 env->spr[SPR_40x_DEAR] = address;
1707 if (rw) {
1708 env->spr[SPR_40x_ESR] |= 0x00800000;
1710 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1711 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1712 env->spr[SPR_BOOKE_DEAR] = address;
1713 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1714 } else {
1715 env->spr[SPR_DAR] = address;
1716 if (rw == 1) {
1717 env->spr[SPR_DSISR] = 0x0A000000;
1718 } else {
1719 env->spr[SPR_DSISR] = 0x08000000;
1722 break;
1723 case -4:
1724 /* Direct store exception */
1725 switch (access_type) {
1726 case ACCESS_FLOAT:
1727 /* Floating point load/store */
1728 env->exception_index = POWERPC_EXCP_ALIGN;
1729 env->error_code = POWERPC_EXCP_ALIGN_FP;
1730 env->spr[SPR_DAR] = address;
1731 break;
1732 case ACCESS_RES:
1733 /* lwarx, ldarx or stwcx. */
1734 env->exception_index = POWERPC_EXCP_DSI;
1735 env->error_code = 0;
1736 env->spr[SPR_DAR] = address;
1737 if (rw == 1)
1738 env->spr[SPR_DSISR] = 0x06000000;
1739 else
1740 env->spr[SPR_DSISR] = 0x04000000;
1741 break;
1742 case ACCESS_EXT:
1743 /* eciwx or ecowx */
1744 env->exception_index = POWERPC_EXCP_DSI;
1745 env->error_code = 0;
1746 env->spr[SPR_DAR] = address;
1747 if (rw == 1)
1748 env->spr[SPR_DSISR] = 0x06100000;
1749 else
1750 env->spr[SPR_DSISR] = 0x04100000;
1751 break;
1752 default:
1753 printf("DSI: invalid exception (%d)\n", ret);
1754 env->exception_index = POWERPC_EXCP_PROGRAM;
1755 env->error_code =
1756 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1757 env->spr[SPR_DAR] = address;
1758 break;
1760 break;
1761 #if defined(TARGET_PPC64)
1762 case -5:
1763 /* No match in segment table */
1764 if (env->mmu_model == POWERPC_MMU_620) {
1765 env->exception_index = POWERPC_EXCP_DSI;
1766 env->error_code = 0;
1767 env->spr[SPR_DAR] = address;
1768 /* XXX: this might be incorrect */
1769 if (rw == 1)
1770 env->spr[SPR_DSISR] = 0x42000000;
1771 else
1772 env->spr[SPR_DSISR] = 0x40000000;
1773 } else {
1774 env->exception_index = POWERPC_EXCP_DSEG;
1775 env->error_code = 0;
1776 env->spr[SPR_DAR] = address;
1778 break;
1779 #endif
1782 #if 0
1783 printf("%s: set exception to %d %02x\n", __func__,
1784 env->exception, env->error_code);
1785 #endif
1786 ret = 1;
1789 return ret;
1792 /*****************************************************************************/
1793 /* BATs management */
1794 #if !defined(FLUSH_ALL_TLBS)
1795 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1796 target_ulong mask)
1798 target_ulong base, end, page;
1800 base = BATu & ~0x0001FFFF;
1801 end = base + mask + 0x00020000;
1802 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1803 TARGET_FMT_lx ")\n", base, end, mask);
1804 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1805 tlb_flush_page(env, page);
1806 LOG_BATS("Flush done\n");
1808 #endif
1810 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1811 target_ulong value)
1813 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1814 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1817 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1819 target_ulong mask;
1821 dump_store_bat(env, 'I', 0, nr, value);
1822 if (env->IBAT[0][nr] != value) {
1823 mask = (value << 15) & 0x0FFE0000UL;
1824 #if !defined(FLUSH_ALL_TLBS)
1825 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1826 #endif
1827 /* When storing valid upper BAT, mask BEPI and BRPN
1828 * and invalidate all TLBs covered by this BAT
1830 mask = (value << 15) & 0x0FFE0000UL;
1831 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1832 (value & ~0x0001FFFFUL & ~mask);
1833 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1834 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1835 #if !defined(FLUSH_ALL_TLBS)
1836 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1837 #else
1838 tlb_flush(env, 1);
1839 #endif
1843 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1845 dump_store_bat(env, 'I', 1, nr, value);
1846 env->IBAT[1][nr] = value;
1849 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1851 target_ulong mask;
1853 dump_store_bat(env, 'D', 0, nr, value);
1854 if (env->DBAT[0][nr] != value) {
1855 /* When storing valid upper BAT, mask BEPI and BRPN
1856 * and invalidate all TLBs covered by this BAT
1858 mask = (value << 15) & 0x0FFE0000UL;
1859 #if !defined(FLUSH_ALL_TLBS)
1860 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1861 #endif
1862 mask = (value << 15) & 0x0FFE0000UL;
1863 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1864 (value & ~0x0001FFFFUL & ~mask);
1865 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1866 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1867 #if !defined(FLUSH_ALL_TLBS)
1868 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1869 #else
1870 tlb_flush(env, 1);
1871 #endif
1875 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1877 dump_store_bat(env, 'D', 1, nr, value);
1878 env->DBAT[1][nr] = value;
1881 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1883 target_ulong mask;
1884 #if defined(FLUSH_ALL_TLBS)
1885 int do_inval;
1886 #endif
1888 dump_store_bat(env, 'I', 0, nr, value);
1889 if (env->IBAT[0][nr] != value) {
1890 #if defined(FLUSH_ALL_TLBS)
1891 do_inval = 0;
1892 #endif
1893 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1894 if (env->IBAT[1][nr] & 0x40) {
1895 /* Invalidate BAT only if it is valid */
1896 #if !defined(FLUSH_ALL_TLBS)
1897 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1898 #else
1899 do_inval = 1;
1900 #endif
1902 /* When storing valid upper BAT, mask BEPI and BRPN
1903 * and invalidate all TLBs covered by this BAT
1905 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1906 (value & ~0x0001FFFFUL & ~mask);
1907 env->DBAT[0][nr] = env->IBAT[0][nr];
1908 if (env->IBAT[1][nr] & 0x40) {
1909 #if !defined(FLUSH_ALL_TLBS)
1910 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1911 #else
1912 do_inval = 1;
1913 #endif
1915 #if defined(FLUSH_ALL_TLBS)
1916 if (do_inval)
1917 tlb_flush(env, 1);
1918 #endif
1922 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1924 target_ulong mask;
1925 #if defined(FLUSH_ALL_TLBS)
1926 int do_inval;
1927 #endif
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
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
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 #endif
1959 /*****************************************************************************/
1960 /* TLB management */
1961 void ppc_tlb_invalidate_all (CPUPPCState *env)
1963 switch (env->mmu_model) {
1964 case POWERPC_MMU_SOFT_6xx:
1965 case POWERPC_MMU_SOFT_74xx:
1966 ppc6xx_tlb_invalidate_all(env);
1967 break;
1968 case POWERPC_MMU_SOFT_4xx:
1969 case POWERPC_MMU_SOFT_4xx_Z:
1970 ppc4xx_tlb_invalidate_all(env);
1971 break;
1972 case POWERPC_MMU_REAL:
1973 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1974 break;
1975 case POWERPC_MMU_MPC8xx:
1976 /* XXX: TODO */
1977 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1978 break;
1979 case POWERPC_MMU_BOOKE:
1980 tlb_flush(env, 1);
1981 break;
1982 case POWERPC_MMU_BOOKE206:
1983 booke206_flush_tlb(env, -1, 0);
1984 break;
1985 case POWERPC_MMU_32B:
1986 case POWERPC_MMU_601:
1987 #if defined(TARGET_PPC64)
1988 case POWERPC_MMU_620:
1989 case POWERPC_MMU_64B:
1990 case POWERPC_MMU_2_06:
1991 #endif /* defined(TARGET_PPC64) */
1992 tlb_flush(env, 1);
1993 break;
1994 default:
1995 /* XXX: TODO */
1996 cpu_abort(env, "Unknown MMU model\n");
1997 break;
2001 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2003 #if !defined(FLUSH_ALL_TLBS)
2004 addr &= TARGET_PAGE_MASK;
2005 switch (env->mmu_model) {
2006 case POWERPC_MMU_SOFT_6xx:
2007 case POWERPC_MMU_SOFT_74xx:
2008 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2009 if (env->id_tlbs == 1)
2010 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2011 break;
2012 case POWERPC_MMU_SOFT_4xx:
2013 case POWERPC_MMU_SOFT_4xx_Z:
2014 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2015 break;
2016 case POWERPC_MMU_REAL:
2017 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2018 break;
2019 case POWERPC_MMU_MPC8xx:
2020 /* XXX: TODO */
2021 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2022 break;
2023 case POWERPC_MMU_BOOKE:
2024 /* XXX: TODO */
2025 cpu_abort(env, "BookE MMU model is not implemented\n");
2026 break;
2027 case POWERPC_MMU_BOOKE206:
2028 /* XXX: TODO */
2029 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2030 break;
2031 case POWERPC_MMU_32B:
2032 case POWERPC_MMU_601:
2033 /* tlbie invalidate TLBs for all segments */
2034 addr &= ~((target_ulong)-1ULL << 28);
2035 /* XXX: this case should be optimized,
2036 * giving a mask to tlb_flush_page
2038 tlb_flush_page(env, addr | (0x0 << 28));
2039 tlb_flush_page(env, addr | (0x1 << 28));
2040 tlb_flush_page(env, addr | (0x2 << 28));
2041 tlb_flush_page(env, addr | (0x3 << 28));
2042 tlb_flush_page(env, addr | (0x4 << 28));
2043 tlb_flush_page(env, addr | (0x5 << 28));
2044 tlb_flush_page(env, addr | (0x6 << 28));
2045 tlb_flush_page(env, addr | (0x7 << 28));
2046 tlb_flush_page(env, addr | (0x8 << 28));
2047 tlb_flush_page(env, addr | (0x9 << 28));
2048 tlb_flush_page(env, addr | (0xA << 28));
2049 tlb_flush_page(env, addr | (0xB << 28));
2050 tlb_flush_page(env, addr | (0xC << 28));
2051 tlb_flush_page(env, addr | (0xD << 28));
2052 tlb_flush_page(env, addr | (0xE << 28));
2053 tlb_flush_page(env, addr | (0xF << 28));
2054 break;
2055 #if defined(TARGET_PPC64)
2056 case POWERPC_MMU_620:
2057 case POWERPC_MMU_64B:
2058 case POWERPC_MMU_2_06:
2059 /* tlbie invalidate TLBs for all segments */
2060 /* XXX: given the fact that there are too many segments to invalidate,
2061 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2062 * we just invalidate all TLBs
2064 tlb_flush(env, 1);
2065 break;
2066 #endif /* defined(TARGET_PPC64) */
2067 default:
2068 /* XXX: TODO */
2069 cpu_abort(env, "Unknown MMU model\n");
2070 break;
2072 #else
2073 ppc_tlb_invalidate_all(env);
2074 #endif
2077 /*****************************************************************************/
2078 /* Special registers manipulation */
2079 #if defined(TARGET_PPC64)
2080 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2082 if (env->asr != value) {
2083 env->asr = value;
2084 tlb_flush(env, 1);
2087 #endif
2089 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2091 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2092 if (env->spr[SPR_SDR1] != value) {
2093 env->spr[SPR_SDR1] = value;
2094 #if defined(TARGET_PPC64)
2095 if (env->mmu_model & POWERPC_MMU_64) {
2096 target_ulong htabsize = value & SDR_64_HTABSIZE;
2098 if (htabsize > 28) {
2099 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2100 " stored in SDR1\n", htabsize);
2101 htabsize = 28;
2103 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2104 env->htab_base = value & SDR_64_HTABORG;
2105 } else
2106 #endif /* defined(TARGET_PPC64) */
2108 /* FIXME: Should check for valid HTABMASK values */
2109 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2110 env->htab_base = value & SDR_32_HTABORG;
2112 tlb_flush(env, 1);
2116 #if defined(TARGET_PPC64)
2117 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2119 // XXX
2120 return 0;
2122 #endif
2124 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2126 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2127 srnum, value, env->sr[srnum]);
2128 #if defined(TARGET_PPC64)
2129 if (env->mmu_model & POWERPC_MMU_64) {
2130 uint64_t rb = 0, rs = 0;
2132 /* ESID = srnum */
2133 rb |= ((uint32_t)srnum & 0xf) << 28;
2134 /* Set the valid bit */
2135 rb |= 1 << 27;
2136 /* Index = ESID */
2137 rb |= (uint32_t)srnum;
2139 /* VSID = VSID */
2140 rs |= (value & 0xfffffff) << 12;
2141 /* flags = flags */
2142 rs |= ((value >> 27) & 0xf) << 8;
2144 ppc_store_slb(env, rb, rs);
2145 } else
2146 #endif
2147 if (env->sr[srnum] != value) {
2148 env->sr[srnum] = value;
2149 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2150 flusing the whole TLB. */
2151 #if !defined(FLUSH_ALL_TLBS) && 0
2153 target_ulong page, end;
2154 /* Invalidate 256 MB of virtual memory */
2155 page = (16 << 20) * srnum;
2156 end = page + (16 << 20);
2157 for (; page != end; page += TARGET_PAGE_SIZE)
2158 tlb_flush_page(env, page);
2160 #else
2161 tlb_flush(env, 1);
2162 #endif
2165 #endif /* !defined (CONFIG_USER_ONLY) */
2167 /* GDBstub can read and write MSR... */
2168 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2170 hreg_store_msr(env, value, 0);
2173 /*****************************************************************************/
2174 /* Exception processing */
2175 #if defined (CONFIG_USER_ONLY)
2176 void do_interrupt (CPUState *env)
2178 env->exception_index = POWERPC_EXCP_NONE;
2179 env->error_code = 0;
2182 void ppc_hw_interrupt (CPUState *env)
2184 env->exception_index = POWERPC_EXCP_NONE;
2185 env->error_code = 0;
2187 #else /* defined (CONFIG_USER_ONLY) */
2188 static inline void dump_syscall(CPUState *env)
2190 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2191 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2192 " nip=" TARGET_FMT_lx "\n",
2193 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2194 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2195 ppc_dump_gpr(env, 6), env->nip);
2198 /* Note that this function should be greatly optimized
2199 * when called with a constant excp, from ppc_hw_interrupt
2201 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2203 target_ulong msr, new_msr, vector;
2204 int srr0, srr1, asrr0, asrr1;
2205 int lpes0, lpes1, lev;
2207 if (0) {
2208 /* XXX: find a suitable condition to enable the hypervisor mode */
2209 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2210 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2211 } else {
2212 /* Those values ensure we won't enter the hypervisor mode */
2213 lpes0 = 0;
2214 lpes1 = 1;
2217 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2218 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2220 /* new srr1 value excluding must-be-zero bits */
2221 msr = env->msr & ~0x783f0000ULL;
2223 /* new interrupt handler msr */
2224 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2226 /* target registers */
2227 srr0 = SPR_SRR0;
2228 srr1 = SPR_SRR1;
2229 asrr0 = -1;
2230 asrr1 = -1;
2232 switch (excp) {
2233 case POWERPC_EXCP_NONE:
2234 /* Should never happen */
2235 return;
2236 case POWERPC_EXCP_CRITICAL: /* Critical input */
2237 switch (excp_model) {
2238 case POWERPC_EXCP_40x:
2239 srr0 = SPR_40x_SRR2;
2240 srr1 = SPR_40x_SRR3;
2241 break;
2242 case POWERPC_EXCP_BOOKE:
2243 srr0 = SPR_BOOKE_CSRR0;
2244 srr1 = SPR_BOOKE_CSRR1;
2245 break;
2246 case POWERPC_EXCP_G2:
2247 break;
2248 default:
2249 goto excp_invalid;
2251 goto store_next;
2252 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2253 if (msr_me == 0) {
2254 /* Machine check exception is not enabled.
2255 * Enter checkstop state.
2257 if (qemu_log_enabled()) {
2258 qemu_log("Machine check while not allowed. "
2259 "Entering checkstop state\n");
2260 } else {
2261 fprintf(stderr, "Machine check while not allowed. "
2262 "Entering checkstop state\n");
2264 env->halted = 1;
2265 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2267 if (0) {
2268 /* XXX: find a suitable condition to enable the hypervisor mode */
2269 new_msr |= (target_ulong)MSR_HVB;
2272 /* machine check exceptions don't have ME set */
2273 new_msr &= ~((target_ulong)1 << MSR_ME);
2275 /* XXX: should also have something loaded in DAR / DSISR */
2276 switch (excp_model) {
2277 case POWERPC_EXCP_40x:
2278 srr0 = SPR_40x_SRR2;
2279 srr1 = SPR_40x_SRR3;
2280 break;
2281 case POWERPC_EXCP_BOOKE:
2282 srr0 = SPR_BOOKE_MCSRR0;
2283 srr1 = SPR_BOOKE_MCSRR1;
2284 asrr0 = SPR_BOOKE_CSRR0;
2285 asrr1 = SPR_BOOKE_CSRR1;
2286 break;
2287 default:
2288 break;
2290 goto store_next;
2291 case POWERPC_EXCP_DSI: /* Data storage exception */
2292 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2293 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2294 if (lpes1 == 0)
2295 new_msr |= (target_ulong)MSR_HVB;
2296 goto store_next;
2297 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2298 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2299 "\n", msr, env->nip);
2300 if (lpes1 == 0)
2301 new_msr |= (target_ulong)MSR_HVB;
2302 msr |= env->error_code;
2303 goto store_next;
2304 case POWERPC_EXCP_EXTERNAL: /* External input */
2305 if (lpes0 == 1)
2306 new_msr |= (target_ulong)MSR_HVB;
2307 goto store_next;
2308 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2309 if (lpes1 == 0)
2310 new_msr |= (target_ulong)MSR_HVB;
2311 /* XXX: this is false */
2312 /* Get rS/rD and rA from faulting opcode */
2313 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2314 goto store_current;
2315 case POWERPC_EXCP_PROGRAM: /* Program exception */
2316 switch (env->error_code & ~0xF) {
2317 case POWERPC_EXCP_FP:
2318 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2319 LOG_EXCP("Ignore floating point exception\n");
2320 env->exception_index = POWERPC_EXCP_NONE;
2321 env->error_code = 0;
2322 return;
2324 if (lpes1 == 0)
2325 new_msr |= (target_ulong)MSR_HVB;
2326 msr |= 0x00100000;
2327 if (msr_fe0 == msr_fe1)
2328 goto store_next;
2329 msr |= 0x00010000;
2330 break;
2331 case POWERPC_EXCP_INVAL:
2332 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2333 if (lpes1 == 0)
2334 new_msr |= (target_ulong)MSR_HVB;
2335 msr |= 0x00080000;
2336 break;
2337 case POWERPC_EXCP_PRIV:
2338 if (lpes1 == 0)
2339 new_msr |= (target_ulong)MSR_HVB;
2340 msr |= 0x00040000;
2341 break;
2342 case POWERPC_EXCP_TRAP:
2343 if (lpes1 == 0)
2344 new_msr |= (target_ulong)MSR_HVB;
2345 msr |= 0x00020000;
2346 break;
2347 default:
2348 /* Should never occur */
2349 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2350 env->error_code);
2351 break;
2353 goto store_current;
2354 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2355 if (lpes1 == 0)
2356 new_msr |= (target_ulong)MSR_HVB;
2357 goto store_current;
2358 case POWERPC_EXCP_SYSCALL: /* System call exception */
2359 dump_syscall(env);
2360 lev = env->error_code;
2361 if ((lev == 1) && cpu_ppc_hypercall) {
2362 cpu_ppc_hypercall(env);
2363 return;
2365 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2366 new_msr |= (target_ulong)MSR_HVB;
2367 goto store_next;
2368 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2369 goto store_current;
2370 case POWERPC_EXCP_DECR: /* Decrementer exception */
2371 if (lpes1 == 0)
2372 new_msr |= (target_ulong)MSR_HVB;
2373 goto store_next;
2374 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2375 /* FIT on 4xx */
2376 LOG_EXCP("FIT exception\n");
2377 goto store_next;
2378 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2379 LOG_EXCP("WDT exception\n");
2380 switch (excp_model) {
2381 case POWERPC_EXCP_BOOKE:
2382 srr0 = SPR_BOOKE_CSRR0;
2383 srr1 = SPR_BOOKE_CSRR1;
2384 break;
2385 default:
2386 break;
2388 goto store_next;
2389 case POWERPC_EXCP_DTLB: /* Data TLB error */
2390 goto store_next;
2391 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2392 goto store_next;
2393 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2394 switch (excp_model) {
2395 case POWERPC_EXCP_BOOKE:
2396 srr0 = SPR_BOOKE_DSRR0;
2397 srr1 = SPR_BOOKE_DSRR1;
2398 asrr0 = SPR_BOOKE_CSRR0;
2399 asrr1 = SPR_BOOKE_CSRR1;
2400 break;
2401 default:
2402 break;
2404 /* XXX: TODO */
2405 cpu_abort(env, "Debug exception is not implemented yet !\n");
2406 goto store_next;
2407 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2408 goto store_current;
2409 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2410 /* XXX: TODO */
2411 cpu_abort(env, "Embedded floating point data exception "
2412 "is not implemented yet !\n");
2413 goto store_next;
2414 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2415 /* XXX: TODO */
2416 cpu_abort(env, "Embedded floating point round exception "
2417 "is not implemented yet !\n");
2418 goto store_next;
2419 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2420 /* XXX: TODO */
2421 cpu_abort(env,
2422 "Performance counter exception is not implemented yet !\n");
2423 goto store_next;
2424 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2425 /* XXX: TODO */
2426 cpu_abort(env,
2427 "Embedded doorbell interrupt is not implemented yet !\n");
2428 goto store_next;
2429 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2430 switch (excp_model) {
2431 case POWERPC_EXCP_BOOKE:
2432 srr0 = SPR_BOOKE_CSRR0;
2433 srr1 = SPR_BOOKE_CSRR1;
2434 break;
2435 default:
2436 break;
2438 /* XXX: TODO */
2439 cpu_abort(env, "Embedded doorbell critical interrupt "
2440 "is not implemented yet !\n");
2441 goto store_next;
2442 case POWERPC_EXCP_RESET: /* System reset exception */
2443 if (msr_pow) {
2444 /* indicate that we resumed from power save mode */
2445 msr |= 0x10000;
2446 } else {
2447 new_msr &= ~((target_ulong)1 << MSR_ME);
2450 if (0) {
2451 /* XXX: find a suitable condition to enable the hypervisor mode */
2452 new_msr |= (target_ulong)MSR_HVB;
2454 goto store_next;
2455 case POWERPC_EXCP_DSEG: /* Data segment exception */
2456 if (lpes1 == 0)
2457 new_msr |= (target_ulong)MSR_HVB;
2458 goto store_next;
2459 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2460 if (lpes1 == 0)
2461 new_msr |= (target_ulong)MSR_HVB;
2462 goto store_next;
2463 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2464 srr0 = SPR_HSRR0;
2465 srr1 = SPR_HSRR1;
2466 new_msr |= (target_ulong)MSR_HVB;
2467 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2468 goto store_next;
2469 case POWERPC_EXCP_TRACE: /* Trace exception */
2470 if (lpes1 == 0)
2471 new_msr |= (target_ulong)MSR_HVB;
2472 goto store_next;
2473 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2474 srr0 = SPR_HSRR0;
2475 srr1 = SPR_HSRR1;
2476 new_msr |= (target_ulong)MSR_HVB;
2477 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2478 goto store_next;
2479 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2480 srr0 = SPR_HSRR0;
2481 srr1 = SPR_HSRR1;
2482 new_msr |= (target_ulong)MSR_HVB;
2483 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2484 goto store_next;
2485 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2486 srr0 = SPR_HSRR0;
2487 srr1 = SPR_HSRR1;
2488 new_msr |= (target_ulong)MSR_HVB;
2489 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2490 goto store_next;
2491 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2492 srr0 = SPR_HSRR0;
2493 srr1 = SPR_HSRR1;
2494 new_msr |= (target_ulong)MSR_HVB;
2495 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2496 goto store_next;
2497 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2498 if (lpes1 == 0)
2499 new_msr |= (target_ulong)MSR_HVB;
2500 goto store_current;
2501 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2502 LOG_EXCP("PIT exception\n");
2503 goto store_next;
2504 case POWERPC_EXCP_IO: /* IO error exception */
2505 /* XXX: TODO */
2506 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2507 goto store_next;
2508 case POWERPC_EXCP_RUNM: /* Run mode exception */
2509 /* XXX: TODO */
2510 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2511 goto store_next;
2512 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2513 /* XXX: TODO */
2514 cpu_abort(env, "602 emulation trap exception "
2515 "is not implemented yet !\n");
2516 goto store_next;
2517 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2518 if (lpes1 == 0) /* XXX: check this */
2519 new_msr |= (target_ulong)MSR_HVB;
2520 switch (excp_model) {
2521 case POWERPC_EXCP_602:
2522 case POWERPC_EXCP_603:
2523 case POWERPC_EXCP_603E:
2524 case POWERPC_EXCP_G2:
2525 goto tlb_miss_tgpr;
2526 case POWERPC_EXCP_7x5:
2527 goto tlb_miss;
2528 case POWERPC_EXCP_74xx:
2529 goto tlb_miss_74xx;
2530 default:
2531 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2532 break;
2534 break;
2535 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2536 if (lpes1 == 0) /* XXX: check this */
2537 new_msr |= (target_ulong)MSR_HVB;
2538 switch (excp_model) {
2539 case POWERPC_EXCP_602:
2540 case POWERPC_EXCP_603:
2541 case POWERPC_EXCP_603E:
2542 case POWERPC_EXCP_G2:
2543 goto tlb_miss_tgpr;
2544 case POWERPC_EXCP_7x5:
2545 goto tlb_miss;
2546 case POWERPC_EXCP_74xx:
2547 goto tlb_miss_74xx;
2548 default:
2549 cpu_abort(env, "Invalid data load TLB miss exception\n");
2550 break;
2552 break;
2553 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2554 if (lpes1 == 0) /* XXX: check this */
2555 new_msr |= (target_ulong)MSR_HVB;
2556 switch (excp_model) {
2557 case POWERPC_EXCP_602:
2558 case POWERPC_EXCP_603:
2559 case POWERPC_EXCP_603E:
2560 case POWERPC_EXCP_G2:
2561 tlb_miss_tgpr:
2562 /* Swap temporary saved registers with GPRs */
2563 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2564 new_msr |= (target_ulong)1 << MSR_TGPR;
2565 hreg_swap_gpr_tgpr(env);
2567 goto tlb_miss;
2568 case POWERPC_EXCP_7x5:
2569 tlb_miss:
2570 #if defined (DEBUG_SOFTWARE_TLB)
2571 if (qemu_log_enabled()) {
2572 const char *es;
2573 target_ulong *miss, *cmp;
2574 int en;
2575 if (excp == POWERPC_EXCP_IFTLB) {
2576 es = "I";
2577 en = 'I';
2578 miss = &env->spr[SPR_IMISS];
2579 cmp = &env->spr[SPR_ICMP];
2580 } else {
2581 if (excp == POWERPC_EXCP_DLTLB)
2582 es = "DL";
2583 else
2584 es = "DS";
2585 en = 'D';
2586 miss = &env->spr[SPR_DMISS];
2587 cmp = &env->spr[SPR_DCMP];
2589 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2590 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2591 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2592 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2593 env->error_code);
2595 #endif
2596 msr |= env->crf[0] << 28;
2597 msr |= env->error_code; /* key, D/I, S/L bits */
2598 /* Set way using a LRU mechanism */
2599 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2600 break;
2601 case POWERPC_EXCP_74xx:
2602 tlb_miss_74xx:
2603 #if defined (DEBUG_SOFTWARE_TLB)
2604 if (qemu_log_enabled()) {
2605 const char *es;
2606 target_ulong *miss, *cmp;
2607 int en;
2608 if (excp == POWERPC_EXCP_IFTLB) {
2609 es = "I";
2610 en = 'I';
2611 miss = &env->spr[SPR_TLBMISS];
2612 cmp = &env->spr[SPR_PTEHI];
2613 } else {
2614 if (excp == POWERPC_EXCP_DLTLB)
2615 es = "DL";
2616 else
2617 es = "DS";
2618 en = 'D';
2619 miss = &env->spr[SPR_TLBMISS];
2620 cmp = &env->spr[SPR_PTEHI];
2622 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2623 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2624 env->error_code);
2626 #endif
2627 msr |= env->error_code; /* key bit */
2628 break;
2629 default:
2630 cpu_abort(env, "Invalid data store TLB miss exception\n");
2631 break;
2633 goto store_next;
2634 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2635 /* XXX: TODO */
2636 cpu_abort(env, "Floating point assist exception "
2637 "is not implemented yet !\n");
2638 goto store_next;
2639 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2640 /* XXX: TODO */
2641 cpu_abort(env, "DABR exception is not implemented yet !\n");
2642 goto store_next;
2643 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2644 /* XXX: TODO */
2645 cpu_abort(env, "IABR exception is not implemented yet !\n");
2646 goto store_next;
2647 case POWERPC_EXCP_SMI: /* System management interrupt */
2648 /* XXX: TODO */
2649 cpu_abort(env, "SMI exception is not implemented yet !\n");
2650 goto store_next;
2651 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2652 /* XXX: TODO */
2653 cpu_abort(env, "Thermal management exception "
2654 "is not implemented yet !\n");
2655 goto store_next;
2656 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2657 if (lpes1 == 0)
2658 new_msr |= (target_ulong)MSR_HVB;
2659 /* XXX: TODO */
2660 cpu_abort(env,
2661 "Performance counter exception is not implemented yet !\n");
2662 goto store_next;
2663 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2664 /* XXX: TODO */
2665 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2666 goto store_next;
2667 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2668 /* XXX: TODO */
2669 cpu_abort(env,
2670 "970 soft-patch exception is not implemented yet !\n");
2671 goto store_next;
2672 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2673 /* XXX: TODO */
2674 cpu_abort(env,
2675 "970 maintenance exception is not implemented yet !\n");
2676 goto store_next;
2677 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2678 /* XXX: TODO */
2679 cpu_abort(env, "Maskable external exception "
2680 "is not implemented yet !\n");
2681 goto store_next;
2682 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2683 /* XXX: TODO */
2684 cpu_abort(env, "Non maskable external exception "
2685 "is not implemented yet !\n");
2686 goto store_next;
2687 default:
2688 excp_invalid:
2689 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2690 break;
2691 store_current:
2692 /* save current instruction location */
2693 env->spr[srr0] = env->nip - 4;
2694 break;
2695 store_next:
2696 /* save next instruction location */
2697 env->spr[srr0] = env->nip;
2698 break;
2700 /* Save MSR */
2701 env->spr[srr1] = msr;
2702 /* If any alternate SRR register are defined, duplicate saved values */
2703 if (asrr0 != -1)
2704 env->spr[asrr0] = env->spr[srr0];
2705 if (asrr1 != -1)
2706 env->spr[asrr1] = env->spr[srr1];
2707 /* If we disactivated any translation, flush TLBs */
2708 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2709 tlb_flush(env, 1);
2711 if (msr_ile) {
2712 new_msr |= (target_ulong)1 << MSR_LE;
2715 /* Jump to handler */
2716 vector = env->excp_vectors[excp];
2717 if (vector == (target_ulong)-1ULL) {
2718 cpu_abort(env, "Raised an exception without defined vector %d\n",
2719 excp);
2721 vector |= env->excp_prefix;
2722 #if defined(TARGET_PPC64)
2723 if (excp_model == POWERPC_EXCP_BOOKE) {
2724 if (!msr_icm) {
2725 vector = (uint32_t)vector;
2726 } else {
2727 new_msr |= (target_ulong)1 << MSR_CM;
2729 } else {
2730 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2731 vector = (uint32_t)vector;
2732 } else {
2733 new_msr |= (target_ulong)1 << MSR_SF;
2736 #endif
2737 /* XXX: we don't use hreg_store_msr here as already have treated
2738 * any special case that could occur. Just store MSR and update hflags
2740 env->msr = new_msr & env->msr_mask;
2741 hreg_compute_hflags(env);
2742 env->nip = vector;
2743 /* Reset exception state */
2744 env->exception_index = POWERPC_EXCP_NONE;
2745 env->error_code = 0;
2747 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2748 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2749 /* XXX: The BookE changes address space when switching modes,
2750 we should probably implement that as different MMU indexes,
2751 but for the moment we do it the slow way and flush all. */
2752 tlb_flush(env, 1);
2756 void do_interrupt (CPUState *env)
2758 powerpc_excp(env, env->excp_model, env->exception_index);
2761 void ppc_hw_interrupt (CPUPPCState *env)
2763 int hdice;
2765 #if 0
2766 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2767 __func__, env, env->pending_interrupts,
2768 env->interrupt_request, (int)msr_me, (int)msr_ee);
2769 #endif
2770 /* External reset */
2771 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2772 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2773 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2774 return;
2776 /* Machine check exception */
2777 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2778 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2779 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2780 return;
2782 #if 0 /* TODO */
2783 /* External debug exception */
2784 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2785 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2786 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2787 return;
2789 #endif
2790 if (0) {
2791 /* XXX: find a suitable condition to enable the hypervisor mode */
2792 hdice = env->spr[SPR_LPCR] & 1;
2793 } else {
2794 hdice = 0;
2796 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2797 /* Hypervisor decrementer exception */
2798 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2799 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2800 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2801 return;
2804 if (msr_ce != 0) {
2805 /* External critical interrupt */
2806 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2807 /* Taking a critical external interrupt does not clear the external
2808 * critical interrupt status
2810 #if 0
2811 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2812 #endif
2813 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2814 return;
2817 if (msr_ee != 0) {
2818 /* Watchdog timer on embedded PowerPC */
2819 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2820 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2821 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2822 return;
2824 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2825 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2826 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2827 return;
2829 /* Fixed interval timer on embedded PowerPC */
2830 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2831 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2832 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2833 return;
2835 /* Programmable interval timer on embedded PowerPC */
2836 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2837 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2838 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2839 return;
2841 /* Decrementer exception */
2842 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2843 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2844 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2845 return;
2847 /* External interrupt */
2848 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2849 /* Taking an external interrupt does not clear the external
2850 * interrupt status
2852 #if 0
2853 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2854 #endif
2855 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2856 return;
2858 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2859 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2860 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2861 return;
2863 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2864 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2865 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2866 return;
2868 /* Thermal interrupt */
2869 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2870 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2871 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2872 return;
2876 #endif /* !CONFIG_USER_ONLY */
2878 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2880 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2881 TARGET_FMT_lx "\n", RA, msr);
2884 void cpu_reset(CPUPPCState *env)
2886 target_ulong msr;
2888 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2889 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2890 log_cpu_state(env, 0);
2893 msr = (target_ulong)0;
2894 if (0) {
2895 /* XXX: find a suitable condition to enable the hypervisor mode */
2896 msr |= (target_ulong)MSR_HVB;
2898 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2899 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2900 msr |= (target_ulong)1 << MSR_EP;
2901 #if defined (DO_SINGLE_STEP) && 0
2902 /* Single step trace mode */
2903 msr |= (target_ulong)1 << MSR_SE;
2904 msr |= (target_ulong)1 << MSR_BE;
2905 #endif
2906 #if defined(CONFIG_USER_ONLY)
2907 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2908 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2909 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2910 msr |= (target_ulong)1 << MSR_PR;
2911 #else
2912 env->excp_prefix = env->hreset_excp_prefix;
2913 env->nip = env->hreset_vector | env->excp_prefix;
2914 if (env->mmu_model != POWERPC_MMU_REAL)
2915 ppc_tlb_invalidate_all(env);
2916 #endif
2917 env->msr = msr & env->msr_mask;
2918 #if defined(TARGET_PPC64)
2919 if (env->mmu_model & POWERPC_MMU_64)
2920 env->msr |= (1ULL << MSR_SF);
2921 #endif
2922 hreg_compute_hflags(env);
2923 env->reserve_addr = (target_ulong)-1ULL;
2924 /* Be sure no exception or interrupt is pending */
2925 env->pending_interrupts = 0;
2926 env->exception_index = POWERPC_EXCP_NONE;
2927 env->error_code = 0;
2928 /* Flush all TLBs */
2929 tlb_flush(env, 1);
2932 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2934 CPUPPCState *env;
2935 const ppc_def_t *def;
2937 def = cpu_ppc_find_by_name(cpu_model);
2938 if (!def)
2939 return NULL;
2941 env = qemu_mallocz(sizeof(CPUPPCState));
2942 cpu_exec_init(env);
2943 ppc_translate_init();
2944 env->cpu_model_str = cpu_model;
2945 cpu_ppc_register_internal(env, def);
2947 qemu_init_vcpu(env);
2949 return env;
2952 void cpu_ppc_close (CPUPPCState *env)
2954 /* Should also remove all opcode tables... */
2955 qemu_free(env);