slirp: Silence warning on Haiku
[qemu/cris-port.git] / target-ppc / helper.c
blob3bc8a3459932e746f050f36c33039009e2d57133
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
74 /*****************************************************************************/
75 /* PowerPC MMU emulation */
77 #if defined(CONFIG_USER_ONLY)
78 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
79 int mmu_idx, int is_softmmu)
81 int exception, error_code;
83 if (rw == 2) {
84 exception = POWERPC_EXCP_ISI;
85 error_code = 0x40000000;
86 } else {
87 exception = POWERPC_EXCP_DSI;
88 error_code = 0x40000000;
89 if (rw)
90 error_code |= 0x02000000;
91 env->spr[SPR_DAR] = address;
92 env->spr[SPR_DSISR] = error_code;
94 env->exception_index = exception;
95 env->error_code = error_code;
97 return 1;
100 #else
101 /* Common routines used by software and hardware TLBs emulation */
102 static inline int pte_is_valid(target_ulong pte0)
104 return pte0 & 0x80000000 ? 1 : 0;
107 static inline void pte_invalidate(target_ulong *pte0)
109 *pte0 &= ~0x80000000;
112 #if defined(TARGET_PPC64)
113 static inline int pte64_is_valid(target_ulong pte0)
115 return pte0 & 0x0000000000000001ULL ? 1 : 0;
118 static inline void pte64_invalidate(target_ulong *pte0)
120 *pte0 &= ~0x0000000000000001ULL;
122 #endif
124 #define PTE_PTEM_MASK 0x7FFFFFBF
125 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
126 #if defined(TARGET_PPC64)
127 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
128 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
129 #endif
131 static inline int pp_check(int key, int pp, int nx)
133 int access;
135 /* Compute access rights */
136 /* When pp is 3/7, the result is undefined. Set it to noaccess */
137 access = 0;
138 if (key == 0) {
139 switch (pp) {
140 case 0x0:
141 case 0x1:
142 case 0x2:
143 access |= PAGE_WRITE;
144 /* No break here */
145 case 0x3:
146 case 0x6:
147 access |= PAGE_READ;
148 break;
150 } else {
151 switch (pp) {
152 case 0x0:
153 case 0x6:
154 access = 0;
155 break;
156 case 0x1:
157 case 0x3:
158 access = PAGE_READ;
159 break;
160 case 0x2:
161 access = PAGE_READ | PAGE_WRITE;
162 break;
165 if (nx == 0)
166 access |= PAGE_EXEC;
168 return access;
171 static inline int check_prot(int prot, int rw, int access_type)
173 int ret;
175 if (access_type == ACCESS_CODE) {
176 if (prot & PAGE_EXEC)
177 ret = 0;
178 else
179 ret = -2;
180 } else if (rw) {
181 if (prot & PAGE_WRITE)
182 ret = 0;
183 else
184 ret = -2;
185 } else {
186 if (prot & PAGE_READ)
187 ret = 0;
188 else
189 ret = -2;
192 return ret;
195 static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
196 target_ulong pte1, int h, int rw, int type)
198 target_ulong ptem, mmask;
199 int access, ret, pteh, ptev, pp;
201 ret = -1;
202 /* Check validity and table match */
203 #if defined(TARGET_PPC64)
204 if (is_64b) {
205 ptev = pte64_is_valid(pte0);
206 pteh = (pte0 >> 1) & 1;
207 } else
208 #endif
210 ptev = pte_is_valid(pte0);
211 pteh = (pte0 >> 6) & 1;
213 if (ptev && h == pteh) {
214 /* Check vsid & api */
215 #if defined(TARGET_PPC64)
216 if (is_64b) {
217 ptem = pte0 & PTE64_PTEM_MASK;
218 mmask = PTE64_CHECK_MASK;
219 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
220 ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
221 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
222 } else
223 #endif
225 ptem = pte0 & PTE_PTEM_MASK;
226 mmask = PTE_CHECK_MASK;
227 pp = pte1 & 0x00000003;
229 if (ptem == ctx->ptem) {
230 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
231 /* all matches should have equal RPN, WIMG & PP */
232 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
233 qemu_log("Bad RPN/WIMG/PP\n");
234 return -3;
237 /* Compute access rights */
238 access = pp_check(ctx->key, pp, ctx->nx);
239 /* Keep the matching PTE informations */
240 ctx->raddr = pte1;
241 ctx->prot = access;
242 ret = check_prot(ctx->prot, rw, type);
243 if (ret == 0) {
244 /* Access granted */
245 LOG_MMU("PTE access granted !\n");
246 } else {
247 /* Access right violation */
248 LOG_MMU("PTE access rejected\n");
253 return ret;
256 static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
257 target_ulong pte1, int h, int rw, int type)
259 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
262 #if defined(TARGET_PPC64)
263 static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
264 target_ulong pte1, int h, int rw, int type)
266 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
268 #endif
270 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
271 int ret, int rw)
273 int store = 0;
275 /* Update page flags */
276 if (!(*pte1p & 0x00000100)) {
277 /* Update accessed flag */
278 *pte1p |= 0x00000100;
279 store = 1;
281 if (!(*pte1p & 0x00000080)) {
282 if (rw == 1 && ret == 0) {
283 /* Update changed flag */
284 *pte1p |= 0x00000080;
285 store = 1;
286 } else {
287 /* Force page fault for first write access */
288 ctx->prot &= ~PAGE_WRITE;
292 return store;
295 /* Software driven TLB helpers */
296 static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
297 int is_code)
299 int nr;
301 /* Select TLB num in a way from address */
302 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
303 /* Select TLB way */
304 nr += env->tlb_per_way * way;
305 /* 6xx have separate TLBs for instructions and data */
306 if (is_code && env->id_tlbs == 1)
307 nr += env->nb_tlb;
309 return nr;
312 static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
314 ppc6xx_tlb_t *tlb;
315 int nr, max;
317 //LOG_SWTLB("Invalidate all TLBs\n");
318 /* Invalidate all defined software TLB */
319 max = env->nb_tlb;
320 if (env->id_tlbs == 1)
321 max *= 2;
322 for (nr = 0; nr < max; nr++) {
323 tlb = &env->tlb[nr].tlb6;
324 pte_invalidate(&tlb->pte0);
326 tlb_flush(env, 1);
329 static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
330 target_ulong eaddr,
331 int is_code, int match_epn)
333 #if !defined(FLUSH_ALL_TLBS)
334 ppc6xx_tlb_t *tlb;
335 int way, nr;
337 /* Invalidate ITLB + DTLB, all ways */
338 for (way = 0; way < env->nb_ways; way++) {
339 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
340 tlb = &env->tlb[nr].tlb6;
341 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
342 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
343 env->nb_tlb, eaddr);
344 pte_invalidate(&tlb->pte0);
345 tlb_flush_page(env, tlb->EPN);
348 #else
349 /* XXX: PowerPC specification say this is valid as well */
350 ppc6xx_tlb_invalidate_all(env);
351 #endif
354 static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
355 target_ulong eaddr, int is_code)
357 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
360 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
361 target_ulong pte0, target_ulong pte1)
363 ppc6xx_tlb_t *tlb;
364 int nr;
366 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
367 tlb = &env->tlb[nr].tlb6;
368 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
369 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
370 /* Invalidate any pending reference in Qemu for this virtual address */
371 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
372 tlb->pte0 = pte0;
373 tlb->pte1 = pte1;
374 tlb->EPN = EPN;
375 /* Store last way for LRU mechanism */
376 env->last_way = way;
379 static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
380 target_ulong eaddr, int rw, int access_type)
382 ppc6xx_tlb_t *tlb;
383 int nr, best, way;
384 int ret;
386 best = -1;
387 ret = -1; /* No TLB found */
388 for (way = 0; way < env->nb_ways; way++) {
389 nr = ppc6xx_tlb_getnum(env, eaddr, way,
390 access_type == ACCESS_CODE ? 1 : 0);
391 tlb = &env->tlb[nr].tlb6;
392 /* This test "emulates" the PTE index match for hardware TLBs */
393 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
394 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
395 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
396 pte_is_valid(tlb->pte0) ? "valid" : "inval",
397 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
398 continue;
400 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
401 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
402 pte_is_valid(tlb->pte0) ? "valid" : "inval",
403 tlb->EPN, eaddr, tlb->pte1,
404 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
405 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
406 case -3:
407 /* TLB inconsistency */
408 return -1;
409 case -2:
410 /* Access violation */
411 ret = -2;
412 best = nr;
413 break;
414 case -1:
415 default:
416 /* No match */
417 break;
418 case 0:
419 /* access granted */
420 /* XXX: we should go on looping to check all TLBs consistency
421 * but we can speed-up the whole thing as the
422 * result would be undefined if TLBs are not consistent.
424 ret = 0;
425 best = nr;
426 goto done;
429 if (best != -1) {
430 done:
431 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
432 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
433 /* Update page flags */
434 pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
437 return ret;
440 /* Perform BAT hit & translation */
441 static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
442 int *protp, target_ulong *BATu,
443 target_ulong *BATl)
445 target_ulong bl;
446 int pp, valid, prot;
448 bl = (*BATu & 0x00001FFC) << 15;
449 valid = 0;
450 prot = 0;
451 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
452 ((msr_pr != 0) && (*BATu & 0x00000001))) {
453 valid = 1;
454 pp = *BATl & 0x00000003;
455 if (pp != 0) {
456 prot = PAGE_READ | PAGE_EXEC;
457 if (pp == 0x2)
458 prot |= PAGE_WRITE;
461 *blp = bl;
462 *validp = valid;
463 *protp = prot;
466 static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
467 int *validp, int *protp,
468 target_ulong *BATu, target_ulong *BATl)
470 target_ulong bl;
471 int key, pp, valid, prot;
473 bl = (*BATl & 0x0000003F) << 17;
474 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
475 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
476 prot = 0;
477 valid = (*BATl >> 6) & 1;
478 if (valid) {
479 pp = *BATu & 0x00000003;
480 if (msr_pr == 0)
481 key = (*BATu >> 3) & 1;
482 else
483 key = (*BATu >> 2) & 1;
484 prot = pp_check(key, pp, 0);
486 *blp = bl;
487 *validp = valid;
488 *protp = prot;
491 static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
492 int rw, int type)
494 target_ulong *BATlt, *BATut, *BATu, *BATl;
495 target_ulong BEPIl, BEPIu, bl;
496 int i, valid, prot;
497 int ret = -1;
499 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
500 type == ACCESS_CODE ? 'I' : 'D', virtual);
501 switch (type) {
502 case ACCESS_CODE:
503 BATlt = env->IBAT[1];
504 BATut = env->IBAT[0];
505 break;
506 default:
507 BATlt = env->DBAT[1];
508 BATut = env->DBAT[0];
509 break;
511 for (i = 0; i < env->nb_BATs; i++) {
512 BATu = &BATut[i];
513 BATl = &BATlt[i];
514 BEPIu = *BATu & 0xF0000000;
515 BEPIl = *BATu & 0x0FFE0000;
516 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
517 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
518 } else {
519 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
521 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
522 " BATl " TARGET_FMT_lx "\n", __func__,
523 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
524 if ((virtual & 0xF0000000) == BEPIu &&
525 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
526 /* BAT matches */
527 if (valid != 0) {
528 /* Get physical address */
529 ctx->raddr = (*BATl & 0xF0000000) |
530 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
531 (virtual & 0x0001F000);
532 /* Compute access rights */
533 ctx->prot = prot;
534 ret = check_prot(ctx->prot, rw, type);
535 if (ret == 0)
536 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
537 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
538 ctx->prot & PAGE_WRITE ? 'W' : '-');
539 break;
543 if (ret < 0) {
544 #if defined(DEBUG_BATS)
545 if (qemu_log_enabled()) {
546 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
547 for (i = 0; i < 4; i++) {
548 BATu = &BATut[i];
549 BATl = &BATlt[i];
550 BEPIu = *BATu & 0xF0000000;
551 BEPIl = *BATu & 0x0FFE0000;
552 bl = (*BATu & 0x00001FFC) << 15;
553 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
554 " BATl " TARGET_FMT_lx " \n\t" TARGET_FMT_lx " "
555 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
556 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
557 *BATu, *BATl, BEPIu, BEPIl, bl);
560 #endif
562 /* No hit */
563 return ret;
566 /* PTE table lookup */
567 static inline int _find_pte(mmu_ctx_t *ctx, int is_64b, int h, int rw,
568 int type, int target_page_bits)
570 target_ulong base, pte0, pte1;
571 int i, good = -1;
572 int ret, r;
574 ret = -1; /* No entry found */
575 base = ctx->pg_addr[h];
576 for (i = 0; i < 8; i++) {
577 #if defined(TARGET_PPC64)
578 if (is_64b) {
579 pte0 = ldq_phys(base + (i * 16));
580 pte1 = ldq_phys(base + (i * 16) + 8);
582 /* We have a TLB that saves 4K pages, so let's
583 * split a huge page to 4k chunks */
584 if (target_page_bits != TARGET_PAGE_BITS)
585 pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
586 & TARGET_PAGE_MASK;
588 r = pte64_check(ctx, pte0, pte1, h, rw, type);
589 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
590 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
591 base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
592 (int)((pte0 >> 1) & 1), ctx->ptem);
593 } else
594 #endif
596 pte0 = ldl_phys(base + (i * 8));
597 pte1 = ldl_phys(base + (i * 8) + 4);
598 r = pte32_check(ctx, pte0, pte1, h, rw, type);
599 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
600 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
601 base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
602 (int)((pte0 >> 6) & 1), ctx->ptem);
604 switch (r) {
605 case -3:
606 /* PTE inconsistency */
607 return -1;
608 case -2:
609 /* Access violation */
610 ret = -2;
611 good = i;
612 break;
613 case -1:
614 default:
615 /* No PTE match */
616 break;
617 case 0:
618 /* access granted */
619 /* XXX: we should go on looping to check all PTEs consistency
620 * but if we can speed-up the whole thing as the
621 * result would be undefined if PTEs are not consistent.
623 ret = 0;
624 good = i;
625 goto done;
628 if (good != -1) {
629 done:
630 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
631 ctx->raddr, ctx->prot, ret);
632 /* Update page flags */
633 pte1 = ctx->raddr;
634 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
635 #if defined(TARGET_PPC64)
636 if (is_64b) {
637 stq_phys_notdirty(base + (good * 16) + 8, pte1);
638 } else
639 #endif
641 stl_phys_notdirty(base + (good * 8) + 4, pte1);
646 return ret;
649 static inline int find_pte32(mmu_ctx_t *ctx, int h, int rw, int type,
650 int target_page_bits)
652 return _find_pte(ctx, 0, h, rw, type, target_page_bits);
655 #if defined(TARGET_PPC64)
656 static inline int find_pte64(mmu_ctx_t *ctx, int h, int rw, int type,
657 int target_page_bits)
659 return _find_pte(ctx, 1, h, rw, type, target_page_bits);
661 #endif
663 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
664 int type, int target_page_bits)
666 #if defined(TARGET_PPC64)
667 if (env->mmu_model & POWERPC_MMU_64)
668 return find_pte64(ctx, h, rw, type, target_page_bits);
669 #endif
671 return find_pte32(ctx, h, rw, type, target_page_bits);
674 #if defined(TARGET_PPC64)
675 static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
677 ppc_slb_t *retval = &env->slb[nr];
679 #if 0 // XXX implement bridge mode?
680 if (env->spr[SPR_ASR] & 1) {
681 target_phys_addr_t sr_base;
683 sr_base = env->spr[SPR_ASR] & 0xfffffffffffff000;
684 sr_base += (12 * nr);
686 retval->tmp64 = ldq_phys(sr_base);
687 retval->tmp = ldl_phys(sr_base + 8);
689 #endif
691 return retval;
694 static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
696 ppc_slb_t *entry = &env->slb[nr];
698 if (slb == entry)
699 return;
701 entry->tmp64 = slb->tmp64;
702 entry->tmp = slb->tmp;
705 static inline int slb_is_valid(ppc_slb_t *slb)
707 return (int)(slb->tmp64 & 0x0000000008000000ULL);
710 static inline void slb_invalidate(ppc_slb_t *slb)
712 slb->tmp64 &= ~0x0000000008000000ULL;
715 static inline int slb_lookup(CPUPPCState *env, target_ulong eaddr,
716 target_ulong *vsid, target_ulong *page_mask,
717 int *attr, int *target_page_bits)
719 target_ulong mask;
720 int n, ret;
722 ret = -5;
723 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
724 mask = 0x0000000000000000ULL; /* Avoid gcc warning */
725 for (n = 0; n < env->slb_nr; n++) {
726 ppc_slb_t *slb = slb_get_entry(env, n);
728 LOG_SLB("%s: seg %d %016" PRIx64 " %08"
729 PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
730 if (slb_is_valid(slb)) {
731 /* SLB entry is valid */
732 mask = 0xFFFFFFFFF0000000ULL;
733 if (slb->tmp & 0x8) {
734 /* 16 MB PTEs */
735 if (target_page_bits)
736 *target_page_bits = 24;
737 } else {
738 /* 4 KB PTEs */
739 if (target_page_bits)
740 *target_page_bits = TARGET_PAGE_BITS;
742 if ((eaddr & mask) == (slb->tmp64 & mask)) {
743 /* SLB match */
744 *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
745 *page_mask = ~mask;
746 *attr = slb->tmp & 0xFF;
747 ret = n;
748 break;
753 return ret;
756 void ppc_slb_invalidate_all (CPUPPCState *env)
758 int n, do_invalidate;
760 do_invalidate = 0;
761 /* XXX: Warning: slbia never invalidates the first segment */
762 for (n = 1; n < env->slb_nr; n++) {
763 ppc_slb_t *slb = slb_get_entry(env, n);
765 if (slb_is_valid(slb)) {
766 slb_invalidate(slb);
767 slb_set_entry(env, n, slb);
768 /* XXX: given the fact that segment size is 256 MB or 1TB,
769 * and we still don't have a tlb_flush_mask(env, n, mask)
770 * in Qemu, we just invalidate all TLBs
772 do_invalidate = 1;
775 if (do_invalidate)
776 tlb_flush(env, 1);
779 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
781 target_ulong vsid, page_mask;
782 int attr;
783 int n;
785 n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
786 if (n >= 0) {
787 ppc_slb_t *slb = slb_get_entry(env, n);
789 if (slb_is_valid(slb)) {
790 slb_invalidate(slb);
791 slb_set_entry(env, n, slb);
792 /* XXX: given the fact that segment size is 256 MB or 1TB,
793 * and we still don't have a tlb_flush_mask(env, n, mask)
794 * in Qemu, we just invalidate all TLBs
796 tlb_flush(env, 1);
801 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
803 target_ulong rt;
804 ppc_slb_t *slb = slb_get_entry(env, slb_nr);
806 if (slb_is_valid(slb)) {
807 /* SLB entry is valid */
808 /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
809 rt = slb->tmp >> 8; /* 65:88 => 40:63 */
810 rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
811 /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
812 rt |= ((slb->tmp >> 4) & 0xF) << 27;
813 } else {
814 rt = 0;
816 LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
817 TARGET_FMT_lx "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
819 return rt;
822 void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
824 ppc_slb_t *slb;
826 uint64_t vsid;
827 uint64_t esid;
828 int flags, valid, slb_nr;
830 vsid = rs >> 12;
831 flags = ((rs >> 8) & 0xf);
833 esid = rb >> 28;
834 valid = (rb & (1 << 27));
835 slb_nr = rb & 0xfff;
837 slb = slb_get_entry(env, slb_nr);
838 slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
839 slb->tmp = (vsid << 8) | (flags << 3);
841 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
842 " %08" PRIx32 "\n", __func__, slb_nr, rb, rs, slb->tmp64,
843 slb->tmp);
845 slb_set_entry(env, slb_nr, slb);
847 #endif /* defined(TARGET_PPC64) */
849 /* Perform segment based translation */
850 static inline target_phys_addr_t get_pgaddr(target_phys_addr_t sdr1,
851 int sdr_sh,
852 target_phys_addr_t hash,
853 target_phys_addr_t mask)
855 return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
858 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
859 target_ulong eaddr, int rw, int type)
861 target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
862 target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
863 #if defined(TARGET_PPC64)
864 int attr;
865 #endif
866 int ds, vsid_sh, sdr_sh, pr, target_page_bits;
867 int ret, ret2;
869 pr = msr_pr;
870 #if defined(TARGET_PPC64)
871 if (env->mmu_model & POWERPC_MMU_64) {
872 LOG_MMU("Check SLBs\n");
873 ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
874 &target_page_bits);
875 if (ret < 0)
876 return ret;
877 ctx->key = ((attr & 0x40) && (pr != 0)) ||
878 ((attr & 0x80) && (pr == 0)) ? 1 : 0;
879 ds = 0;
880 ctx->nx = attr & 0x10 ? 1 : 0;
881 ctx->eaddr = eaddr;
882 vsid_mask = 0x00003FFFFFFFFF80ULL;
883 vsid_sh = 7;
884 sdr_sh = 18;
885 sdr_mask = 0x3FF80;
886 } else
887 #endif /* defined(TARGET_PPC64) */
889 sr = env->sr[eaddr >> 28];
890 page_mask = 0x0FFFFFFF;
891 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
892 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
893 ds = sr & 0x80000000 ? 1 : 0;
894 ctx->nx = sr & 0x10000000 ? 1 : 0;
895 vsid = sr & 0x00FFFFFF;
896 vsid_mask = 0x01FFFFC0;
897 vsid_sh = 6;
898 sdr_sh = 16;
899 sdr_mask = 0xFFC0;
900 target_page_bits = TARGET_PAGE_BITS;
901 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
902 TARGET_FMT_lx " lr=" TARGET_FMT_lx
903 " ir=%d dr=%d pr=%d %d t=%d\n",
904 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
905 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
907 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
908 ctx->key, ds, ctx->nx, vsid);
909 ret = -1;
910 if (!ds) {
911 /* Check if instruction fetch is allowed, if needed */
912 if (type != ACCESS_CODE || ctx->nx == 0) {
913 /* Page address translation */
914 /* Primary table address */
915 sdr = env->sdr1;
916 pgidx = (eaddr & page_mask) >> target_page_bits;
917 #if defined(TARGET_PPC64)
918 if (env->mmu_model & POWERPC_MMU_64) {
919 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
920 /* XXX: this is false for 1 TB segments */
921 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
922 } else
923 #endif
925 htab_mask = sdr & 0x000001FF;
926 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
928 mask = (htab_mask << sdr_sh) | sdr_mask;
929 LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
930 " mask " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
931 sdr, sdr_sh, hash, mask, page_mask);
932 ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
933 /* Secondary table address */
934 hash = (~hash) & vsid_mask;
935 LOG_MMU("sdr " TARGET_FMT_plx " sh %d hash " TARGET_FMT_plx
936 " mask " TARGET_FMT_plx "\n", sdr, sdr_sh, hash, mask);
937 ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
938 #if defined(TARGET_PPC64)
939 if (env->mmu_model & POWERPC_MMU_64) {
940 /* Only 5 bits of the page index are used in the AVPN */
941 if (target_page_bits > 23) {
942 ctx->ptem = (vsid << 12) |
943 ((pgidx << (target_page_bits - 16)) & 0xF80);
944 } else {
945 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
947 } else
948 #endif
950 ctx->ptem = (vsid << 7) | (pgidx >> 10);
952 /* Initialize real address with an invalid value */
953 ctx->raddr = (target_phys_addr_t)-1ULL;
954 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
955 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
956 /* Software TLB search */
957 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
958 } else {
959 LOG_MMU("0 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
960 "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
961 " pg_addr=" TARGET_FMT_plx "\n",
962 sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
963 /* Primary table lookup */
964 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
965 if (ret < 0) {
966 /* Secondary table lookup */
967 if (eaddr != 0xEFFFFFFF)
968 LOG_MMU("1 sdr1=" TARGET_FMT_plx " vsid=" TARGET_FMT_lx " "
969 "api=" TARGET_FMT_lx " hash=" TARGET_FMT_plx
970 " pg_addr=" TARGET_FMT_plx "\n", sdr, vsid,
971 pgidx, hash, ctx->pg_addr[1]);
972 ret2 = find_pte(env, ctx, 1, rw, type,
973 target_page_bits);
974 if (ret2 != -1)
975 ret = ret2;
978 #if defined (DUMP_PAGE_TABLES)
979 if (qemu_log_enabled()) {
980 target_phys_addr_t curaddr;
981 uint32_t a0, a1, a2, a3;
982 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
983 "\n", sdr, mask + 0x80);
984 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
985 curaddr += 16) {
986 a0 = ldl_phys(curaddr);
987 a1 = ldl_phys(curaddr + 4);
988 a2 = ldl_phys(curaddr + 8);
989 a3 = ldl_phys(curaddr + 12);
990 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
991 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
992 curaddr, a0, a1, a2, a3);
996 #endif
997 } else {
998 LOG_MMU("No access allowed\n");
999 ret = -3;
1001 } else {
1002 LOG_MMU("direct store...\n");
1003 /* Direct-store segment : absolutely *BUGGY* for now */
1004 switch (type) {
1005 case ACCESS_INT:
1006 /* Integer load/store : only access allowed */
1007 break;
1008 case ACCESS_CODE:
1009 /* No code fetch is allowed in direct-store areas */
1010 return -4;
1011 case ACCESS_FLOAT:
1012 /* Floating point load/store */
1013 return -4;
1014 case ACCESS_RES:
1015 /* lwarx, ldarx or srwcx. */
1016 return -4;
1017 case ACCESS_CACHE:
1018 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1019 /* Should make the instruction do no-op.
1020 * As it already do no-op, it's quite easy :-)
1022 ctx->raddr = eaddr;
1023 return 0;
1024 case ACCESS_EXT:
1025 /* eciwx or ecowx */
1026 return -4;
1027 default:
1028 qemu_log("ERROR: instruction should not need "
1029 "address translation\n");
1030 return -4;
1032 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1033 ctx->raddr = eaddr;
1034 ret = 2;
1035 } else {
1036 ret = -2;
1040 return ret;
1043 /* Generic TLB check function for embedded PowerPC implementations */
1044 static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1045 target_phys_addr_t *raddrp,
1046 target_ulong address, uint32_t pid, int ext,
1047 int i)
1049 target_ulong mask;
1051 /* Check valid flag */
1052 if (!(tlb->prot & PAGE_VALID)) {
1053 return -1;
1055 mask = ~(tlb->size - 1);
1056 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1057 " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
1058 mask, (uint32_t)tlb->PID);
1059 /* Check PID */
1060 if (tlb->PID != 0 && tlb->PID != pid)
1061 return -1;
1062 /* Check effective address */
1063 if ((address & mask) != tlb->EPN)
1064 return -1;
1065 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1066 #if (TARGET_PHYS_ADDR_BITS >= 36)
1067 if (ext) {
1068 /* Extend the physical address to 36 bits */
1069 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1071 #endif
1073 return 0;
1076 /* Generic TLB search function for PowerPC embedded implementations */
1077 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1079 ppcemb_tlb_t *tlb;
1080 target_phys_addr_t raddr;
1081 int i, ret;
1083 /* Default return value is no match */
1084 ret = -1;
1085 for (i = 0; i < env->nb_tlb; i++) {
1086 tlb = &env->tlb[i].tlbe;
1087 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1088 ret = i;
1089 break;
1093 return ret;
1096 /* Helpers specific to PowerPC 40x implementations */
1097 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1099 ppcemb_tlb_t *tlb;
1100 int i;
1102 for (i = 0; i < env->nb_tlb; i++) {
1103 tlb = &env->tlb[i].tlbe;
1104 tlb->prot &= ~PAGE_VALID;
1106 tlb_flush(env, 1);
1109 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1110 target_ulong eaddr, uint32_t pid)
1112 #if !defined(FLUSH_ALL_TLBS)
1113 ppcemb_tlb_t *tlb;
1114 target_phys_addr_t raddr;
1115 target_ulong page, end;
1116 int i;
1118 for (i = 0; i < env->nb_tlb; i++) {
1119 tlb = &env->tlb[i].tlbe;
1120 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1121 end = tlb->EPN + tlb->size;
1122 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1123 tlb_flush_page(env, page);
1124 tlb->prot &= ~PAGE_VALID;
1125 break;
1128 #else
1129 ppc4xx_tlb_invalidate_all(env);
1130 #endif
1133 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1134 target_ulong address, int rw, int access_type)
1136 ppcemb_tlb_t *tlb;
1137 target_phys_addr_t raddr;
1138 int i, ret, zsel, zpr, pr;
1140 ret = -1;
1141 raddr = (target_phys_addr_t)-1ULL;
1142 pr = msr_pr;
1143 for (i = 0; i < env->nb_tlb; i++) {
1144 tlb = &env->tlb[i].tlbe;
1145 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1146 env->spr[SPR_40x_PID], 0, i) < 0)
1147 continue;
1148 zsel = (tlb->attr >> 4) & 0xF;
1149 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1150 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1151 __func__, i, zsel, zpr, rw, tlb->attr);
1152 /* Check execute enable bit */
1153 switch (zpr) {
1154 case 0x2:
1155 if (pr != 0)
1156 goto check_perms;
1157 /* No break here */
1158 case 0x3:
1159 /* All accesses granted */
1160 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1161 ret = 0;
1162 break;
1163 case 0x0:
1164 if (pr != 0) {
1165 /* Raise Zone protection fault. */
1166 env->spr[SPR_40x_ESR] = 1 << 22;
1167 ctx->prot = 0;
1168 ret = -2;
1169 break;
1171 /* No break here */
1172 case 0x1:
1173 check_perms:
1174 /* Check from TLB entry */
1175 /* XXX: there is a problem here or in the TLB fill code... */
1176 ctx->prot = tlb->prot;
1177 ctx->prot |= PAGE_EXEC;
1178 ret = check_prot(ctx->prot, rw, access_type);
1179 if (ret == -2)
1180 env->spr[SPR_40x_ESR] = 0;
1181 break;
1183 if (ret >= 0) {
1184 ctx->raddr = raddr;
1185 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1186 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1187 ret);
1188 return 0;
1191 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1192 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1194 return ret;
1197 void store_40x_sler (CPUPPCState *env, uint32_t val)
1199 /* XXX: TO BE FIXED */
1200 if (val != 0x00000000) {
1201 cpu_abort(env, "Little-endian regions are not supported by now\n");
1203 env->spr[SPR_405_SLER] = val;
1206 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1207 target_ulong address, int rw,
1208 int access_type)
1210 ppcemb_tlb_t *tlb;
1211 target_phys_addr_t raddr;
1212 int i, prot, ret;
1214 ret = -1;
1215 raddr = (target_phys_addr_t)-1ULL;
1216 for (i = 0; i < env->nb_tlb; i++) {
1217 tlb = &env->tlb[i].tlbe;
1218 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1219 env->spr[SPR_BOOKE_PID], 1, i) < 0)
1220 continue;
1221 if (msr_pr != 0)
1222 prot = tlb->prot & 0xF;
1223 else
1224 prot = (tlb->prot >> 4) & 0xF;
1225 /* Check the address space */
1226 if (access_type == ACCESS_CODE) {
1227 if (msr_ir != (tlb->attr & 1))
1228 continue;
1229 ctx->prot = prot;
1230 if (prot & PAGE_EXEC) {
1231 ret = 0;
1232 break;
1234 ret = -3;
1235 } else {
1236 if (msr_dr != (tlb->attr & 1))
1237 continue;
1238 ctx->prot = prot;
1239 if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1240 ret = 0;
1241 break;
1243 ret = -2;
1246 if (ret >= 0)
1247 ctx->raddr = raddr;
1249 return ret;
1252 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1253 target_ulong eaddr, int rw)
1255 int in_plb, ret;
1257 ctx->raddr = eaddr;
1258 ctx->prot = PAGE_READ | PAGE_EXEC;
1259 ret = 0;
1260 switch (env->mmu_model) {
1261 case POWERPC_MMU_32B:
1262 case POWERPC_MMU_601:
1263 case POWERPC_MMU_SOFT_6xx:
1264 case POWERPC_MMU_SOFT_74xx:
1265 case POWERPC_MMU_SOFT_4xx:
1266 case POWERPC_MMU_REAL:
1267 case POWERPC_MMU_BOOKE:
1268 ctx->prot |= PAGE_WRITE;
1269 break;
1270 #if defined(TARGET_PPC64)
1271 case POWERPC_MMU_620:
1272 case POWERPC_MMU_64B:
1273 /* Real address are 60 bits long */
1274 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1275 ctx->prot |= PAGE_WRITE;
1276 break;
1277 #endif
1278 case POWERPC_MMU_SOFT_4xx_Z:
1279 if (unlikely(msr_pe != 0)) {
1280 /* 403 family add some particular protections,
1281 * using PBL/PBU registers for accesses with no translation.
1283 in_plb =
1284 /* Check PLB validity */
1285 (env->pb[0] < env->pb[1] &&
1286 /* and address in plb area */
1287 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1288 (env->pb[2] < env->pb[3] &&
1289 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1290 if (in_plb ^ msr_px) {
1291 /* Access in protected area */
1292 if (rw == 1) {
1293 /* Access is not allowed */
1294 ret = -2;
1296 } else {
1297 /* Read-write access is allowed */
1298 ctx->prot |= PAGE_WRITE;
1301 break;
1302 case POWERPC_MMU_MPC8xx:
1303 /* XXX: TODO */
1304 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1305 break;
1306 case POWERPC_MMU_BOOKE_FSL:
1307 /* XXX: TODO */
1308 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1309 break;
1310 default:
1311 cpu_abort(env, "Unknown or invalid MMU model\n");
1312 return -1;
1315 return ret;
1318 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1319 int rw, int access_type)
1321 int ret;
1323 #if 0
1324 qemu_log("%s\n", __func__);
1325 #endif
1326 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1327 (access_type != ACCESS_CODE && msr_dr == 0)) {
1328 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1329 /* The BookE MMU always performs address translation. The
1330 IS and DS bits only affect the address space. */
1331 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1332 rw, access_type);
1333 } else {
1334 /* No address translation. */
1335 ret = check_physical(env, ctx, eaddr, rw);
1337 } else {
1338 ret = -1;
1339 switch (env->mmu_model) {
1340 case POWERPC_MMU_32B:
1341 case POWERPC_MMU_601:
1342 case POWERPC_MMU_SOFT_6xx:
1343 case POWERPC_MMU_SOFT_74xx:
1344 /* Try to find a BAT */
1345 if (env->nb_BATs != 0)
1346 ret = get_bat(env, ctx, eaddr, rw, access_type);
1347 #if defined(TARGET_PPC64)
1348 case POWERPC_MMU_620:
1349 case POWERPC_MMU_64B:
1350 #endif
1351 if (ret < 0) {
1352 /* We didn't match any BAT entry or don't have BATs */
1353 ret = get_segment(env, ctx, eaddr, rw, access_type);
1355 break;
1356 case POWERPC_MMU_SOFT_4xx:
1357 case POWERPC_MMU_SOFT_4xx_Z:
1358 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1359 rw, access_type);
1360 break;
1361 case POWERPC_MMU_BOOKE:
1362 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1363 rw, access_type);
1364 break;
1365 case POWERPC_MMU_MPC8xx:
1366 /* XXX: TODO */
1367 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1368 break;
1369 case POWERPC_MMU_BOOKE_FSL:
1370 /* XXX: TODO */
1371 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1372 return -1;
1373 case POWERPC_MMU_REAL:
1374 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1375 return -1;
1376 default:
1377 cpu_abort(env, "Unknown or invalid MMU model\n");
1378 return -1;
1381 #if 0
1382 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1383 __func__, eaddr, ret, ctx->raddr);
1384 #endif
1386 return ret;
1389 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1391 mmu_ctx_t ctx;
1393 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1394 return -1;
1396 return ctx.raddr & TARGET_PAGE_MASK;
1399 /* Perform address translation */
1400 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1401 int mmu_idx, int is_softmmu)
1403 mmu_ctx_t ctx;
1404 int access_type;
1405 int ret = 0;
1407 if (rw == 2) {
1408 /* code access */
1409 rw = 0;
1410 access_type = ACCESS_CODE;
1411 } else {
1412 /* data access */
1413 access_type = env->access_type;
1415 ret = get_physical_address(env, &ctx, address, rw, access_type);
1416 if (ret == 0) {
1417 tlb_set_page(env, address & TARGET_PAGE_MASK,
1418 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1419 mmu_idx, TARGET_PAGE_SIZE);
1420 ret = 0;
1421 } else if (ret < 0) {
1422 LOG_MMU_STATE(env);
1423 if (access_type == ACCESS_CODE) {
1424 switch (ret) {
1425 case -1:
1426 /* No matches in page tables or TLB */
1427 switch (env->mmu_model) {
1428 case POWERPC_MMU_SOFT_6xx:
1429 env->exception_index = POWERPC_EXCP_IFTLB;
1430 env->error_code = 1 << 18;
1431 env->spr[SPR_IMISS] = address;
1432 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1433 goto tlb_miss;
1434 case POWERPC_MMU_SOFT_74xx:
1435 env->exception_index = POWERPC_EXCP_IFTLB;
1436 goto tlb_miss_74xx;
1437 case POWERPC_MMU_SOFT_4xx:
1438 case POWERPC_MMU_SOFT_4xx_Z:
1439 env->exception_index = POWERPC_EXCP_ITLB;
1440 env->error_code = 0;
1441 env->spr[SPR_40x_DEAR] = address;
1442 env->spr[SPR_40x_ESR] = 0x00000000;
1443 break;
1444 case POWERPC_MMU_32B:
1445 case POWERPC_MMU_601:
1446 #if defined(TARGET_PPC64)
1447 case POWERPC_MMU_620:
1448 case POWERPC_MMU_64B:
1449 #endif
1450 env->exception_index = POWERPC_EXCP_ISI;
1451 env->error_code = 0x40000000;
1452 break;
1453 case POWERPC_MMU_BOOKE:
1454 env->exception_index = POWERPC_EXCP_ITLB;
1455 env->error_code = 0;
1456 env->spr[SPR_BOOKE_DEAR] = address;
1457 return -1;
1458 case POWERPC_MMU_BOOKE_FSL:
1459 /* XXX: TODO */
1460 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1461 return -1;
1462 case POWERPC_MMU_MPC8xx:
1463 /* XXX: TODO */
1464 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1465 break;
1466 case POWERPC_MMU_REAL:
1467 cpu_abort(env, "PowerPC in real mode should never raise "
1468 "any MMU exceptions\n");
1469 return -1;
1470 default:
1471 cpu_abort(env, "Unknown or invalid MMU model\n");
1472 return -1;
1474 break;
1475 case -2:
1476 /* Access rights violation */
1477 env->exception_index = POWERPC_EXCP_ISI;
1478 env->error_code = 0x08000000;
1479 break;
1480 case -3:
1481 /* No execute protection violation */
1482 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1483 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1485 env->exception_index = POWERPC_EXCP_ISI;
1486 env->error_code = 0x10000000;
1487 break;
1488 case -4:
1489 /* Direct store exception */
1490 /* No code fetch is allowed in direct-store areas */
1491 env->exception_index = POWERPC_EXCP_ISI;
1492 env->error_code = 0x10000000;
1493 break;
1494 #if defined(TARGET_PPC64)
1495 case -5:
1496 /* No match in segment table */
1497 if (env->mmu_model == POWERPC_MMU_620) {
1498 env->exception_index = POWERPC_EXCP_ISI;
1499 /* XXX: this might be incorrect */
1500 env->error_code = 0x40000000;
1501 } else {
1502 env->exception_index = POWERPC_EXCP_ISEG;
1503 env->error_code = 0;
1505 break;
1506 #endif
1508 } else {
1509 switch (ret) {
1510 case -1:
1511 /* No matches in page tables or TLB */
1512 switch (env->mmu_model) {
1513 case POWERPC_MMU_SOFT_6xx:
1514 if (rw == 1) {
1515 env->exception_index = POWERPC_EXCP_DSTLB;
1516 env->error_code = 1 << 16;
1517 } else {
1518 env->exception_index = POWERPC_EXCP_DLTLB;
1519 env->error_code = 0;
1521 env->spr[SPR_DMISS] = address;
1522 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1523 tlb_miss:
1524 env->error_code |= ctx.key << 19;
1525 env->spr[SPR_HASH1] = ctx.pg_addr[0];
1526 env->spr[SPR_HASH2] = ctx.pg_addr[1];
1527 break;
1528 case POWERPC_MMU_SOFT_74xx:
1529 if (rw == 1) {
1530 env->exception_index = POWERPC_EXCP_DSTLB;
1531 } else {
1532 env->exception_index = POWERPC_EXCP_DLTLB;
1534 tlb_miss_74xx:
1535 /* Implement LRU algorithm */
1536 env->error_code = ctx.key << 19;
1537 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1538 ((env->last_way + 1) & (env->nb_ways - 1));
1539 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1540 break;
1541 case POWERPC_MMU_SOFT_4xx:
1542 case POWERPC_MMU_SOFT_4xx_Z:
1543 env->exception_index = POWERPC_EXCP_DTLB;
1544 env->error_code = 0;
1545 env->spr[SPR_40x_DEAR] = address;
1546 if (rw)
1547 env->spr[SPR_40x_ESR] = 0x00800000;
1548 else
1549 env->spr[SPR_40x_ESR] = 0x00000000;
1550 break;
1551 case POWERPC_MMU_32B:
1552 case POWERPC_MMU_601:
1553 #if defined(TARGET_PPC64)
1554 case POWERPC_MMU_620:
1555 case POWERPC_MMU_64B:
1556 #endif
1557 env->exception_index = POWERPC_EXCP_DSI;
1558 env->error_code = 0;
1559 env->spr[SPR_DAR] = address;
1560 if (rw == 1)
1561 env->spr[SPR_DSISR] = 0x42000000;
1562 else
1563 env->spr[SPR_DSISR] = 0x40000000;
1564 break;
1565 case POWERPC_MMU_MPC8xx:
1566 /* XXX: TODO */
1567 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1568 break;
1569 case POWERPC_MMU_BOOKE:
1570 env->exception_index = POWERPC_EXCP_DTLB;
1571 env->error_code = 0;
1572 env->spr[SPR_BOOKE_DEAR] = address;
1573 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1574 return -1;
1575 case POWERPC_MMU_BOOKE_FSL:
1576 /* XXX: TODO */
1577 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1578 return -1;
1579 case POWERPC_MMU_REAL:
1580 cpu_abort(env, "PowerPC in real mode should never raise "
1581 "any MMU exceptions\n");
1582 return -1;
1583 default:
1584 cpu_abort(env, "Unknown or invalid MMU model\n");
1585 return -1;
1587 break;
1588 case -2:
1589 /* Access rights violation */
1590 env->exception_index = POWERPC_EXCP_DSI;
1591 env->error_code = 0;
1592 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1593 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1594 env->spr[SPR_40x_DEAR] = address;
1595 if (rw) {
1596 env->spr[SPR_40x_ESR] |= 0x00800000;
1598 } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1599 env->spr[SPR_BOOKE_DEAR] = address;
1600 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1601 } else {
1602 env->spr[SPR_DAR] = address;
1603 if (rw == 1) {
1604 env->spr[SPR_DSISR] = 0x0A000000;
1605 } else {
1606 env->spr[SPR_DSISR] = 0x08000000;
1609 break;
1610 case -4:
1611 /* Direct store exception */
1612 switch (access_type) {
1613 case ACCESS_FLOAT:
1614 /* Floating point load/store */
1615 env->exception_index = POWERPC_EXCP_ALIGN;
1616 env->error_code = POWERPC_EXCP_ALIGN_FP;
1617 env->spr[SPR_DAR] = address;
1618 break;
1619 case ACCESS_RES:
1620 /* lwarx, ldarx or stwcx. */
1621 env->exception_index = POWERPC_EXCP_DSI;
1622 env->error_code = 0;
1623 env->spr[SPR_DAR] = address;
1624 if (rw == 1)
1625 env->spr[SPR_DSISR] = 0x06000000;
1626 else
1627 env->spr[SPR_DSISR] = 0x04000000;
1628 break;
1629 case ACCESS_EXT:
1630 /* eciwx or ecowx */
1631 env->exception_index = POWERPC_EXCP_DSI;
1632 env->error_code = 0;
1633 env->spr[SPR_DAR] = address;
1634 if (rw == 1)
1635 env->spr[SPR_DSISR] = 0x06100000;
1636 else
1637 env->spr[SPR_DSISR] = 0x04100000;
1638 break;
1639 default:
1640 printf("DSI: invalid exception (%d)\n", ret);
1641 env->exception_index = POWERPC_EXCP_PROGRAM;
1642 env->error_code =
1643 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1644 env->spr[SPR_DAR] = address;
1645 break;
1647 break;
1648 #if defined(TARGET_PPC64)
1649 case -5:
1650 /* No match in segment table */
1651 if (env->mmu_model == POWERPC_MMU_620) {
1652 env->exception_index = POWERPC_EXCP_DSI;
1653 env->error_code = 0;
1654 env->spr[SPR_DAR] = address;
1655 /* XXX: this might be incorrect */
1656 if (rw == 1)
1657 env->spr[SPR_DSISR] = 0x42000000;
1658 else
1659 env->spr[SPR_DSISR] = 0x40000000;
1660 } else {
1661 env->exception_index = POWERPC_EXCP_DSEG;
1662 env->error_code = 0;
1663 env->spr[SPR_DAR] = address;
1665 break;
1666 #endif
1669 #if 0
1670 printf("%s: set exception to %d %02x\n", __func__,
1671 env->exception, env->error_code);
1672 #endif
1673 ret = 1;
1676 return ret;
1679 /*****************************************************************************/
1680 /* BATs management */
1681 #if !defined(FLUSH_ALL_TLBS)
1682 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1683 target_ulong mask)
1685 target_ulong base, end, page;
1687 base = BATu & ~0x0001FFFF;
1688 end = base + mask + 0x00020000;
1689 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1690 TARGET_FMT_lx ")\n", base, end, mask);
1691 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1692 tlb_flush_page(env, page);
1693 LOG_BATS("Flush done\n");
1695 #endif
1697 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1698 target_ulong value)
1700 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1701 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1704 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1706 target_ulong mask;
1708 dump_store_bat(env, 'I', 0, nr, value);
1709 if (env->IBAT[0][nr] != value) {
1710 mask = (value << 15) & 0x0FFE0000UL;
1711 #if !defined(FLUSH_ALL_TLBS)
1712 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1713 #endif
1714 /* When storing valid upper BAT, mask BEPI and BRPN
1715 * and invalidate all TLBs covered by this BAT
1717 mask = (value << 15) & 0x0FFE0000UL;
1718 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1719 (value & ~0x0001FFFFUL & ~mask);
1720 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1721 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1722 #if !defined(FLUSH_ALL_TLBS)
1723 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1724 #else
1725 tlb_flush(env, 1);
1726 #endif
1730 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1732 dump_store_bat(env, 'I', 1, nr, value);
1733 env->IBAT[1][nr] = value;
1736 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1738 target_ulong mask;
1740 dump_store_bat(env, 'D', 0, nr, value);
1741 if (env->DBAT[0][nr] != value) {
1742 /* When storing valid upper BAT, mask BEPI and BRPN
1743 * and invalidate all TLBs covered by this BAT
1745 mask = (value << 15) & 0x0FFE0000UL;
1746 #if !defined(FLUSH_ALL_TLBS)
1747 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1748 #endif
1749 mask = (value << 15) & 0x0FFE0000UL;
1750 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1751 (value & ~0x0001FFFFUL & ~mask);
1752 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1753 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1754 #if !defined(FLUSH_ALL_TLBS)
1755 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1756 #else
1757 tlb_flush(env, 1);
1758 #endif
1762 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1764 dump_store_bat(env, 'D', 1, nr, value);
1765 env->DBAT[1][nr] = value;
1768 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1770 target_ulong mask;
1771 #if defined(FLUSH_ALL_TLBS)
1772 int do_inval;
1773 #endif
1775 dump_store_bat(env, 'I', 0, nr, value);
1776 if (env->IBAT[0][nr] != value) {
1777 #if defined(FLUSH_ALL_TLBS)
1778 do_inval = 0;
1779 #endif
1780 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1781 if (env->IBAT[1][nr] & 0x40) {
1782 /* Invalidate BAT only if it is valid */
1783 #if !defined(FLUSH_ALL_TLBS)
1784 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1785 #else
1786 do_inval = 1;
1787 #endif
1789 /* When storing valid upper BAT, mask BEPI and BRPN
1790 * and invalidate all TLBs covered by this BAT
1792 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1793 (value & ~0x0001FFFFUL & ~mask);
1794 env->DBAT[0][nr] = env->IBAT[0][nr];
1795 if (env->IBAT[1][nr] & 0x40) {
1796 #if !defined(FLUSH_ALL_TLBS)
1797 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1798 #else
1799 do_inval = 1;
1800 #endif
1802 #if defined(FLUSH_ALL_TLBS)
1803 if (do_inval)
1804 tlb_flush(env, 1);
1805 #endif
1809 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1811 target_ulong mask;
1812 #if defined(FLUSH_ALL_TLBS)
1813 int do_inval;
1814 #endif
1816 dump_store_bat(env, 'I', 1, nr, value);
1817 if (env->IBAT[1][nr] != value) {
1818 #if defined(FLUSH_ALL_TLBS)
1819 do_inval = 0;
1820 #endif
1821 if (env->IBAT[1][nr] & 0x40) {
1822 #if !defined(FLUSH_ALL_TLBS)
1823 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1824 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1825 #else
1826 do_inval = 1;
1827 #endif
1829 if (value & 0x40) {
1830 #if !defined(FLUSH_ALL_TLBS)
1831 mask = (value << 17) & 0x0FFE0000UL;
1832 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1833 #else
1834 do_inval = 1;
1835 #endif
1837 env->IBAT[1][nr] = value;
1838 env->DBAT[1][nr] = value;
1839 #if defined(FLUSH_ALL_TLBS)
1840 if (do_inval)
1841 tlb_flush(env, 1);
1842 #endif
1846 /*****************************************************************************/
1847 /* TLB management */
1848 void ppc_tlb_invalidate_all (CPUPPCState *env)
1850 switch (env->mmu_model) {
1851 case POWERPC_MMU_SOFT_6xx:
1852 case POWERPC_MMU_SOFT_74xx:
1853 ppc6xx_tlb_invalidate_all(env);
1854 break;
1855 case POWERPC_MMU_SOFT_4xx:
1856 case POWERPC_MMU_SOFT_4xx_Z:
1857 ppc4xx_tlb_invalidate_all(env);
1858 break;
1859 case POWERPC_MMU_REAL:
1860 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1861 break;
1862 case POWERPC_MMU_MPC8xx:
1863 /* XXX: TODO */
1864 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1865 break;
1866 case POWERPC_MMU_BOOKE:
1867 tlb_flush(env, 1);
1868 break;
1869 case POWERPC_MMU_BOOKE_FSL:
1870 /* XXX: TODO */
1871 if (!kvm_enabled())
1872 cpu_abort(env, "BookE MMU model is not implemented\n");
1873 break;
1874 case POWERPC_MMU_32B:
1875 case POWERPC_MMU_601:
1876 #if defined(TARGET_PPC64)
1877 case POWERPC_MMU_620:
1878 case POWERPC_MMU_64B:
1879 #endif /* defined(TARGET_PPC64) */
1880 tlb_flush(env, 1);
1881 break;
1882 default:
1883 /* XXX: TODO */
1884 cpu_abort(env, "Unknown MMU model\n");
1885 break;
1889 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1891 #if !defined(FLUSH_ALL_TLBS)
1892 addr &= TARGET_PAGE_MASK;
1893 switch (env->mmu_model) {
1894 case POWERPC_MMU_SOFT_6xx:
1895 case POWERPC_MMU_SOFT_74xx:
1896 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1897 if (env->id_tlbs == 1)
1898 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1899 break;
1900 case POWERPC_MMU_SOFT_4xx:
1901 case POWERPC_MMU_SOFT_4xx_Z:
1902 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1903 break;
1904 case POWERPC_MMU_REAL:
1905 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1906 break;
1907 case POWERPC_MMU_MPC8xx:
1908 /* XXX: TODO */
1909 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1910 break;
1911 case POWERPC_MMU_BOOKE:
1912 /* XXX: TODO */
1913 cpu_abort(env, "BookE MMU model is not implemented\n");
1914 break;
1915 case POWERPC_MMU_BOOKE_FSL:
1916 /* XXX: TODO */
1917 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1918 break;
1919 case POWERPC_MMU_32B:
1920 case POWERPC_MMU_601:
1921 /* tlbie invalidate TLBs for all segments */
1922 addr &= ~((target_ulong)-1ULL << 28);
1923 /* XXX: this case should be optimized,
1924 * giving a mask to tlb_flush_page
1926 tlb_flush_page(env, addr | (0x0 << 28));
1927 tlb_flush_page(env, addr | (0x1 << 28));
1928 tlb_flush_page(env, addr | (0x2 << 28));
1929 tlb_flush_page(env, addr | (0x3 << 28));
1930 tlb_flush_page(env, addr | (0x4 << 28));
1931 tlb_flush_page(env, addr | (0x5 << 28));
1932 tlb_flush_page(env, addr | (0x6 << 28));
1933 tlb_flush_page(env, addr | (0x7 << 28));
1934 tlb_flush_page(env, addr | (0x8 << 28));
1935 tlb_flush_page(env, addr | (0x9 << 28));
1936 tlb_flush_page(env, addr | (0xA << 28));
1937 tlb_flush_page(env, addr | (0xB << 28));
1938 tlb_flush_page(env, addr | (0xC << 28));
1939 tlb_flush_page(env, addr | (0xD << 28));
1940 tlb_flush_page(env, addr | (0xE << 28));
1941 tlb_flush_page(env, addr | (0xF << 28));
1942 break;
1943 #if defined(TARGET_PPC64)
1944 case POWERPC_MMU_620:
1945 case POWERPC_MMU_64B:
1946 /* tlbie invalidate TLBs for all segments */
1947 /* XXX: given the fact that there are too many segments to invalidate,
1948 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1949 * we just invalidate all TLBs
1951 tlb_flush(env, 1);
1952 break;
1953 #endif /* defined(TARGET_PPC64) */
1954 default:
1955 /* XXX: TODO */
1956 cpu_abort(env, "Unknown MMU model\n");
1957 break;
1959 #else
1960 ppc_tlb_invalidate_all(env);
1961 #endif
1964 /*****************************************************************************/
1965 /* Special registers manipulation */
1966 #if defined(TARGET_PPC64)
1967 void ppc_store_asr (CPUPPCState *env, target_ulong value)
1969 if (env->asr != value) {
1970 env->asr = value;
1971 tlb_flush(env, 1);
1974 #endif
1976 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1978 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1979 if (env->sdr1 != value) {
1980 /* XXX: for PowerPC 64, should check that the HTABSIZE value
1981 * is <= 28
1983 env->sdr1 = value;
1984 tlb_flush(env, 1);
1988 #if defined(TARGET_PPC64)
1989 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1991 // XXX
1992 return 0;
1994 #endif
1996 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1998 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1999 srnum, value, env->sr[srnum]);
2000 #if defined(TARGET_PPC64)
2001 if (env->mmu_model & POWERPC_MMU_64) {
2002 uint64_t rb = 0, rs = 0;
2004 /* ESID = srnum */
2005 rb |= ((uint32_t)srnum & 0xf) << 28;
2006 /* Set the valid bit */
2007 rb |= 1 << 27;
2008 /* Index = ESID */
2009 rb |= (uint32_t)srnum;
2011 /* VSID = VSID */
2012 rs |= (value & 0xfffffff) << 12;
2013 /* flags = flags */
2014 rs |= ((value >> 27) & 0xf) << 9;
2016 ppc_store_slb(env, rb, rs);
2017 } else
2018 #endif
2019 if (env->sr[srnum] != value) {
2020 env->sr[srnum] = value;
2021 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2022 flusing the whole TLB. */
2023 #if !defined(FLUSH_ALL_TLBS) && 0
2025 target_ulong page, end;
2026 /* Invalidate 256 MB of virtual memory */
2027 page = (16 << 20) * srnum;
2028 end = page + (16 << 20);
2029 for (; page != end; page += TARGET_PAGE_SIZE)
2030 tlb_flush_page(env, page);
2032 #else
2033 tlb_flush(env, 1);
2034 #endif
2037 #endif /* !defined (CONFIG_USER_ONLY) */
2039 /* GDBstub can read and write MSR... */
2040 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2042 hreg_store_msr(env, value, 0);
2045 /*****************************************************************************/
2046 /* Exception processing */
2047 #if defined (CONFIG_USER_ONLY)
2048 void do_interrupt (CPUState *env)
2050 env->exception_index = POWERPC_EXCP_NONE;
2051 env->error_code = 0;
2054 void ppc_hw_interrupt (CPUState *env)
2056 env->exception_index = POWERPC_EXCP_NONE;
2057 env->error_code = 0;
2059 #else /* defined (CONFIG_USER_ONLY) */
2060 static inline void dump_syscall(CPUState *env)
2062 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2063 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2064 " nip=" TARGET_FMT_lx "\n",
2065 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2066 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2067 ppc_dump_gpr(env, 6), env->nip);
2070 /* Note that this function should be greatly optimized
2071 * when called with a constant excp, from ppc_hw_interrupt
2073 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2075 target_ulong msr, new_msr, vector;
2076 int srr0, srr1, asrr0, asrr1;
2077 int lpes0, lpes1, lev;
2079 if (0) {
2080 /* XXX: find a suitable condition to enable the hypervisor mode */
2081 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2082 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2083 } else {
2084 /* Those values ensure we won't enter the hypervisor mode */
2085 lpes0 = 0;
2086 lpes1 = 1;
2089 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2090 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2092 /* new srr1 value excluding must-be-zero bits */
2093 msr = env->msr & ~0x783f0000ULL;
2095 /* new interrupt handler msr */
2096 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2098 /* target registers */
2099 srr0 = SPR_SRR0;
2100 srr1 = SPR_SRR1;
2101 asrr0 = -1;
2102 asrr1 = -1;
2104 switch (excp) {
2105 case POWERPC_EXCP_NONE:
2106 /* Should never happen */
2107 return;
2108 case POWERPC_EXCP_CRITICAL: /* Critical input */
2109 switch (excp_model) {
2110 case POWERPC_EXCP_40x:
2111 srr0 = SPR_40x_SRR2;
2112 srr1 = SPR_40x_SRR3;
2113 break;
2114 case POWERPC_EXCP_BOOKE:
2115 srr0 = SPR_BOOKE_CSRR0;
2116 srr1 = SPR_BOOKE_CSRR1;
2117 break;
2118 case POWERPC_EXCP_G2:
2119 break;
2120 default:
2121 goto excp_invalid;
2123 goto store_next;
2124 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2125 if (msr_me == 0) {
2126 /* Machine check exception is not enabled.
2127 * Enter checkstop state.
2129 if (qemu_log_enabled()) {
2130 qemu_log("Machine check while not allowed. "
2131 "Entering checkstop state\n");
2132 } else {
2133 fprintf(stderr, "Machine check while not allowed. "
2134 "Entering checkstop state\n");
2136 env->halted = 1;
2137 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2139 if (0) {
2140 /* XXX: find a suitable condition to enable the hypervisor mode */
2141 new_msr |= (target_ulong)MSR_HVB;
2144 /* machine check exceptions don't have ME set */
2145 new_msr &= ~((target_ulong)1 << MSR_ME);
2147 /* XXX: should also have something loaded in DAR / DSISR */
2148 switch (excp_model) {
2149 case POWERPC_EXCP_40x:
2150 srr0 = SPR_40x_SRR2;
2151 srr1 = SPR_40x_SRR3;
2152 break;
2153 case POWERPC_EXCP_BOOKE:
2154 srr0 = SPR_BOOKE_MCSRR0;
2155 srr1 = SPR_BOOKE_MCSRR1;
2156 asrr0 = SPR_BOOKE_CSRR0;
2157 asrr1 = SPR_BOOKE_CSRR1;
2158 break;
2159 default:
2160 break;
2162 goto store_next;
2163 case POWERPC_EXCP_DSI: /* Data storage exception */
2164 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2165 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2166 if (lpes1 == 0)
2167 new_msr |= (target_ulong)MSR_HVB;
2168 goto store_next;
2169 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2170 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2171 "\n", msr, env->nip);
2172 if (lpes1 == 0)
2173 new_msr |= (target_ulong)MSR_HVB;
2174 msr |= env->error_code;
2175 goto store_next;
2176 case POWERPC_EXCP_EXTERNAL: /* External input */
2177 if (lpes0 == 1)
2178 new_msr |= (target_ulong)MSR_HVB;
2179 goto store_next;
2180 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2181 if (lpes1 == 0)
2182 new_msr |= (target_ulong)MSR_HVB;
2183 /* XXX: this is false */
2184 /* Get rS/rD and rA from faulting opcode */
2185 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2186 goto store_current;
2187 case POWERPC_EXCP_PROGRAM: /* Program exception */
2188 switch (env->error_code & ~0xF) {
2189 case POWERPC_EXCP_FP:
2190 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2191 LOG_EXCP("Ignore floating point exception\n");
2192 env->exception_index = POWERPC_EXCP_NONE;
2193 env->error_code = 0;
2194 return;
2196 if (lpes1 == 0)
2197 new_msr |= (target_ulong)MSR_HVB;
2198 msr |= 0x00100000;
2199 if (msr_fe0 == msr_fe1)
2200 goto store_next;
2201 msr |= 0x00010000;
2202 break;
2203 case POWERPC_EXCP_INVAL:
2204 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2205 if (lpes1 == 0)
2206 new_msr |= (target_ulong)MSR_HVB;
2207 msr |= 0x00080000;
2208 break;
2209 case POWERPC_EXCP_PRIV:
2210 if (lpes1 == 0)
2211 new_msr |= (target_ulong)MSR_HVB;
2212 msr |= 0x00040000;
2213 break;
2214 case POWERPC_EXCP_TRAP:
2215 if (lpes1 == 0)
2216 new_msr |= (target_ulong)MSR_HVB;
2217 msr |= 0x00020000;
2218 break;
2219 default:
2220 /* Should never occur */
2221 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2222 env->error_code);
2223 break;
2225 goto store_current;
2226 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2227 if (lpes1 == 0)
2228 new_msr |= (target_ulong)MSR_HVB;
2229 goto store_current;
2230 case POWERPC_EXCP_SYSCALL: /* System call exception */
2231 /* NOTE: this is a temporary hack to support graphics OSI
2232 calls from the MOL driver */
2233 /* XXX: To be removed */
2234 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2235 env->osi_call) {
2236 if (env->osi_call(env) != 0) {
2237 env->exception_index = POWERPC_EXCP_NONE;
2238 env->error_code = 0;
2239 return;
2242 dump_syscall(env);
2243 lev = env->error_code;
2244 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2245 new_msr |= (target_ulong)MSR_HVB;
2246 goto store_next;
2247 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2248 goto store_current;
2249 case POWERPC_EXCP_DECR: /* Decrementer exception */
2250 if (lpes1 == 0)
2251 new_msr |= (target_ulong)MSR_HVB;
2252 goto store_next;
2253 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2254 /* FIT on 4xx */
2255 LOG_EXCP("FIT exception\n");
2256 goto store_next;
2257 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2258 LOG_EXCP("WDT exception\n");
2259 switch (excp_model) {
2260 case POWERPC_EXCP_BOOKE:
2261 srr0 = SPR_BOOKE_CSRR0;
2262 srr1 = SPR_BOOKE_CSRR1;
2263 break;
2264 default:
2265 break;
2267 goto store_next;
2268 case POWERPC_EXCP_DTLB: /* Data TLB error */
2269 goto store_next;
2270 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2271 goto store_next;
2272 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2273 switch (excp_model) {
2274 case POWERPC_EXCP_BOOKE:
2275 srr0 = SPR_BOOKE_DSRR0;
2276 srr1 = SPR_BOOKE_DSRR1;
2277 asrr0 = SPR_BOOKE_CSRR0;
2278 asrr1 = SPR_BOOKE_CSRR1;
2279 break;
2280 default:
2281 break;
2283 /* XXX: TODO */
2284 cpu_abort(env, "Debug exception is not implemented yet !\n");
2285 goto store_next;
2286 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2287 goto store_current;
2288 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2289 /* XXX: TODO */
2290 cpu_abort(env, "Embedded floating point data exception "
2291 "is not implemented yet !\n");
2292 goto store_next;
2293 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2294 /* XXX: TODO */
2295 cpu_abort(env, "Embedded floating point round exception "
2296 "is not implemented yet !\n");
2297 goto store_next;
2298 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2299 /* XXX: TODO */
2300 cpu_abort(env,
2301 "Performance counter exception is not implemented yet !\n");
2302 goto store_next;
2303 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2304 /* XXX: TODO */
2305 cpu_abort(env,
2306 "Embedded doorbell interrupt is not implemented yet !\n");
2307 goto store_next;
2308 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2309 switch (excp_model) {
2310 case POWERPC_EXCP_BOOKE:
2311 srr0 = SPR_BOOKE_CSRR0;
2312 srr1 = SPR_BOOKE_CSRR1;
2313 break;
2314 default:
2315 break;
2317 /* XXX: TODO */
2318 cpu_abort(env, "Embedded doorbell critical interrupt "
2319 "is not implemented yet !\n");
2320 goto store_next;
2321 case POWERPC_EXCP_RESET: /* System reset exception */
2322 if (msr_pow) {
2323 /* indicate that we resumed from power save mode */
2324 msr |= 0x10000;
2325 } else {
2326 new_msr &= ~((target_ulong)1 << MSR_ME);
2329 if (0) {
2330 /* XXX: find a suitable condition to enable the hypervisor mode */
2331 new_msr |= (target_ulong)MSR_HVB;
2333 goto store_next;
2334 case POWERPC_EXCP_DSEG: /* Data segment exception */
2335 if (lpes1 == 0)
2336 new_msr |= (target_ulong)MSR_HVB;
2337 goto store_next;
2338 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2339 if (lpes1 == 0)
2340 new_msr |= (target_ulong)MSR_HVB;
2341 goto store_next;
2342 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2343 srr0 = SPR_HSRR0;
2344 srr1 = SPR_HSRR1;
2345 new_msr |= (target_ulong)MSR_HVB;
2346 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2347 goto store_next;
2348 case POWERPC_EXCP_TRACE: /* Trace exception */
2349 if (lpes1 == 0)
2350 new_msr |= (target_ulong)MSR_HVB;
2351 goto store_next;
2352 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2353 srr0 = SPR_HSRR0;
2354 srr1 = SPR_HSRR1;
2355 new_msr |= (target_ulong)MSR_HVB;
2356 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2357 goto store_next;
2358 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2359 srr0 = SPR_HSRR0;
2360 srr1 = SPR_HSRR1;
2361 new_msr |= (target_ulong)MSR_HVB;
2362 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2363 goto store_next;
2364 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2365 srr0 = SPR_HSRR0;
2366 srr1 = SPR_HSRR1;
2367 new_msr |= (target_ulong)MSR_HVB;
2368 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2369 goto store_next;
2370 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2371 srr0 = SPR_HSRR0;
2372 srr1 = SPR_HSRR1;
2373 new_msr |= (target_ulong)MSR_HVB;
2374 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2375 goto store_next;
2376 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2377 if (lpes1 == 0)
2378 new_msr |= (target_ulong)MSR_HVB;
2379 goto store_current;
2380 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2381 LOG_EXCP("PIT exception\n");
2382 goto store_next;
2383 case POWERPC_EXCP_IO: /* IO error exception */
2384 /* XXX: TODO */
2385 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2386 goto store_next;
2387 case POWERPC_EXCP_RUNM: /* Run mode exception */
2388 /* XXX: TODO */
2389 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2390 goto store_next;
2391 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2392 /* XXX: TODO */
2393 cpu_abort(env, "602 emulation trap exception "
2394 "is not implemented yet !\n");
2395 goto store_next;
2396 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2397 if (lpes1 == 0) /* XXX: check this */
2398 new_msr |= (target_ulong)MSR_HVB;
2399 switch (excp_model) {
2400 case POWERPC_EXCP_602:
2401 case POWERPC_EXCP_603:
2402 case POWERPC_EXCP_603E:
2403 case POWERPC_EXCP_G2:
2404 goto tlb_miss_tgpr;
2405 case POWERPC_EXCP_7x5:
2406 goto tlb_miss;
2407 case POWERPC_EXCP_74xx:
2408 goto tlb_miss_74xx;
2409 default:
2410 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2411 break;
2413 break;
2414 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2415 if (lpes1 == 0) /* XXX: check this */
2416 new_msr |= (target_ulong)MSR_HVB;
2417 switch (excp_model) {
2418 case POWERPC_EXCP_602:
2419 case POWERPC_EXCP_603:
2420 case POWERPC_EXCP_603E:
2421 case POWERPC_EXCP_G2:
2422 goto tlb_miss_tgpr;
2423 case POWERPC_EXCP_7x5:
2424 goto tlb_miss;
2425 case POWERPC_EXCP_74xx:
2426 goto tlb_miss_74xx;
2427 default:
2428 cpu_abort(env, "Invalid data load TLB miss exception\n");
2429 break;
2431 break;
2432 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2433 if (lpes1 == 0) /* XXX: check this */
2434 new_msr |= (target_ulong)MSR_HVB;
2435 switch (excp_model) {
2436 case POWERPC_EXCP_602:
2437 case POWERPC_EXCP_603:
2438 case POWERPC_EXCP_603E:
2439 case POWERPC_EXCP_G2:
2440 tlb_miss_tgpr:
2441 /* Swap temporary saved registers with GPRs */
2442 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2443 new_msr |= (target_ulong)1 << MSR_TGPR;
2444 hreg_swap_gpr_tgpr(env);
2446 goto tlb_miss;
2447 case POWERPC_EXCP_7x5:
2448 tlb_miss:
2449 #if defined (DEBUG_SOFTWARE_TLB)
2450 if (qemu_log_enabled()) {
2451 const char *es;
2452 target_ulong *miss, *cmp;
2453 int en;
2454 if (excp == POWERPC_EXCP_IFTLB) {
2455 es = "I";
2456 en = 'I';
2457 miss = &env->spr[SPR_IMISS];
2458 cmp = &env->spr[SPR_ICMP];
2459 } else {
2460 if (excp == POWERPC_EXCP_DLTLB)
2461 es = "DL";
2462 else
2463 es = "DS";
2464 en = 'D';
2465 miss = &env->spr[SPR_DMISS];
2466 cmp = &env->spr[SPR_DCMP];
2468 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2469 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2470 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2471 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2472 env->error_code);
2474 #endif
2475 msr |= env->crf[0] << 28;
2476 msr |= env->error_code; /* key, D/I, S/L bits */
2477 /* Set way using a LRU mechanism */
2478 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2479 break;
2480 case POWERPC_EXCP_74xx:
2481 tlb_miss_74xx:
2482 #if defined (DEBUG_SOFTWARE_TLB)
2483 if (qemu_log_enabled()) {
2484 const char *es;
2485 target_ulong *miss, *cmp;
2486 int en;
2487 if (excp == POWERPC_EXCP_IFTLB) {
2488 es = "I";
2489 en = 'I';
2490 miss = &env->spr[SPR_TLBMISS];
2491 cmp = &env->spr[SPR_PTEHI];
2492 } else {
2493 if (excp == POWERPC_EXCP_DLTLB)
2494 es = "DL";
2495 else
2496 es = "DS";
2497 en = 'D';
2498 miss = &env->spr[SPR_TLBMISS];
2499 cmp = &env->spr[SPR_PTEHI];
2501 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2502 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2503 env->error_code);
2505 #endif
2506 msr |= env->error_code; /* key bit */
2507 break;
2508 default:
2509 cpu_abort(env, "Invalid data store TLB miss exception\n");
2510 break;
2512 goto store_next;
2513 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2514 /* XXX: TODO */
2515 cpu_abort(env, "Floating point assist exception "
2516 "is not implemented yet !\n");
2517 goto store_next;
2518 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2519 /* XXX: TODO */
2520 cpu_abort(env, "DABR exception is not implemented yet !\n");
2521 goto store_next;
2522 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2523 /* XXX: TODO */
2524 cpu_abort(env, "IABR exception is not implemented yet !\n");
2525 goto store_next;
2526 case POWERPC_EXCP_SMI: /* System management interrupt */
2527 /* XXX: TODO */
2528 cpu_abort(env, "SMI exception is not implemented yet !\n");
2529 goto store_next;
2530 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2531 /* XXX: TODO */
2532 cpu_abort(env, "Thermal management exception "
2533 "is not implemented yet !\n");
2534 goto store_next;
2535 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2536 if (lpes1 == 0)
2537 new_msr |= (target_ulong)MSR_HVB;
2538 /* XXX: TODO */
2539 cpu_abort(env,
2540 "Performance counter exception is not implemented yet !\n");
2541 goto store_next;
2542 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2543 /* XXX: TODO */
2544 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2545 goto store_next;
2546 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2547 /* XXX: TODO */
2548 cpu_abort(env,
2549 "970 soft-patch exception is not implemented yet !\n");
2550 goto store_next;
2551 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2552 /* XXX: TODO */
2553 cpu_abort(env,
2554 "970 maintenance exception is not implemented yet !\n");
2555 goto store_next;
2556 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2557 /* XXX: TODO */
2558 cpu_abort(env, "Maskable external exception "
2559 "is not implemented yet !\n");
2560 goto store_next;
2561 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2562 /* XXX: TODO */
2563 cpu_abort(env, "Non maskable external exception "
2564 "is not implemented yet !\n");
2565 goto store_next;
2566 default:
2567 excp_invalid:
2568 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2569 break;
2570 store_current:
2571 /* save current instruction location */
2572 env->spr[srr0] = env->nip - 4;
2573 break;
2574 store_next:
2575 /* save next instruction location */
2576 env->spr[srr0] = env->nip;
2577 break;
2579 /* Save MSR */
2580 env->spr[srr1] = msr;
2581 /* If any alternate SRR register are defined, duplicate saved values */
2582 if (asrr0 != -1)
2583 env->spr[asrr0] = env->spr[srr0];
2584 if (asrr1 != -1)
2585 env->spr[asrr1] = env->spr[srr1];
2586 /* If we disactivated any translation, flush TLBs */
2587 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2588 tlb_flush(env, 1);
2590 if (msr_ile) {
2591 new_msr |= (target_ulong)1 << MSR_LE;
2594 /* Jump to handler */
2595 vector = env->excp_vectors[excp];
2596 if (vector == (target_ulong)-1ULL) {
2597 cpu_abort(env, "Raised an exception without defined vector %d\n",
2598 excp);
2600 vector |= env->excp_prefix;
2601 #if defined(TARGET_PPC64)
2602 if (excp_model == POWERPC_EXCP_BOOKE) {
2603 if (!msr_icm) {
2604 vector = (uint32_t)vector;
2605 } else {
2606 new_msr |= (target_ulong)1 << MSR_CM;
2608 } else {
2609 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2610 vector = (uint32_t)vector;
2611 } else {
2612 new_msr |= (target_ulong)1 << MSR_SF;
2615 #endif
2616 /* XXX: we don't use hreg_store_msr here as already have treated
2617 * any special case that could occur. Just store MSR and update hflags
2619 env->msr = new_msr & env->msr_mask;
2620 hreg_compute_hflags(env);
2621 env->nip = vector;
2622 /* Reset exception state */
2623 env->exception_index = POWERPC_EXCP_NONE;
2624 env->error_code = 0;
2626 if (env->mmu_model == POWERPC_MMU_BOOKE) {
2627 /* XXX: The BookE changes address space when switching modes,
2628 we should probably implement that as different MMU indexes,
2629 but for the moment we do it the slow way and flush all. */
2630 tlb_flush(env, 1);
2634 void do_interrupt (CPUState *env)
2636 powerpc_excp(env, env->excp_model, env->exception_index);
2639 void ppc_hw_interrupt (CPUPPCState *env)
2641 int hdice;
2643 #if 0
2644 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2645 __func__, env, env->pending_interrupts,
2646 env->interrupt_request, (int)msr_me, (int)msr_ee);
2647 #endif
2648 /* External reset */
2649 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2650 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2651 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2652 return;
2654 /* Machine check exception */
2655 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2656 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2657 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2658 return;
2660 #if 0 /* TODO */
2661 /* External debug exception */
2662 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2663 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2664 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2665 return;
2667 #endif
2668 if (0) {
2669 /* XXX: find a suitable condition to enable the hypervisor mode */
2670 hdice = env->spr[SPR_LPCR] & 1;
2671 } else {
2672 hdice = 0;
2674 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2675 /* Hypervisor decrementer exception */
2676 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2677 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2678 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2679 return;
2682 if (msr_ce != 0) {
2683 /* External critical interrupt */
2684 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2685 /* Taking a critical external interrupt does not clear the external
2686 * critical interrupt status
2688 #if 0
2689 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2690 #endif
2691 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2692 return;
2695 if (msr_ee != 0) {
2696 /* Watchdog timer on embedded PowerPC */
2697 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2698 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2699 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2700 return;
2702 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2703 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2704 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2705 return;
2707 /* Fixed interval timer on embedded PowerPC */
2708 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2709 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2710 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2711 return;
2713 /* Programmable interval timer on embedded PowerPC */
2714 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2715 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2716 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2717 return;
2719 /* Decrementer exception */
2720 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2721 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2722 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2723 return;
2725 /* External interrupt */
2726 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2727 /* Taking an external interrupt does not clear the external
2728 * interrupt status
2730 #if 0
2731 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2732 #endif
2733 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2734 return;
2736 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2737 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2738 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2739 return;
2741 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2742 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2743 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2744 return;
2746 /* Thermal interrupt */
2747 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2748 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2749 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2750 return;
2754 #endif /* !CONFIG_USER_ONLY */
2756 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2758 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2759 TARGET_FMT_lx "\n", RA, msr);
2762 void cpu_reset(CPUPPCState *env)
2764 target_ulong msr;
2766 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2767 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2768 log_cpu_state(env, 0);
2771 msr = (target_ulong)0;
2772 if (0) {
2773 /* XXX: find a suitable condition to enable the hypervisor mode */
2774 msr |= (target_ulong)MSR_HVB;
2776 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2777 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2778 msr |= (target_ulong)1 << MSR_EP;
2779 #if defined (DO_SINGLE_STEP) && 0
2780 /* Single step trace mode */
2781 msr |= (target_ulong)1 << MSR_SE;
2782 msr |= (target_ulong)1 << MSR_BE;
2783 #endif
2784 #if defined(CONFIG_USER_ONLY)
2785 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2786 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2787 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2788 msr |= (target_ulong)1 << MSR_PR;
2789 #else
2790 env->excp_prefix = env->hreset_excp_prefix;
2791 env->nip = env->hreset_vector | env->excp_prefix;
2792 if (env->mmu_model != POWERPC_MMU_REAL)
2793 ppc_tlb_invalidate_all(env);
2794 #endif
2795 env->msr = msr & env->msr_mask;
2796 #if defined(TARGET_PPC64)
2797 if (env->mmu_model & POWERPC_MMU_64)
2798 env->msr |= (1ULL << MSR_SF);
2799 #endif
2800 hreg_compute_hflags(env);
2801 env->reserve_addr = (target_ulong)-1ULL;
2802 /* Be sure no exception or interrupt is pending */
2803 env->pending_interrupts = 0;
2804 env->exception_index = POWERPC_EXCP_NONE;
2805 env->error_code = 0;
2806 /* Flush all TLBs */
2807 tlb_flush(env, 1);
2810 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2812 CPUPPCState *env;
2813 const ppc_def_t *def;
2815 def = cpu_ppc_find_by_name(cpu_model);
2816 if (!def)
2817 return NULL;
2819 env = qemu_mallocz(sizeof(CPUPPCState));
2820 cpu_exec_init(env);
2821 ppc_translate_init();
2822 env->cpu_model_str = cpu_model;
2823 cpu_ppc_register_internal(env, def);
2825 qemu_init_vcpu(env);
2827 return env;
2830 void cpu_ppc_close (CPUPPCState *env)
2832 /* Should also remove all opcode tables... */
2833 qemu_free(env);