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