get_maintainer: update to match qemu tree
[qemu.git] / target-ppc / helper.c
blobcf2a368b57bde791d6c83ac35a6563ea1f78c945
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>
25 #include "cpu.h"
26 #include "exec-all.h"
27 #include "helper_regs.h"
28 #include "qemu-common.h"
29 #include "kvm.h"
31 //#define DEBUG_MMU
32 //#define DEBUG_BATS
33 //#define DEBUG_SLB
34 //#define DEBUG_SOFTWARE_TLB
35 //#define DUMP_PAGE_TABLES
36 //#define DEBUG_EXCEPTIONS
37 //#define FLUSH_ALL_TLBS
39 #ifdef DEBUG_MMU
40 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
41 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
42 #else
43 # define LOG_MMU(...) do { } while (0)
44 # define LOG_MMU_STATE(...) do { } while (0)
45 #endif
48 #ifdef DEBUG_SOFTWARE_TLB
49 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
50 #else
51 # define LOG_SWTLB(...) do { } while (0)
52 #endif
54 #ifdef DEBUG_BATS
55 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
56 #else
57 # define LOG_BATS(...) do { } while (0)
58 #endif
60 #ifdef DEBUG_SLB
61 # define LOG_SLB(...) qemu_log(__VA_ARGS__)
62 #else
63 # define LOG_SLB(...) do { } while (0)
64 #endif
66 #ifdef DEBUG_EXCEPTIONS
67 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
68 #else
69 # define LOG_EXCP(...) do { } while (0)
70 #endif
72 /*****************************************************************************/
73 /* PowerPC Hypercall emulation */
75 void (*cpu_ppc_hypercall)(CPUState *);
77 /*****************************************************************************/
78 /* PowerPC MMU emulation */
80 #if defined(CONFIG_USER_ONLY)
81 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
82 int mmu_idx, int is_softmmu)
84 int exception, error_code;
86 if (rw == 2) {
87 exception = POWERPC_EXCP_ISI;
88 error_code = 0x40000000;
89 } else {
90 exception = POWERPC_EXCP_DSI;
91 error_code = 0x40000000;
92 if (rw)
93 error_code |= 0x02000000;
94 env->spr[SPR_DAR] = address;
95 env->spr[SPR_DSISR] = error_code;
97 env->exception_index = exception;
98 env->error_code = error_code;
100 return 1;
103 #else
104 /* Common routines used by software and hardware TLBs emulation */
105 static inline int pte_is_valid(target_ulong pte0)
107 return pte0 & 0x80000000 ? 1 : 0;
110 static inline void pte_invalidate(target_ulong *pte0)
112 *pte0 &= ~0x80000000;
115 #if defined(TARGET_PPC64)
116 static inline int pte64_is_valid(target_ulong pte0)
118 return pte0 & 0x0000000000000001ULL ? 1 : 0;
121 static inline void pte64_invalidate(target_ulong *pte0)
123 *pte0 &= ~0x0000000000000001ULL;
125 #endif
127 #define PTE_PTEM_MASK 0x7FFFFFBF
128 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
129 #if defined(TARGET_PPC64)
130 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
131 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
132 #endif
134 static inline int pp_check(int key, int pp, int nx)
136 int access;
138 /* Compute access rights */
139 /* When pp is 3/7, the result is undefined. Set it to noaccess */
140 access = 0;
141 if (key == 0) {
142 switch (pp) {
143 case 0x0:
144 case 0x1:
145 case 0x2:
146 access |= PAGE_WRITE;
147 /* No break here */
148 case 0x3:
149 case 0x6:
150 access |= PAGE_READ;
151 break;
153 } else {
154 switch (pp) {
155 case 0x0:
156 case 0x6:
157 access = 0;
158 break;
159 case 0x1:
160 case 0x3:
161 access = PAGE_READ;
162 break;
163 case 0x2:
164 access = PAGE_READ | PAGE_WRITE;
165 break;
168 if (nx == 0)
169 access |= PAGE_EXEC;
171 return access;
174 static inline int check_prot(int prot, int rw, int access_type)
176 int ret;
178 if (access_type == ACCESS_CODE) {
179 if (prot & PAGE_EXEC)
180 ret = 0;
181 else
182 ret = -2;
183 } else if (rw) {
184 if (prot & PAGE_WRITE)
185 ret = 0;
186 else
187 ret = -2;
188 } else {
189 if (prot & PAGE_READ)
190 ret = 0;
191 else
192 ret = -2;
195 return ret;
198 static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
199 target_ulong pte1, int h, int rw, int type)
201 target_ulong ptem, mmask;
202 int access, ret, pteh, ptev, pp;
204 ret = -1;
205 /* Check validity and table match */
206 #if defined(TARGET_PPC64)
207 if (is_64b) {
208 ptev = pte64_is_valid(pte0);
209 pteh = (pte0 >> 1) & 1;
210 } else
211 #endif
213 ptev = pte_is_valid(pte0);
214 pteh = (pte0 >> 6) & 1;
216 if (ptev && h == pteh) {
217 /* Check vsid & api */
218 #if defined(TARGET_PPC64)
219 if (is_64b) {
220 ptem = pte0 & PTE64_PTEM_MASK;
221 mmask = PTE64_CHECK_MASK;
222 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
223 ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
224 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
225 } else
226 #endif
228 ptem = pte0 & PTE_PTEM_MASK;
229 mmask = PTE_CHECK_MASK;
230 pp = pte1 & 0x00000003;
232 if (ptem == ctx->ptem) {
233 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
234 /* all matches should have equal RPN, WIMG & PP */
235 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
236 qemu_log("Bad RPN/WIMG/PP\n");
237 return -3;
240 /* Compute access rights */
241 access = pp_check(ctx->key, pp, ctx->nx);
242 /* Keep the matching PTE informations */
243 ctx->raddr = pte1;
244 ctx->prot = access;
245 ret = check_prot(ctx->prot, rw, type);
246 if (ret == 0) {
247 /* Access granted */
248 LOG_MMU("PTE access granted !\n");
249 } else {
250 /* Access right violation */
251 LOG_MMU("PTE access rejected\n");
256 return ret;
259 static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
260 target_ulong pte1, int h, int rw, int type)
262 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
265 #if defined(TARGET_PPC64)
266 static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
267 target_ulong pte1, int h, int rw, int type)
269 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
271 #endif
273 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
274 int ret, int rw)
276 int store = 0;
278 /* Update page flags */
279 if (!(*pte1p & 0x00000100)) {
280 /* Update accessed flag */
281 *pte1p |= 0x00000100;
282 store = 1;
284 if (!(*pte1p & 0x00000080)) {
285 if (rw == 1 && ret == 0) {
286 /* Update changed flag */
287 *pte1p |= 0x00000080;
288 store = 1;
289 } else {
290 /* Force page fault for first write access */
291 ctx->prot &= ~PAGE_WRITE;
295 return store;
298 /* Software driven TLB helpers */
299 static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
300 int is_code)
302 int nr;
304 /* Select TLB num in a way from address */
305 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
306 /* Select TLB way */
307 nr += env->tlb_per_way * way;
308 /* 6xx have separate TLBs for instructions and data */
309 if (is_code && env->id_tlbs == 1)
310 nr += env->nb_tlb;
312 return nr;
315 static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
317 ppc6xx_tlb_t *tlb;
318 int nr, max;
320 //LOG_SWTLB("Invalidate all TLBs\n");
321 /* Invalidate all defined software TLB */
322 max = env->nb_tlb;
323 if (env->id_tlbs == 1)
324 max *= 2;
325 for (nr = 0; nr < max; nr++) {
326 tlb = &env->tlb[nr].tlb6;
327 pte_invalidate(&tlb->pte0);
329 tlb_flush(env, 1);
332 static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
333 target_ulong eaddr,
334 int is_code, int match_epn)
336 #if !defined(FLUSH_ALL_TLBS)
337 ppc6xx_tlb_t *tlb;
338 int way, nr;
340 /* Invalidate ITLB + DTLB, all ways */
341 for (way = 0; way < env->nb_ways; way++) {
342 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
343 tlb = &env->tlb[nr].tlb6;
344 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
345 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
346 env->nb_tlb, eaddr);
347 pte_invalidate(&tlb->pte0);
348 tlb_flush_page(env, tlb->EPN);
351 #else
352 /* XXX: PowerPC specification say this is valid as well */
353 ppc6xx_tlb_invalidate_all(env);
354 #endif
357 static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
358 target_ulong eaddr, int is_code)
360 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
363 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
364 target_ulong pte0, target_ulong pte1)
366 ppc6xx_tlb_t *tlb;
367 int nr;
369 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
370 tlb = &env->tlb[nr].tlb6;
371 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
372 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
373 /* Invalidate any pending reference in Qemu for this virtual address */
374 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
375 tlb->pte0 = pte0;
376 tlb->pte1 = pte1;
377 tlb->EPN = EPN;
378 /* Store last way for LRU mechanism */
379 env->last_way = way;
382 static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
383 target_ulong eaddr, int rw, int access_type)
385 ppc6xx_tlb_t *tlb;
386 int nr, best, way;
387 int ret;
389 best = -1;
390 ret = -1; /* No TLB found */
391 for (way = 0; way < env->nb_ways; way++) {
392 nr = ppc6xx_tlb_getnum(env, eaddr, way,
393 access_type == ACCESS_CODE ? 1 : 0);
394 tlb = &env->tlb[nr].tlb6;
395 /* This test "emulates" the PTE index match for hardware TLBs */
396 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
397 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
398 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
399 pte_is_valid(tlb->pte0) ? "valid" : "inval",
400 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
401 continue;
403 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
404 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
405 pte_is_valid(tlb->pte0) ? "valid" : "inval",
406 tlb->EPN, eaddr, tlb->pte1,
407 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
408 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
409 case -3:
410 /* TLB inconsistency */
411 return -1;
412 case -2:
413 /* Access violation */
414 ret = -2;
415 best = nr;
416 break;
417 case -1:
418 default:
419 /* No match */
420 break;
421 case 0:
422 /* access granted */
423 /* XXX: we should go on looping to check all TLBs consistency
424 * but we can speed-up the whole thing as the
425 * result would be undefined if TLBs are not consistent.
427 ret = 0;
428 best = nr;
429 goto done;
432 if (best != -1) {
433 done:
434 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
435 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
436 /* Update page flags */
437 pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
440 return ret;
443 /* Perform BAT hit & translation */
444 static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
445 int *protp, target_ulong *BATu,
446 target_ulong *BATl)
448 target_ulong bl;
449 int pp, valid, prot;
451 bl = (*BATu & 0x00001FFC) << 15;
452 valid = 0;
453 prot = 0;
454 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
455 ((msr_pr != 0) && (*BATu & 0x00000001))) {
456 valid = 1;
457 pp = *BATl & 0x00000003;
458 if (pp != 0) {
459 prot = PAGE_READ | PAGE_EXEC;
460 if (pp == 0x2)
461 prot |= PAGE_WRITE;
464 *blp = bl;
465 *validp = valid;
466 *protp = prot;
469 static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
470 int *validp, int *protp,
471 target_ulong *BATu, target_ulong *BATl)
473 target_ulong bl;
474 int key, pp, valid, prot;
476 bl = (*BATl & 0x0000003F) << 17;
477 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
478 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
479 prot = 0;
480 valid = (*BATl >> 6) & 1;
481 if (valid) {
482 pp = *BATu & 0x00000003;
483 if (msr_pr == 0)
484 key = (*BATu >> 3) & 1;
485 else
486 key = (*BATu >> 2) & 1;
487 prot = pp_check(key, pp, 0);
489 *blp = bl;
490 *validp = valid;
491 *protp = prot;
494 static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
495 int rw, int type)
497 target_ulong *BATlt, *BATut, *BATu, *BATl;
498 target_ulong BEPIl, BEPIu, bl;
499 int i, valid, prot;
500 int ret = -1;
502 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
503 type == ACCESS_CODE ? 'I' : 'D', virtual);
504 switch (type) {
505 case ACCESS_CODE:
506 BATlt = env->IBAT[1];
507 BATut = env->IBAT[0];
508 break;
509 default:
510 BATlt = env->DBAT[1];
511 BATut = env->DBAT[0];
512 break;
514 for (i = 0; i < env->nb_BATs; i++) {
515 BATu = &BATut[i];
516 BATl = &BATlt[i];
517 BEPIu = *BATu & 0xF0000000;
518 BEPIl = *BATu & 0x0FFE0000;
519 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
520 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
521 } else {
522 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
524 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
525 " BATl " TARGET_FMT_lx "\n", __func__,
526 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
527 if ((virtual & 0xF0000000) == BEPIu &&
528 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
529 /* BAT matches */
530 if (valid != 0) {
531 /* Get physical address */
532 ctx->raddr = (*BATl & 0xF0000000) |
533 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
534 (virtual & 0x0001F000);
535 /* Compute access rights */
536 ctx->prot = prot;
537 ret = check_prot(ctx->prot, rw, type);
538 if (ret == 0)
539 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
540 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
541 ctx->prot & PAGE_WRITE ? 'W' : '-');
542 break;
546 if (ret < 0) {
547 #if defined(DEBUG_BATS)
548 if (qemu_log_enabled()) {
549 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
550 for (i = 0; i < 4; i++) {
551 BATu = &BATut[i];
552 BATl = &BATlt[i];
553 BEPIu = *BATu & 0xF0000000;
554 BEPIl = *BATu & 0x0FFE0000;
555 bl = (*BATu & 0x00001FFC) << 15;
556 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
557 " BATl " TARGET_FMT_lx " \n\t" TARGET_FMT_lx " "
558 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
559 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
560 *BATu, *BATl, BEPIu, BEPIl, bl);
563 #endif
565 /* No hit */
566 return ret;
569 static inline target_phys_addr_t get_pteg_offset(CPUState *env,
570 target_phys_addr_t hash,
571 int pte_size)
573 return (hash * pte_size * 8) & env->htab_mask;
576 /* PTE table lookup */
577 static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
578 int rw, int type, int target_page_bits)
580 target_phys_addr_t pteg_off;
581 target_ulong pte0, pte1;
582 int i, good = -1;
583 int ret, r;
585 ret = -1; /* No entry found */
586 pteg_off = get_pteg_offset(env, ctx->hash[h],
587 is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
588 for (i = 0; i < 8; i++) {
589 #if defined(TARGET_PPC64)
590 if (is_64b) {
591 if (env->external_htab) {
592 pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
593 pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
594 } else {
595 pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
596 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
599 /* We have a TLB that saves 4K pages, so let's
600 * split a huge page to 4k chunks */
601 if (target_page_bits != TARGET_PAGE_BITS)
602 pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
603 & TARGET_PAGE_MASK;
605 r = pte64_check(ctx, pte0, pte1, h, rw, type);
606 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
607 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
608 pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
609 (int)((pte0 >> 1) & 1), ctx->ptem);
610 } else
611 #endif
613 if (env->external_htab) {
614 pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
615 pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
616 } else {
617 pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
618 pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
620 r = pte32_check(ctx, pte0, pte1, h, rw, type);
621 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
622 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
623 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
624 (int)((pte0 >> 6) & 1), ctx->ptem);
626 switch (r) {
627 case -3:
628 /* PTE inconsistency */
629 return -1;
630 case -2:
631 /* Access violation */
632 ret = -2;
633 good = i;
634 break;
635 case -1:
636 default:
637 /* No PTE match */
638 break;
639 case 0:
640 /* access granted */
641 /* XXX: we should go on looping to check all PTEs consistency
642 * but if we can speed-up the whole thing as the
643 * result would be undefined if PTEs are not consistent.
645 ret = 0;
646 good = i;
647 goto done;
650 if (good != -1) {
651 done:
652 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
653 ctx->raddr, ctx->prot, ret);
654 /* Update page flags */
655 pte1 = ctx->raddr;
656 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
657 #if defined(TARGET_PPC64)
658 if (is_64b) {
659 if (env->external_htab) {
660 stq_p(env->external_htab + pteg_off + (good * 16) + 8,
661 pte1);
662 } else {
663 stq_phys_notdirty(env->htab_base + pteg_off +
664 (good * 16) + 8, pte1);
666 } else
667 #endif
669 if (env->external_htab) {
670 stl_p(env->external_htab + pteg_off + (good * 8) + 4,
671 pte1);
672 } else {
673 stl_phys_notdirty(env->htab_base + pteg_off +
674 (good * 8) + 4, pte1);
680 return ret;
683 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
684 int type, int target_page_bits)
686 #if defined(TARGET_PPC64)
687 if (env->mmu_model & POWERPC_MMU_64)
688 return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
689 #endif
691 return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
694 #if defined(TARGET_PPC64)
695 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
697 uint64_t esid_256M, esid_1T;
698 int n;
700 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
702 esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
703 esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
705 for (n = 0; n < env->slb_nr; n++) {
706 ppc_slb_t *slb = &env->slb[n];
708 LOG_SLB("%s: slot %d %016" PRIx64 " %016"
709 PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
710 /* We check for 1T matches on all MMUs here - if the MMU
711 * doesn't have 1T segment support, we will have prevented 1T
712 * entries from being inserted in the slbmte code. */
713 if (((slb->esid == esid_256M) &&
714 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
715 || ((slb->esid == esid_1T) &&
716 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
717 return slb;
721 return NULL;
724 void ppc_slb_invalidate_all (CPUPPCState *env)
726 int n, do_invalidate;
728 do_invalidate = 0;
729 /* XXX: Warning: slbia never invalidates the first segment */
730 for (n = 1; n < env->slb_nr; n++) {
731 ppc_slb_t *slb = &env->slb[n];
733 if (slb->esid & SLB_ESID_V) {
734 slb->esid &= ~SLB_ESID_V;
735 /* XXX: given the fact that segment size is 256 MB or 1TB,
736 * and we still don't have a tlb_flush_mask(env, n, mask)
737 * in Qemu, we just invalidate all TLBs
739 do_invalidate = 1;
742 if (do_invalidate)
743 tlb_flush(env, 1);
746 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
748 ppc_slb_t *slb;
750 slb = slb_lookup(env, T0);
751 if (!slb) {
752 return;
755 if (slb->esid & SLB_ESID_V) {
756 slb->esid &= ~SLB_ESID_V;
758 /* XXX: given the fact that segment size is 256 MB or 1TB,
759 * and we still don't have a tlb_flush_mask(env, n, mask)
760 * in Qemu, we just invalidate all TLBs
762 tlb_flush(env, 1);
766 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
768 int slot = rb & 0xfff;
769 ppc_slb_t *slb = &env->slb[slot];
771 if (rb & (0x1000 - env->slb_nr)) {
772 return -1; /* Reserved bits set or slot too high */
774 if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
775 return -1; /* Bad segment size */
777 if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
778 return -1; /* 1T segment on MMU that doesn't support it */
781 /* Mask out the slot number as we store the entry */
782 slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
783 slb->vsid = rs;
785 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
786 " %016" PRIx64 "\n", __func__, slot, rb, rs,
787 slb->esid, slb->vsid);
789 return 0;
792 int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
794 int slot = rb & 0xfff;
795 ppc_slb_t *slb = &env->slb[slot];
797 if (slot >= env->slb_nr) {
798 return -1;
801 *rt = slb->esid;
802 return 0;
805 int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
807 int slot = rb & 0xfff;
808 ppc_slb_t *slb = &env->slb[slot];
810 if (slot >= env->slb_nr) {
811 return -1;
814 *rt = slb->vsid;
815 return 0;
817 #endif /* defined(TARGET_PPC64) */
819 /* Perform segment based translation */
820 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
821 target_ulong eaddr, int rw, int type)
823 target_phys_addr_t hash;
824 target_ulong vsid;
825 int ds, pr, target_page_bits;
826 int ret, ret2;
828 pr = msr_pr;
829 ctx->eaddr = eaddr;
830 #if defined(TARGET_PPC64)
831 if (env->mmu_model & POWERPC_MMU_64) {
832 ppc_slb_t *slb;
833 target_ulong pageaddr;
834 int segment_bits;
836 LOG_MMU("Check SLBs\n");
837 slb = slb_lookup(env, eaddr);
838 if (!slb) {
839 return -5;
842 if (slb->vsid & SLB_VSID_B) {
843 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
844 segment_bits = 40;
845 } else {
846 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
847 segment_bits = 28;
850 target_page_bits = (slb->vsid & SLB_VSID_L)
851 ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
852 ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
853 : (slb->vsid & SLB_VSID_KS));
854 ds = 0;
855 ctx->nx = !!(slb->vsid & SLB_VSID_N);
857 pageaddr = eaddr & ((1ULL << segment_bits)
858 - (1ULL << target_page_bits));
859 if (slb->vsid & SLB_VSID_B) {
860 hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
861 } else {
862 hash = vsid ^ (pageaddr >> target_page_bits);
864 /* Only 5 bits of the page index are used in the AVPN */
865 ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
866 ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
867 } else
868 #endif /* defined(TARGET_PPC64) */
870 target_ulong sr, pgidx;
872 sr = env->sr[eaddr >> 28];
873 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
874 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
875 ds = sr & 0x80000000 ? 1 : 0;
876 ctx->nx = sr & 0x10000000 ? 1 : 0;
877 vsid = sr & 0x00FFFFFF;
878 target_page_bits = TARGET_PAGE_BITS;
879 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
880 TARGET_FMT_lx " lr=" TARGET_FMT_lx
881 " ir=%d dr=%d pr=%d %d t=%d\n",
882 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
883 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
884 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
885 hash = vsid ^ pgidx;
886 ctx->ptem = (vsid << 7) | (pgidx >> 10);
888 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
889 ctx->key, ds, ctx->nx, vsid);
890 ret = -1;
891 if (!ds) {
892 /* Check if instruction fetch is allowed, if needed */
893 if (type != ACCESS_CODE || ctx->nx == 0) {
894 /* Page address translation */
895 LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
896 " hash " TARGET_FMT_plx "\n",
897 env->htab_base, env->htab_mask, hash);
898 ctx->hash[0] = hash;
899 ctx->hash[1] = ~hash;
901 /* Initialize real address with an invalid value */
902 ctx->raddr = (target_phys_addr_t)-1ULL;
903 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
904 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
905 /* Software TLB search */
906 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
907 } else {
908 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
909 " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
910 " hash=" TARGET_FMT_plx "\n",
911 env->htab_base, env->htab_mask, vsid, ctx->ptem,
912 ctx->hash[0]);
913 /* Primary table lookup */
914 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
915 if (ret < 0) {
916 /* Secondary table lookup */
917 if (eaddr != 0xEFFFFFFF)
918 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
919 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
920 " hash=" TARGET_FMT_plx "\n", env->htab_base,
921 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
922 ret2 = find_pte(env, ctx, 1, rw, type,
923 target_page_bits);
924 if (ret2 != -1)
925 ret = ret2;
928 #if defined (DUMP_PAGE_TABLES)
929 if (qemu_log_enabled()) {
930 target_phys_addr_t curaddr;
931 uint32_t a0, a1, a2, a3;
932 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
933 "\n", sdr, mask + 0x80);
934 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
935 curaddr += 16) {
936 a0 = ldl_phys(curaddr);
937 a1 = ldl_phys(curaddr + 4);
938 a2 = ldl_phys(curaddr + 8);
939 a3 = ldl_phys(curaddr + 12);
940 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
941 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
942 curaddr, a0, a1, a2, a3);
946 #endif
947 } else {
948 LOG_MMU("No access allowed\n");
949 ret = -3;
951 } else {
952 LOG_MMU("direct store...\n");
953 /* Direct-store segment : absolutely *BUGGY* for now */
954 switch (type) {
955 case ACCESS_INT:
956 /* Integer load/store : only access allowed */
957 break;
958 case ACCESS_CODE:
959 /* No code fetch is allowed in direct-store areas */
960 return -4;
961 case ACCESS_FLOAT:
962 /* Floating point load/store */
963 return -4;
964 case ACCESS_RES:
965 /* lwarx, ldarx or srwcx. */
966 return -4;
967 case ACCESS_CACHE:
968 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
969 /* Should make the instruction do no-op.
970 * As it already do no-op, it's quite easy :-)
972 ctx->raddr = eaddr;
973 return 0;
974 case ACCESS_EXT:
975 /* eciwx or ecowx */
976 return -4;
977 default:
978 qemu_log("ERROR: instruction should not need "
979 "address translation\n");
980 return -4;
982 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
983 ctx->raddr = eaddr;
984 ret = 2;
985 } else {
986 ret = -2;
990 return ret;
993 /* Generic TLB check function for embedded PowerPC implementations */
994 int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
995 target_phys_addr_t *raddrp,
996 target_ulong address, uint32_t pid, int ext,
997 int i)
999 target_ulong mask;
1001 /* Check valid flag */
1002 if (!(tlb->prot & PAGE_VALID)) {
1003 return -1;
1005 mask = ~(tlb->size - 1);
1006 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1007 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1008 mask, (uint32_t)tlb->PID, tlb->prot);
1009 /* Check PID */
1010 if (tlb->PID != 0 && tlb->PID != pid)
1011 return -1;
1012 /* Check effective address */
1013 if ((address & mask) != tlb->EPN)
1014 return -1;
1015 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1016 #if (TARGET_PHYS_ADDR_BITS >= 36)
1017 if (ext) {
1018 /* Extend the physical address to 36 bits */
1019 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1021 #endif
1023 return 0;
1026 /* Generic TLB search function for PowerPC embedded implementations */
1027 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1029 ppcemb_tlb_t *tlb;
1030 target_phys_addr_t raddr;
1031 int i, ret;
1033 /* Default return value is no match */
1034 ret = -1;
1035 for (i = 0; i < env->nb_tlb; i++) {
1036 tlb = &env->tlb[i].tlbe;
1037 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1038 ret = i;
1039 break;
1043 return ret;
1046 /* Helpers specific to PowerPC 40x implementations */
1047 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1049 ppcemb_tlb_t *tlb;
1050 int i;
1052 for (i = 0; i < env->nb_tlb; i++) {
1053 tlb = &env->tlb[i].tlbe;
1054 tlb->prot &= ~PAGE_VALID;
1056 tlb_flush(env, 1);
1059 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1060 target_ulong eaddr, uint32_t pid)
1062 #if !defined(FLUSH_ALL_TLBS)
1063 ppcemb_tlb_t *tlb;
1064 target_phys_addr_t raddr;
1065 target_ulong page, end;
1066 int i;
1068 for (i = 0; i < env->nb_tlb; i++) {
1069 tlb = &env->tlb[i].tlbe;
1070 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1071 end = tlb->EPN + tlb->size;
1072 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1073 tlb_flush_page(env, page);
1074 tlb->prot &= ~PAGE_VALID;
1075 break;
1078 #else
1079 ppc4xx_tlb_invalidate_all(env);
1080 #endif
1083 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1084 target_ulong address, int rw, int access_type)
1086 ppcemb_tlb_t *tlb;
1087 target_phys_addr_t raddr;
1088 int i, ret, zsel, zpr, pr;
1090 ret = -1;
1091 raddr = (target_phys_addr_t)-1ULL;
1092 pr = msr_pr;
1093 for (i = 0; i < env->nb_tlb; i++) {
1094 tlb = &env->tlb[i].tlbe;
1095 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1096 env->spr[SPR_40x_PID], 0, i) < 0)
1097 continue;
1098 zsel = (tlb->attr >> 4) & 0xF;
1099 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1100 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1101 __func__, i, zsel, zpr, rw, tlb->attr);
1102 /* Check execute enable bit */
1103 switch (zpr) {
1104 case 0x2:
1105 if (pr != 0)
1106 goto check_perms;
1107 /* No break here */
1108 case 0x3:
1109 /* All accesses granted */
1110 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1111 ret = 0;
1112 break;
1113 case 0x0:
1114 if (pr != 0) {
1115 /* Raise Zone protection fault. */
1116 env->spr[SPR_40x_ESR] = 1 << 22;
1117 ctx->prot = 0;
1118 ret = -2;
1119 break;
1121 /* No break here */
1122 case 0x1:
1123 check_perms:
1124 /* Check from TLB entry */
1125 ctx->prot = tlb->prot;
1126 ret = check_prot(ctx->prot, rw, access_type);
1127 if (ret == -2)
1128 env->spr[SPR_40x_ESR] = 0;
1129 break;
1131 if (ret >= 0) {
1132 ctx->raddr = raddr;
1133 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1134 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1135 ret);
1136 return 0;
1139 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1140 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1142 return ret;
1145 void store_40x_sler (CPUPPCState *env, uint32_t val)
1147 /* XXX: TO BE FIXED */
1148 if (val != 0x00000000) {
1149 cpu_abort(env, "Little-endian regions are not supported by now\n");
1151 env->spr[SPR_405_SLER] = val;
1154 static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1155 target_phys_addr_t *raddr, int *prot,
1156 target_ulong address, int rw,
1157 int access_type, int i)
1159 int ret, _prot;
1161 if (ppcemb_tlb_check(env, tlb, raddr, address,
1162 env->spr[SPR_BOOKE_PID],
1163 !env->nb_pids, i) >= 0) {
1164 goto found_tlb;
1167 if (env->spr[SPR_BOOKE_PID1] &&
1168 ppcemb_tlb_check(env, tlb, raddr, address,
1169 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1170 goto found_tlb;
1173 if (env->spr[SPR_BOOKE_PID2] &&
1174 ppcemb_tlb_check(env, tlb, raddr, address,
1175 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1176 goto found_tlb;
1179 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1180 return -1;
1182 found_tlb:
1184 if (msr_pr != 0) {
1185 _prot = tlb->prot & 0xF;
1186 } else {
1187 _prot = (tlb->prot >> 4) & 0xF;
1190 /* Check the address space */
1191 if (access_type == ACCESS_CODE) {
1192 if (msr_ir != (tlb->attr & 1)) {
1193 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1194 return -1;
1197 *prot = _prot;
1198 if (_prot & PAGE_EXEC) {
1199 LOG_SWTLB("%s: good TLB!\n", __func__);
1200 return 0;
1203 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1204 ret = -3;
1205 } else {
1206 if (msr_dr != (tlb->attr & 1)) {
1207 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1208 return -1;
1211 *prot = _prot;
1212 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1213 LOG_SWTLB("%s: found TLB!\n", __func__);
1214 return 0;
1217 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1218 ret = -2;
1221 return ret;
1224 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1225 target_ulong address, int rw,
1226 int access_type)
1228 ppcemb_tlb_t *tlb;
1229 target_phys_addr_t raddr;
1230 int i, ret;
1232 ret = -1;
1233 raddr = (target_phys_addr_t)-1ULL;
1234 for (i = 0; i < env->nb_tlb; i++) {
1235 tlb = &env->tlb[i].tlbe;
1236 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1237 access_type, i);
1238 if (!ret) {
1239 break;
1243 if (ret >= 0) {
1244 ctx->raddr = raddr;
1245 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1246 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1247 ret);
1248 } else {
1249 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1250 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1253 return ret;
1256 void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1258 int tlb_size;
1259 int i, j;
1260 ppc_tlb_t *tlb = env->tlb;
1262 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1263 if (flags & (1 << i)) {
1264 tlb_size = booke206_tlb_size(env, i);
1265 for (j = 0; j < tlb_size; j++) {
1266 if (!check_iprot || !(tlb[j].tlbe.attr & MAS1_IPROT)) {
1267 tlb[j].tlbe.prot = 0;
1271 tlb += booke206_tlb_size(env, i);
1274 tlb_flush(env, 1);
1277 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1278 target_ulong address, int rw,
1279 int access_type)
1281 ppcemb_tlb_t *tlb;
1282 target_phys_addr_t raddr;
1283 int i, j, ret;
1285 ret = -1;
1286 raddr = (target_phys_addr_t)-1ULL;
1288 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1289 int ways = booke206_tlb_ways(env, i);
1291 for (j = 0; j < ways; j++) {
1292 tlb = booke206_get_tlbe(env, i, address, j);
1293 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1294 access_type, j);
1295 if (ret != -1) {
1296 goto found_tlb;
1301 found_tlb:
1303 if (ret >= 0) {
1304 ctx->raddr = raddr;
1305 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1306 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1307 ret);
1308 } else {
1309 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1310 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1313 return ret;
1316 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1317 target_ulong eaddr, int rw)
1319 int in_plb, ret;
1321 ctx->raddr = eaddr;
1322 ctx->prot = PAGE_READ | PAGE_EXEC;
1323 ret = 0;
1324 switch (env->mmu_model) {
1325 case POWERPC_MMU_32B:
1326 case POWERPC_MMU_601:
1327 case POWERPC_MMU_SOFT_6xx:
1328 case POWERPC_MMU_SOFT_74xx:
1329 case POWERPC_MMU_SOFT_4xx:
1330 case POWERPC_MMU_REAL:
1331 case POWERPC_MMU_BOOKE:
1332 ctx->prot |= PAGE_WRITE;
1333 break;
1334 #if defined(TARGET_PPC64)
1335 case POWERPC_MMU_620:
1336 case POWERPC_MMU_64B:
1337 case POWERPC_MMU_2_06:
1338 /* Real address are 60 bits long */
1339 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1340 ctx->prot |= PAGE_WRITE;
1341 break;
1342 #endif
1343 case POWERPC_MMU_SOFT_4xx_Z:
1344 if (unlikely(msr_pe != 0)) {
1345 /* 403 family add some particular protections,
1346 * using PBL/PBU registers for accesses with no translation.
1348 in_plb =
1349 /* Check PLB validity */
1350 (env->pb[0] < env->pb[1] &&
1351 /* and address in plb area */
1352 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1353 (env->pb[2] < env->pb[3] &&
1354 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1355 if (in_plb ^ msr_px) {
1356 /* Access in protected area */
1357 if (rw == 1) {
1358 /* Access is not allowed */
1359 ret = -2;
1361 } else {
1362 /* Read-write access is allowed */
1363 ctx->prot |= PAGE_WRITE;
1366 break;
1367 case POWERPC_MMU_MPC8xx:
1368 /* XXX: TODO */
1369 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1370 break;
1371 case POWERPC_MMU_BOOKE206:
1372 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1373 break;
1374 default:
1375 cpu_abort(env, "Unknown or invalid MMU model\n");
1376 return -1;
1379 return ret;
1382 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1383 int rw, int access_type)
1385 int ret;
1387 #if 0
1388 qemu_log("%s\n", __func__);
1389 #endif
1390 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1391 (access_type != ACCESS_CODE && msr_dr == 0)) {
1392 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1393 /* The BookE MMU always performs address translation. The
1394 IS and DS bits only affect the address space. */
1395 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1396 rw, access_type);
1397 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1398 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1399 access_type);
1400 } else {
1401 /* No address translation. */
1402 ret = check_physical(env, ctx, eaddr, rw);
1404 } else {
1405 ret = -1;
1406 switch (env->mmu_model) {
1407 case POWERPC_MMU_32B:
1408 case POWERPC_MMU_601:
1409 case POWERPC_MMU_SOFT_6xx:
1410 case POWERPC_MMU_SOFT_74xx:
1411 /* Try to find a BAT */
1412 if (env->nb_BATs != 0)
1413 ret = get_bat(env, ctx, eaddr, rw, access_type);
1414 #if defined(TARGET_PPC64)
1415 case POWERPC_MMU_620:
1416 case POWERPC_MMU_64B:
1417 case POWERPC_MMU_2_06:
1418 #endif
1419 if (ret < 0) {
1420 /* We didn't match any BAT entry or don't have BATs */
1421 ret = get_segment(env, ctx, eaddr, rw, access_type);
1423 break;
1424 case POWERPC_MMU_SOFT_4xx:
1425 case POWERPC_MMU_SOFT_4xx_Z:
1426 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1427 rw, access_type);
1428 break;
1429 case POWERPC_MMU_BOOKE:
1430 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1431 rw, access_type);
1432 break;
1433 case POWERPC_MMU_BOOKE206:
1434 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1435 access_type);
1436 break;
1437 case POWERPC_MMU_MPC8xx:
1438 /* XXX: TODO */
1439 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1440 break;
1441 case POWERPC_MMU_REAL:
1442 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1443 return -1;
1444 default:
1445 cpu_abort(env, "Unknown or invalid MMU model\n");
1446 return -1;
1449 #if 0
1450 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1451 __func__, eaddr, ret, ctx->raddr);
1452 #endif
1454 return ret;
1457 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1459 mmu_ctx_t ctx;
1461 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1462 return -1;
1464 return ctx.raddr & TARGET_PAGE_MASK;
1467 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1468 int rw)
1470 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1471 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1472 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1473 env->spr[SPR_BOOKE_MAS3] = 0;
1474 env->spr[SPR_BOOKE_MAS6] = 0;
1475 env->spr[SPR_BOOKE_MAS7] = 0;
1477 /* AS */
1478 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1479 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1480 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1483 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1484 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1486 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1487 case MAS4_TIDSELD_PID0:
1488 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1489 break;
1490 case MAS4_TIDSELD_PID1:
1491 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1492 break;
1493 case MAS4_TIDSELD_PID2:
1494 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1495 break;
1498 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1500 /* next victim logic */
1501 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1502 env->last_way++;
1503 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1504 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1507 /* Perform address translation */
1508 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1509 int mmu_idx, int is_softmmu)
1511 mmu_ctx_t ctx;
1512 int access_type;
1513 int ret = 0;
1515 if (rw == 2) {
1516 /* code access */
1517 rw = 0;
1518 access_type = ACCESS_CODE;
1519 } else {
1520 /* data access */
1521 access_type = env->access_type;
1523 ret = get_physical_address(env, &ctx, address, rw, access_type);
1524 if (ret == 0) {
1525 tlb_set_page(env, address & TARGET_PAGE_MASK,
1526 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1527 mmu_idx, TARGET_PAGE_SIZE);
1528 ret = 0;
1529 } else if (ret < 0) {
1530 LOG_MMU_STATE(env);
1531 if (access_type == ACCESS_CODE) {
1532 switch (ret) {
1533 case -1:
1534 /* No matches in page tables or TLB */
1535 switch (env->mmu_model) {
1536 case POWERPC_MMU_SOFT_6xx:
1537 env->exception_index = POWERPC_EXCP_IFTLB;
1538 env->error_code = 1 << 18;
1539 env->spr[SPR_IMISS] = address;
1540 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1541 goto tlb_miss;
1542 case POWERPC_MMU_SOFT_74xx:
1543 env->exception_index = POWERPC_EXCP_IFTLB;
1544 goto tlb_miss_74xx;
1545 case POWERPC_MMU_SOFT_4xx:
1546 case POWERPC_MMU_SOFT_4xx_Z:
1547 env->exception_index = POWERPC_EXCP_ITLB;
1548 env->error_code = 0;
1549 env->spr[SPR_40x_DEAR] = address;
1550 env->spr[SPR_40x_ESR] = 0x00000000;
1551 break;
1552 case POWERPC_MMU_32B:
1553 case POWERPC_MMU_601:
1554 #if defined(TARGET_PPC64)
1555 case POWERPC_MMU_620:
1556 case POWERPC_MMU_64B:
1557 case POWERPC_MMU_2_06:
1558 #endif
1559 env->exception_index = POWERPC_EXCP_ISI;
1560 env->error_code = 0x40000000;
1561 break;
1562 case POWERPC_MMU_BOOKE206:
1563 booke206_update_mas_tlb_miss(env, address, rw);
1564 /* fall through */
1565 case POWERPC_MMU_BOOKE:
1566 env->exception_index = POWERPC_EXCP_ITLB;
1567 env->error_code = 0;
1568 env->spr[SPR_BOOKE_DEAR] = address;
1569 return -1;
1570 case POWERPC_MMU_MPC8xx:
1571 /* XXX: TODO */
1572 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1573 break;
1574 case POWERPC_MMU_REAL:
1575 cpu_abort(env, "PowerPC in real mode should never raise "
1576 "any MMU exceptions\n");
1577 return -1;
1578 default:
1579 cpu_abort(env, "Unknown or invalid MMU model\n");
1580 return -1;
1582 break;
1583 case -2:
1584 /* Access rights violation */
1585 env->exception_index = POWERPC_EXCP_ISI;
1586 env->error_code = 0x08000000;
1587 break;
1588 case -3:
1589 /* No execute protection violation */
1590 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1591 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1592 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1594 env->exception_index = POWERPC_EXCP_ISI;
1595 env->error_code = 0x10000000;
1596 break;
1597 case -4:
1598 /* Direct store exception */
1599 /* No code fetch is allowed in direct-store areas */
1600 env->exception_index = POWERPC_EXCP_ISI;
1601 env->error_code = 0x10000000;
1602 break;
1603 #if defined(TARGET_PPC64)
1604 case -5:
1605 /* No match in segment table */
1606 if (env->mmu_model == POWERPC_MMU_620) {
1607 env->exception_index = POWERPC_EXCP_ISI;
1608 /* XXX: this might be incorrect */
1609 env->error_code = 0x40000000;
1610 } else {
1611 env->exception_index = POWERPC_EXCP_ISEG;
1612 env->error_code = 0;
1614 break;
1615 #endif
1617 } else {
1618 switch (ret) {
1619 case -1:
1620 /* No matches in page tables or TLB */
1621 switch (env->mmu_model) {
1622 case POWERPC_MMU_SOFT_6xx:
1623 if (rw == 1) {
1624 env->exception_index = POWERPC_EXCP_DSTLB;
1625 env->error_code = 1 << 16;
1626 } else {
1627 env->exception_index = POWERPC_EXCP_DLTLB;
1628 env->error_code = 0;
1630 env->spr[SPR_DMISS] = address;
1631 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1632 tlb_miss:
1633 env->error_code |= ctx.key << 19;
1634 env->spr[SPR_HASH1] = env->htab_base +
1635 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1636 env->spr[SPR_HASH2] = env->htab_base +
1637 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1638 break;
1639 case POWERPC_MMU_SOFT_74xx:
1640 if (rw == 1) {
1641 env->exception_index = POWERPC_EXCP_DSTLB;
1642 } else {
1643 env->exception_index = POWERPC_EXCP_DLTLB;
1645 tlb_miss_74xx:
1646 /* Implement LRU algorithm */
1647 env->error_code = ctx.key << 19;
1648 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1649 ((env->last_way + 1) & (env->nb_ways - 1));
1650 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1651 break;
1652 case POWERPC_MMU_SOFT_4xx:
1653 case POWERPC_MMU_SOFT_4xx_Z:
1654 env->exception_index = POWERPC_EXCP_DTLB;
1655 env->error_code = 0;
1656 env->spr[SPR_40x_DEAR] = address;
1657 if (rw)
1658 env->spr[SPR_40x_ESR] = 0x00800000;
1659 else
1660 env->spr[SPR_40x_ESR] = 0x00000000;
1661 break;
1662 case POWERPC_MMU_32B:
1663 case POWERPC_MMU_601:
1664 #if defined(TARGET_PPC64)
1665 case POWERPC_MMU_620:
1666 case POWERPC_MMU_64B:
1667 case POWERPC_MMU_2_06:
1668 #endif
1669 env->exception_index = POWERPC_EXCP_DSI;
1670 env->error_code = 0;
1671 env->spr[SPR_DAR] = address;
1672 if (rw == 1)
1673 env->spr[SPR_DSISR] = 0x42000000;
1674 else
1675 env->spr[SPR_DSISR] = 0x40000000;
1676 break;
1677 case POWERPC_MMU_MPC8xx:
1678 /* XXX: TODO */
1679 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1680 break;
1681 case POWERPC_MMU_BOOKE206:
1682 booke206_update_mas_tlb_miss(env, address, rw);
1683 /* fall through */
1684 case POWERPC_MMU_BOOKE:
1685 env->exception_index = POWERPC_EXCP_DTLB;
1686 env->error_code = 0;
1687 env->spr[SPR_BOOKE_DEAR] = address;
1688 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1689 return -1;
1690 case POWERPC_MMU_REAL:
1691 cpu_abort(env, "PowerPC in real mode should never raise "
1692 "any MMU exceptions\n");
1693 return -1;
1694 default:
1695 cpu_abort(env, "Unknown or invalid MMU model\n");
1696 return -1;
1698 break;
1699 case -2:
1700 /* Access rights violation */
1701 env->exception_index = POWERPC_EXCP_DSI;
1702 env->error_code = 0;
1703 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1704 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1705 env->spr[SPR_40x_DEAR] = address;
1706 if (rw) {
1707 env->spr[SPR_40x_ESR] |= 0x00800000;
1709 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1710 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1711 env->spr[SPR_BOOKE_DEAR] = address;
1712 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1713 } else {
1714 env->spr[SPR_DAR] = address;
1715 if (rw == 1) {
1716 env->spr[SPR_DSISR] = 0x0A000000;
1717 } else {
1718 env->spr[SPR_DSISR] = 0x08000000;
1721 break;
1722 case -4:
1723 /* Direct store exception */
1724 switch (access_type) {
1725 case ACCESS_FLOAT:
1726 /* Floating point load/store */
1727 env->exception_index = POWERPC_EXCP_ALIGN;
1728 env->error_code = POWERPC_EXCP_ALIGN_FP;
1729 env->spr[SPR_DAR] = address;
1730 break;
1731 case ACCESS_RES:
1732 /* lwarx, ldarx or stwcx. */
1733 env->exception_index = POWERPC_EXCP_DSI;
1734 env->error_code = 0;
1735 env->spr[SPR_DAR] = address;
1736 if (rw == 1)
1737 env->spr[SPR_DSISR] = 0x06000000;
1738 else
1739 env->spr[SPR_DSISR] = 0x04000000;
1740 break;
1741 case ACCESS_EXT:
1742 /* eciwx or ecowx */
1743 env->exception_index = POWERPC_EXCP_DSI;
1744 env->error_code = 0;
1745 env->spr[SPR_DAR] = address;
1746 if (rw == 1)
1747 env->spr[SPR_DSISR] = 0x06100000;
1748 else
1749 env->spr[SPR_DSISR] = 0x04100000;
1750 break;
1751 default:
1752 printf("DSI: invalid exception (%d)\n", ret);
1753 env->exception_index = POWERPC_EXCP_PROGRAM;
1754 env->error_code =
1755 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1756 env->spr[SPR_DAR] = address;
1757 break;
1759 break;
1760 #if defined(TARGET_PPC64)
1761 case -5:
1762 /* No match in segment table */
1763 if (env->mmu_model == POWERPC_MMU_620) {
1764 env->exception_index = POWERPC_EXCP_DSI;
1765 env->error_code = 0;
1766 env->spr[SPR_DAR] = address;
1767 /* XXX: this might be incorrect */
1768 if (rw == 1)
1769 env->spr[SPR_DSISR] = 0x42000000;
1770 else
1771 env->spr[SPR_DSISR] = 0x40000000;
1772 } else {
1773 env->exception_index = POWERPC_EXCP_DSEG;
1774 env->error_code = 0;
1775 env->spr[SPR_DAR] = address;
1777 break;
1778 #endif
1781 #if 0
1782 printf("%s: set exception to %d %02x\n", __func__,
1783 env->exception, env->error_code);
1784 #endif
1785 ret = 1;
1788 return ret;
1791 /*****************************************************************************/
1792 /* BATs management */
1793 #if !defined(FLUSH_ALL_TLBS)
1794 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1795 target_ulong mask)
1797 target_ulong base, end, page;
1799 base = BATu & ~0x0001FFFF;
1800 end = base + mask + 0x00020000;
1801 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1802 TARGET_FMT_lx ")\n", base, end, mask);
1803 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1804 tlb_flush_page(env, page);
1805 LOG_BATS("Flush done\n");
1807 #endif
1809 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1810 target_ulong value)
1812 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1813 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1816 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1818 target_ulong mask;
1820 dump_store_bat(env, 'I', 0, nr, value);
1821 if (env->IBAT[0][nr] != value) {
1822 mask = (value << 15) & 0x0FFE0000UL;
1823 #if !defined(FLUSH_ALL_TLBS)
1824 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1825 #endif
1826 /* When storing valid upper BAT, mask BEPI and BRPN
1827 * and invalidate all TLBs covered by this BAT
1829 mask = (value << 15) & 0x0FFE0000UL;
1830 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1831 (value & ~0x0001FFFFUL & ~mask);
1832 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1833 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1834 #if !defined(FLUSH_ALL_TLBS)
1835 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1836 #else
1837 tlb_flush(env, 1);
1838 #endif
1842 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1844 dump_store_bat(env, 'I', 1, nr, value);
1845 env->IBAT[1][nr] = value;
1848 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1850 target_ulong mask;
1852 dump_store_bat(env, 'D', 0, nr, value);
1853 if (env->DBAT[0][nr] != value) {
1854 /* When storing valid upper BAT, mask BEPI and BRPN
1855 * and invalidate all TLBs covered by this BAT
1857 mask = (value << 15) & 0x0FFE0000UL;
1858 #if !defined(FLUSH_ALL_TLBS)
1859 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1860 #endif
1861 mask = (value << 15) & 0x0FFE0000UL;
1862 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1863 (value & ~0x0001FFFFUL & ~mask);
1864 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1865 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1866 #if !defined(FLUSH_ALL_TLBS)
1867 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1868 #else
1869 tlb_flush(env, 1);
1870 #endif
1874 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1876 dump_store_bat(env, 'D', 1, nr, value);
1877 env->DBAT[1][nr] = value;
1880 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1882 target_ulong mask;
1883 #if defined(FLUSH_ALL_TLBS)
1884 int do_inval;
1885 #endif
1887 dump_store_bat(env, 'I', 0, nr, value);
1888 if (env->IBAT[0][nr] != value) {
1889 #if defined(FLUSH_ALL_TLBS)
1890 do_inval = 0;
1891 #endif
1892 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1893 if (env->IBAT[1][nr] & 0x40) {
1894 /* Invalidate BAT only if it is valid */
1895 #if !defined(FLUSH_ALL_TLBS)
1896 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1897 #else
1898 do_inval = 1;
1899 #endif
1901 /* When storing valid upper BAT, mask BEPI and BRPN
1902 * and invalidate all TLBs covered by this BAT
1904 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1905 (value & ~0x0001FFFFUL & ~mask);
1906 env->DBAT[0][nr] = env->IBAT[0][nr];
1907 if (env->IBAT[1][nr] & 0x40) {
1908 #if !defined(FLUSH_ALL_TLBS)
1909 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1910 #else
1911 do_inval = 1;
1912 #endif
1914 #if defined(FLUSH_ALL_TLBS)
1915 if (do_inval)
1916 tlb_flush(env, 1);
1917 #endif
1921 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1923 target_ulong mask;
1924 #if defined(FLUSH_ALL_TLBS)
1925 int do_inval;
1926 #endif
1928 dump_store_bat(env, 'I', 1, nr, value);
1929 if (env->IBAT[1][nr] != value) {
1930 #if defined(FLUSH_ALL_TLBS)
1931 do_inval = 0;
1932 #endif
1933 if (env->IBAT[1][nr] & 0x40) {
1934 #if !defined(FLUSH_ALL_TLBS)
1935 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1936 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1937 #else
1938 do_inval = 1;
1939 #endif
1941 if (value & 0x40) {
1942 #if !defined(FLUSH_ALL_TLBS)
1943 mask = (value << 17) & 0x0FFE0000UL;
1944 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1945 #else
1946 do_inval = 1;
1947 #endif
1949 env->IBAT[1][nr] = value;
1950 env->DBAT[1][nr] = value;
1951 #if defined(FLUSH_ALL_TLBS)
1952 if (do_inval)
1953 tlb_flush(env, 1);
1954 #endif
1958 /*****************************************************************************/
1959 /* TLB management */
1960 void ppc_tlb_invalidate_all (CPUPPCState *env)
1962 switch (env->mmu_model) {
1963 case POWERPC_MMU_SOFT_6xx:
1964 case POWERPC_MMU_SOFT_74xx:
1965 ppc6xx_tlb_invalidate_all(env);
1966 break;
1967 case POWERPC_MMU_SOFT_4xx:
1968 case POWERPC_MMU_SOFT_4xx_Z:
1969 ppc4xx_tlb_invalidate_all(env);
1970 break;
1971 case POWERPC_MMU_REAL:
1972 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1973 break;
1974 case POWERPC_MMU_MPC8xx:
1975 /* XXX: TODO */
1976 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1977 break;
1978 case POWERPC_MMU_BOOKE:
1979 tlb_flush(env, 1);
1980 break;
1981 case POWERPC_MMU_BOOKE206:
1982 booke206_flush_tlb(env, -1, 0);
1983 break;
1984 case POWERPC_MMU_32B:
1985 case POWERPC_MMU_601:
1986 #if defined(TARGET_PPC64)
1987 case POWERPC_MMU_620:
1988 case POWERPC_MMU_64B:
1989 case POWERPC_MMU_2_06:
1990 #endif /* defined(TARGET_PPC64) */
1991 tlb_flush(env, 1);
1992 break;
1993 default:
1994 /* XXX: TODO */
1995 cpu_abort(env, "Unknown MMU model\n");
1996 break;
2000 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2002 #if !defined(FLUSH_ALL_TLBS)
2003 addr &= TARGET_PAGE_MASK;
2004 switch (env->mmu_model) {
2005 case POWERPC_MMU_SOFT_6xx:
2006 case POWERPC_MMU_SOFT_74xx:
2007 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2008 if (env->id_tlbs == 1)
2009 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2010 break;
2011 case POWERPC_MMU_SOFT_4xx:
2012 case POWERPC_MMU_SOFT_4xx_Z:
2013 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2014 break;
2015 case POWERPC_MMU_REAL:
2016 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2017 break;
2018 case POWERPC_MMU_MPC8xx:
2019 /* XXX: TODO */
2020 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2021 break;
2022 case POWERPC_MMU_BOOKE:
2023 /* XXX: TODO */
2024 cpu_abort(env, "BookE MMU model is not implemented\n");
2025 break;
2026 case POWERPC_MMU_BOOKE206:
2027 /* XXX: TODO */
2028 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2029 break;
2030 case POWERPC_MMU_32B:
2031 case POWERPC_MMU_601:
2032 /* tlbie invalidate TLBs for all segments */
2033 addr &= ~((target_ulong)-1ULL << 28);
2034 /* XXX: this case should be optimized,
2035 * giving a mask to tlb_flush_page
2037 tlb_flush_page(env, addr | (0x0 << 28));
2038 tlb_flush_page(env, addr | (0x1 << 28));
2039 tlb_flush_page(env, addr | (0x2 << 28));
2040 tlb_flush_page(env, addr | (0x3 << 28));
2041 tlb_flush_page(env, addr | (0x4 << 28));
2042 tlb_flush_page(env, addr | (0x5 << 28));
2043 tlb_flush_page(env, addr | (0x6 << 28));
2044 tlb_flush_page(env, addr | (0x7 << 28));
2045 tlb_flush_page(env, addr | (0x8 << 28));
2046 tlb_flush_page(env, addr | (0x9 << 28));
2047 tlb_flush_page(env, addr | (0xA << 28));
2048 tlb_flush_page(env, addr | (0xB << 28));
2049 tlb_flush_page(env, addr | (0xC << 28));
2050 tlb_flush_page(env, addr | (0xD << 28));
2051 tlb_flush_page(env, addr | (0xE << 28));
2052 tlb_flush_page(env, addr | (0xF << 28));
2053 break;
2054 #if defined(TARGET_PPC64)
2055 case POWERPC_MMU_620:
2056 case POWERPC_MMU_64B:
2057 case POWERPC_MMU_2_06:
2058 /* tlbie invalidate TLBs for all segments */
2059 /* XXX: given the fact that there are too many segments to invalidate,
2060 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2061 * we just invalidate all TLBs
2063 tlb_flush(env, 1);
2064 break;
2065 #endif /* defined(TARGET_PPC64) */
2066 default:
2067 /* XXX: TODO */
2068 cpu_abort(env, "Unknown MMU model\n");
2069 break;
2071 #else
2072 ppc_tlb_invalidate_all(env);
2073 #endif
2076 /*****************************************************************************/
2077 /* Special registers manipulation */
2078 #if defined(TARGET_PPC64)
2079 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2081 if (env->asr != value) {
2082 env->asr = value;
2083 tlb_flush(env, 1);
2086 #endif
2088 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2090 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2091 if (env->spr[SPR_SDR1] != value) {
2092 env->spr[SPR_SDR1] = value;
2093 #if defined(TARGET_PPC64)
2094 if (env->mmu_model & POWERPC_MMU_64) {
2095 target_ulong htabsize = value & SDR_64_HTABSIZE;
2097 if (htabsize > 28) {
2098 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2099 " stored in SDR1\n", htabsize);
2100 htabsize = 28;
2102 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2103 env->htab_base = value & SDR_64_HTABORG;
2104 } else
2105 #endif /* defined(TARGET_PPC64) */
2107 /* FIXME: Should check for valid HTABMASK values */
2108 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2109 env->htab_base = value & SDR_32_HTABORG;
2111 tlb_flush(env, 1);
2115 #if defined(TARGET_PPC64)
2116 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2118 // XXX
2119 return 0;
2121 #endif
2123 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2125 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2126 srnum, value, env->sr[srnum]);
2127 #if defined(TARGET_PPC64)
2128 if (env->mmu_model & POWERPC_MMU_64) {
2129 uint64_t rb = 0, rs = 0;
2131 /* ESID = srnum */
2132 rb |= ((uint32_t)srnum & 0xf) << 28;
2133 /* Set the valid bit */
2134 rb |= 1 << 27;
2135 /* Index = ESID */
2136 rb |= (uint32_t)srnum;
2138 /* VSID = VSID */
2139 rs |= (value & 0xfffffff) << 12;
2140 /* flags = flags */
2141 rs |= ((value >> 27) & 0xf) << 8;
2143 ppc_store_slb(env, rb, rs);
2144 } else
2145 #endif
2146 if (env->sr[srnum] != value) {
2147 env->sr[srnum] = value;
2148 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2149 flusing the whole TLB. */
2150 #if !defined(FLUSH_ALL_TLBS) && 0
2152 target_ulong page, end;
2153 /* Invalidate 256 MB of virtual memory */
2154 page = (16 << 20) * srnum;
2155 end = page + (16 << 20);
2156 for (; page != end; page += TARGET_PAGE_SIZE)
2157 tlb_flush_page(env, page);
2159 #else
2160 tlb_flush(env, 1);
2161 #endif
2164 #endif /* !defined (CONFIG_USER_ONLY) */
2166 /* GDBstub can read and write MSR... */
2167 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2169 hreg_store_msr(env, value, 0);
2172 /*****************************************************************************/
2173 /* Exception processing */
2174 #if defined (CONFIG_USER_ONLY)
2175 void do_interrupt (CPUState *env)
2177 env->exception_index = POWERPC_EXCP_NONE;
2178 env->error_code = 0;
2181 void ppc_hw_interrupt (CPUState *env)
2183 env->exception_index = POWERPC_EXCP_NONE;
2184 env->error_code = 0;
2186 #else /* defined (CONFIG_USER_ONLY) */
2187 static inline void dump_syscall(CPUState *env)
2189 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2190 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2191 " nip=" TARGET_FMT_lx "\n",
2192 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2193 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2194 ppc_dump_gpr(env, 6), env->nip);
2197 /* Note that this function should be greatly optimized
2198 * when called with a constant excp, from ppc_hw_interrupt
2200 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2202 target_ulong msr, new_msr, vector;
2203 int srr0, srr1, asrr0, asrr1;
2204 int lpes0, lpes1, lev;
2206 if (0) {
2207 /* XXX: find a suitable condition to enable the hypervisor mode */
2208 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2209 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2210 } else {
2211 /* Those values ensure we won't enter the hypervisor mode */
2212 lpes0 = 0;
2213 lpes1 = 1;
2216 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2217 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2219 /* new srr1 value excluding must-be-zero bits */
2220 msr = env->msr & ~0x783f0000ULL;
2222 /* new interrupt handler msr */
2223 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2225 /* target registers */
2226 srr0 = SPR_SRR0;
2227 srr1 = SPR_SRR1;
2228 asrr0 = -1;
2229 asrr1 = -1;
2231 switch (excp) {
2232 case POWERPC_EXCP_NONE:
2233 /* Should never happen */
2234 return;
2235 case POWERPC_EXCP_CRITICAL: /* Critical input */
2236 switch (excp_model) {
2237 case POWERPC_EXCP_40x:
2238 srr0 = SPR_40x_SRR2;
2239 srr1 = SPR_40x_SRR3;
2240 break;
2241 case POWERPC_EXCP_BOOKE:
2242 srr0 = SPR_BOOKE_CSRR0;
2243 srr1 = SPR_BOOKE_CSRR1;
2244 break;
2245 case POWERPC_EXCP_G2:
2246 break;
2247 default:
2248 goto excp_invalid;
2250 goto store_next;
2251 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2252 if (msr_me == 0) {
2253 /* Machine check exception is not enabled.
2254 * Enter checkstop state.
2256 if (qemu_log_enabled()) {
2257 qemu_log("Machine check while not allowed. "
2258 "Entering checkstop state\n");
2259 } else {
2260 fprintf(stderr, "Machine check while not allowed. "
2261 "Entering checkstop state\n");
2263 env->halted = 1;
2264 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2266 if (0) {
2267 /* XXX: find a suitable condition to enable the hypervisor mode */
2268 new_msr |= (target_ulong)MSR_HVB;
2271 /* machine check exceptions don't have ME set */
2272 new_msr &= ~((target_ulong)1 << MSR_ME);
2274 /* XXX: should also have something loaded in DAR / DSISR */
2275 switch (excp_model) {
2276 case POWERPC_EXCP_40x:
2277 srr0 = SPR_40x_SRR2;
2278 srr1 = SPR_40x_SRR3;
2279 break;
2280 case POWERPC_EXCP_BOOKE:
2281 srr0 = SPR_BOOKE_MCSRR0;
2282 srr1 = SPR_BOOKE_MCSRR1;
2283 asrr0 = SPR_BOOKE_CSRR0;
2284 asrr1 = SPR_BOOKE_CSRR1;
2285 break;
2286 default:
2287 break;
2289 goto store_next;
2290 case POWERPC_EXCP_DSI: /* Data storage exception */
2291 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2292 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2293 if (lpes1 == 0)
2294 new_msr |= (target_ulong)MSR_HVB;
2295 goto store_next;
2296 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2297 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2298 "\n", msr, env->nip);
2299 if (lpes1 == 0)
2300 new_msr |= (target_ulong)MSR_HVB;
2301 msr |= env->error_code;
2302 goto store_next;
2303 case POWERPC_EXCP_EXTERNAL: /* External input */
2304 if (lpes0 == 1)
2305 new_msr |= (target_ulong)MSR_HVB;
2306 goto store_next;
2307 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2308 if (lpes1 == 0)
2309 new_msr |= (target_ulong)MSR_HVB;
2310 /* XXX: this is false */
2311 /* Get rS/rD and rA from faulting opcode */
2312 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2313 goto store_current;
2314 case POWERPC_EXCP_PROGRAM: /* Program exception */
2315 switch (env->error_code & ~0xF) {
2316 case POWERPC_EXCP_FP:
2317 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2318 LOG_EXCP("Ignore floating point exception\n");
2319 env->exception_index = POWERPC_EXCP_NONE;
2320 env->error_code = 0;
2321 return;
2323 if (lpes1 == 0)
2324 new_msr |= (target_ulong)MSR_HVB;
2325 msr |= 0x00100000;
2326 if (msr_fe0 == msr_fe1)
2327 goto store_next;
2328 msr |= 0x00010000;
2329 break;
2330 case POWERPC_EXCP_INVAL:
2331 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2332 if (lpes1 == 0)
2333 new_msr |= (target_ulong)MSR_HVB;
2334 msr |= 0x00080000;
2335 break;
2336 case POWERPC_EXCP_PRIV:
2337 if (lpes1 == 0)
2338 new_msr |= (target_ulong)MSR_HVB;
2339 msr |= 0x00040000;
2340 break;
2341 case POWERPC_EXCP_TRAP:
2342 if (lpes1 == 0)
2343 new_msr |= (target_ulong)MSR_HVB;
2344 msr |= 0x00020000;
2345 break;
2346 default:
2347 /* Should never occur */
2348 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2349 env->error_code);
2350 break;
2352 goto store_current;
2353 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2354 if (lpes1 == 0)
2355 new_msr |= (target_ulong)MSR_HVB;
2356 goto store_current;
2357 case POWERPC_EXCP_SYSCALL: /* System call exception */
2358 dump_syscall(env);
2359 lev = env->error_code;
2360 if ((lev == 1) && cpu_ppc_hypercall) {
2361 cpu_ppc_hypercall(env);
2362 return;
2364 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2365 new_msr |= (target_ulong)MSR_HVB;
2366 goto store_next;
2367 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2368 goto store_current;
2369 case POWERPC_EXCP_DECR: /* Decrementer exception */
2370 if (lpes1 == 0)
2371 new_msr |= (target_ulong)MSR_HVB;
2372 goto store_next;
2373 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2374 /* FIT on 4xx */
2375 LOG_EXCP("FIT exception\n");
2376 goto store_next;
2377 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2378 LOG_EXCP("WDT exception\n");
2379 switch (excp_model) {
2380 case POWERPC_EXCP_BOOKE:
2381 srr0 = SPR_BOOKE_CSRR0;
2382 srr1 = SPR_BOOKE_CSRR1;
2383 break;
2384 default:
2385 break;
2387 goto store_next;
2388 case POWERPC_EXCP_DTLB: /* Data TLB error */
2389 goto store_next;
2390 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2391 goto store_next;
2392 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2393 switch (excp_model) {
2394 case POWERPC_EXCP_BOOKE:
2395 srr0 = SPR_BOOKE_DSRR0;
2396 srr1 = SPR_BOOKE_DSRR1;
2397 asrr0 = SPR_BOOKE_CSRR0;
2398 asrr1 = SPR_BOOKE_CSRR1;
2399 break;
2400 default:
2401 break;
2403 /* XXX: TODO */
2404 cpu_abort(env, "Debug exception is not implemented yet !\n");
2405 goto store_next;
2406 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2407 goto store_current;
2408 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2409 /* XXX: TODO */
2410 cpu_abort(env, "Embedded floating point data exception "
2411 "is not implemented yet !\n");
2412 goto store_next;
2413 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2414 /* XXX: TODO */
2415 cpu_abort(env, "Embedded floating point round exception "
2416 "is not implemented yet !\n");
2417 goto store_next;
2418 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2419 /* XXX: TODO */
2420 cpu_abort(env,
2421 "Performance counter exception is not implemented yet !\n");
2422 goto store_next;
2423 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2424 /* XXX: TODO */
2425 cpu_abort(env,
2426 "Embedded doorbell interrupt is not implemented yet !\n");
2427 goto store_next;
2428 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2429 switch (excp_model) {
2430 case POWERPC_EXCP_BOOKE:
2431 srr0 = SPR_BOOKE_CSRR0;
2432 srr1 = SPR_BOOKE_CSRR1;
2433 break;
2434 default:
2435 break;
2437 /* XXX: TODO */
2438 cpu_abort(env, "Embedded doorbell critical interrupt "
2439 "is not implemented yet !\n");
2440 goto store_next;
2441 case POWERPC_EXCP_RESET: /* System reset exception */
2442 if (msr_pow) {
2443 /* indicate that we resumed from power save mode */
2444 msr |= 0x10000;
2445 } else {
2446 new_msr &= ~((target_ulong)1 << MSR_ME);
2449 if (0) {
2450 /* XXX: find a suitable condition to enable the hypervisor mode */
2451 new_msr |= (target_ulong)MSR_HVB;
2453 goto store_next;
2454 case POWERPC_EXCP_DSEG: /* Data segment exception */
2455 if (lpes1 == 0)
2456 new_msr |= (target_ulong)MSR_HVB;
2457 goto store_next;
2458 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2459 if (lpes1 == 0)
2460 new_msr |= (target_ulong)MSR_HVB;
2461 goto store_next;
2462 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2463 srr0 = SPR_HSRR0;
2464 srr1 = SPR_HSRR1;
2465 new_msr |= (target_ulong)MSR_HVB;
2466 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2467 goto store_next;
2468 case POWERPC_EXCP_TRACE: /* Trace exception */
2469 if (lpes1 == 0)
2470 new_msr |= (target_ulong)MSR_HVB;
2471 goto store_next;
2472 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2473 srr0 = SPR_HSRR0;
2474 srr1 = SPR_HSRR1;
2475 new_msr |= (target_ulong)MSR_HVB;
2476 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2477 goto store_next;
2478 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2479 srr0 = SPR_HSRR0;
2480 srr1 = SPR_HSRR1;
2481 new_msr |= (target_ulong)MSR_HVB;
2482 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2483 goto store_next;
2484 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2485 srr0 = SPR_HSRR0;
2486 srr1 = SPR_HSRR1;
2487 new_msr |= (target_ulong)MSR_HVB;
2488 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2489 goto store_next;
2490 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2491 srr0 = SPR_HSRR0;
2492 srr1 = SPR_HSRR1;
2493 new_msr |= (target_ulong)MSR_HVB;
2494 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2495 goto store_next;
2496 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2497 if (lpes1 == 0)
2498 new_msr |= (target_ulong)MSR_HVB;
2499 goto store_current;
2500 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2501 LOG_EXCP("PIT exception\n");
2502 goto store_next;
2503 case POWERPC_EXCP_IO: /* IO error exception */
2504 /* XXX: TODO */
2505 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2506 goto store_next;
2507 case POWERPC_EXCP_RUNM: /* Run mode exception */
2508 /* XXX: TODO */
2509 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2510 goto store_next;
2511 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2512 /* XXX: TODO */
2513 cpu_abort(env, "602 emulation trap exception "
2514 "is not implemented yet !\n");
2515 goto store_next;
2516 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2517 if (lpes1 == 0) /* XXX: check this */
2518 new_msr |= (target_ulong)MSR_HVB;
2519 switch (excp_model) {
2520 case POWERPC_EXCP_602:
2521 case POWERPC_EXCP_603:
2522 case POWERPC_EXCP_603E:
2523 case POWERPC_EXCP_G2:
2524 goto tlb_miss_tgpr;
2525 case POWERPC_EXCP_7x5:
2526 goto tlb_miss;
2527 case POWERPC_EXCP_74xx:
2528 goto tlb_miss_74xx;
2529 default:
2530 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2531 break;
2533 break;
2534 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2535 if (lpes1 == 0) /* XXX: check this */
2536 new_msr |= (target_ulong)MSR_HVB;
2537 switch (excp_model) {
2538 case POWERPC_EXCP_602:
2539 case POWERPC_EXCP_603:
2540 case POWERPC_EXCP_603E:
2541 case POWERPC_EXCP_G2:
2542 goto tlb_miss_tgpr;
2543 case POWERPC_EXCP_7x5:
2544 goto tlb_miss;
2545 case POWERPC_EXCP_74xx:
2546 goto tlb_miss_74xx;
2547 default:
2548 cpu_abort(env, "Invalid data load TLB miss exception\n");
2549 break;
2551 break;
2552 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2553 if (lpes1 == 0) /* XXX: check this */
2554 new_msr |= (target_ulong)MSR_HVB;
2555 switch (excp_model) {
2556 case POWERPC_EXCP_602:
2557 case POWERPC_EXCP_603:
2558 case POWERPC_EXCP_603E:
2559 case POWERPC_EXCP_G2:
2560 tlb_miss_tgpr:
2561 /* Swap temporary saved registers with GPRs */
2562 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2563 new_msr |= (target_ulong)1 << MSR_TGPR;
2564 hreg_swap_gpr_tgpr(env);
2566 goto tlb_miss;
2567 case POWERPC_EXCP_7x5:
2568 tlb_miss:
2569 #if defined (DEBUG_SOFTWARE_TLB)
2570 if (qemu_log_enabled()) {
2571 const char *es;
2572 target_ulong *miss, *cmp;
2573 int en;
2574 if (excp == POWERPC_EXCP_IFTLB) {
2575 es = "I";
2576 en = 'I';
2577 miss = &env->spr[SPR_IMISS];
2578 cmp = &env->spr[SPR_ICMP];
2579 } else {
2580 if (excp == POWERPC_EXCP_DLTLB)
2581 es = "DL";
2582 else
2583 es = "DS";
2584 en = 'D';
2585 miss = &env->spr[SPR_DMISS];
2586 cmp = &env->spr[SPR_DCMP];
2588 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2589 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2590 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2591 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2592 env->error_code);
2594 #endif
2595 msr |= env->crf[0] << 28;
2596 msr |= env->error_code; /* key, D/I, S/L bits */
2597 /* Set way using a LRU mechanism */
2598 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2599 break;
2600 case POWERPC_EXCP_74xx:
2601 tlb_miss_74xx:
2602 #if defined (DEBUG_SOFTWARE_TLB)
2603 if (qemu_log_enabled()) {
2604 const char *es;
2605 target_ulong *miss, *cmp;
2606 int en;
2607 if (excp == POWERPC_EXCP_IFTLB) {
2608 es = "I";
2609 en = 'I';
2610 miss = &env->spr[SPR_TLBMISS];
2611 cmp = &env->spr[SPR_PTEHI];
2612 } else {
2613 if (excp == POWERPC_EXCP_DLTLB)
2614 es = "DL";
2615 else
2616 es = "DS";
2617 en = 'D';
2618 miss = &env->spr[SPR_TLBMISS];
2619 cmp = &env->spr[SPR_PTEHI];
2621 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2622 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2623 env->error_code);
2625 #endif
2626 msr |= env->error_code; /* key bit */
2627 break;
2628 default:
2629 cpu_abort(env, "Invalid data store TLB miss exception\n");
2630 break;
2632 goto store_next;
2633 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2634 /* XXX: TODO */
2635 cpu_abort(env, "Floating point assist exception "
2636 "is not implemented yet !\n");
2637 goto store_next;
2638 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2639 /* XXX: TODO */
2640 cpu_abort(env, "DABR exception is not implemented yet !\n");
2641 goto store_next;
2642 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2643 /* XXX: TODO */
2644 cpu_abort(env, "IABR exception is not implemented yet !\n");
2645 goto store_next;
2646 case POWERPC_EXCP_SMI: /* System management interrupt */
2647 /* XXX: TODO */
2648 cpu_abort(env, "SMI exception is not implemented yet !\n");
2649 goto store_next;
2650 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2651 /* XXX: TODO */
2652 cpu_abort(env, "Thermal management exception "
2653 "is not implemented yet !\n");
2654 goto store_next;
2655 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2656 if (lpes1 == 0)
2657 new_msr |= (target_ulong)MSR_HVB;
2658 /* XXX: TODO */
2659 cpu_abort(env,
2660 "Performance counter exception is not implemented yet !\n");
2661 goto store_next;
2662 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2663 /* XXX: TODO */
2664 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2665 goto store_next;
2666 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2667 /* XXX: TODO */
2668 cpu_abort(env,
2669 "970 soft-patch exception is not implemented yet !\n");
2670 goto store_next;
2671 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2672 /* XXX: TODO */
2673 cpu_abort(env,
2674 "970 maintenance exception is not implemented yet !\n");
2675 goto store_next;
2676 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2677 /* XXX: TODO */
2678 cpu_abort(env, "Maskable external exception "
2679 "is not implemented yet !\n");
2680 goto store_next;
2681 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2682 /* XXX: TODO */
2683 cpu_abort(env, "Non maskable external exception "
2684 "is not implemented yet !\n");
2685 goto store_next;
2686 default:
2687 excp_invalid:
2688 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2689 break;
2690 store_current:
2691 /* save current instruction location */
2692 env->spr[srr0] = env->nip - 4;
2693 break;
2694 store_next:
2695 /* save next instruction location */
2696 env->spr[srr0] = env->nip;
2697 break;
2699 /* Save MSR */
2700 env->spr[srr1] = msr;
2701 /* If any alternate SRR register are defined, duplicate saved values */
2702 if (asrr0 != -1)
2703 env->spr[asrr0] = env->spr[srr0];
2704 if (asrr1 != -1)
2705 env->spr[asrr1] = env->spr[srr1];
2706 /* If we disactivated any translation, flush TLBs */
2707 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2708 tlb_flush(env, 1);
2710 if (msr_ile) {
2711 new_msr |= (target_ulong)1 << MSR_LE;
2714 /* Jump to handler */
2715 vector = env->excp_vectors[excp];
2716 if (vector == (target_ulong)-1ULL) {
2717 cpu_abort(env, "Raised an exception without defined vector %d\n",
2718 excp);
2720 vector |= env->excp_prefix;
2721 #if defined(TARGET_PPC64)
2722 if (excp_model == POWERPC_EXCP_BOOKE) {
2723 if (!msr_icm) {
2724 vector = (uint32_t)vector;
2725 } else {
2726 new_msr |= (target_ulong)1 << MSR_CM;
2728 } else {
2729 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2730 vector = (uint32_t)vector;
2731 } else {
2732 new_msr |= (target_ulong)1 << MSR_SF;
2735 #endif
2736 /* XXX: we don't use hreg_store_msr here as already have treated
2737 * any special case that could occur. Just store MSR and update hflags
2739 env->msr = new_msr & env->msr_mask;
2740 hreg_compute_hflags(env);
2741 env->nip = vector;
2742 /* Reset exception state */
2743 env->exception_index = POWERPC_EXCP_NONE;
2744 env->error_code = 0;
2746 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2747 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2748 /* XXX: The BookE changes address space when switching modes,
2749 we should probably implement that as different MMU indexes,
2750 but for the moment we do it the slow way and flush all. */
2751 tlb_flush(env, 1);
2755 void do_interrupt (CPUState *env)
2757 powerpc_excp(env, env->excp_model, env->exception_index);
2760 void ppc_hw_interrupt (CPUPPCState *env)
2762 int hdice;
2764 #if 0
2765 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2766 __func__, env, env->pending_interrupts,
2767 env->interrupt_request, (int)msr_me, (int)msr_ee);
2768 #endif
2769 /* External reset */
2770 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2771 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2772 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2773 return;
2775 /* Machine check exception */
2776 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2777 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2778 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2779 return;
2781 #if 0 /* TODO */
2782 /* External debug exception */
2783 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2784 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2785 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2786 return;
2788 #endif
2789 if (0) {
2790 /* XXX: find a suitable condition to enable the hypervisor mode */
2791 hdice = env->spr[SPR_LPCR] & 1;
2792 } else {
2793 hdice = 0;
2795 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2796 /* Hypervisor decrementer exception */
2797 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2798 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2799 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2800 return;
2803 if (msr_ce != 0) {
2804 /* External critical interrupt */
2805 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2806 /* Taking a critical external interrupt does not clear the external
2807 * critical interrupt status
2809 #if 0
2810 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2811 #endif
2812 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2813 return;
2816 if (msr_ee != 0) {
2817 /* Watchdog timer on embedded PowerPC */
2818 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2819 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2820 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2821 return;
2823 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2824 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2825 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2826 return;
2828 /* Fixed interval timer on embedded PowerPC */
2829 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2830 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2831 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2832 return;
2834 /* Programmable interval timer on embedded PowerPC */
2835 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2836 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2837 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2838 return;
2840 /* Decrementer exception */
2841 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2842 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2843 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2844 return;
2846 /* External interrupt */
2847 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2848 /* Taking an external interrupt does not clear the external
2849 * interrupt status
2851 #if 0
2852 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2853 #endif
2854 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2855 return;
2857 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2858 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2859 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2860 return;
2862 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2863 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2864 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2865 return;
2867 /* Thermal interrupt */
2868 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2869 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2870 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2871 return;
2875 #endif /* !CONFIG_USER_ONLY */
2877 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2879 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2880 TARGET_FMT_lx "\n", RA, msr);
2883 void cpu_reset(CPUPPCState *env)
2885 target_ulong msr;
2887 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2888 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2889 log_cpu_state(env, 0);
2892 msr = (target_ulong)0;
2893 if (0) {
2894 /* XXX: find a suitable condition to enable the hypervisor mode */
2895 msr |= (target_ulong)MSR_HVB;
2897 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2898 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2899 msr |= (target_ulong)1 << MSR_EP;
2900 #if defined (DO_SINGLE_STEP) && 0
2901 /* Single step trace mode */
2902 msr |= (target_ulong)1 << MSR_SE;
2903 msr |= (target_ulong)1 << MSR_BE;
2904 #endif
2905 #if defined(CONFIG_USER_ONLY)
2906 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2907 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2908 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2909 msr |= (target_ulong)1 << MSR_PR;
2910 #else
2911 env->excp_prefix = env->hreset_excp_prefix;
2912 env->nip = env->hreset_vector | env->excp_prefix;
2913 if (env->mmu_model != POWERPC_MMU_REAL)
2914 ppc_tlb_invalidate_all(env);
2915 #endif
2916 env->msr = msr & env->msr_mask;
2917 #if defined(TARGET_PPC64)
2918 if (env->mmu_model & POWERPC_MMU_64)
2919 env->msr |= (1ULL << MSR_SF);
2920 #endif
2921 hreg_compute_hflags(env);
2922 env->reserve_addr = (target_ulong)-1ULL;
2923 /* Be sure no exception or interrupt is pending */
2924 env->pending_interrupts = 0;
2925 env->exception_index = POWERPC_EXCP_NONE;
2926 env->error_code = 0;
2927 /* Flush all TLBs */
2928 tlb_flush(env, 1);
2931 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2933 CPUPPCState *env;
2934 const ppc_def_t *def;
2936 def = cpu_ppc_find_by_name(cpu_model);
2937 if (!def)
2938 return NULL;
2940 env = qemu_mallocz(sizeof(CPUPPCState));
2941 cpu_exec_init(env);
2942 ppc_translate_init();
2943 env->cpu_model_str = cpu_model;
2944 cpu_ppc_register_internal(env, def);
2946 qemu_init_vcpu(env);
2948 return env;
2951 void cpu_ppc_close (CPUPPCState *env)
2953 /* Should also remove all opcode tables... */
2954 qemu_free(env);