Merge remote-tracking branch 'agraf/xen-next' into staging
[qemu.git] / target-ppc / helper.c
blob5e4030bb531e8c7fad83237d0c89c0ce4c485a29
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 static inline 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\n", __func__, i, address, pid, tlb->EPN,
1010 mask, (uint32_t)tlb->PID);
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 int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1157 target_ulong address, int rw,
1158 int access_type)
1160 ppcemb_tlb_t *tlb;
1161 target_phys_addr_t raddr;
1162 int i, prot, ret;
1164 ret = -1;
1165 raddr = (target_phys_addr_t)-1ULL;
1166 for (i = 0; i < env->nb_tlb; i++) {
1167 tlb = &env->tlb[i].tlbe;
1168 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1169 env->spr[SPR_BOOKE_PID], 1, i) < 0)
1170 continue;
1171 if (msr_pr != 0)
1172 prot = tlb->prot & 0xF;
1173 else
1174 prot = (tlb->prot >> 4) & 0xF;
1175 /* Check the address space */
1176 if (access_type == ACCESS_CODE) {
1177 if (msr_ir != (tlb->attr & 1))
1178 continue;
1179 ctx->prot = prot;
1180 if (prot & PAGE_EXEC) {
1181 ret = 0;
1182 break;
1184 ret = -3;
1185 } else {
1186 if (msr_dr != (tlb->attr & 1))
1187 continue;
1188 ctx->prot = prot;
1189 if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1190 ret = 0;
1191 break;
1193 ret = -2;
1196 if (ret >= 0)
1197 ctx->raddr = raddr;
1199 return ret;
1202 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1203 target_ulong eaddr, int rw)
1205 int in_plb, ret;
1207 ctx->raddr = eaddr;
1208 ctx->prot = PAGE_READ | PAGE_EXEC;
1209 ret = 0;
1210 switch (env->mmu_model) {
1211 case POWERPC_MMU_32B:
1212 case POWERPC_MMU_601:
1213 case POWERPC_MMU_SOFT_6xx:
1214 case POWERPC_MMU_SOFT_74xx:
1215 case POWERPC_MMU_SOFT_4xx:
1216 case POWERPC_MMU_REAL:
1217 case POWERPC_MMU_BOOKE:
1218 ctx->prot |= PAGE_WRITE;
1219 break;
1220 #if defined(TARGET_PPC64)
1221 case POWERPC_MMU_620:
1222 case POWERPC_MMU_64B:
1223 case POWERPC_MMU_2_06:
1224 /* Real address are 60 bits long */
1225 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1226 ctx->prot |= PAGE_WRITE;
1227 break;
1228 #endif
1229 case POWERPC_MMU_SOFT_4xx_Z:
1230 if (unlikely(msr_pe != 0)) {
1231 /* 403 family add some particular protections,
1232 * using PBL/PBU registers for accesses with no translation.
1234 in_plb =
1235 /* Check PLB validity */
1236 (env->pb[0] < env->pb[1] &&
1237 /* and address in plb area */
1238 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1239 (env->pb[2] < env->pb[3] &&
1240 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1241 if (in_plb ^ msr_px) {
1242 /* Access in protected area */
1243 if (rw == 1) {
1244 /* Access is not allowed */
1245 ret = -2;
1247 } else {
1248 /* Read-write access is allowed */
1249 ctx->prot |= PAGE_WRITE;
1252 break;
1253 case POWERPC_MMU_MPC8xx:
1254 /* XXX: TODO */
1255 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1256 break;
1257 case POWERPC_MMU_BOOKE_FSL:
1258 /* XXX: TODO */
1259 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1260 break;
1261 default:
1262 cpu_abort(env, "Unknown or invalid MMU model\n");
1263 return -1;
1266 return ret;
1269 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1270 int rw, int access_type)
1272 int ret;
1274 #if 0
1275 qemu_log("%s\n", __func__);
1276 #endif
1277 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1278 (access_type != ACCESS_CODE && msr_dr == 0)) {
1279 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1280 /* The BookE MMU always performs address translation. The
1281 IS and DS bits only affect the address space. */
1282 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1283 rw, access_type);
1284 } else {
1285 /* No address translation. */
1286 ret = check_physical(env, ctx, eaddr, rw);
1288 } else {
1289 ret = -1;
1290 switch (env->mmu_model) {
1291 case POWERPC_MMU_32B:
1292 case POWERPC_MMU_601:
1293 case POWERPC_MMU_SOFT_6xx:
1294 case POWERPC_MMU_SOFT_74xx:
1295 /* Try to find a BAT */
1296 if (env->nb_BATs != 0)
1297 ret = get_bat(env, ctx, eaddr, rw, access_type);
1298 #if defined(TARGET_PPC64)
1299 case POWERPC_MMU_620:
1300 case POWERPC_MMU_64B:
1301 case POWERPC_MMU_2_06:
1302 #endif
1303 if (ret < 0) {
1304 /* We didn't match any BAT entry or don't have BATs */
1305 ret = get_segment(env, ctx, eaddr, rw, access_type);
1307 break;
1308 case POWERPC_MMU_SOFT_4xx:
1309 case POWERPC_MMU_SOFT_4xx_Z:
1310 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1311 rw, access_type);
1312 break;
1313 case POWERPC_MMU_BOOKE:
1314 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1315 rw, access_type);
1316 break;
1317 case POWERPC_MMU_MPC8xx:
1318 /* XXX: TODO */
1319 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1320 break;
1321 case POWERPC_MMU_BOOKE_FSL:
1322 /* XXX: TODO */
1323 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1324 return -1;
1325 case POWERPC_MMU_REAL:
1326 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1327 return -1;
1328 default:
1329 cpu_abort(env, "Unknown or invalid MMU model\n");
1330 return -1;
1333 #if 0
1334 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1335 __func__, eaddr, ret, ctx->raddr);
1336 #endif
1338 return ret;
1341 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1343 mmu_ctx_t ctx;
1345 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1346 return -1;
1348 return ctx.raddr & TARGET_PAGE_MASK;
1351 /* Perform address translation */
1352 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1353 int mmu_idx, int is_softmmu)
1355 mmu_ctx_t ctx;
1356 int access_type;
1357 int ret = 0;
1359 if (rw == 2) {
1360 /* code access */
1361 rw = 0;
1362 access_type = ACCESS_CODE;
1363 } else {
1364 /* data access */
1365 access_type = env->access_type;
1367 ret = get_physical_address(env, &ctx, address, rw, access_type);
1368 if (ret == 0) {
1369 tlb_set_page(env, address & TARGET_PAGE_MASK,
1370 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1371 mmu_idx, TARGET_PAGE_SIZE);
1372 ret = 0;
1373 } else if (ret < 0) {
1374 LOG_MMU_STATE(env);
1375 if (access_type == ACCESS_CODE) {
1376 switch (ret) {
1377 case -1:
1378 /* No matches in page tables or TLB */
1379 switch (env->mmu_model) {
1380 case POWERPC_MMU_SOFT_6xx:
1381 env->exception_index = POWERPC_EXCP_IFTLB;
1382 env->error_code = 1 << 18;
1383 env->spr[SPR_IMISS] = address;
1384 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1385 goto tlb_miss;
1386 case POWERPC_MMU_SOFT_74xx:
1387 env->exception_index = POWERPC_EXCP_IFTLB;
1388 goto tlb_miss_74xx;
1389 case POWERPC_MMU_SOFT_4xx:
1390 case POWERPC_MMU_SOFT_4xx_Z:
1391 env->exception_index = POWERPC_EXCP_ITLB;
1392 env->error_code = 0;
1393 env->spr[SPR_40x_DEAR] = address;
1394 env->spr[SPR_40x_ESR] = 0x00000000;
1395 break;
1396 case POWERPC_MMU_32B:
1397 case POWERPC_MMU_601:
1398 #if defined(TARGET_PPC64)
1399 case POWERPC_MMU_620:
1400 case POWERPC_MMU_64B:
1401 case POWERPC_MMU_2_06:
1402 #endif
1403 env->exception_index = POWERPC_EXCP_ISI;
1404 env->error_code = 0x40000000;
1405 break;
1406 case POWERPC_MMU_BOOKE:
1407 env->exception_index = POWERPC_EXCP_ITLB;
1408 env->error_code = 0;
1409 env->spr[SPR_BOOKE_DEAR] = address;
1410 return -1;
1411 case POWERPC_MMU_BOOKE_FSL:
1412 /* XXX: TODO */
1413 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1414 return -1;
1415 case POWERPC_MMU_MPC8xx:
1416 /* XXX: TODO */
1417 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1418 break;
1419 case POWERPC_MMU_REAL:
1420 cpu_abort(env, "PowerPC in real mode should never raise "
1421 "any MMU exceptions\n");
1422 return -1;
1423 default:
1424 cpu_abort(env, "Unknown or invalid MMU model\n");
1425 return -1;
1427 break;
1428 case -2:
1429 /* Access rights violation */
1430 env->exception_index = POWERPC_EXCP_ISI;
1431 env->error_code = 0x08000000;
1432 break;
1433 case -3:
1434 /* No execute protection violation */
1435 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1436 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1438 env->exception_index = POWERPC_EXCP_ISI;
1439 env->error_code = 0x10000000;
1440 break;
1441 case -4:
1442 /* Direct store exception */
1443 /* No code fetch is allowed in direct-store areas */
1444 env->exception_index = POWERPC_EXCP_ISI;
1445 env->error_code = 0x10000000;
1446 break;
1447 #if defined(TARGET_PPC64)
1448 case -5:
1449 /* No match in segment table */
1450 if (env->mmu_model == POWERPC_MMU_620) {
1451 env->exception_index = POWERPC_EXCP_ISI;
1452 /* XXX: this might be incorrect */
1453 env->error_code = 0x40000000;
1454 } else {
1455 env->exception_index = POWERPC_EXCP_ISEG;
1456 env->error_code = 0;
1458 break;
1459 #endif
1461 } else {
1462 switch (ret) {
1463 case -1:
1464 /* No matches in page tables or TLB */
1465 switch (env->mmu_model) {
1466 case POWERPC_MMU_SOFT_6xx:
1467 if (rw == 1) {
1468 env->exception_index = POWERPC_EXCP_DSTLB;
1469 env->error_code = 1 << 16;
1470 } else {
1471 env->exception_index = POWERPC_EXCP_DLTLB;
1472 env->error_code = 0;
1474 env->spr[SPR_DMISS] = address;
1475 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1476 tlb_miss:
1477 env->error_code |= ctx.key << 19;
1478 env->spr[SPR_HASH1] = env->htab_base +
1479 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1480 env->spr[SPR_HASH2] = env->htab_base +
1481 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1482 break;
1483 case POWERPC_MMU_SOFT_74xx:
1484 if (rw == 1) {
1485 env->exception_index = POWERPC_EXCP_DSTLB;
1486 } else {
1487 env->exception_index = POWERPC_EXCP_DLTLB;
1489 tlb_miss_74xx:
1490 /* Implement LRU algorithm */
1491 env->error_code = ctx.key << 19;
1492 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1493 ((env->last_way + 1) & (env->nb_ways - 1));
1494 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1495 break;
1496 case POWERPC_MMU_SOFT_4xx:
1497 case POWERPC_MMU_SOFT_4xx_Z:
1498 env->exception_index = POWERPC_EXCP_DTLB;
1499 env->error_code = 0;
1500 env->spr[SPR_40x_DEAR] = address;
1501 if (rw)
1502 env->spr[SPR_40x_ESR] = 0x00800000;
1503 else
1504 env->spr[SPR_40x_ESR] = 0x00000000;
1505 break;
1506 case POWERPC_MMU_32B:
1507 case POWERPC_MMU_601:
1508 #if defined(TARGET_PPC64)
1509 case POWERPC_MMU_620:
1510 case POWERPC_MMU_64B:
1511 case POWERPC_MMU_2_06:
1512 #endif
1513 env->exception_index = POWERPC_EXCP_DSI;
1514 env->error_code = 0;
1515 env->spr[SPR_DAR] = address;
1516 if (rw == 1)
1517 env->spr[SPR_DSISR] = 0x42000000;
1518 else
1519 env->spr[SPR_DSISR] = 0x40000000;
1520 break;
1521 case POWERPC_MMU_MPC8xx:
1522 /* XXX: TODO */
1523 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1524 break;
1525 case POWERPC_MMU_BOOKE:
1526 env->exception_index = POWERPC_EXCP_DTLB;
1527 env->error_code = 0;
1528 env->spr[SPR_BOOKE_DEAR] = address;
1529 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1530 return -1;
1531 case POWERPC_MMU_BOOKE_FSL:
1532 /* XXX: TODO */
1533 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1534 return -1;
1535 case POWERPC_MMU_REAL:
1536 cpu_abort(env, "PowerPC in real mode should never raise "
1537 "any MMU exceptions\n");
1538 return -1;
1539 default:
1540 cpu_abort(env, "Unknown or invalid MMU model\n");
1541 return -1;
1543 break;
1544 case -2:
1545 /* Access rights violation */
1546 env->exception_index = POWERPC_EXCP_DSI;
1547 env->error_code = 0;
1548 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1549 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1550 env->spr[SPR_40x_DEAR] = address;
1551 if (rw) {
1552 env->spr[SPR_40x_ESR] |= 0x00800000;
1554 } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1555 env->spr[SPR_BOOKE_DEAR] = address;
1556 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1557 } else {
1558 env->spr[SPR_DAR] = address;
1559 if (rw == 1) {
1560 env->spr[SPR_DSISR] = 0x0A000000;
1561 } else {
1562 env->spr[SPR_DSISR] = 0x08000000;
1565 break;
1566 case -4:
1567 /* Direct store exception */
1568 switch (access_type) {
1569 case ACCESS_FLOAT:
1570 /* Floating point load/store */
1571 env->exception_index = POWERPC_EXCP_ALIGN;
1572 env->error_code = POWERPC_EXCP_ALIGN_FP;
1573 env->spr[SPR_DAR] = address;
1574 break;
1575 case ACCESS_RES:
1576 /* lwarx, ldarx or stwcx. */
1577 env->exception_index = POWERPC_EXCP_DSI;
1578 env->error_code = 0;
1579 env->spr[SPR_DAR] = address;
1580 if (rw == 1)
1581 env->spr[SPR_DSISR] = 0x06000000;
1582 else
1583 env->spr[SPR_DSISR] = 0x04000000;
1584 break;
1585 case ACCESS_EXT:
1586 /* eciwx or ecowx */
1587 env->exception_index = POWERPC_EXCP_DSI;
1588 env->error_code = 0;
1589 env->spr[SPR_DAR] = address;
1590 if (rw == 1)
1591 env->spr[SPR_DSISR] = 0x06100000;
1592 else
1593 env->spr[SPR_DSISR] = 0x04100000;
1594 break;
1595 default:
1596 printf("DSI: invalid exception (%d)\n", ret);
1597 env->exception_index = POWERPC_EXCP_PROGRAM;
1598 env->error_code =
1599 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1600 env->spr[SPR_DAR] = address;
1601 break;
1603 break;
1604 #if defined(TARGET_PPC64)
1605 case -5:
1606 /* No match in segment table */
1607 if (env->mmu_model == POWERPC_MMU_620) {
1608 env->exception_index = POWERPC_EXCP_DSI;
1609 env->error_code = 0;
1610 env->spr[SPR_DAR] = address;
1611 /* XXX: this might be incorrect */
1612 if (rw == 1)
1613 env->spr[SPR_DSISR] = 0x42000000;
1614 else
1615 env->spr[SPR_DSISR] = 0x40000000;
1616 } else {
1617 env->exception_index = POWERPC_EXCP_DSEG;
1618 env->error_code = 0;
1619 env->spr[SPR_DAR] = address;
1621 break;
1622 #endif
1625 #if 0
1626 printf("%s: set exception to %d %02x\n", __func__,
1627 env->exception, env->error_code);
1628 #endif
1629 ret = 1;
1632 return ret;
1635 /*****************************************************************************/
1636 /* BATs management */
1637 #if !defined(FLUSH_ALL_TLBS)
1638 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1639 target_ulong mask)
1641 target_ulong base, end, page;
1643 base = BATu & ~0x0001FFFF;
1644 end = base + mask + 0x00020000;
1645 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1646 TARGET_FMT_lx ")\n", base, end, mask);
1647 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1648 tlb_flush_page(env, page);
1649 LOG_BATS("Flush done\n");
1651 #endif
1653 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1654 target_ulong value)
1656 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1657 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1660 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1662 target_ulong mask;
1664 dump_store_bat(env, 'I', 0, nr, value);
1665 if (env->IBAT[0][nr] != value) {
1666 mask = (value << 15) & 0x0FFE0000UL;
1667 #if !defined(FLUSH_ALL_TLBS)
1668 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1669 #endif
1670 /* When storing valid upper BAT, mask BEPI and BRPN
1671 * and invalidate all TLBs covered by this BAT
1673 mask = (value << 15) & 0x0FFE0000UL;
1674 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1675 (value & ~0x0001FFFFUL & ~mask);
1676 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1677 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1678 #if !defined(FLUSH_ALL_TLBS)
1679 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1680 #else
1681 tlb_flush(env, 1);
1682 #endif
1686 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1688 dump_store_bat(env, 'I', 1, nr, value);
1689 env->IBAT[1][nr] = value;
1692 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1694 target_ulong mask;
1696 dump_store_bat(env, 'D', 0, nr, value);
1697 if (env->DBAT[0][nr] != value) {
1698 /* When storing valid upper BAT, mask BEPI and BRPN
1699 * and invalidate all TLBs covered by this BAT
1701 mask = (value << 15) & 0x0FFE0000UL;
1702 #if !defined(FLUSH_ALL_TLBS)
1703 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1704 #endif
1705 mask = (value << 15) & 0x0FFE0000UL;
1706 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1707 (value & ~0x0001FFFFUL & ~mask);
1708 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1709 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1710 #if !defined(FLUSH_ALL_TLBS)
1711 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1712 #else
1713 tlb_flush(env, 1);
1714 #endif
1718 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1720 dump_store_bat(env, 'D', 1, nr, value);
1721 env->DBAT[1][nr] = value;
1724 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1726 target_ulong mask;
1727 #if defined(FLUSH_ALL_TLBS)
1728 int do_inval;
1729 #endif
1731 dump_store_bat(env, 'I', 0, nr, value);
1732 if (env->IBAT[0][nr] != value) {
1733 #if defined(FLUSH_ALL_TLBS)
1734 do_inval = 0;
1735 #endif
1736 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1737 if (env->IBAT[1][nr] & 0x40) {
1738 /* Invalidate BAT only if it is valid */
1739 #if !defined(FLUSH_ALL_TLBS)
1740 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1741 #else
1742 do_inval = 1;
1743 #endif
1745 /* When storing valid upper BAT, mask BEPI and BRPN
1746 * and invalidate all TLBs covered by this BAT
1748 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1749 (value & ~0x0001FFFFUL & ~mask);
1750 env->DBAT[0][nr] = env->IBAT[0][nr];
1751 if (env->IBAT[1][nr] & 0x40) {
1752 #if !defined(FLUSH_ALL_TLBS)
1753 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1754 #else
1755 do_inval = 1;
1756 #endif
1758 #if defined(FLUSH_ALL_TLBS)
1759 if (do_inval)
1760 tlb_flush(env, 1);
1761 #endif
1765 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1767 target_ulong mask;
1768 #if defined(FLUSH_ALL_TLBS)
1769 int do_inval;
1770 #endif
1772 dump_store_bat(env, 'I', 1, nr, value);
1773 if (env->IBAT[1][nr] != value) {
1774 #if defined(FLUSH_ALL_TLBS)
1775 do_inval = 0;
1776 #endif
1777 if (env->IBAT[1][nr] & 0x40) {
1778 #if !defined(FLUSH_ALL_TLBS)
1779 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1780 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1781 #else
1782 do_inval = 1;
1783 #endif
1785 if (value & 0x40) {
1786 #if !defined(FLUSH_ALL_TLBS)
1787 mask = (value << 17) & 0x0FFE0000UL;
1788 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1789 #else
1790 do_inval = 1;
1791 #endif
1793 env->IBAT[1][nr] = value;
1794 env->DBAT[1][nr] = value;
1795 #if defined(FLUSH_ALL_TLBS)
1796 if (do_inval)
1797 tlb_flush(env, 1);
1798 #endif
1802 /*****************************************************************************/
1803 /* TLB management */
1804 void ppc_tlb_invalidate_all (CPUPPCState *env)
1806 switch (env->mmu_model) {
1807 case POWERPC_MMU_SOFT_6xx:
1808 case POWERPC_MMU_SOFT_74xx:
1809 ppc6xx_tlb_invalidate_all(env);
1810 break;
1811 case POWERPC_MMU_SOFT_4xx:
1812 case POWERPC_MMU_SOFT_4xx_Z:
1813 ppc4xx_tlb_invalidate_all(env);
1814 break;
1815 case POWERPC_MMU_REAL:
1816 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1817 break;
1818 case POWERPC_MMU_MPC8xx:
1819 /* XXX: TODO */
1820 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1821 break;
1822 case POWERPC_MMU_BOOKE:
1823 tlb_flush(env, 1);
1824 break;
1825 case POWERPC_MMU_BOOKE_FSL:
1826 /* XXX: TODO */
1827 if (!kvm_enabled())
1828 cpu_abort(env, "BookE MMU model is not implemented\n");
1829 break;
1830 case POWERPC_MMU_32B:
1831 case POWERPC_MMU_601:
1832 #if defined(TARGET_PPC64)
1833 case POWERPC_MMU_620:
1834 case POWERPC_MMU_64B:
1835 case POWERPC_MMU_2_06:
1836 #endif /* defined(TARGET_PPC64) */
1837 tlb_flush(env, 1);
1838 break;
1839 default:
1840 /* XXX: TODO */
1841 cpu_abort(env, "Unknown MMU model\n");
1842 break;
1846 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1848 #if !defined(FLUSH_ALL_TLBS)
1849 addr &= TARGET_PAGE_MASK;
1850 switch (env->mmu_model) {
1851 case POWERPC_MMU_SOFT_6xx:
1852 case POWERPC_MMU_SOFT_74xx:
1853 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1854 if (env->id_tlbs == 1)
1855 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1856 break;
1857 case POWERPC_MMU_SOFT_4xx:
1858 case POWERPC_MMU_SOFT_4xx_Z:
1859 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1860 break;
1861 case POWERPC_MMU_REAL:
1862 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1863 break;
1864 case POWERPC_MMU_MPC8xx:
1865 /* XXX: TODO */
1866 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1867 break;
1868 case POWERPC_MMU_BOOKE:
1869 /* XXX: TODO */
1870 cpu_abort(env, "BookE MMU model is not implemented\n");
1871 break;
1872 case POWERPC_MMU_BOOKE_FSL:
1873 /* XXX: TODO */
1874 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1875 break;
1876 case POWERPC_MMU_32B:
1877 case POWERPC_MMU_601:
1878 /* tlbie invalidate TLBs for all segments */
1879 addr &= ~((target_ulong)-1ULL << 28);
1880 /* XXX: this case should be optimized,
1881 * giving a mask to tlb_flush_page
1883 tlb_flush_page(env, addr | (0x0 << 28));
1884 tlb_flush_page(env, addr | (0x1 << 28));
1885 tlb_flush_page(env, addr | (0x2 << 28));
1886 tlb_flush_page(env, addr | (0x3 << 28));
1887 tlb_flush_page(env, addr | (0x4 << 28));
1888 tlb_flush_page(env, addr | (0x5 << 28));
1889 tlb_flush_page(env, addr | (0x6 << 28));
1890 tlb_flush_page(env, addr | (0x7 << 28));
1891 tlb_flush_page(env, addr | (0x8 << 28));
1892 tlb_flush_page(env, addr | (0x9 << 28));
1893 tlb_flush_page(env, addr | (0xA << 28));
1894 tlb_flush_page(env, addr | (0xB << 28));
1895 tlb_flush_page(env, addr | (0xC << 28));
1896 tlb_flush_page(env, addr | (0xD << 28));
1897 tlb_flush_page(env, addr | (0xE << 28));
1898 tlb_flush_page(env, addr | (0xF << 28));
1899 break;
1900 #if defined(TARGET_PPC64)
1901 case POWERPC_MMU_620:
1902 case POWERPC_MMU_64B:
1903 case POWERPC_MMU_2_06:
1904 /* tlbie invalidate TLBs for all segments */
1905 /* XXX: given the fact that there are too many segments to invalidate,
1906 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1907 * we just invalidate all TLBs
1909 tlb_flush(env, 1);
1910 break;
1911 #endif /* defined(TARGET_PPC64) */
1912 default:
1913 /* XXX: TODO */
1914 cpu_abort(env, "Unknown MMU model\n");
1915 break;
1917 #else
1918 ppc_tlb_invalidate_all(env);
1919 #endif
1922 /*****************************************************************************/
1923 /* Special registers manipulation */
1924 #if defined(TARGET_PPC64)
1925 void ppc_store_asr (CPUPPCState *env, target_ulong value)
1927 if (env->asr != value) {
1928 env->asr = value;
1929 tlb_flush(env, 1);
1932 #endif
1934 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1936 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1937 if (env->spr[SPR_SDR1] != value) {
1938 env->spr[SPR_SDR1] = value;
1939 #if defined(TARGET_PPC64)
1940 if (env->mmu_model & POWERPC_MMU_64) {
1941 target_ulong htabsize = value & SDR_64_HTABSIZE;
1943 if (htabsize > 28) {
1944 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1945 " stored in SDR1\n", htabsize);
1946 htabsize = 28;
1948 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1949 env->htab_base = value & SDR_64_HTABORG;
1950 } else
1951 #endif /* defined(TARGET_PPC64) */
1953 /* FIXME: Should check for valid HTABMASK values */
1954 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1955 env->htab_base = value & SDR_32_HTABORG;
1957 tlb_flush(env, 1);
1961 #if defined(TARGET_PPC64)
1962 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1964 // XXX
1965 return 0;
1967 #endif
1969 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1971 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1972 srnum, value, env->sr[srnum]);
1973 #if defined(TARGET_PPC64)
1974 if (env->mmu_model & POWERPC_MMU_64) {
1975 uint64_t rb = 0, rs = 0;
1977 /* ESID = srnum */
1978 rb |= ((uint32_t)srnum & 0xf) << 28;
1979 /* Set the valid bit */
1980 rb |= 1 << 27;
1981 /* Index = ESID */
1982 rb |= (uint32_t)srnum;
1984 /* VSID = VSID */
1985 rs |= (value & 0xfffffff) << 12;
1986 /* flags = flags */
1987 rs |= ((value >> 27) & 0xf) << 9;
1989 ppc_store_slb(env, rb, rs);
1990 } else
1991 #endif
1992 if (env->sr[srnum] != value) {
1993 env->sr[srnum] = value;
1994 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
1995 flusing the whole TLB. */
1996 #if !defined(FLUSH_ALL_TLBS) && 0
1998 target_ulong page, end;
1999 /* Invalidate 256 MB of virtual memory */
2000 page = (16 << 20) * srnum;
2001 end = page + (16 << 20);
2002 for (; page != end; page += TARGET_PAGE_SIZE)
2003 tlb_flush_page(env, page);
2005 #else
2006 tlb_flush(env, 1);
2007 #endif
2010 #endif /* !defined (CONFIG_USER_ONLY) */
2012 /* GDBstub can read and write MSR... */
2013 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2015 hreg_store_msr(env, value, 0);
2018 /*****************************************************************************/
2019 /* Exception processing */
2020 #if defined (CONFIG_USER_ONLY)
2021 void do_interrupt (CPUState *env)
2023 env->exception_index = POWERPC_EXCP_NONE;
2024 env->error_code = 0;
2027 void ppc_hw_interrupt (CPUState *env)
2029 env->exception_index = POWERPC_EXCP_NONE;
2030 env->error_code = 0;
2032 #else /* defined (CONFIG_USER_ONLY) */
2033 static inline void dump_syscall(CPUState *env)
2035 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2036 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2037 " nip=" TARGET_FMT_lx "\n",
2038 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2039 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2040 ppc_dump_gpr(env, 6), env->nip);
2043 /* Note that this function should be greatly optimized
2044 * when called with a constant excp, from ppc_hw_interrupt
2046 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2048 target_ulong msr, new_msr, vector;
2049 int srr0, srr1, asrr0, asrr1;
2050 int lpes0, lpes1, lev;
2052 if (0) {
2053 /* XXX: find a suitable condition to enable the hypervisor mode */
2054 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2055 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2056 } else {
2057 /* Those values ensure we won't enter the hypervisor mode */
2058 lpes0 = 0;
2059 lpes1 = 1;
2062 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2063 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2065 /* new srr1 value excluding must-be-zero bits */
2066 msr = env->msr & ~0x783f0000ULL;
2068 /* new interrupt handler msr */
2069 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2071 /* target registers */
2072 srr0 = SPR_SRR0;
2073 srr1 = SPR_SRR1;
2074 asrr0 = -1;
2075 asrr1 = -1;
2077 switch (excp) {
2078 case POWERPC_EXCP_NONE:
2079 /* Should never happen */
2080 return;
2081 case POWERPC_EXCP_CRITICAL: /* Critical input */
2082 switch (excp_model) {
2083 case POWERPC_EXCP_40x:
2084 srr0 = SPR_40x_SRR2;
2085 srr1 = SPR_40x_SRR3;
2086 break;
2087 case POWERPC_EXCP_BOOKE:
2088 srr0 = SPR_BOOKE_CSRR0;
2089 srr1 = SPR_BOOKE_CSRR1;
2090 break;
2091 case POWERPC_EXCP_G2:
2092 break;
2093 default:
2094 goto excp_invalid;
2096 goto store_next;
2097 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2098 if (msr_me == 0) {
2099 /* Machine check exception is not enabled.
2100 * Enter checkstop state.
2102 if (qemu_log_enabled()) {
2103 qemu_log("Machine check while not allowed. "
2104 "Entering checkstop state\n");
2105 } else {
2106 fprintf(stderr, "Machine check while not allowed. "
2107 "Entering checkstop state\n");
2109 env->halted = 1;
2110 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2112 if (0) {
2113 /* XXX: find a suitable condition to enable the hypervisor mode */
2114 new_msr |= (target_ulong)MSR_HVB;
2117 /* machine check exceptions don't have ME set */
2118 new_msr &= ~((target_ulong)1 << MSR_ME);
2120 /* XXX: should also have something loaded in DAR / DSISR */
2121 switch (excp_model) {
2122 case POWERPC_EXCP_40x:
2123 srr0 = SPR_40x_SRR2;
2124 srr1 = SPR_40x_SRR3;
2125 break;
2126 case POWERPC_EXCP_BOOKE:
2127 srr0 = SPR_BOOKE_MCSRR0;
2128 srr1 = SPR_BOOKE_MCSRR1;
2129 asrr0 = SPR_BOOKE_CSRR0;
2130 asrr1 = SPR_BOOKE_CSRR1;
2131 break;
2132 default:
2133 break;
2135 goto store_next;
2136 case POWERPC_EXCP_DSI: /* Data storage exception */
2137 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2138 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2139 if (lpes1 == 0)
2140 new_msr |= (target_ulong)MSR_HVB;
2141 goto store_next;
2142 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2143 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2144 "\n", msr, env->nip);
2145 if (lpes1 == 0)
2146 new_msr |= (target_ulong)MSR_HVB;
2147 msr |= env->error_code;
2148 goto store_next;
2149 case POWERPC_EXCP_EXTERNAL: /* External input */
2150 if (lpes0 == 1)
2151 new_msr |= (target_ulong)MSR_HVB;
2152 goto store_next;
2153 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2154 if (lpes1 == 0)
2155 new_msr |= (target_ulong)MSR_HVB;
2156 /* XXX: this is false */
2157 /* Get rS/rD and rA from faulting opcode */
2158 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2159 goto store_current;
2160 case POWERPC_EXCP_PROGRAM: /* Program exception */
2161 switch (env->error_code & ~0xF) {
2162 case POWERPC_EXCP_FP:
2163 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2164 LOG_EXCP("Ignore floating point exception\n");
2165 env->exception_index = POWERPC_EXCP_NONE;
2166 env->error_code = 0;
2167 return;
2169 if (lpes1 == 0)
2170 new_msr |= (target_ulong)MSR_HVB;
2171 msr |= 0x00100000;
2172 if (msr_fe0 == msr_fe1)
2173 goto store_next;
2174 msr |= 0x00010000;
2175 break;
2176 case POWERPC_EXCP_INVAL:
2177 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2178 if (lpes1 == 0)
2179 new_msr |= (target_ulong)MSR_HVB;
2180 msr |= 0x00080000;
2181 break;
2182 case POWERPC_EXCP_PRIV:
2183 if (lpes1 == 0)
2184 new_msr |= (target_ulong)MSR_HVB;
2185 msr |= 0x00040000;
2186 break;
2187 case POWERPC_EXCP_TRAP:
2188 if (lpes1 == 0)
2189 new_msr |= (target_ulong)MSR_HVB;
2190 msr |= 0x00020000;
2191 break;
2192 default:
2193 /* Should never occur */
2194 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2195 env->error_code);
2196 break;
2198 goto store_current;
2199 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2200 if (lpes1 == 0)
2201 new_msr |= (target_ulong)MSR_HVB;
2202 goto store_current;
2203 case POWERPC_EXCP_SYSCALL: /* System call exception */
2204 dump_syscall(env);
2205 lev = env->error_code;
2206 if ((lev == 1) && cpu_ppc_hypercall) {
2207 cpu_ppc_hypercall(env);
2208 return;
2210 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2211 new_msr |= (target_ulong)MSR_HVB;
2212 goto store_next;
2213 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2214 goto store_current;
2215 case POWERPC_EXCP_DECR: /* Decrementer exception */
2216 if (lpes1 == 0)
2217 new_msr |= (target_ulong)MSR_HVB;
2218 goto store_next;
2219 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2220 /* FIT on 4xx */
2221 LOG_EXCP("FIT exception\n");
2222 goto store_next;
2223 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2224 LOG_EXCP("WDT exception\n");
2225 switch (excp_model) {
2226 case POWERPC_EXCP_BOOKE:
2227 srr0 = SPR_BOOKE_CSRR0;
2228 srr1 = SPR_BOOKE_CSRR1;
2229 break;
2230 default:
2231 break;
2233 goto store_next;
2234 case POWERPC_EXCP_DTLB: /* Data TLB error */
2235 goto store_next;
2236 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2237 goto store_next;
2238 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2239 switch (excp_model) {
2240 case POWERPC_EXCP_BOOKE:
2241 srr0 = SPR_BOOKE_DSRR0;
2242 srr1 = SPR_BOOKE_DSRR1;
2243 asrr0 = SPR_BOOKE_CSRR0;
2244 asrr1 = SPR_BOOKE_CSRR1;
2245 break;
2246 default:
2247 break;
2249 /* XXX: TODO */
2250 cpu_abort(env, "Debug exception is not implemented yet !\n");
2251 goto store_next;
2252 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2253 goto store_current;
2254 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2255 /* XXX: TODO */
2256 cpu_abort(env, "Embedded floating point data exception "
2257 "is not implemented yet !\n");
2258 goto store_next;
2259 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2260 /* XXX: TODO */
2261 cpu_abort(env, "Embedded floating point round exception "
2262 "is not implemented yet !\n");
2263 goto store_next;
2264 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2265 /* XXX: TODO */
2266 cpu_abort(env,
2267 "Performance counter exception is not implemented yet !\n");
2268 goto store_next;
2269 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2270 /* XXX: TODO */
2271 cpu_abort(env,
2272 "Embedded doorbell interrupt is not implemented yet !\n");
2273 goto store_next;
2274 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2275 switch (excp_model) {
2276 case POWERPC_EXCP_BOOKE:
2277 srr0 = SPR_BOOKE_CSRR0;
2278 srr1 = SPR_BOOKE_CSRR1;
2279 break;
2280 default:
2281 break;
2283 /* XXX: TODO */
2284 cpu_abort(env, "Embedded doorbell critical interrupt "
2285 "is not implemented yet !\n");
2286 goto store_next;
2287 case POWERPC_EXCP_RESET: /* System reset exception */
2288 if (msr_pow) {
2289 /* indicate that we resumed from power save mode */
2290 msr |= 0x10000;
2291 } else {
2292 new_msr &= ~((target_ulong)1 << MSR_ME);
2295 if (0) {
2296 /* XXX: find a suitable condition to enable the hypervisor mode */
2297 new_msr |= (target_ulong)MSR_HVB;
2299 goto store_next;
2300 case POWERPC_EXCP_DSEG: /* Data segment exception */
2301 if (lpes1 == 0)
2302 new_msr |= (target_ulong)MSR_HVB;
2303 goto store_next;
2304 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2305 if (lpes1 == 0)
2306 new_msr |= (target_ulong)MSR_HVB;
2307 goto store_next;
2308 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2309 srr0 = SPR_HSRR0;
2310 srr1 = SPR_HSRR1;
2311 new_msr |= (target_ulong)MSR_HVB;
2312 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2313 goto store_next;
2314 case POWERPC_EXCP_TRACE: /* Trace exception */
2315 if (lpes1 == 0)
2316 new_msr |= (target_ulong)MSR_HVB;
2317 goto store_next;
2318 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2319 srr0 = SPR_HSRR0;
2320 srr1 = SPR_HSRR1;
2321 new_msr |= (target_ulong)MSR_HVB;
2322 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2323 goto store_next;
2324 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2325 srr0 = SPR_HSRR0;
2326 srr1 = SPR_HSRR1;
2327 new_msr |= (target_ulong)MSR_HVB;
2328 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2329 goto store_next;
2330 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2331 srr0 = SPR_HSRR0;
2332 srr1 = SPR_HSRR1;
2333 new_msr |= (target_ulong)MSR_HVB;
2334 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2335 goto store_next;
2336 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2337 srr0 = SPR_HSRR0;
2338 srr1 = SPR_HSRR1;
2339 new_msr |= (target_ulong)MSR_HVB;
2340 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2341 goto store_next;
2342 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2343 if (lpes1 == 0)
2344 new_msr |= (target_ulong)MSR_HVB;
2345 goto store_current;
2346 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2347 LOG_EXCP("PIT exception\n");
2348 goto store_next;
2349 case POWERPC_EXCP_IO: /* IO error exception */
2350 /* XXX: TODO */
2351 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2352 goto store_next;
2353 case POWERPC_EXCP_RUNM: /* Run mode exception */
2354 /* XXX: TODO */
2355 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2356 goto store_next;
2357 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2358 /* XXX: TODO */
2359 cpu_abort(env, "602 emulation trap exception "
2360 "is not implemented yet !\n");
2361 goto store_next;
2362 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2363 if (lpes1 == 0) /* XXX: check this */
2364 new_msr |= (target_ulong)MSR_HVB;
2365 switch (excp_model) {
2366 case POWERPC_EXCP_602:
2367 case POWERPC_EXCP_603:
2368 case POWERPC_EXCP_603E:
2369 case POWERPC_EXCP_G2:
2370 goto tlb_miss_tgpr;
2371 case POWERPC_EXCP_7x5:
2372 goto tlb_miss;
2373 case POWERPC_EXCP_74xx:
2374 goto tlb_miss_74xx;
2375 default:
2376 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2377 break;
2379 break;
2380 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2381 if (lpes1 == 0) /* XXX: check this */
2382 new_msr |= (target_ulong)MSR_HVB;
2383 switch (excp_model) {
2384 case POWERPC_EXCP_602:
2385 case POWERPC_EXCP_603:
2386 case POWERPC_EXCP_603E:
2387 case POWERPC_EXCP_G2:
2388 goto tlb_miss_tgpr;
2389 case POWERPC_EXCP_7x5:
2390 goto tlb_miss;
2391 case POWERPC_EXCP_74xx:
2392 goto tlb_miss_74xx;
2393 default:
2394 cpu_abort(env, "Invalid data load TLB miss exception\n");
2395 break;
2397 break;
2398 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2399 if (lpes1 == 0) /* XXX: check this */
2400 new_msr |= (target_ulong)MSR_HVB;
2401 switch (excp_model) {
2402 case POWERPC_EXCP_602:
2403 case POWERPC_EXCP_603:
2404 case POWERPC_EXCP_603E:
2405 case POWERPC_EXCP_G2:
2406 tlb_miss_tgpr:
2407 /* Swap temporary saved registers with GPRs */
2408 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2409 new_msr |= (target_ulong)1 << MSR_TGPR;
2410 hreg_swap_gpr_tgpr(env);
2412 goto tlb_miss;
2413 case POWERPC_EXCP_7x5:
2414 tlb_miss:
2415 #if defined (DEBUG_SOFTWARE_TLB)
2416 if (qemu_log_enabled()) {
2417 const char *es;
2418 target_ulong *miss, *cmp;
2419 int en;
2420 if (excp == POWERPC_EXCP_IFTLB) {
2421 es = "I";
2422 en = 'I';
2423 miss = &env->spr[SPR_IMISS];
2424 cmp = &env->spr[SPR_ICMP];
2425 } else {
2426 if (excp == POWERPC_EXCP_DLTLB)
2427 es = "DL";
2428 else
2429 es = "DS";
2430 en = 'D';
2431 miss = &env->spr[SPR_DMISS];
2432 cmp = &env->spr[SPR_DCMP];
2434 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2435 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2436 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2437 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2438 env->error_code);
2440 #endif
2441 msr |= env->crf[0] << 28;
2442 msr |= env->error_code; /* key, D/I, S/L bits */
2443 /* Set way using a LRU mechanism */
2444 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2445 break;
2446 case POWERPC_EXCP_74xx:
2447 tlb_miss_74xx:
2448 #if defined (DEBUG_SOFTWARE_TLB)
2449 if (qemu_log_enabled()) {
2450 const char *es;
2451 target_ulong *miss, *cmp;
2452 int en;
2453 if (excp == POWERPC_EXCP_IFTLB) {
2454 es = "I";
2455 en = 'I';
2456 miss = &env->spr[SPR_TLBMISS];
2457 cmp = &env->spr[SPR_PTEHI];
2458 } else {
2459 if (excp == POWERPC_EXCP_DLTLB)
2460 es = "DL";
2461 else
2462 es = "DS";
2463 en = 'D';
2464 miss = &env->spr[SPR_TLBMISS];
2465 cmp = &env->spr[SPR_PTEHI];
2467 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2468 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2469 env->error_code);
2471 #endif
2472 msr |= env->error_code; /* key bit */
2473 break;
2474 default:
2475 cpu_abort(env, "Invalid data store TLB miss exception\n");
2476 break;
2478 goto store_next;
2479 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2480 /* XXX: TODO */
2481 cpu_abort(env, "Floating point assist exception "
2482 "is not implemented yet !\n");
2483 goto store_next;
2484 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2485 /* XXX: TODO */
2486 cpu_abort(env, "DABR exception is not implemented yet !\n");
2487 goto store_next;
2488 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2489 /* XXX: TODO */
2490 cpu_abort(env, "IABR exception is not implemented yet !\n");
2491 goto store_next;
2492 case POWERPC_EXCP_SMI: /* System management interrupt */
2493 /* XXX: TODO */
2494 cpu_abort(env, "SMI exception is not implemented yet !\n");
2495 goto store_next;
2496 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2497 /* XXX: TODO */
2498 cpu_abort(env, "Thermal management exception "
2499 "is not implemented yet !\n");
2500 goto store_next;
2501 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2502 if (lpes1 == 0)
2503 new_msr |= (target_ulong)MSR_HVB;
2504 /* XXX: TODO */
2505 cpu_abort(env,
2506 "Performance counter exception is not implemented yet !\n");
2507 goto store_next;
2508 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2509 /* XXX: TODO */
2510 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2511 goto store_next;
2512 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2513 /* XXX: TODO */
2514 cpu_abort(env,
2515 "970 soft-patch exception is not implemented yet !\n");
2516 goto store_next;
2517 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2518 /* XXX: TODO */
2519 cpu_abort(env,
2520 "970 maintenance exception is not implemented yet !\n");
2521 goto store_next;
2522 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2523 /* XXX: TODO */
2524 cpu_abort(env, "Maskable external exception "
2525 "is not implemented yet !\n");
2526 goto store_next;
2527 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2528 /* XXX: TODO */
2529 cpu_abort(env, "Non maskable external exception "
2530 "is not implemented yet !\n");
2531 goto store_next;
2532 default:
2533 excp_invalid:
2534 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2535 break;
2536 store_current:
2537 /* save current instruction location */
2538 env->spr[srr0] = env->nip - 4;
2539 break;
2540 store_next:
2541 /* save next instruction location */
2542 env->spr[srr0] = env->nip;
2543 break;
2545 /* Save MSR */
2546 env->spr[srr1] = msr;
2547 /* If any alternate SRR register are defined, duplicate saved values */
2548 if (asrr0 != -1)
2549 env->spr[asrr0] = env->spr[srr0];
2550 if (asrr1 != -1)
2551 env->spr[asrr1] = env->spr[srr1];
2552 /* If we disactivated any translation, flush TLBs */
2553 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2554 tlb_flush(env, 1);
2556 if (msr_ile) {
2557 new_msr |= (target_ulong)1 << MSR_LE;
2560 /* Jump to handler */
2561 vector = env->excp_vectors[excp];
2562 if (vector == (target_ulong)-1ULL) {
2563 cpu_abort(env, "Raised an exception without defined vector %d\n",
2564 excp);
2566 vector |= env->excp_prefix;
2567 #if defined(TARGET_PPC64)
2568 if (excp_model == POWERPC_EXCP_BOOKE) {
2569 if (!msr_icm) {
2570 vector = (uint32_t)vector;
2571 } else {
2572 new_msr |= (target_ulong)1 << MSR_CM;
2574 } else {
2575 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2576 vector = (uint32_t)vector;
2577 } else {
2578 new_msr |= (target_ulong)1 << MSR_SF;
2581 #endif
2582 /* XXX: we don't use hreg_store_msr here as already have treated
2583 * any special case that could occur. Just store MSR and update hflags
2585 env->msr = new_msr & env->msr_mask;
2586 hreg_compute_hflags(env);
2587 env->nip = vector;
2588 /* Reset exception state */
2589 env->exception_index = POWERPC_EXCP_NONE;
2590 env->error_code = 0;
2592 if (env->mmu_model == POWERPC_MMU_BOOKE) {
2593 /* XXX: The BookE changes address space when switching modes,
2594 we should probably implement that as different MMU indexes,
2595 but for the moment we do it the slow way and flush all. */
2596 tlb_flush(env, 1);
2600 void do_interrupt (CPUState *env)
2602 powerpc_excp(env, env->excp_model, env->exception_index);
2605 void ppc_hw_interrupt (CPUPPCState *env)
2607 int hdice;
2609 #if 0
2610 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2611 __func__, env, env->pending_interrupts,
2612 env->interrupt_request, (int)msr_me, (int)msr_ee);
2613 #endif
2614 /* External reset */
2615 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2616 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2617 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2618 return;
2620 /* Machine check exception */
2621 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2622 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2623 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2624 return;
2626 #if 0 /* TODO */
2627 /* External debug exception */
2628 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2629 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2630 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2631 return;
2633 #endif
2634 if (0) {
2635 /* XXX: find a suitable condition to enable the hypervisor mode */
2636 hdice = env->spr[SPR_LPCR] & 1;
2637 } else {
2638 hdice = 0;
2640 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2641 /* Hypervisor decrementer exception */
2642 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2643 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2644 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2645 return;
2648 if (msr_ce != 0) {
2649 /* External critical interrupt */
2650 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2651 /* Taking a critical external interrupt does not clear the external
2652 * critical interrupt status
2654 #if 0
2655 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2656 #endif
2657 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2658 return;
2661 if (msr_ee != 0) {
2662 /* Watchdog timer on embedded PowerPC */
2663 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2664 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2665 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2666 return;
2668 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2669 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2670 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2671 return;
2673 /* Fixed interval timer on embedded PowerPC */
2674 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2675 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2676 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2677 return;
2679 /* Programmable interval timer on embedded PowerPC */
2680 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2681 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2682 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2683 return;
2685 /* Decrementer exception */
2686 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2687 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2688 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2689 return;
2691 /* External interrupt */
2692 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2693 /* Taking an external interrupt does not clear the external
2694 * interrupt status
2696 #if 0
2697 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2698 #endif
2699 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2700 return;
2702 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2703 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2704 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2705 return;
2707 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2708 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2709 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2710 return;
2712 /* Thermal interrupt */
2713 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2714 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2715 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2716 return;
2720 #endif /* !CONFIG_USER_ONLY */
2722 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2724 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2725 TARGET_FMT_lx "\n", RA, msr);
2728 void cpu_reset(CPUPPCState *env)
2730 target_ulong msr;
2732 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2733 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2734 log_cpu_state(env, 0);
2737 msr = (target_ulong)0;
2738 if (0) {
2739 /* XXX: find a suitable condition to enable the hypervisor mode */
2740 msr |= (target_ulong)MSR_HVB;
2742 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2743 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2744 msr |= (target_ulong)1 << MSR_EP;
2745 #if defined (DO_SINGLE_STEP) && 0
2746 /* Single step trace mode */
2747 msr |= (target_ulong)1 << MSR_SE;
2748 msr |= (target_ulong)1 << MSR_BE;
2749 #endif
2750 #if defined(CONFIG_USER_ONLY)
2751 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2752 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2753 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2754 msr |= (target_ulong)1 << MSR_PR;
2755 #else
2756 env->excp_prefix = env->hreset_excp_prefix;
2757 env->nip = env->hreset_vector | env->excp_prefix;
2758 if (env->mmu_model != POWERPC_MMU_REAL)
2759 ppc_tlb_invalidate_all(env);
2760 #endif
2761 env->msr = msr & env->msr_mask;
2762 #if defined(TARGET_PPC64)
2763 if (env->mmu_model & POWERPC_MMU_64)
2764 env->msr |= (1ULL << MSR_SF);
2765 #endif
2766 hreg_compute_hflags(env);
2767 env->reserve_addr = (target_ulong)-1ULL;
2768 /* Be sure no exception or interrupt is pending */
2769 env->pending_interrupts = 0;
2770 env->exception_index = POWERPC_EXCP_NONE;
2771 env->error_code = 0;
2772 /* Flush all TLBs */
2773 tlb_flush(env, 1);
2776 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2778 CPUPPCState *env;
2779 const ppc_def_t *def;
2781 def = cpu_ppc_find_by_name(cpu_model);
2782 if (!def)
2783 return NULL;
2785 env = qemu_mallocz(sizeof(CPUPPCState));
2786 cpu_exec_init(env);
2787 ppc_translate_init();
2788 env->cpu_model_str = cpu_model;
2789 cpu_ppc_register_internal(env, def);
2791 qemu_init_vcpu(env);
2793 return env;
2796 void cpu_ppc_close (CPUPPCState *env)
2798 /* Should also remove all opcode tables... */
2799 qemu_free(env);