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