qemu-kvm: Remove kvm subdirectory (Jan Kiszka)
[qemu-kvm.git] / target-ppc / helper.c
blob58474536c0fefb73808c04f06a16214b4b05d36b
1 /*
2 * PowerPC emulation helpers for qemu.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
25 #include "cpu.h"
26 #include "helper_regs.h"
27 #include "qemu-common.h"
28 #include "kvm.h"
29 #include "kvm_ppc.h"
30 #include "cpus.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)
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.tlb6[nr];
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.tlb6[nr];
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.tlb6[nr];
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.tlb6[nr];
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.tlb6[best].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_off + (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_off + (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 "\n", env->htab_base,
922 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
923 ret2 = find_pte(env, ctx, 1, rw, type,
924 target_page_bits);
925 if (ret2 != -1)
926 ret = ret2;
929 #if defined (DUMP_PAGE_TABLES)
930 if (qemu_log_enabled()) {
931 target_phys_addr_t curaddr;
932 uint32_t a0, a1, a2, a3;
933 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
934 "\n", sdr, mask + 0x80);
935 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
936 curaddr += 16) {
937 a0 = ldl_phys(curaddr);
938 a1 = ldl_phys(curaddr + 4);
939 a2 = ldl_phys(curaddr + 8);
940 a3 = ldl_phys(curaddr + 12);
941 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
942 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
943 curaddr, a0, a1, a2, a3);
947 #endif
948 } else {
949 LOG_MMU("No access allowed\n");
950 ret = -3;
952 } else {
953 target_ulong sr;
954 LOG_MMU("direct store...\n");
955 /* Direct-store segment : absolutely *BUGGY* for now */
957 /* Direct-store implies a 32-bit MMU.
958 * Check the Segment Register's bus unit ID (BUID).
960 sr = env->sr[eaddr >> 28];
961 if ((sr & 0x1FF00000) >> 20 == 0x07f) {
962 /* Memory-forced I/O controller interface access */
963 /* If T=1 and BUID=x'07F', the 601 performs a memory access
964 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
966 ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
967 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
968 return 0;
971 switch (type) {
972 case ACCESS_INT:
973 /* Integer load/store : only access allowed */
974 break;
975 case ACCESS_CODE:
976 /* No code fetch is allowed in direct-store areas */
977 return -4;
978 case ACCESS_FLOAT:
979 /* Floating point load/store */
980 return -4;
981 case ACCESS_RES:
982 /* lwarx, ldarx or srwcx. */
983 return -4;
984 case ACCESS_CACHE:
985 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
986 /* Should make the instruction do no-op.
987 * As it already do no-op, it's quite easy :-)
989 ctx->raddr = eaddr;
990 return 0;
991 case ACCESS_EXT:
992 /* eciwx or ecowx */
993 return -4;
994 default:
995 qemu_log("ERROR: instruction should not need "
996 "address translation\n");
997 return -4;
999 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1000 ctx->raddr = eaddr;
1001 ret = 2;
1002 } else {
1003 ret = -2;
1007 return ret;
1010 /* Generic TLB check function for embedded PowerPC implementations */
1011 int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1012 target_phys_addr_t *raddrp,
1013 target_ulong address, uint32_t pid, int ext,
1014 int i)
1016 target_ulong mask;
1018 /* Check valid flag */
1019 if (!(tlb->prot & PAGE_VALID)) {
1020 return -1;
1022 mask = ~(tlb->size - 1);
1023 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1024 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1025 mask, (uint32_t)tlb->PID, tlb->prot);
1026 /* Check PID */
1027 if (tlb->PID != 0 && tlb->PID != pid)
1028 return -1;
1029 /* Check effective address */
1030 if ((address & mask) != tlb->EPN)
1031 return -1;
1032 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1033 #if (TARGET_PHYS_ADDR_BITS >= 36)
1034 if (ext) {
1035 /* Extend the physical address to 36 bits */
1036 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1038 #endif
1040 return 0;
1043 /* Generic TLB search function for PowerPC embedded implementations */
1044 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1046 ppcemb_tlb_t *tlb;
1047 target_phys_addr_t raddr;
1048 int i, ret;
1050 /* Default return value is no match */
1051 ret = -1;
1052 for (i = 0; i < env->nb_tlb; i++) {
1053 tlb = &env->tlb.tlbe[i];
1054 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1055 ret = i;
1056 break;
1060 return ret;
1063 /* Helpers specific to PowerPC 40x implementations */
1064 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1066 ppcemb_tlb_t *tlb;
1067 int i;
1069 for (i = 0; i < env->nb_tlb; i++) {
1070 tlb = &env->tlb.tlbe[i];
1071 tlb->prot &= ~PAGE_VALID;
1073 tlb_flush(env, 1);
1076 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1077 target_ulong eaddr, uint32_t pid)
1079 #if !defined(FLUSH_ALL_TLBS)
1080 ppcemb_tlb_t *tlb;
1081 target_phys_addr_t raddr;
1082 target_ulong page, end;
1083 int i;
1085 for (i = 0; i < env->nb_tlb; i++) {
1086 tlb = &env->tlb.tlbe[i];
1087 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1088 end = tlb->EPN + tlb->size;
1089 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1090 tlb_flush_page(env, page);
1091 tlb->prot &= ~PAGE_VALID;
1092 break;
1095 #else
1096 ppc4xx_tlb_invalidate_all(env);
1097 #endif
1100 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1101 target_ulong address, int rw, int access_type)
1103 ppcemb_tlb_t *tlb;
1104 target_phys_addr_t raddr;
1105 int i, ret, zsel, zpr, pr;
1107 ret = -1;
1108 raddr = (target_phys_addr_t)-1ULL;
1109 pr = msr_pr;
1110 for (i = 0; i < env->nb_tlb; i++) {
1111 tlb = &env->tlb.tlbe[i];
1112 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1113 env->spr[SPR_40x_PID], 0, i) < 0)
1114 continue;
1115 zsel = (tlb->attr >> 4) & 0xF;
1116 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1117 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1118 __func__, i, zsel, zpr, rw, tlb->attr);
1119 /* Check execute enable bit */
1120 switch (zpr) {
1121 case 0x2:
1122 if (pr != 0)
1123 goto check_perms;
1124 /* No break here */
1125 case 0x3:
1126 /* All accesses granted */
1127 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1128 ret = 0;
1129 break;
1130 case 0x0:
1131 if (pr != 0) {
1132 /* Raise Zone protection fault. */
1133 env->spr[SPR_40x_ESR] = 1 << 22;
1134 ctx->prot = 0;
1135 ret = -2;
1136 break;
1138 /* No break here */
1139 case 0x1:
1140 check_perms:
1141 /* Check from TLB entry */
1142 ctx->prot = tlb->prot;
1143 ret = check_prot(ctx->prot, rw, access_type);
1144 if (ret == -2)
1145 env->spr[SPR_40x_ESR] = 0;
1146 break;
1148 if (ret >= 0) {
1149 ctx->raddr = raddr;
1150 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1151 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1152 ret);
1153 return 0;
1156 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1157 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1159 return ret;
1162 void store_40x_sler (CPUPPCState *env, uint32_t val)
1164 /* XXX: TO BE FIXED */
1165 if (val != 0x00000000) {
1166 cpu_abort(env, "Little-endian regions are not supported by now\n");
1168 env->spr[SPR_405_SLER] = val;
1171 static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1172 target_phys_addr_t *raddr, int *prot,
1173 target_ulong address, int rw,
1174 int access_type, int i)
1176 int ret, _prot;
1178 if (ppcemb_tlb_check(env, tlb, raddr, address,
1179 env->spr[SPR_BOOKE_PID],
1180 !env->nb_pids, i) >= 0) {
1181 goto found_tlb;
1184 if (env->spr[SPR_BOOKE_PID1] &&
1185 ppcemb_tlb_check(env, tlb, raddr, address,
1186 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1187 goto found_tlb;
1190 if (env->spr[SPR_BOOKE_PID2] &&
1191 ppcemb_tlb_check(env, tlb, raddr, address,
1192 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1193 goto found_tlb;
1196 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1197 return -1;
1199 found_tlb:
1201 if (msr_pr != 0) {
1202 _prot = tlb->prot & 0xF;
1203 } else {
1204 _prot = (tlb->prot >> 4) & 0xF;
1207 /* Check the address space */
1208 if (access_type == ACCESS_CODE) {
1209 if (msr_ir != (tlb->attr & 1)) {
1210 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1211 return -1;
1214 *prot = _prot;
1215 if (_prot & PAGE_EXEC) {
1216 LOG_SWTLB("%s: good TLB!\n", __func__);
1217 return 0;
1220 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1221 ret = -3;
1222 } else {
1223 if (msr_dr != (tlb->attr & 1)) {
1224 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1225 return -1;
1228 *prot = _prot;
1229 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1230 LOG_SWTLB("%s: found TLB!\n", __func__);
1231 return 0;
1234 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1235 ret = -2;
1238 return ret;
1241 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1242 target_ulong address, int rw,
1243 int access_type)
1245 ppcemb_tlb_t *tlb;
1246 target_phys_addr_t raddr;
1247 int i, ret;
1249 ret = -1;
1250 raddr = (target_phys_addr_t)-1ULL;
1251 for (i = 0; i < env->nb_tlb; i++) {
1252 tlb = &env->tlb.tlbe[i];
1253 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1254 access_type, i);
1255 if (!ret) {
1256 break;
1260 if (ret >= 0) {
1261 ctx->raddr = raddr;
1262 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1263 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1264 ret);
1265 } else {
1266 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1267 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1270 return ret;
1273 void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1275 int tlb_size;
1276 int i, j;
1277 ppcmas_tlb_t *tlb = env->tlb.tlbm;
1279 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1280 if (flags & (1 << i)) {
1281 tlb_size = booke206_tlb_size(env, i);
1282 for (j = 0; j < tlb_size; j++) {
1283 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
1284 tlb[j].mas1 &= ~MAS1_VALID;
1288 tlb += booke206_tlb_size(env, i);
1291 tlb_flush(env, 1);
1294 target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
1296 uint32_t tlbncfg;
1297 int tlbn = booke206_tlbm_to_tlbn(env, tlb);
1298 int tlbm_size;
1300 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
1302 if (tlbncfg & TLBnCFG_AVAIL) {
1303 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1304 } else {
1305 tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
1306 tlbm_size <<= 1;
1309 return 1024ULL << tlbm_size;
1312 /* TLB check function for MAS based SoftTLBs */
1313 int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
1314 target_phys_addr_t *raddrp,
1315 target_ulong address, uint32_t pid)
1317 target_ulong mask;
1318 uint32_t tlb_pid;
1320 /* Check valid flag */
1321 if (!(tlb->mas1 & MAS1_VALID)) {
1322 return -1;
1325 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1326 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
1327 PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
1328 __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
1329 tlb->mas8);
1331 /* Check PID */
1332 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
1333 if (tlb_pid != 0 && tlb_pid != pid) {
1334 return -1;
1337 /* Check effective address */
1338 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
1339 return -1;
1341 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
1343 return 0;
1346 static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
1347 target_phys_addr_t *raddr, int *prot,
1348 target_ulong address, int rw,
1349 int access_type)
1351 int ret;
1352 int _prot = 0;
1354 if (ppcmas_tlb_check(env, tlb, raddr, address,
1355 env->spr[SPR_BOOKE_PID]) >= 0) {
1356 goto found_tlb;
1359 if (env->spr[SPR_BOOKE_PID1] &&
1360 ppcmas_tlb_check(env, tlb, raddr, address,
1361 env->spr[SPR_BOOKE_PID1]) >= 0) {
1362 goto found_tlb;
1365 if (env->spr[SPR_BOOKE_PID2] &&
1366 ppcmas_tlb_check(env, tlb, raddr, address,
1367 env->spr[SPR_BOOKE_PID2]) >= 0) {
1368 goto found_tlb;
1371 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1372 return -1;
1374 found_tlb:
1376 if (msr_pr != 0) {
1377 if (tlb->mas7_3 & MAS3_UR) {
1378 _prot |= PAGE_READ;
1380 if (tlb->mas7_3 & MAS3_UW) {
1381 _prot |= PAGE_WRITE;
1383 if (tlb->mas7_3 & MAS3_UX) {
1384 _prot |= PAGE_EXEC;
1386 } else {
1387 if (tlb->mas7_3 & MAS3_SR) {
1388 _prot |= PAGE_READ;
1390 if (tlb->mas7_3 & MAS3_SW) {
1391 _prot |= PAGE_WRITE;
1393 if (tlb->mas7_3 & MAS3_SX) {
1394 _prot |= PAGE_EXEC;
1398 /* Check the address space and permissions */
1399 if (access_type == ACCESS_CODE) {
1400 if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1401 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1402 return -1;
1405 *prot = _prot;
1406 if (_prot & PAGE_EXEC) {
1407 LOG_SWTLB("%s: good TLB!\n", __func__);
1408 return 0;
1411 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1412 ret = -3;
1413 } else {
1414 if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1415 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1416 return -1;
1419 *prot = _prot;
1420 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1421 LOG_SWTLB("%s: found TLB!\n", __func__);
1422 return 0;
1425 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1426 ret = -2;
1429 return ret;
1432 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1433 target_ulong address, int rw,
1434 int access_type)
1436 ppcmas_tlb_t *tlb;
1437 target_phys_addr_t raddr;
1438 int i, j, ret;
1440 ret = -1;
1441 raddr = (target_phys_addr_t)-1ULL;
1443 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1444 int ways = booke206_tlb_ways(env, i);
1446 for (j = 0; j < ways; j++) {
1447 tlb = booke206_get_tlbm(env, i, address, j);
1448 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1449 rw, access_type);
1450 if (ret != -1) {
1451 goto found_tlb;
1456 found_tlb:
1458 if (ret >= 0) {
1459 ctx->raddr = raddr;
1460 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1461 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1462 ret);
1463 } else {
1464 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1465 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1468 return ret;
1471 static const char *book3e_tsize_to_str[32] = {
1472 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1473 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1474 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1475 "1T", "2T"
1478 static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1479 CPUState *env, int tlbn, int offset,
1480 int tlbsize)
1482 ppcmas_tlb_t *entry;
1483 int i;
1485 cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1486 cpu_fprintf(f, "Effective Physical Size TID TS SRWX URWX WIMGE U0123\n");
1488 entry = &env->tlb.tlbm[offset];
1489 for (i = 0; i < tlbsize; i++, entry++) {
1490 target_phys_addr_t ea, pa, size;
1491 int tsize;
1493 if (!(entry->mas1 & MAS1_VALID)) {
1494 continue;
1497 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1498 size = 1024ULL << tsize;
1499 ea = entry->mas2 & ~(size - 1);
1500 pa = entry->mas7_3 & ~(size - 1);
1502 cpu_fprintf(f, "0x%016" PRIx64 " 0x%016" PRIx64 " %4s %-5u %1u S%c%c%c U%c%c%c %c%c%c%c%c U%c%c%c%c\n",
1503 (uint64_t)ea, (uint64_t)pa,
1504 book3e_tsize_to_str[tsize],
1505 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1506 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1507 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1508 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1509 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1510 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1511 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1512 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1513 entry->mas2 & MAS2_W ? 'W' : '-',
1514 entry->mas2 & MAS2_I ? 'I' : '-',
1515 entry->mas2 & MAS2_M ? 'M' : '-',
1516 entry->mas2 & MAS2_G ? 'G' : '-',
1517 entry->mas2 & MAS2_E ? 'E' : '-',
1518 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1519 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1520 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1521 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1525 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1526 CPUState *env)
1528 int offset = 0;
1529 int i;
1531 if (kvm_enabled() && !env->kvm_sw_tlb) {
1532 cpu_fprintf(f, "Cannot access KVM TLB\n");
1533 return;
1536 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1537 int size = booke206_tlb_size(env, i);
1539 if (size == 0) {
1540 continue;
1543 mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1544 offset += size;
1548 #if defined(TARGET_PPC64)
1549 static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1550 CPUState *env)
1552 int i;
1553 uint64_t slbe, slbv;
1555 cpu_synchronize_state(env);
1557 cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
1558 for (i = 0; i < env->slb_nr; i++) {
1559 slbe = env->slb[i].esid;
1560 slbv = env->slb[i].vsid;
1561 if (slbe == 0 && slbv == 0) {
1562 continue;
1564 cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
1565 i, slbe, slbv);
1568 #endif
1570 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
1572 switch (env->mmu_model) {
1573 case POWERPC_MMU_BOOKE206:
1574 mmubooke206_dump_mmu(f, cpu_fprintf, env);
1575 break;
1576 #if defined(TARGET_PPC64)
1577 case POWERPC_MMU_64B:
1578 case POWERPC_MMU_2_06:
1579 mmubooks_dump_mmu(f, cpu_fprintf, env);
1580 break;
1581 #endif
1582 default:
1583 cpu_fprintf(f, "%s: unimplemented\n", __func__);
1587 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1588 target_ulong eaddr, int rw)
1590 int in_plb, ret;
1592 ctx->raddr = eaddr;
1593 ctx->prot = PAGE_READ | PAGE_EXEC;
1594 ret = 0;
1595 switch (env->mmu_model) {
1596 case POWERPC_MMU_32B:
1597 case POWERPC_MMU_601:
1598 case POWERPC_MMU_SOFT_6xx:
1599 case POWERPC_MMU_SOFT_74xx:
1600 case POWERPC_MMU_SOFT_4xx:
1601 case POWERPC_MMU_REAL:
1602 case POWERPC_MMU_BOOKE:
1603 ctx->prot |= PAGE_WRITE;
1604 break;
1605 #if defined(TARGET_PPC64)
1606 case POWERPC_MMU_620:
1607 case POWERPC_MMU_64B:
1608 case POWERPC_MMU_2_06:
1609 /* Real address are 60 bits long */
1610 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1611 ctx->prot |= PAGE_WRITE;
1612 break;
1613 #endif
1614 case POWERPC_MMU_SOFT_4xx_Z:
1615 if (unlikely(msr_pe != 0)) {
1616 /* 403 family add some particular protections,
1617 * using PBL/PBU registers for accesses with no translation.
1619 in_plb =
1620 /* Check PLB validity */
1621 (env->pb[0] < env->pb[1] &&
1622 /* and address in plb area */
1623 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1624 (env->pb[2] < env->pb[3] &&
1625 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1626 if (in_plb ^ msr_px) {
1627 /* Access in protected area */
1628 if (rw == 1) {
1629 /* Access is not allowed */
1630 ret = -2;
1632 } else {
1633 /* Read-write access is allowed */
1634 ctx->prot |= PAGE_WRITE;
1637 break;
1638 case POWERPC_MMU_MPC8xx:
1639 /* XXX: TODO */
1640 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1641 break;
1642 case POWERPC_MMU_BOOKE206:
1643 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1644 break;
1645 default:
1646 cpu_abort(env, "Unknown or invalid MMU model\n");
1647 return -1;
1650 return ret;
1653 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1654 int rw, int access_type)
1656 int ret;
1658 #if 0
1659 qemu_log("%s\n", __func__);
1660 #endif
1661 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1662 (access_type != ACCESS_CODE && msr_dr == 0)) {
1663 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1664 /* The BookE MMU always performs address translation. The
1665 IS and DS bits only affect the address space. */
1666 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1667 rw, access_type);
1668 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1669 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1670 access_type);
1671 } else {
1672 /* No address translation. */
1673 ret = check_physical(env, ctx, eaddr, rw);
1675 } else {
1676 ret = -1;
1677 switch (env->mmu_model) {
1678 case POWERPC_MMU_32B:
1679 case POWERPC_MMU_601:
1680 case POWERPC_MMU_SOFT_6xx:
1681 case POWERPC_MMU_SOFT_74xx:
1682 /* Try to find a BAT */
1683 if (env->nb_BATs != 0)
1684 ret = get_bat(env, ctx, eaddr, rw, access_type);
1685 #if defined(TARGET_PPC64)
1686 case POWERPC_MMU_620:
1687 case POWERPC_MMU_64B:
1688 case POWERPC_MMU_2_06:
1689 #endif
1690 if (ret < 0) {
1691 /* We didn't match any BAT entry or don't have BATs */
1692 ret = get_segment(env, ctx, eaddr, rw, access_type);
1694 break;
1695 case POWERPC_MMU_SOFT_4xx:
1696 case POWERPC_MMU_SOFT_4xx_Z:
1697 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1698 rw, access_type);
1699 break;
1700 case POWERPC_MMU_BOOKE:
1701 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1702 rw, access_type);
1703 break;
1704 case POWERPC_MMU_BOOKE206:
1705 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1706 access_type);
1707 break;
1708 case POWERPC_MMU_MPC8xx:
1709 /* XXX: TODO */
1710 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1711 break;
1712 case POWERPC_MMU_REAL:
1713 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1714 return -1;
1715 default:
1716 cpu_abort(env, "Unknown or invalid MMU model\n");
1717 return -1;
1720 #if 0
1721 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1722 __func__, eaddr, ret, ctx->raddr);
1723 #endif
1725 return ret;
1728 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1730 mmu_ctx_t ctx;
1732 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1733 return -1;
1735 return ctx.raddr & TARGET_PAGE_MASK;
1738 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1739 int rw)
1741 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1742 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1743 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1744 env->spr[SPR_BOOKE_MAS3] = 0;
1745 env->spr[SPR_BOOKE_MAS6] = 0;
1746 env->spr[SPR_BOOKE_MAS7] = 0;
1748 /* AS */
1749 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1750 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1751 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1754 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1755 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1757 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1758 case MAS4_TIDSELD_PID0:
1759 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1760 break;
1761 case MAS4_TIDSELD_PID1:
1762 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1763 break;
1764 case MAS4_TIDSELD_PID2:
1765 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1766 break;
1769 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1771 /* next victim logic */
1772 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1773 env->last_way++;
1774 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1775 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1778 /* Perform address translation */
1779 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1780 int mmu_idx)
1782 mmu_ctx_t ctx;
1783 int access_type;
1784 int ret = 0;
1786 if (rw == 2) {
1787 /* code access */
1788 rw = 0;
1789 access_type = ACCESS_CODE;
1790 } else {
1791 /* data access */
1792 access_type = env->access_type;
1794 ret = get_physical_address(env, &ctx, address, rw, access_type);
1795 if (ret == 0) {
1796 tlb_set_page(env, address & TARGET_PAGE_MASK,
1797 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1798 mmu_idx, TARGET_PAGE_SIZE);
1799 ret = 0;
1800 } else if (ret < 0) {
1801 LOG_MMU_STATE(env);
1802 if (access_type == ACCESS_CODE) {
1803 switch (ret) {
1804 case -1:
1805 /* No matches in page tables or TLB */
1806 switch (env->mmu_model) {
1807 case POWERPC_MMU_SOFT_6xx:
1808 env->exception_index = POWERPC_EXCP_IFTLB;
1809 env->error_code = 1 << 18;
1810 env->spr[SPR_IMISS] = address;
1811 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1812 goto tlb_miss;
1813 case POWERPC_MMU_SOFT_74xx:
1814 env->exception_index = POWERPC_EXCP_IFTLB;
1815 goto tlb_miss_74xx;
1816 case POWERPC_MMU_SOFT_4xx:
1817 case POWERPC_MMU_SOFT_4xx_Z:
1818 env->exception_index = POWERPC_EXCP_ITLB;
1819 env->error_code = 0;
1820 env->spr[SPR_40x_DEAR] = address;
1821 env->spr[SPR_40x_ESR] = 0x00000000;
1822 break;
1823 case POWERPC_MMU_32B:
1824 case POWERPC_MMU_601:
1825 #if defined(TARGET_PPC64)
1826 case POWERPC_MMU_620:
1827 case POWERPC_MMU_64B:
1828 case POWERPC_MMU_2_06:
1829 #endif
1830 env->exception_index = POWERPC_EXCP_ISI;
1831 env->error_code = 0x40000000;
1832 break;
1833 case POWERPC_MMU_BOOKE206:
1834 booke206_update_mas_tlb_miss(env, address, rw);
1835 /* fall through */
1836 case POWERPC_MMU_BOOKE:
1837 env->exception_index = POWERPC_EXCP_ITLB;
1838 env->error_code = 0;
1839 env->spr[SPR_BOOKE_DEAR] = address;
1840 return -1;
1841 case POWERPC_MMU_MPC8xx:
1842 /* XXX: TODO */
1843 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1844 break;
1845 case POWERPC_MMU_REAL:
1846 cpu_abort(env, "PowerPC in real mode should never raise "
1847 "any MMU exceptions\n");
1848 return -1;
1849 default:
1850 cpu_abort(env, "Unknown or invalid MMU model\n");
1851 return -1;
1853 break;
1854 case -2:
1855 /* Access rights violation */
1856 env->exception_index = POWERPC_EXCP_ISI;
1857 env->error_code = 0x08000000;
1858 break;
1859 case -3:
1860 /* No execute protection violation */
1861 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1862 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1863 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1865 env->exception_index = POWERPC_EXCP_ISI;
1866 env->error_code = 0x10000000;
1867 break;
1868 case -4:
1869 /* Direct store exception */
1870 /* No code fetch is allowed in direct-store areas */
1871 env->exception_index = POWERPC_EXCP_ISI;
1872 env->error_code = 0x10000000;
1873 break;
1874 #if defined(TARGET_PPC64)
1875 case -5:
1876 /* No match in segment table */
1877 if (env->mmu_model == POWERPC_MMU_620) {
1878 env->exception_index = POWERPC_EXCP_ISI;
1879 /* XXX: this might be incorrect */
1880 env->error_code = 0x40000000;
1881 } else {
1882 env->exception_index = POWERPC_EXCP_ISEG;
1883 env->error_code = 0;
1885 break;
1886 #endif
1888 } else {
1889 switch (ret) {
1890 case -1:
1891 /* No matches in page tables or TLB */
1892 switch (env->mmu_model) {
1893 case POWERPC_MMU_SOFT_6xx:
1894 if (rw == 1) {
1895 env->exception_index = POWERPC_EXCP_DSTLB;
1896 env->error_code = 1 << 16;
1897 } else {
1898 env->exception_index = POWERPC_EXCP_DLTLB;
1899 env->error_code = 0;
1901 env->spr[SPR_DMISS] = address;
1902 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1903 tlb_miss:
1904 env->error_code |= ctx.key << 19;
1905 env->spr[SPR_HASH1] = env->htab_base +
1906 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1907 env->spr[SPR_HASH2] = env->htab_base +
1908 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1909 break;
1910 case POWERPC_MMU_SOFT_74xx:
1911 if (rw == 1) {
1912 env->exception_index = POWERPC_EXCP_DSTLB;
1913 } else {
1914 env->exception_index = POWERPC_EXCP_DLTLB;
1916 tlb_miss_74xx:
1917 /* Implement LRU algorithm */
1918 env->error_code = ctx.key << 19;
1919 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1920 ((env->last_way + 1) & (env->nb_ways - 1));
1921 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1922 break;
1923 case POWERPC_MMU_SOFT_4xx:
1924 case POWERPC_MMU_SOFT_4xx_Z:
1925 env->exception_index = POWERPC_EXCP_DTLB;
1926 env->error_code = 0;
1927 env->spr[SPR_40x_DEAR] = address;
1928 if (rw)
1929 env->spr[SPR_40x_ESR] = 0x00800000;
1930 else
1931 env->spr[SPR_40x_ESR] = 0x00000000;
1932 break;
1933 case POWERPC_MMU_32B:
1934 case POWERPC_MMU_601:
1935 #if defined(TARGET_PPC64)
1936 case POWERPC_MMU_620:
1937 case POWERPC_MMU_64B:
1938 case POWERPC_MMU_2_06:
1939 #endif
1940 env->exception_index = POWERPC_EXCP_DSI;
1941 env->error_code = 0;
1942 env->spr[SPR_DAR] = address;
1943 if (rw == 1)
1944 env->spr[SPR_DSISR] = 0x42000000;
1945 else
1946 env->spr[SPR_DSISR] = 0x40000000;
1947 break;
1948 case POWERPC_MMU_MPC8xx:
1949 /* XXX: TODO */
1950 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1951 break;
1952 case POWERPC_MMU_BOOKE206:
1953 booke206_update_mas_tlb_miss(env, address, rw);
1954 /* fall through */
1955 case POWERPC_MMU_BOOKE:
1956 env->exception_index = POWERPC_EXCP_DTLB;
1957 env->error_code = 0;
1958 env->spr[SPR_BOOKE_DEAR] = address;
1959 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1960 return -1;
1961 case POWERPC_MMU_REAL:
1962 cpu_abort(env, "PowerPC in real mode should never raise "
1963 "any MMU exceptions\n");
1964 return -1;
1965 default:
1966 cpu_abort(env, "Unknown or invalid MMU model\n");
1967 return -1;
1969 break;
1970 case -2:
1971 /* Access rights violation */
1972 env->exception_index = POWERPC_EXCP_DSI;
1973 env->error_code = 0;
1974 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1975 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1976 env->spr[SPR_40x_DEAR] = address;
1977 if (rw) {
1978 env->spr[SPR_40x_ESR] |= 0x00800000;
1980 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1981 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1982 env->spr[SPR_BOOKE_DEAR] = address;
1983 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1984 } else {
1985 env->spr[SPR_DAR] = address;
1986 if (rw == 1) {
1987 env->spr[SPR_DSISR] = 0x0A000000;
1988 } else {
1989 env->spr[SPR_DSISR] = 0x08000000;
1992 break;
1993 case -4:
1994 /* Direct store exception */
1995 switch (access_type) {
1996 case ACCESS_FLOAT:
1997 /* Floating point load/store */
1998 env->exception_index = POWERPC_EXCP_ALIGN;
1999 env->error_code = POWERPC_EXCP_ALIGN_FP;
2000 env->spr[SPR_DAR] = address;
2001 break;
2002 case ACCESS_RES:
2003 /* lwarx, ldarx or stwcx. */
2004 env->exception_index = POWERPC_EXCP_DSI;
2005 env->error_code = 0;
2006 env->spr[SPR_DAR] = address;
2007 if (rw == 1)
2008 env->spr[SPR_DSISR] = 0x06000000;
2009 else
2010 env->spr[SPR_DSISR] = 0x04000000;
2011 break;
2012 case ACCESS_EXT:
2013 /* eciwx or ecowx */
2014 env->exception_index = POWERPC_EXCP_DSI;
2015 env->error_code = 0;
2016 env->spr[SPR_DAR] = address;
2017 if (rw == 1)
2018 env->spr[SPR_DSISR] = 0x06100000;
2019 else
2020 env->spr[SPR_DSISR] = 0x04100000;
2021 break;
2022 default:
2023 printf("DSI: invalid exception (%d)\n", ret);
2024 env->exception_index = POWERPC_EXCP_PROGRAM;
2025 env->error_code =
2026 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
2027 env->spr[SPR_DAR] = address;
2028 break;
2030 break;
2031 #if defined(TARGET_PPC64)
2032 case -5:
2033 /* No match in segment table */
2034 if (env->mmu_model == POWERPC_MMU_620) {
2035 env->exception_index = POWERPC_EXCP_DSI;
2036 env->error_code = 0;
2037 env->spr[SPR_DAR] = address;
2038 /* XXX: this might be incorrect */
2039 if (rw == 1)
2040 env->spr[SPR_DSISR] = 0x42000000;
2041 else
2042 env->spr[SPR_DSISR] = 0x40000000;
2043 } else {
2044 env->exception_index = POWERPC_EXCP_DSEG;
2045 env->error_code = 0;
2046 env->spr[SPR_DAR] = address;
2048 break;
2049 #endif
2052 #if 0
2053 printf("%s: set exception to %d %02x\n", __func__,
2054 env->exception, env->error_code);
2055 #endif
2056 ret = 1;
2059 return ret;
2062 /*****************************************************************************/
2063 /* BATs management */
2064 #if !defined(FLUSH_ALL_TLBS)
2065 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2066 target_ulong mask)
2068 target_ulong base, end, page;
2070 base = BATu & ~0x0001FFFF;
2071 end = base + mask + 0x00020000;
2072 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2073 TARGET_FMT_lx ")\n", base, end, mask);
2074 for (page = base; page != end; page += TARGET_PAGE_SIZE)
2075 tlb_flush_page(env, page);
2076 LOG_BATS("Flush done\n");
2078 #endif
2080 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2081 target_ulong value)
2083 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2084 nr, ul == 0 ? 'u' : 'l', value, env->nip);
2087 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2089 target_ulong mask;
2091 dump_store_bat(env, 'I', 0, nr, value);
2092 if (env->IBAT[0][nr] != value) {
2093 mask = (value << 15) & 0x0FFE0000UL;
2094 #if !defined(FLUSH_ALL_TLBS)
2095 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2096 #endif
2097 /* When storing valid upper BAT, mask BEPI and BRPN
2098 * and invalidate all TLBs covered by this BAT
2100 mask = (value << 15) & 0x0FFE0000UL;
2101 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2102 (value & ~0x0001FFFFUL & ~mask);
2103 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2104 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2105 #if !defined(FLUSH_ALL_TLBS)
2106 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2107 #else
2108 tlb_flush(env, 1);
2109 #endif
2113 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2115 dump_store_bat(env, 'I', 1, nr, value);
2116 env->IBAT[1][nr] = value;
2119 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2121 target_ulong mask;
2123 dump_store_bat(env, 'D', 0, nr, value);
2124 if (env->DBAT[0][nr] != value) {
2125 /* When storing valid upper BAT, mask BEPI and BRPN
2126 * and invalidate all TLBs covered by this BAT
2128 mask = (value << 15) & 0x0FFE0000UL;
2129 #if !defined(FLUSH_ALL_TLBS)
2130 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2131 #endif
2132 mask = (value << 15) & 0x0FFE0000UL;
2133 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2134 (value & ~0x0001FFFFUL & ~mask);
2135 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2136 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2137 #if !defined(FLUSH_ALL_TLBS)
2138 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2139 #else
2140 tlb_flush(env, 1);
2141 #endif
2145 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2147 dump_store_bat(env, 'D', 1, nr, value);
2148 env->DBAT[1][nr] = value;
2151 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2153 target_ulong mask;
2154 #if defined(FLUSH_ALL_TLBS)
2155 int do_inval;
2156 #endif
2158 dump_store_bat(env, 'I', 0, nr, value);
2159 if (env->IBAT[0][nr] != value) {
2160 #if defined(FLUSH_ALL_TLBS)
2161 do_inval = 0;
2162 #endif
2163 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2164 if (env->IBAT[1][nr] & 0x40) {
2165 /* Invalidate BAT only if it is valid */
2166 #if !defined(FLUSH_ALL_TLBS)
2167 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2168 #else
2169 do_inval = 1;
2170 #endif
2172 /* When storing valid upper BAT, mask BEPI and BRPN
2173 * and invalidate all TLBs covered by this BAT
2175 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2176 (value & ~0x0001FFFFUL & ~mask);
2177 env->DBAT[0][nr] = env->IBAT[0][nr];
2178 if (env->IBAT[1][nr] & 0x40) {
2179 #if !defined(FLUSH_ALL_TLBS)
2180 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2181 #else
2182 do_inval = 1;
2183 #endif
2185 #if defined(FLUSH_ALL_TLBS)
2186 if (do_inval)
2187 tlb_flush(env, 1);
2188 #endif
2192 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2194 target_ulong mask;
2195 #if defined(FLUSH_ALL_TLBS)
2196 int do_inval;
2197 #endif
2199 dump_store_bat(env, 'I', 1, nr, value);
2200 if (env->IBAT[1][nr] != value) {
2201 #if defined(FLUSH_ALL_TLBS)
2202 do_inval = 0;
2203 #endif
2204 if (env->IBAT[1][nr] & 0x40) {
2205 #if !defined(FLUSH_ALL_TLBS)
2206 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2207 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2208 #else
2209 do_inval = 1;
2210 #endif
2212 if (value & 0x40) {
2213 #if !defined(FLUSH_ALL_TLBS)
2214 mask = (value << 17) & 0x0FFE0000UL;
2215 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2216 #else
2217 do_inval = 1;
2218 #endif
2220 env->IBAT[1][nr] = value;
2221 env->DBAT[1][nr] = value;
2222 #if defined(FLUSH_ALL_TLBS)
2223 if (do_inval)
2224 tlb_flush(env, 1);
2225 #endif
2229 /*****************************************************************************/
2230 /* TLB management */
2231 void ppc_tlb_invalidate_all (CPUPPCState *env)
2233 switch (env->mmu_model) {
2234 case POWERPC_MMU_SOFT_6xx:
2235 case POWERPC_MMU_SOFT_74xx:
2236 ppc6xx_tlb_invalidate_all(env);
2237 break;
2238 case POWERPC_MMU_SOFT_4xx:
2239 case POWERPC_MMU_SOFT_4xx_Z:
2240 ppc4xx_tlb_invalidate_all(env);
2241 break;
2242 case POWERPC_MMU_REAL:
2243 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2244 break;
2245 case POWERPC_MMU_MPC8xx:
2246 /* XXX: TODO */
2247 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2248 break;
2249 case POWERPC_MMU_BOOKE:
2250 tlb_flush(env, 1);
2251 break;
2252 case POWERPC_MMU_BOOKE206:
2253 booke206_flush_tlb(env, -1, 0);
2254 break;
2255 case POWERPC_MMU_32B:
2256 case POWERPC_MMU_601:
2257 #if defined(TARGET_PPC64)
2258 case POWERPC_MMU_620:
2259 case POWERPC_MMU_64B:
2260 case POWERPC_MMU_2_06:
2261 #endif /* defined(TARGET_PPC64) */
2262 tlb_flush(env, 1);
2263 break;
2264 default:
2265 /* XXX: TODO */
2266 cpu_abort(env, "Unknown MMU model\n");
2267 break;
2271 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2273 #if !defined(FLUSH_ALL_TLBS)
2274 addr &= TARGET_PAGE_MASK;
2275 switch (env->mmu_model) {
2276 case POWERPC_MMU_SOFT_6xx:
2277 case POWERPC_MMU_SOFT_74xx:
2278 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2279 if (env->id_tlbs == 1)
2280 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2281 break;
2282 case POWERPC_MMU_SOFT_4xx:
2283 case POWERPC_MMU_SOFT_4xx_Z:
2284 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2285 break;
2286 case POWERPC_MMU_REAL:
2287 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2288 break;
2289 case POWERPC_MMU_MPC8xx:
2290 /* XXX: TODO */
2291 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2292 break;
2293 case POWERPC_MMU_BOOKE:
2294 /* XXX: TODO */
2295 cpu_abort(env, "BookE MMU model is not implemented\n");
2296 break;
2297 case POWERPC_MMU_BOOKE206:
2298 /* XXX: TODO */
2299 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2300 break;
2301 case POWERPC_MMU_32B:
2302 case POWERPC_MMU_601:
2303 /* tlbie invalidate TLBs for all segments */
2304 addr &= ~((target_ulong)-1ULL << 28);
2305 /* XXX: this case should be optimized,
2306 * giving a mask to tlb_flush_page
2308 tlb_flush_page(env, addr | (0x0 << 28));
2309 tlb_flush_page(env, addr | (0x1 << 28));
2310 tlb_flush_page(env, addr | (0x2 << 28));
2311 tlb_flush_page(env, addr | (0x3 << 28));
2312 tlb_flush_page(env, addr | (0x4 << 28));
2313 tlb_flush_page(env, addr | (0x5 << 28));
2314 tlb_flush_page(env, addr | (0x6 << 28));
2315 tlb_flush_page(env, addr | (0x7 << 28));
2316 tlb_flush_page(env, addr | (0x8 << 28));
2317 tlb_flush_page(env, addr | (0x9 << 28));
2318 tlb_flush_page(env, addr | (0xA << 28));
2319 tlb_flush_page(env, addr | (0xB << 28));
2320 tlb_flush_page(env, addr | (0xC << 28));
2321 tlb_flush_page(env, addr | (0xD << 28));
2322 tlb_flush_page(env, addr | (0xE << 28));
2323 tlb_flush_page(env, addr | (0xF << 28));
2324 break;
2325 #if defined(TARGET_PPC64)
2326 case POWERPC_MMU_620:
2327 case POWERPC_MMU_64B:
2328 case POWERPC_MMU_2_06:
2329 /* tlbie invalidate TLBs for all segments */
2330 /* XXX: given the fact that there are too many segments to invalidate,
2331 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2332 * we just invalidate all TLBs
2334 tlb_flush(env, 1);
2335 break;
2336 #endif /* defined(TARGET_PPC64) */
2337 default:
2338 /* XXX: TODO */
2339 cpu_abort(env, "Unknown MMU model\n");
2340 break;
2342 #else
2343 ppc_tlb_invalidate_all(env);
2344 #endif
2347 /*****************************************************************************/
2348 /* Special registers manipulation */
2349 #if defined(TARGET_PPC64)
2350 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2352 if (env->asr != value) {
2353 env->asr = value;
2354 tlb_flush(env, 1);
2357 #endif
2359 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2361 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2362 if (env->spr[SPR_SDR1] != value) {
2363 env->spr[SPR_SDR1] = value;
2364 #if defined(TARGET_PPC64)
2365 if (env->mmu_model & POWERPC_MMU_64) {
2366 target_ulong htabsize = value & SDR_64_HTABSIZE;
2368 if (htabsize > 28) {
2369 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2370 " stored in SDR1\n", htabsize);
2371 htabsize = 28;
2373 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2374 env->htab_base = value & SDR_64_HTABORG;
2375 } else
2376 #endif /* defined(TARGET_PPC64) */
2378 /* FIXME: Should check for valid HTABMASK values */
2379 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2380 env->htab_base = value & SDR_32_HTABORG;
2382 tlb_flush(env, 1);
2386 #if defined(TARGET_PPC64)
2387 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2389 // XXX
2390 return 0;
2392 #endif
2394 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2396 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2397 srnum, value, env->sr[srnum]);
2398 #if defined(TARGET_PPC64)
2399 if (env->mmu_model & POWERPC_MMU_64) {
2400 uint64_t rb = 0, rs = 0;
2402 /* ESID = srnum */
2403 rb |= ((uint32_t)srnum & 0xf) << 28;
2404 /* Set the valid bit */
2405 rb |= 1 << 27;
2406 /* Index = ESID */
2407 rb |= (uint32_t)srnum;
2409 /* VSID = VSID */
2410 rs |= (value & 0xfffffff) << 12;
2411 /* flags = flags */
2412 rs |= ((value >> 27) & 0xf) << 8;
2414 ppc_store_slb(env, rb, rs);
2415 } else
2416 #endif
2417 if (env->sr[srnum] != value) {
2418 env->sr[srnum] = value;
2419 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2420 flusing the whole TLB. */
2421 #if !defined(FLUSH_ALL_TLBS) && 0
2423 target_ulong page, end;
2424 /* Invalidate 256 MB of virtual memory */
2425 page = (16 << 20) * srnum;
2426 end = page + (16 << 20);
2427 for (; page != end; page += TARGET_PAGE_SIZE)
2428 tlb_flush_page(env, page);
2430 #else
2431 tlb_flush(env, 1);
2432 #endif
2435 #endif /* !defined (CONFIG_USER_ONLY) */
2437 /* GDBstub can read and write MSR... */
2438 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2440 hreg_store_msr(env, value, 0);
2443 /*****************************************************************************/
2444 /* Exception processing */
2445 #if defined (CONFIG_USER_ONLY)
2446 void do_interrupt (CPUState *env)
2448 env->exception_index = POWERPC_EXCP_NONE;
2449 env->error_code = 0;
2452 void ppc_hw_interrupt (CPUState *env)
2454 env->exception_index = POWERPC_EXCP_NONE;
2455 env->error_code = 0;
2457 #else /* defined (CONFIG_USER_ONLY) */
2458 static inline void dump_syscall(CPUState *env)
2460 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2461 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2462 " nip=" TARGET_FMT_lx "\n",
2463 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2464 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2465 ppc_dump_gpr(env, 6), env->nip);
2468 /* Note that this function should be greatly optimized
2469 * when called with a constant excp, from ppc_hw_interrupt
2471 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2473 target_ulong msr, new_msr, vector;
2474 int srr0, srr1, asrr0, asrr1;
2475 int lpes0, lpes1, lev;
2477 if (0) {
2478 /* XXX: find a suitable condition to enable the hypervisor mode */
2479 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2480 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2481 } else {
2482 /* Those values ensure we won't enter the hypervisor mode */
2483 lpes0 = 0;
2484 lpes1 = 1;
2487 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2488 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2490 /* new srr1 value excluding must-be-zero bits */
2491 msr = env->msr & ~0x783f0000ULL;
2493 /* new interrupt handler msr */
2494 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2496 /* target registers */
2497 srr0 = SPR_SRR0;
2498 srr1 = SPR_SRR1;
2499 asrr0 = -1;
2500 asrr1 = -1;
2502 switch (excp) {
2503 case POWERPC_EXCP_NONE:
2504 /* Should never happen */
2505 return;
2506 case POWERPC_EXCP_CRITICAL: /* Critical input */
2507 switch (excp_model) {
2508 case POWERPC_EXCP_40x:
2509 srr0 = SPR_40x_SRR2;
2510 srr1 = SPR_40x_SRR3;
2511 break;
2512 case POWERPC_EXCP_BOOKE:
2513 srr0 = SPR_BOOKE_CSRR0;
2514 srr1 = SPR_BOOKE_CSRR1;
2515 break;
2516 case POWERPC_EXCP_G2:
2517 break;
2518 default:
2519 goto excp_invalid;
2521 goto store_next;
2522 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2523 if (msr_me == 0) {
2524 /* Machine check exception is not enabled.
2525 * Enter checkstop state.
2527 if (qemu_log_enabled()) {
2528 qemu_log("Machine check while not allowed. "
2529 "Entering checkstop state\n");
2530 } else {
2531 fprintf(stderr, "Machine check while not allowed. "
2532 "Entering checkstop state\n");
2534 env->halted = 1;
2535 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2537 if (0) {
2538 /* XXX: find a suitable condition to enable the hypervisor mode */
2539 new_msr |= (target_ulong)MSR_HVB;
2542 /* machine check exceptions don't have ME set */
2543 new_msr &= ~((target_ulong)1 << MSR_ME);
2545 /* XXX: should also have something loaded in DAR / DSISR */
2546 switch (excp_model) {
2547 case POWERPC_EXCP_40x:
2548 srr0 = SPR_40x_SRR2;
2549 srr1 = SPR_40x_SRR3;
2550 break;
2551 case POWERPC_EXCP_BOOKE:
2552 srr0 = SPR_BOOKE_MCSRR0;
2553 srr1 = SPR_BOOKE_MCSRR1;
2554 asrr0 = SPR_BOOKE_CSRR0;
2555 asrr1 = SPR_BOOKE_CSRR1;
2556 break;
2557 default:
2558 break;
2560 goto store_next;
2561 case POWERPC_EXCP_DSI: /* Data storage exception */
2562 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2563 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2564 if (lpes1 == 0)
2565 new_msr |= (target_ulong)MSR_HVB;
2566 goto store_next;
2567 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2568 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2569 "\n", msr, env->nip);
2570 if (lpes1 == 0)
2571 new_msr |= (target_ulong)MSR_HVB;
2572 msr |= env->error_code;
2573 goto store_next;
2574 case POWERPC_EXCP_EXTERNAL: /* External input */
2575 if (lpes0 == 1)
2576 new_msr |= (target_ulong)MSR_HVB;
2577 goto store_next;
2578 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2579 if (lpes1 == 0)
2580 new_msr |= (target_ulong)MSR_HVB;
2581 /* XXX: this is false */
2582 /* Get rS/rD and rA from faulting opcode */
2583 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2584 goto store_current;
2585 case POWERPC_EXCP_PROGRAM: /* Program exception */
2586 switch (env->error_code & ~0xF) {
2587 case POWERPC_EXCP_FP:
2588 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2589 LOG_EXCP("Ignore floating point exception\n");
2590 env->exception_index = POWERPC_EXCP_NONE;
2591 env->error_code = 0;
2592 return;
2594 if (lpes1 == 0)
2595 new_msr |= (target_ulong)MSR_HVB;
2596 msr |= 0x00100000;
2597 if (msr_fe0 == msr_fe1)
2598 goto store_next;
2599 msr |= 0x00010000;
2600 break;
2601 case POWERPC_EXCP_INVAL:
2602 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2603 if (lpes1 == 0)
2604 new_msr |= (target_ulong)MSR_HVB;
2605 msr |= 0x00080000;
2606 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2607 break;
2608 case POWERPC_EXCP_PRIV:
2609 if (lpes1 == 0)
2610 new_msr |= (target_ulong)MSR_HVB;
2611 msr |= 0x00040000;
2612 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2613 break;
2614 case POWERPC_EXCP_TRAP:
2615 if (lpes1 == 0)
2616 new_msr |= (target_ulong)MSR_HVB;
2617 msr |= 0x00020000;
2618 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2619 break;
2620 default:
2621 /* Should never occur */
2622 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2623 env->error_code);
2624 break;
2626 goto store_current;
2627 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2628 if (lpes1 == 0)
2629 new_msr |= (target_ulong)MSR_HVB;
2630 goto store_current;
2631 case POWERPC_EXCP_SYSCALL: /* System call exception */
2632 dump_syscall(env);
2633 lev = env->error_code;
2634 if ((lev == 1) && cpu_ppc_hypercall) {
2635 cpu_ppc_hypercall(env);
2636 return;
2638 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2639 new_msr |= (target_ulong)MSR_HVB;
2640 goto store_next;
2641 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2642 goto store_current;
2643 case POWERPC_EXCP_DECR: /* Decrementer exception */
2644 if (lpes1 == 0)
2645 new_msr |= (target_ulong)MSR_HVB;
2646 goto store_next;
2647 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2648 /* FIT on 4xx */
2649 LOG_EXCP("FIT exception\n");
2650 goto store_next;
2651 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2652 LOG_EXCP("WDT exception\n");
2653 switch (excp_model) {
2654 case POWERPC_EXCP_BOOKE:
2655 srr0 = SPR_BOOKE_CSRR0;
2656 srr1 = SPR_BOOKE_CSRR1;
2657 break;
2658 default:
2659 break;
2661 goto store_next;
2662 case POWERPC_EXCP_DTLB: /* Data TLB error */
2663 goto store_next;
2664 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2665 goto store_next;
2666 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2667 switch (excp_model) {
2668 case POWERPC_EXCP_BOOKE:
2669 srr0 = SPR_BOOKE_DSRR0;
2670 srr1 = SPR_BOOKE_DSRR1;
2671 asrr0 = SPR_BOOKE_CSRR0;
2672 asrr1 = SPR_BOOKE_CSRR1;
2673 break;
2674 default:
2675 break;
2677 /* XXX: TODO */
2678 cpu_abort(env, "Debug exception is not implemented yet !\n");
2679 goto store_next;
2680 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2681 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2682 goto store_current;
2683 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2684 /* XXX: TODO */
2685 cpu_abort(env, "Embedded floating point data exception "
2686 "is not implemented yet !\n");
2687 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2688 goto store_next;
2689 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2690 /* XXX: TODO */
2691 cpu_abort(env, "Embedded floating point round exception "
2692 "is not implemented yet !\n");
2693 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2694 goto store_next;
2695 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2696 /* XXX: TODO */
2697 cpu_abort(env,
2698 "Performance counter exception is not implemented yet !\n");
2699 goto store_next;
2700 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2701 /* XXX: TODO */
2702 cpu_abort(env,
2703 "Embedded doorbell interrupt is not implemented yet !\n");
2704 goto store_next;
2705 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2706 switch (excp_model) {
2707 case POWERPC_EXCP_BOOKE:
2708 srr0 = SPR_BOOKE_CSRR0;
2709 srr1 = SPR_BOOKE_CSRR1;
2710 break;
2711 default:
2712 break;
2714 /* XXX: TODO */
2715 cpu_abort(env, "Embedded doorbell critical interrupt "
2716 "is not implemented yet !\n");
2717 goto store_next;
2718 case POWERPC_EXCP_RESET: /* System reset exception */
2719 if (msr_pow) {
2720 /* indicate that we resumed from power save mode */
2721 msr |= 0x10000;
2722 } else {
2723 new_msr &= ~((target_ulong)1 << MSR_ME);
2726 if (0) {
2727 /* XXX: find a suitable condition to enable the hypervisor mode */
2728 new_msr |= (target_ulong)MSR_HVB;
2730 goto store_next;
2731 case POWERPC_EXCP_DSEG: /* Data segment exception */
2732 if (lpes1 == 0)
2733 new_msr |= (target_ulong)MSR_HVB;
2734 goto store_next;
2735 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2736 if (lpes1 == 0)
2737 new_msr |= (target_ulong)MSR_HVB;
2738 goto store_next;
2739 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2740 srr0 = SPR_HSRR0;
2741 srr1 = SPR_HSRR1;
2742 new_msr |= (target_ulong)MSR_HVB;
2743 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2744 goto store_next;
2745 case POWERPC_EXCP_TRACE: /* Trace exception */
2746 if (lpes1 == 0)
2747 new_msr |= (target_ulong)MSR_HVB;
2748 goto store_next;
2749 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2750 srr0 = SPR_HSRR0;
2751 srr1 = SPR_HSRR1;
2752 new_msr |= (target_ulong)MSR_HVB;
2753 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2754 goto store_next;
2755 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2756 srr0 = SPR_HSRR0;
2757 srr1 = SPR_HSRR1;
2758 new_msr |= (target_ulong)MSR_HVB;
2759 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2760 goto store_next;
2761 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2762 srr0 = SPR_HSRR0;
2763 srr1 = SPR_HSRR1;
2764 new_msr |= (target_ulong)MSR_HVB;
2765 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2766 goto store_next;
2767 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2768 srr0 = SPR_HSRR0;
2769 srr1 = SPR_HSRR1;
2770 new_msr |= (target_ulong)MSR_HVB;
2771 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2772 goto store_next;
2773 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2774 if (lpes1 == 0)
2775 new_msr |= (target_ulong)MSR_HVB;
2776 goto store_current;
2777 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2778 LOG_EXCP("PIT exception\n");
2779 goto store_next;
2780 case POWERPC_EXCP_IO: /* IO error exception */
2781 /* XXX: TODO */
2782 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2783 goto store_next;
2784 case POWERPC_EXCP_RUNM: /* Run mode exception */
2785 /* XXX: TODO */
2786 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2787 goto store_next;
2788 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2789 /* XXX: TODO */
2790 cpu_abort(env, "602 emulation trap exception "
2791 "is not implemented yet !\n");
2792 goto store_next;
2793 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2794 if (lpes1 == 0) /* XXX: check this */
2795 new_msr |= (target_ulong)MSR_HVB;
2796 switch (excp_model) {
2797 case POWERPC_EXCP_602:
2798 case POWERPC_EXCP_603:
2799 case POWERPC_EXCP_603E:
2800 case POWERPC_EXCP_G2:
2801 goto tlb_miss_tgpr;
2802 case POWERPC_EXCP_7x5:
2803 goto tlb_miss;
2804 case POWERPC_EXCP_74xx:
2805 goto tlb_miss_74xx;
2806 default:
2807 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2808 break;
2810 break;
2811 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2812 if (lpes1 == 0) /* XXX: check this */
2813 new_msr |= (target_ulong)MSR_HVB;
2814 switch (excp_model) {
2815 case POWERPC_EXCP_602:
2816 case POWERPC_EXCP_603:
2817 case POWERPC_EXCP_603E:
2818 case POWERPC_EXCP_G2:
2819 goto tlb_miss_tgpr;
2820 case POWERPC_EXCP_7x5:
2821 goto tlb_miss;
2822 case POWERPC_EXCP_74xx:
2823 goto tlb_miss_74xx;
2824 default:
2825 cpu_abort(env, "Invalid data load TLB miss exception\n");
2826 break;
2828 break;
2829 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2830 if (lpes1 == 0) /* XXX: check this */
2831 new_msr |= (target_ulong)MSR_HVB;
2832 switch (excp_model) {
2833 case POWERPC_EXCP_602:
2834 case POWERPC_EXCP_603:
2835 case POWERPC_EXCP_603E:
2836 case POWERPC_EXCP_G2:
2837 tlb_miss_tgpr:
2838 /* Swap temporary saved registers with GPRs */
2839 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2840 new_msr |= (target_ulong)1 << MSR_TGPR;
2841 hreg_swap_gpr_tgpr(env);
2843 goto tlb_miss;
2844 case POWERPC_EXCP_7x5:
2845 tlb_miss:
2846 #if defined (DEBUG_SOFTWARE_TLB)
2847 if (qemu_log_enabled()) {
2848 const char *es;
2849 target_ulong *miss, *cmp;
2850 int en;
2851 if (excp == POWERPC_EXCP_IFTLB) {
2852 es = "I";
2853 en = 'I';
2854 miss = &env->spr[SPR_IMISS];
2855 cmp = &env->spr[SPR_ICMP];
2856 } else {
2857 if (excp == POWERPC_EXCP_DLTLB)
2858 es = "DL";
2859 else
2860 es = "DS";
2861 en = 'D';
2862 miss = &env->spr[SPR_DMISS];
2863 cmp = &env->spr[SPR_DCMP];
2865 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2866 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2867 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2868 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2869 env->error_code);
2871 #endif
2872 msr |= env->crf[0] << 28;
2873 msr |= env->error_code; /* key, D/I, S/L bits */
2874 /* Set way using a LRU mechanism */
2875 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2876 break;
2877 case POWERPC_EXCP_74xx:
2878 tlb_miss_74xx:
2879 #if defined (DEBUG_SOFTWARE_TLB)
2880 if (qemu_log_enabled()) {
2881 const char *es;
2882 target_ulong *miss, *cmp;
2883 int en;
2884 if (excp == POWERPC_EXCP_IFTLB) {
2885 es = "I";
2886 en = 'I';
2887 miss = &env->spr[SPR_TLBMISS];
2888 cmp = &env->spr[SPR_PTEHI];
2889 } else {
2890 if (excp == POWERPC_EXCP_DLTLB)
2891 es = "DL";
2892 else
2893 es = "DS";
2894 en = 'D';
2895 miss = &env->spr[SPR_TLBMISS];
2896 cmp = &env->spr[SPR_PTEHI];
2898 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2899 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2900 env->error_code);
2902 #endif
2903 msr |= env->error_code; /* key bit */
2904 break;
2905 default:
2906 cpu_abort(env, "Invalid data store TLB miss exception\n");
2907 break;
2909 goto store_next;
2910 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2911 /* XXX: TODO */
2912 cpu_abort(env, "Floating point assist exception "
2913 "is not implemented yet !\n");
2914 goto store_next;
2915 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2916 /* XXX: TODO */
2917 cpu_abort(env, "DABR exception is not implemented yet !\n");
2918 goto store_next;
2919 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2920 /* XXX: TODO */
2921 cpu_abort(env, "IABR exception is not implemented yet !\n");
2922 goto store_next;
2923 case POWERPC_EXCP_SMI: /* System management interrupt */
2924 /* XXX: TODO */
2925 cpu_abort(env, "SMI exception is not implemented yet !\n");
2926 goto store_next;
2927 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2928 /* XXX: TODO */
2929 cpu_abort(env, "Thermal management exception "
2930 "is not implemented yet !\n");
2931 goto store_next;
2932 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2933 if (lpes1 == 0)
2934 new_msr |= (target_ulong)MSR_HVB;
2935 /* XXX: TODO */
2936 cpu_abort(env,
2937 "Performance counter exception is not implemented yet !\n");
2938 goto store_next;
2939 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2940 /* XXX: TODO */
2941 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2942 goto store_next;
2943 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2944 /* XXX: TODO */
2945 cpu_abort(env,
2946 "970 soft-patch exception is not implemented yet !\n");
2947 goto store_next;
2948 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2949 /* XXX: TODO */
2950 cpu_abort(env,
2951 "970 maintenance exception is not implemented yet !\n");
2952 goto store_next;
2953 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2954 /* XXX: TODO */
2955 cpu_abort(env, "Maskable external exception "
2956 "is not implemented yet !\n");
2957 goto store_next;
2958 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2959 /* XXX: TODO */
2960 cpu_abort(env, "Non maskable external exception "
2961 "is not implemented yet !\n");
2962 goto store_next;
2963 default:
2964 excp_invalid:
2965 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2966 break;
2967 store_current:
2968 /* save current instruction location */
2969 env->spr[srr0] = env->nip - 4;
2970 break;
2971 store_next:
2972 /* save next instruction location */
2973 env->spr[srr0] = env->nip;
2974 break;
2976 /* Save MSR */
2977 env->spr[srr1] = msr;
2978 /* If any alternate SRR register are defined, duplicate saved values */
2979 if (asrr0 != -1)
2980 env->spr[asrr0] = env->spr[srr0];
2981 if (asrr1 != -1)
2982 env->spr[asrr1] = env->spr[srr1];
2983 /* If we disactivated any translation, flush TLBs */
2984 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2985 tlb_flush(env, 1);
2987 if (msr_ile) {
2988 new_msr |= (target_ulong)1 << MSR_LE;
2991 /* Jump to handler */
2992 vector = env->excp_vectors[excp];
2993 if (vector == (target_ulong)-1ULL) {
2994 cpu_abort(env, "Raised an exception without defined vector %d\n",
2995 excp);
2997 vector |= env->excp_prefix;
2998 #if defined(TARGET_PPC64)
2999 if (excp_model == POWERPC_EXCP_BOOKE) {
3000 if (!msr_icm) {
3001 vector = (uint32_t)vector;
3002 } else {
3003 new_msr |= (target_ulong)1 << MSR_CM;
3005 } else {
3006 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
3007 vector = (uint32_t)vector;
3008 } else {
3009 new_msr |= (target_ulong)1 << MSR_SF;
3012 #endif
3013 /* XXX: we don't use hreg_store_msr here as already have treated
3014 * any special case that could occur. Just store MSR and update hflags
3016 env->msr = new_msr & env->msr_mask;
3017 hreg_compute_hflags(env);
3018 env->nip = vector;
3019 /* Reset exception state */
3020 env->exception_index = POWERPC_EXCP_NONE;
3021 env->error_code = 0;
3023 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
3024 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
3025 /* XXX: The BookE changes address space when switching modes,
3026 we should probably implement that as different MMU indexes,
3027 but for the moment we do it the slow way and flush all. */
3028 tlb_flush(env, 1);
3032 void do_interrupt (CPUState *env)
3034 powerpc_excp(env, env->excp_model, env->exception_index);
3037 void ppc_hw_interrupt (CPUPPCState *env)
3039 int hdice;
3041 #if 0
3042 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3043 __func__, env, env->pending_interrupts,
3044 env->interrupt_request, (int)msr_me, (int)msr_ee);
3045 #endif
3046 /* External reset */
3047 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3048 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3049 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3050 return;
3052 /* Machine check exception */
3053 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3054 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3055 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3056 return;
3058 #if 0 /* TODO */
3059 /* External debug exception */
3060 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3061 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3062 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3063 return;
3065 #endif
3066 if (0) {
3067 /* XXX: find a suitable condition to enable the hypervisor mode */
3068 hdice = env->spr[SPR_LPCR] & 1;
3069 } else {
3070 hdice = 0;
3072 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3073 /* Hypervisor decrementer exception */
3074 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3075 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3076 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3077 return;
3080 if (msr_ce != 0) {
3081 /* External critical interrupt */
3082 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3083 /* Taking a critical external interrupt does not clear the external
3084 * critical interrupt status
3086 #if 0
3087 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3088 #endif
3089 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3090 return;
3093 if (msr_ee != 0) {
3094 /* Watchdog timer on embedded PowerPC */
3095 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3096 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3097 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3098 return;
3100 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3101 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3102 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3103 return;
3105 /* Fixed interval timer on embedded PowerPC */
3106 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3107 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3108 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3109 return;
3111 /* Programmable interval timer on embedded PowerPC */
3112 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3113 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3114 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3115 return;
3117 /* Decrementer exception */
3118 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3119 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3120 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3121 return;
3123 /* External interrupt */
3124 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3125 /* Taking an external interrupt does not clear the external
3126 * interrupt status
3128 #if 0
3129 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3130 #endif
3131 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3132 return;
3134 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3135 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3136 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3137 return;
3139 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3140 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3141 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3142 return;
3144 /* Thermal interrupt */
3145 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3146 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3147 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3148 return;
3152 #endif /* !CONFIG_USER_ONLY */
3154 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3156 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3157 TARGET_FMT_lx "\n", RA, msr);
3160 void cpu_reset(CPUPPCState *env)
3162 target_ulong msr;
3164 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3165 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3166 log_cpu_state(env, 0);
3169 msr = (target_ulong)0;
3170 if (0) {
3171 /* XXX: find a suitable condition to enable the hypervisor mode */
3172 msr |= (target_ulong)MSR_HVB;
3174 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3175 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3176 msr |= (target_ulong)1 << MSR_EP;
3177 #if defined (DO_SINGLE_STEP) && 0
3178 /* Single step trace mode */
3179 msr |= (target_ulong)1 << MSR_SE;
3180 msr |= (target_ulong)1 << MSR_BE;
3181 #endif
3182 #if defined(CONFIG_USER_ONLY)
3183 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3184 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3185 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3186 msr |= (target_ulong)1 << MSR_PR;
3187 #else
3188 env->excp_prefix = env->hreset_excp_prefix;
3189 env->nip = env->hreset_vector | env->excp_prefix;
3190 if (env->mmu_model != POWERPC_MMU_REAL)
3191 ppc_tlb_invalidate_all(env);
3192 #endif
3193 env->msr = msr & env->msr_mask;
3194 #if defined(TARGET_PPC64)
3195 if (env->mmu_model & POWERPC_MMU_64)
3196 env->msr |= (1ULL << MSR_SF);
3197 #endif
3198 hreg_compute_hflags(env);
3199 env->reserve_addr = (target_ulong)-1ULL;
3200 /* Be sure no exception or interrupt is pending */
3201 env->pending_interrupts = 0;
3202 env->exception_index = POWERPC_EXCP_NONE;
3203 env->error_code = 0;
3204 /* Flush all TLBs */
3205 tlb_flush(env, 1);
3208 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3210 CPUPPCState *env;
3211 const ppc_def_t *def;
3213 def = cpu_ppc_find_by_name(cpu_model);
3214 if (!def)
3215 return NULL;
3217 env = g_malloc0(sizeof(CPUPPCState));
3218 cpu_exec_init(env);
3219 if (tcg_enabled()) {
3220 ppc_translate_init();
3222 /* Adjust cpu index for SMT */
3223 #if !defined(CONFIG_USER_ONLY)
3224 if (kvm_enabled()) {
3225 int smt = kvmppc_smt_threads();
3227 env->cpu_index = (env->cpu_index / smp_threads)*smt
3228 + (env->cpu_index % smp_threads);
3230 #endif /* !CONFIG_USER_ONLY */
3231 env->cpu_model_str = cpu_model;
3232 cpu_ppc_register_internal(env, def);
3234 qemu_init_vcpu(env);
3236 return env;
3239 void cpu_ppc_close (CPUPPCState *env)
3241 /* Should also remove all opcode tables... */
3242 g_free(env);