qapi: fix typos in documentation JSON examples
[qemu/ar7.git] / target-ppc / helper.c
blob6339be3a75a6ceab48dc0053867e1f6e981a15a0
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"
30 //#define DEBUG_MMU
31 //#define DEBUG_BATS
32 //#define DEBUG_SLB
33 //#define DEBUG_SOFTWARE_TLB
34 //#define DUMP_PAGE_TABLES
35 //#define DEBUG_EXCEPTIONS
36 //#define FLUSH_ALL_TLBS
38 #ifdef DEBUG_MMU
39 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
40 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
41 #else
42 # define LOG_MMU(...) do { } while (0)
43 # define LOG_MMU_STATE(...) do { } while (0)
44 #endif
47 #ifdef DEBUG_SOFTWARE_TLB
48 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
49 #else
50 # define LOG_SWTLB(...) do { } while (0)
51 #endif
53 #ifdef DEBUG_BATS
54 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
55 #else
56 # define LOG_BATS(...) do { } while (0)
57 #endif
59 #ifdef DEBUG_SLB
60 # define LOG_SLB(...) qemu_log(__VA_ARGS__)
61 #else
62 # define LOG_SLB(...) do { } while (0)
63 #endif
65 #ifdef DEBUG_EXCEPTIONS
66 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
67 #else
68 # define LOG_EXCP(...) do { } while (0)
69 #endif
71 /*****************************************************************************/
72 /* PowerPC Hypercall emulation */
74 void (*cpu_ppc_hypercall)(CPUState *);
76 /*****************************************************************************/
77 /* PowerPC MMU emulation */
79 #if defined(CONFIG_USER_ONLY)
80 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
81 int mmu_idx)
83 int exception, error_code;
85 if (rw == 2) {
86 exception = POWERPC_EXCP_ISI;
87 error_code = 0x40000000;
88 } else {
89 exception = POWERPC_EXCP_DSI;
90 error_code = 0x40000000;
91 if (rw)
92 error_code |= 0x02000000;
93 env->spr[SPR_DAR] = address;
94 env->spr[SPR_DSISR] = error_code;
96 env->exception_index = exception;
97 env->error_code = error_code;
99 return 1;
102 #else
103 /* Common routines used by software and hardware TLBs emulation */
104 static inline int pte_is_valid(target_ulong pte0)
106 return pte0 & 0x80000000 ? 1 : 0;
109 static inline void pte_invalidate(target_ulong *pte0)
111 *pte0 &= ~0x80000000;
114 #if defined(TARGET_PPC64)
115 static inline int pte64_is_valid(target_ulong pte0)
117 return pte0 & 0x0000000000000001ULL ? 1 : 0;
120 static inline void pte64_invalidate(target_ulong *pte0)
122 *pte0 &= ~0x0000000000000001ULL;
124 #endif
126 #define PTE_PTEM_MASK 0x7FFFFFBF
127 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
128 #if defined(TARGET_PPC64)
129 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
130 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
131 #endif
133 static inline int pp_check(int key, int pp, int nx)
135 int access;
137 /* Compute access rights */
138 /* When pp is 3/7, the result is undefined. Set it to noaccess */
139 access = 0;
140 if (key == 0) {
141 switch (pp) {
142 case 0x0:
143 case 0x1:
144 case 0x2:
145 access |= PAGE_WRITE;
146 /* No break here */
147 case 0x3:
148 case 0x6:
149 access |= PAGE_READ;
150 break;
152 } else {
153 switch (pp) {
154 case 0x0:
155 case 0x6:
156 access = 0;
157 break;
158 case 0x1:
159 case 0x3:
160 access = PAGE_READ;
161 break;
162 case 0x2:
163 access = PAGE_READ | PAGE_WRITE;
164 break;
167 if (nx == 0)
168 access |= PAGE_EXEC;
170 return access;
173 static inline int check_prot(int prot, int rw, int access_type)
175 int ret;
177 if (access_type == ACCESS_CODE) {
178 if (prot & PAGE_EXEC)
179 ret = 0;
180 else
181 ret = -2;
182 } else if (rw) {
183 if (prot & PAGE_WRITE)
184 ret = 0;
185 else
186 ret = -2;
187 } else {
188 if (prot & PAGE_READ)
189 ret = 0;
190 else
191 ret = -2;
194 return ret;
197 static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
198 target_ulong pte1, int h, int rw, int type)
200 target_ulong ptem, mmask;
201 int access, ret, pteh, ptev, pp;
203 ret = -1;
204 /* Check validity and table match */
205 #if defined(TARGET_PPC64)
206 if (is_64b) {
207 ptev = pte64_is_valid(pte0);
208 pteh = (pte0 >> 1) & 1;
209 } else
210 #endif
212 ptev = pte_is_valid(pte0);
213 pteh = (pte0 >> 6) & 1;
215 if (ptev && h == pteh) {
216 /* Check vsid & api */
217 #if defined(TARGET_PPC64)
218 if (is_64b) {
219 ptem = pte0 & PTE64_PTEM_MASK;
220 mmask = PTE64_CHECK_MASK;
221 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
222 ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
223 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
224 } else
225 #endif
227 ptem = pte0 & PTE_PTEM_MASK;
228 mmask = PTE_CHECK_MASK;
229 pp = pte1 & 0x00000003;
231 if (ptem == ctx->ptem) {
232 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
233 /* all matches should have equal RPN, WIMG & PP */
234 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
235 qemu_log("Bad RPN/WIMG/PP\n");
236 return -3;
239 /* Compute access rights */
240 access = pp_check(ctx->key, pp, ctx->nx);
241 /* Keep the matching PTE informations */
242 ctx->raddr = pte1;
243 ctx->prot = access;
244 ret = check_prot(ctx->prot, rw, type);
245 if (ret == 0) {
246 /* Access granted */
247 LOG_MMU("PTE access granted !\n");
248 } else {
249 /* Access right violation */
250 LOG_MMU("PTE access rejected\n");
255 return ret;
258 static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
259 target_ulong pte1, int h, int rw, int type)
261 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
264 #if defined(TARGET_PPC64)
265 static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
266 target_ulong pte1, int h, int rw, int type)
268 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
270 #endif
272 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
273 int ret, int rw)
275 int store = 0;
277 /* Update page flags */
278 if (!(*pte1p & 0x00000100)) {
279 /* Update accessed flag */
280 *pte1p |= 0x00000100;
281 store = 1;
283 if (!(*pte1p & 0x00000080)) {
284 if (rw == 1 && ret == 0) {
285 /* Update changed flag */
286 *pte1p |= 0x00000080;
287 store = 1;
288 } else {
289 /* Force page fault for first write access */
290 ctx->prot &= ~PAGE_WRITE;
294 return store;
297 /* Software driven TLB helpers */
298 static inline int ppc6xx_tlb_getnum(CPUState *env, target_ulong eaddr, int way,
299 int is_code)
301 int nr;
303 /* Select TLB num in a way from address */
304 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
305 /* Select TLB way */
306 nr += env->tlb_per_way * way;
307 /* 6xx have separate TLBs for instructions and data */
308 if (is_code && env->id_tlbs == 1)
309 nr += env->nb_tlb;
311 return nr;
314 static inline void ppc6xx_tlb_invalidate_all(CPUState *env)
316 ppc6xx_tlb_t *tlb;
317 int nr, max;
319 //LOG_SWTLB("Invalidate all TLBs\n");
320 /* Invalidate all defined software TLB */
321 max = env->nb_tlb;
322 if (env->id_tlbs == 1)
323 max *= 2;
324 for (nr = 0; nr < max; nr++) {
325 tlb = &env->tlb.tlb6[nr];
326 pte_invalidate(&tlb->pte0);
328 tlb_flush(env, 1);
331 static inline void __ppc6xx_tlb_invalidate_virt(CPUState *env,
332 target_ulong eaddr,
333 int is_code, int match_epn)
335 #if !defined(FLUSH_ALL_TLBS)
336 ppc6xx_tlb_t *tlb;
337 int way, nr;
339 /* Invalidate ITLB + DTLB, all ways */
340 for (way = 0; way < env->nb_ways; way++) {
341 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
342 tlb = &env->tlb.tlb6[nr];
343 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
344 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
345 env->nb_tlb, eaddr);
346 pte_invalidate(&tlb->pte0);
347 tlb_flush_page(env, tlb->EPN);
350 #else
351 /* XXX: PowerPC specification say this is valid as well */
352 ppc6xx_tlb_invalidate_all(env);
353 #endif
356 static inline void ppc6xx_tlb_invalidate_virt(CPUState *env,
357 target_ulong eaddr, int is_code)
359 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
362 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
363 target_ulong pte0, target_ulong pte1)
365 ppc6xx_tlb_t *tlb;
366 int nr;
368 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
369 tlb = &env->tlb.tlb6[nr];
370 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
371 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
372 /* Invalidate any pending reference in Qemu for this virtual address */
373 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
374 tlb->pte0 = pte0;
375 tlb->pte1 = pte1;
376 tlb->EPN = EPN;
377 /* Store last way for LRU mechanism */
378 env->last_way = way;
381 static inline int ppc6xx_tlb_check(CPUState *env, mmu_ctx_t *ctx,
382 target_ulong eaddr, int rw, int access_type)
384 ppc6xx_tlb_t *tlb;
385 int nr, best, way;
386 int ret;
388 best = -1;
389 ret = -1; /* No TLB found */
390 for (way = 0; way < env->nb_ways; way++) {
391 nr = ppc6xx_tlb_getnum(env, eaddr, way,
392 access_type == ACCESS_CODE ? 1 : 0);
393 tlb = &env->tlb.tlb6[nr];
394 /* This test "emulates" the PTE index match for hardware TLBs */
395 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
396 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
397 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
398 pte_is_valid(tlb->pte0) ? "valid" : "inval",
399 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
400 continue;
402 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
403 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
404 pte_is_valid(tlb->pte0) ? "valid" : "inval",
405 tlb->EPN, eaddr, tlb->pte1,
406 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
407 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
408 case -3:
409 /* TLB inconsistency */
410 return -1;
411 case -2:
412 /* Access violation */
413 ret = -2;
414 best = nr;
415 break;
416 case -1:
417 default:
418 /* No match */
419 break;
420 case 0:
421 /* access granted */
422 /* XXX: we should go on looping to check all TLBs consistency
423 * but we can speed-up the whole thing as the
424 * result would be undefined if TLBs are not consistent.
426 ret = 0;
427 best = nr;
428 goto done;
431 if (best != -1) {
432 done:
433 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
434 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
435 /* Update page flags */
436 pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
439 return ret;
442 /* Perform BAT hit & translation */
443 static inline void bat_size_prot(CPUState *env, target_ulong *blp, int *validp,
444 int *protp, target_ulong *BATu,
445 target_ulong *BATl)
447 target_ulong bl;
448 int pp, valid, prot;
450 bl = (*BATu & 0x00001FFC) << 15;
451 valid = 0;
452 prot = 0;
453 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
454 ((msr_pr != 0) && (*BATu & 0x00000001))) {
455 valid = 1;
456 pp = *BATl & 0x00000003;
457 if (pp != 0) {
458 prot = PAGE_READ | PAGE_EXEC;
459 if (pp == 0x2)
460 prot |= PAGE_WRITE;
463 *blp = bl;
464 *validp = valid;
465 *protp = prot;
468 static inline void bat_601_size_prot(CPUState *env, target_ulong *blp,
469 int *validp, int *protp,
470 target_ulong *BATu, target_ulong *BATl)
472 target_ulong bl;
473 int key, pp, valid, prot;
475 bl = (*BATl & 0x0000003F) << 17;
476 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
477 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
478 prot = 0;
479 valid = (*BATl >> 6) & 1;
480 if (valid) {
481 pp = *BATu & 0x00000003;
482 if (msr_pr == 0)
483 key = (*BATu >> 3) & 1;
484 else
485 key = (*BATu >> 2) & 1;
486 prot = pp_check(key, pp, 0);
488 *blp = bl;
489 *validp = valid;
490 *protp = prot;
493 static inline int get_bat(CPUState *env, mmu_ctx_t *ctx, target_ulong virtual,
494 int rw, int type)
496 target_ulong *BATlt, *BATut, *BATu, *BATl;
497 target_ulong BEPIl, BEPIu, bl;
498 int i, valid, prot;
499 int ret = -1;
501 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
502 type == ACCESS_CODE ? 'I' : 'D', virtual);
503 switch (type) {
504 case ACCESS_CODE:
505 BATlt = env->IBAT[1];
506 BATut = env->IBAT[0];
507 break;
508 default:
509 BATlt = env->DBAT[1];
510 BATut = env->DBAT[0];
511 break;
513 for (i = 0; i < env->nb_BATs; i++) {
514 BATu = &BATut[i];
515 BATl = &BATlt[i];
516 BEPIu = *BATu & 0xF0000000;
517 BEPIl = *BATu & 0x0FFE0000;
518 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
519 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
520 } else {
521 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
523 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
524 " BATl " TARGET_FMT_lx "\n", __func__,
525 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
526 if ((virtual & 0xF0000000) == BEPIu &&
527 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
528 /* BAT matches */
529 if (valid != 0) {
530 /* Get physical address */
531 ctx->raddr = (*BATl & 0xF0000000) |
532 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
533 (virtual & 0x0001F000);
534 /* Compute access rights */
535 ctx->prot = prot;
536 ret = check_prot(ctx->prot, rw, type);
537 if (ret == 0)
538 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
539 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
540 ctx->prot & PAGE_WRITE ? 'W' : '-');
541 break;
545 if (ret < 0) {
546 #if defined(DEBUG_BATS)
547 if (qemu_log_enabled()) {
548 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
549 for (i = 0; i < 4; i++) {
550 BATu = &BATut[i];
551 BATl = &BATlt[i];
552 BEPIu = *BATu & 0xF0000000;
553 BEPIl = *BATu & 0x0FFE0000;
554 bl = (*BATu & 0x00001FFC) << 15;
555 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
556 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
557 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
558 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
559 *BATu, *BATl, BEPIu, BEPIl, bl);
562 #endif
564 /* No hit */
565 return ret;
568 static inline target_phys_addr_t get_pteg_offset(CPUState *env,
569 target_phys_addr_t hash,
570 int pte_size)
572 return (hash * pte_size * 8) & env->htab_mask;
575 /* PTE table lookup */
576 static inline int _find_pte(CPUState *env, mmu_ctx_t *ctx, int is_64b, int h,
577 int rw, int type, int target_page_bits)
579 target_phys_addr_t pteg_off;
580 target_ulong pte0, pte1;
581 int i, good = -1;
582 int ret, r;
584 ret = -1; /* No entry found */
585 pteg_off = get_pteg_offset(env, ctx->hash[h],
586 is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
587 for (i = 0; i < 8; i++) {
588 #if defined(TARGET_PPC64)
589 if (is_64b) {
590 if (env->external_htab) {
591 pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
592 pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
593 } else {
594 pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
595 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
598 /* We have a TLB that saves 4K pages, so let's
599 * split a huge page to 4k chunks */
600 if (target_page_bits != TARGET_PAGE_BITS)
601 pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
602 & TARGET_PAGE_MASK;
604 r = pte64_check(ctx, pte0, pte1, h, rw, type);
605 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
606 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
607 pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
608 (int)((pte0 >> 1) & 1), ctx->ptem);
609 } else
610 #endif
612 if (env->external_htab) {
613 pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
614 pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
615 } else {
616 pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
617 pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
619 r = pte32_check(ctx, pte0, pte1, h, rw, type);
620 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
621 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
622 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
623 (int)((pte0 >> 6) & 1), ctx->ptem);
625 switch (r) {
626 case -3:
627 /* PTE inconsistency */
628 return -1;
629 case -2:
630 /* Access violation */
631 ret = -2;
632 good = i;
633 break;
634 case -1:
635 default:
636 /* No PTE match */
637 break;
638 case 0:
639 /* access granted */
640 /* XXX: we should go on looping to check all PTEs consistency
641 * but if we can speed-up the whole thing as the
642 * result would be undefined if PTEs are not consistent.
644 ret = 0;
645 good = i;
646 goto done;
649 if (good != -1) {
650 done:
651 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
652 ctx->raddr, ctx->prot, ret);
653 /* Update page flags */
654 pte1 = ctx->raddr;
655 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
656 #if defined(TARGET_PPC64)
657 if (is_64b) {
658 if (env->external_htab) {
659 stq_p(env->external_htab + pteg_off + (good * 16) + 8,
660 pte1);
661 } else {
662 stq_phys_notdirty(env->htab_base + pteg_off +
663 (good * 16) + 8, pte1);
665 } else
666 #endif
668 if (env->external_htab) {
669 stl_p(env->external_htab + pteg_off + (good * 8) + 4,
670 pte1);
671 } else {
672 stl_phys_notdirty(env->htab_base + pteg_off +
673 (good * 8) + 4, pte1);
679 return ret;
682 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
683 int type, int target_page_bits)
685 #if defined(TARGET_PPC64)
686 if (env->mmu_model & POWERPC_MMU_64)
687 return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
688 #endif
690 return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
693 #if defined(TARGET_PPC64)
694 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
696 uint64_t esid_256M, esid_1T;
697 int n;
699 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
701 esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
702 esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
704 for (n = 0; n < env->slb_nr; n++) {
705 ppc_slb_t *slb = &env->slb[n];
707 LOG_SLB("%s: slot %d %016" PRIx64 " %016"
708 PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
709 /* We check for 1T matches on all MMUs here - if the MMU
710 * doesn't have 1T segment support, we will have prevented 1T
711 * entries from being inserted in the slbmte code. */
712 if (((slb->esid == esid_256M) &&
713 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
714 || ((slb->esid == esid_1T) &&
715 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
716 return slb;
720 return NULL;
723 void ppc_slb_invalidate_all (CPUPPCState *env)
725 int n, do_invalidate;
727 do_invalidate = 0;
728 /* XXX: Warning: slbia never invalidates the first segment */
729 for (n = 1; n < env->slb_nr; n++) {
730 ppc_slb_t *slb = &env->slb[n];
732 if (slb->esid & SLB_ESID_V) {
733 slb->esid &= ~SLB_ESID_V;
734 /* XXX: given the fact that segment size is 256 MB or 1TB,
735 * and we still don't have a tlb_flush_mask(env, n, mask)
736 * in Qemu, we just invalidate all TLBs
738 do_invalidate = 1;
741 if (do_invalidate)
742 tlb_flush(env, 1);
745 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
747 ppc_slb_t *slb;
749 slb = slb_lookup(env, T0);
750 if (!slb) {
751 return;
754 if (slb->esid & SLB_ESID_V) {
755 slb->esid &= ~SLB_ESID_V;
757 /* XXX: given the fact that segment size is 256 MB or 1TB,
758 * and we still don't have a tlb_flush_mask(env, n, mask)
759 * in Qemu, we just invalidate all TLBs
761 tlb_flush(env, 1);
765 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
767 int slot = rb & 0xfff;
768 ppc_slb_t *slb = &env->slb[slot];
770 if (rb & (0x1000 - env->slb_nr)) {
771 return -1; /* Reserved bits set or slot too high */
773 if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
774 return -1; /* Bad segment size */
776 if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
777 return -1; /* 1T segment on MMU that doesn't support it */
780 /* Mask out the slot number as we store the entry */
781 slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
782 slb->vsid = rs;
784 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
785 " %016" PRIx64 "\n", __func__, slot, rb, rs,
786 slb->esid, slb->vsid);
788 return 0;
791 int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
793 int slot = rb & 0xfff;
794 ppc_slb_t *slb = &env->slb[slot];
796 if (slot >= env->slb_nr) {
797 return -1;
800 *rt = slb->esid;
801 return 0;
804 int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
806 int slot = rb & 0xfff;
807 ppc_slb_t *slb = &env->slb[slot];
809 if (slot >= env->slb_nr) {
810 return -1;
813 *rt = slb->vsid;
814 return 0;
816 #endif /* defined(TARGET_PPC64) */
818 /* Perform segment based translation */
819 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
820 target_ulong eaddr, int rw, int type)
822 target_phys_addr_t hash;
823 target_ulong vsid;
824 int ds, pr, target_page_bits;
825 int ret, ret2;
827 pr = msr_pr;
828 ctx->eaddr = eaddr;
829 #if defined(TARGET_PPC64)
830 if (env->mmu_model & POWERPC_MMU_64) {
831 ppc_slb_t *slb;
832 target_ulong pageaddr;
833 int segment_bits;
835 LOG_MMU("Check SLBs\n");
836 slb = slb_lookup(env, eaddr);
837 if (!slb) {
838 return -5;
841 if (slb->vsid & SLB_VSID_B) {
842 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
843 segment_bits = 40;
844 } else {
845 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
846 segment_bits = 28;
849 target_page_bits = (slb->vsid & SLB_VSID_L)
850 ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
851 ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
852 : (slb->vsid & SLB_VSID_KS));
853 ds = 0;
854 ctx->nx = !!(slb->vsid & SLB_VSID_N);
856 pageaddr = eaddr & ((1ULL << segment_bits)
857 - (1ULL << target_page_bits));
858 if (slb->vsid & SLB_VSID_B) {
859 hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
860 } else {
861 hash = vsid ^ (pageaddr >> target_page_bits);
863 /* Only 5 bits of the page index are used in the AVPN */
864 ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
865 ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
866 } else
867 #endif /* defined(TARGET_PPC64) */
869 target_ulong sr, pgidx;
871 sr = env->sr[eaddr >> 28];
872 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
873 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
874 ds = sr & 0x80000000 ? 1 : 0;
875 ctx->nx = sr & 0x10000000 ? 1 : 0;
876 vsid = sr & 0x00FFFFFF;
877 target_page_bits = TARGET_PAGE_BITS;
878 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
879 TARGET_FMT_lx " lr=" TARGET_FMT_lx
880 " ir=%d dr=%d pr=%d %d t=%d\n",
881 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
882 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
883 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
884 hash = vsid ^ pgidx;
885 ctx->ptem = (vsid << 7) | (pgidx >> 10);
887 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
888 ctx->key, ds, ctx->nx, vsid);
889 ret = -1;
890 if (!ds) {
891 /* Check if instruction fetch is allowed, if needed */
892 if (type != ACCESS_CODE || ctx->nx == 0) {
893 /* Page address translation */
894 LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
895 " hash " TARGET_FMT_plx "\n",
896 env->htab_base, env->htab_mask, hash);
897 ctx->hash[0] = hash;
898 ctx->hash[1] = ~hash;
900 /* Initialize real address with an invalid value */
901 ctx->raddr = (target_phys_addr_t)-1ULL;
902 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
903 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
904 /* Software TLB search */
905 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
906 } else {
907 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
908 " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
909 " hash=" TARGET_FMT_plx "\n",
910 env->htab_base, env->htab_mask, vsid, ctx->ptem,
911 ctx->hash[0]);
912 /* Primary table lookup */
913 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
914 if (ret < 0) {
915 /* Secondary table lookup */
916 if (eaddr != 0xEFFFFFFF)
917 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
918 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
919 " hash=" TARGET_FMT_plx "\n", env->htab_base,
920 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
921 ret2 = find_pte(env, ctx, 1, rw, type,
922 target_page_bits);
923 if (ret2 != -1)
924 ret = ret2;
927 #if defined (DUMP_PAGE_TABLES)
928 if (qemu_log_enabled()) {
929 target_phys_addr_t curaddr;
930 uint32_t a0, a1, a2, a3;
931 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
932 "\n", sdr, mask + 0x80);
933 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
934 curaddr += 16) {
935 a0 = ldl_phys(curaddr);
936 a1 = ldl_phys(curaddr + 4);
937 a2 = ldl_phys(curaddr + 8);
938 a3 = ldl_phys(curaddr + 12);
939 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
940 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
941 curaddr, a0, a1, a2, a3);
945 #endif
946 } else {
947 LOG_MMU("No access allowed\n");
948 ret = -3;
950 } else {
951 target_ulong sr;
952 LOG_MMU("direct store...\n");
953 /* Direct-store segment : absolutely *BUGGY* for now */
955 /* Direct-store implies a 32-bit MMU.
956 * Check the Segment Register's bus unit ID (BUID).
958 sr = env->sr[eaddr >> 28];
959 if ((sr & 0x1FF00000) >> 20 == 0x07f) {
960 /* Memory-forced I/O controller interface access */
961 /* If T=1 and BUID=x'07F', the 601 performs a memory access
962 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
964 ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
965 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
966 return 0;
969 switch (type) {
970 case ACCESS_INT:
971 /* Integer load/store : only access allowed */
972 break;
973 case ACCESS_CODE:
974 /* No code fetch is allowed in direct-store areas */
975 return -4;
976 case ACCESS_FLOAT:
977 /* Floating point load/store */
978 return -4;
979 case ACCESS_RES:
980 /* lwarx, ldarx or srwcx. */
981 return -4;
982 case ACCESS_CACHE:
983 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
984 /* Should make the instruction do no-op.
985 * As it already do no-op, it's quite easy :-)
987 ctx->raddr = eaddr;
988 return 0;
989 case ACCESS_EXT:
990 /* eciwx or ecowx */
991 return -4;
992 default:
993 qemu_log("ERROR: instruction should not need "
994 "address translation\n");
995 return -4;
997 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
998 ctx->raddr = eaddr;
999 ret = 2;
1000 } else {
1001 ret = -2;
1005 return ret;
1008 /* Generic TLB check function for embedded PowerPC implementations */
1009 int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
1010 target_phys_addr_t *raddrp,
1011 target_ulong address, uint32_t pid, int ext,
1012 int i)
1014 target_ulong mask;
1016 /* Check valid flag */
1017 if (!(tlb->prot & PAGE_VALID)) {
1018 return -1;
1020 mask = ~(tlb->size - 1);
1021 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1022 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1023 mask, (uint32_t)tlb->PID, tlb->prot);
1024 /* Check PID */
1025 if (tlb->PID != 0 && tlb->PID != pid)
1026 return -1;
1027 /* Check effective address */
1028 if ((address & mask) != tlb->EPN)
1029 return -1;
1030 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1031 #if (TARGET_PHYS_ADDR_BITS >= 36)
1032 if (ext) {
1033 /* Extend the physical address to 36 bits */
1034 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1036 #endif
1038 return 0;
1041 /* Generic TLB search function for PowerPC embedded implementations */
1042 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1044 ppcemb_tlb_t *tlb;
1045 target_phys_addr_t raddr;
1046 int i, ret;
1048 /* Default return value is no match */
1049 ret = -1;
1050 for (i = 0; i < env->nb_tlb; i++) {
1051 tlb = &env->tlb.tlbe[i];
1052 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1053 ret = i;
1054 break;
1058 return ret;
1061 /* Helpers specific to PowerPC 40x implementations */
1062 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1064 ppcemb_tlb_t *tlb;
1065 int i;
1067 for (i = 0; i < env->nb_tlb; i++) {
1068 tlb = &env->tlb.tlbe[i];
1069 tlb->prot &= ~PAGE_VALID;
1071 tlb_flush(env, 1);
1074 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1075 target_ulong eaddr, uint32_t pid)
1077 #if !defined(FLUSH_ALL_TLBS)
1078 ppcemb_tlb_t *tlb;
1079 target_phys_addr_t raddr;
1080 target_ulong page, end;
1081 int i;
1083 for (i = 0; i < env->nb_tlb; i++) {
1084 tlb = &env->tlb.tlbe[i];
1085 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1086 end = tlb->EPN + tlb->size;
1087 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1088 tlb_flush_page(env, page);
1089 tlb->prot &= ~PAGE_VALID;
1090 break;
1093 #else
1094 ppc4xx_tlb_invalidate_all(env);
1095 #endif
1098 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1099 target_ulong address, int rw, int access_type)
1101 ppcemb_tlb_t *tlb;
1102 target_phys_addr_t raddr;
1103 int i, ret, zsel, zpr, pr;
1105 ret = -1;
1106 raddr = (target_phys_addr_t)-1ULL;
1107 pr = msr_pr;
1108 for (i = 0; i < env->nb_tlb; i++) {
1109 tlb = &env->tlb.tlbe[i];
1110 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1111 env->spr[SPR_40x_PID], 0, i) < 0)
1112 continue;
1113 zsel = (tlb->attr >> 4) & 0xF;
1114 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1115 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1116 __func__, i, zsel, zpr, rw, tlb->attr);
1117 /* Check execute enable bit */
1118 switch (zpr) {
1119 case 0x2:
1120 if (pr != 0)
1121 goto check_perms;
1122 /* No break here */
1123 case 0x3:
1124 /* All accesses granted */
1125 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1126 ret = 0;
1127 break;
1128 case 0x0:
1129 if (pr != 0) {
1130 /* Raise Zone protection fault. */
1131 env->spr[SPR_40x_ESR] = 1 << 22;
1132 ctx->prot = 0;
1133 ret = -2;
1134 break;
1136 /* No break here */
1137 case 0x1:
1138 check_perms:
1139 /* Check from TLB entry */
1140 ctx->prot = tlb->prot;
1141 ret = check_prot(ctx->prot, rw, access_type);
1142 if (ret == -2)
1143 env->spr[SPR_40x_ESR] = 0;
1144 break;
1146 if (ret >= 0) {
1147 ctx->raddr = raddr;
1148 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1149 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1150 ret);
1151 return 0;
1154 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1155 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1157 return ret;
1160 void store_40x_sler (CPUPPCState *env, uint32_t val)
1162 /* XXX: TO BE FIXED */
1163 if (val != 0x00000000) {
1164 cpu_abort(env, "Little-endian regions are not supported by now\n");
1166 env->spr[SPR_405_SLER] = val;
1169 static inline int mmubooke_check_tlb (CPUState *env, ppcemb_tlb_t *tlb,
1170 target_phys_addr_t *raddr, int *prot,
1171 target_ulong address, int rw,
1172 int access_type, int i)
1174 int ret, _prot;
1176 if (ppcemb_tlb_check(env, tlb, raddr, address,
1177 env->spr[SPR_BOOKE_PID],
1178 !env->nb_pids, i) >= 0) {
1179 goto found_tlb;
1182 if (env->spr[SPR_BOOKE_PID1] &&
1183 ppcemb_tlb_check(env, tlb, raddr, address,
1184 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1185 goto found_tlb;
1188 if (env->spr[SPR_BOOKE_PID2] &&
1189 ppcemb_tlb_check(env, tlb, raddr, address,
1190 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1191 goto found_tlb;
1194 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1195 return -1;
1197 found_tlb:
1199 if (msr_pr != 0) {
1200 _prot = tlb->prot & 0xF;
1201 } else {
1202 _prot = (tlb->prot >> 4) & 0xF;
1205 /* Check the address space */
1206 if (access_type == ACCESS_CODE) {
1207 if (msr_ir != (tlb->attr & 1)) {
1208 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1209 return -1;
1212 *prot = _prot;
1213 if (_prot & PAGE_EXEC) {
1214 LOG_SWTLB("%s: good TLB!\n", __func__);
1215 return 0;
1218 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1219 ret = -3;
1220 } else {
1221 if (msr_dr != (tlb->attr & 1)) {
1222 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1223 return -1;
1226 *prot = _prot;
1227 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1228 LOG_SWTLB("%s: found TLB!\n", __func__);
1229 return 0;
1232 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1233 ret = -2;
1236 return ret;
1239 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1240 target_ulong address, int rw,
1241 int access_type)
1243 ppcemb_tlb_t *tlb;
1244 target_phys_addr_t raddr;
1245 int i, ret;
1247 ret = -1;
1248 raddr = (target_phys_addr_t)-1ULL;
1249 for (i = 0; i < env->nb_tlb; i++) {
1250 tlb = &env->tlb.tlbe[i];
1251 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1252 access_type, i);
1253 if (!ret) {
1254 break;
1258 if (ret >= 0) {
1259 ctx->raddr = raddr;
1260 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1261 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1262 ret);
1263 } else {
1264 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1265 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1268 return ret;
1271 void booke206_flush_tlb(CPUState *env, int flags, const int check_iprot)
1273 int tlb_size;
1274 int i, j;
1275 ppcmas_tlb_t *tlb = env->tlb.tlbm;
1277 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1278 if (flags & (1 << i)) {
1279 tlb_size = booke206_tlb_size(env, i);
1280 for (j = 0; j < tlb_size; j++) {
1281 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
1282 tlb[j].mas1 &= ~MAS1_VALID;
1286 tlb += booke206_tlb_size(env, i);
1289 tlb_flush(env, 1);
1292 target_phys_addr_t booke206_tlb_to_page_size(CPUState *env, ppcmas_tlb_t *tlb)
1294 uint32_t tlbncfg;
1295 int tlbn = booke206_tlbm_to_tlbn(env, tlb);
1296 int tlbm_size;
1298 tlbncfg = env->spr[SPR_BOOKE_TLB0CFG + tlbn];
1300 if (tlbncfg & TLBnCFG_AVAIL) {
1301 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1302 } else {
1303 tlbm_size = (tlbncfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT;
1304 tlbm_size <<= 1;
1307 return 1024ULL << tlbm_size;
1310 /* TLB check function for MAS based SoftTLBs */
1311 int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
1312 target_phys_addr_t *raddrp,
1313 target_ulong address, uint32_t pid)
1315 target_ulong mask;
1316 uint32_t tlb_pid;
1318 /* Check valid flag */
1319 if (!(tlb->mas1 & MAS1_VALID)) {
1320 return -1;
1323 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1324 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
1325 PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
1326 __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
1327 tlb->mas8);
1329 /* Check PID */
1330 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
1331 if (tlb_pid != 0 && tlb_pid != pid) {
1332 return -1;
1335 /* Check effective address */
1336 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
1337 return -1;
1339 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
1341 return 0;
1344 static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
1345 target_phys_addr_t *raddr, int *prot,
1346 target_ulong address, int rw,
1347 int access_type)
1349 int ret;
1350 int _prot = 0;
1352 if (ppcmas_tlb_check(env, tlb, raddr, address,
1353 env->spr[SPR_BOOKE_PID]) >= 0) {
1354 goto found_tlb;
1357 if (env->spr[SPR_BOOKE_PID1] &&
1358 ppcmas_tlb_check(env, tlb, raddr, address,
1359 env->spr[SPR_BOOKE_PID1]) >= 0) {
1360 goto found_tlb;
1363 if (env->spr[SPR_BOOKE_PID2] &&
1364 ppcmas_tlb_check(env, tlb, raddr, address,
1365 env->spr[SPR_BOOKE_PID2]) >= 0) {
1366 goto found_tlb;
1369 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1370 return -1;
1372 found_tlb:
1374 if (msr_pr != 0) {
1375 if (tlb->mas7_3 & MAS3_UR) {
1376 _prot |= PAGE_READ;
1378 if (tlb->mas7_3 & MAS3_UW) {
1379 _prot |= PAGE_WRITE;
1381 if (tlb->mas7_3 & MAS3_UX) {
1382 _prot |= PAGE_EXEC;
1384 } else {
1385 if (tlb->mas7_3 & MAS3_SR) {
1386 _prot |= PAGE_READ;
1388 if (tlb->mas7_3 & MAS3_SW) {
1389 _prot |= PAGE_WRITE;
1391 if (tlb->mas7_3 & MAS3_SX) {
1392 _prot |= PAGE_EXEC;
1396 /* Check the address space and permissions */
1397 if (access_type == ACCESS_CODE) {
1398 if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1399 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1400 return -1;
1403 *prot = _prot;
1404 if (_prot & PAGE_EXEC) {
1405 LOG_SWTLB("%s: good TLB!\n", __func__);
1406 return 0;
1409 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1410 ret = -3;
1411 } else {
1412 if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1413 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1414 return -1;
1417 *prot = _prot;
1418 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1419 LOG_SWTLB("%s: found TLB!\n", __func__);
1420 return 0;
1423 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1424 ret = -2;
1427 return ret;
1430 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1431 target_ulong address, int rw,
1432 int access_type)
1434 ppcmas_tlb_t *tlb;
1435 target_phys_addr_t raddr;
1436 int i, j, ret;
1438 ret = -1;
1439 raddr = (target_phys_addr_t)-1ULL;
1441 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1442 int ways = booke206_tlb_ways(env, i);
1444 for (j = 0; j < ways; j++) {
1445 tlb = booke206_get_tlbm(env, i, address, j);
1446 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1447 rw, access_type);
1448 if (ret != -1) {
1449 goto found_tlb;
1454 found_tlb:
1456 if (ret >= 0) {
1457 ctx->raddr = raddr;
1458 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1459 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1460 ret);
1461 } else {
1462 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1463 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1466 return ret;
1469 static const char *book3e_tsize_to_str[32] = {
1470 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1471 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1472 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1473 "1T", "2T"
1476 static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1477 CPUState *env, int tlbn, int offset,
1478 int tlbsize)
1480 ppcmas_tlb_t *entry;
1481 int i;
1483 cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1484 cpu_fprintf(f, "Effective Physical Size TID TS SRWX URWX WIMGE U0123\n");
1486 entry = &env->tlb.tlbm[offset];
1487 for (i = 0; i < tlbsize; i++, entry++) {
1488 target_phys_addr_t ea, pa, size;
1489 int tsize;
1491 if (!(entry->mas1 & MAS1_VALID)) {
1492 continue;
1495 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1496 size = 1024ULL << tsize;
1497 ea = entry->mas2 & ~(size - 1);
1498 pa = entry->mas7_3 & ~(size - 1);
1500 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",
1501 (uint64_t)ea, (uint64_t)pa,
1502 book3e_tsize_to_str[tsize],
1503 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1504 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1505 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1506 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1507 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1508 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1509 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1510 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1511 entry->mas2 & MAS2_W ? 'W' : '-',
1512 entry->mas2 & MAS2_I ? 'I' : '-',
1513 entry->mas2 & MAS2_M ? 'M' : '-',
1514 entry->mas2 & MAS2_G ? 'G' : '-',
1515 entry->mas2 & MAS2_E ? 'E' : '-',
1516 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1517 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1518 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1519 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1523 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1524 CPUState *env)
1526 int offset = 0;
1527 int i;
1529 if (kvm_enabled() && !env->kvm_sw_tlb) {
1530 cpu_fprintf(f, "Cannot access KVM TLB\n");
1531 return;
1534 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1535 int size = booke206_tlb_size(env, i);
1537 if (size == 0) {
1538 continue;
1541 mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1542 offset += size;
1546 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
1548 switch (env->mmu_model) {
1549 case POWERPC_MMU_BOOKE206:
1550 mmubooke206_dump_mmu(f, cpu_fprintf, env);
1551 break;
1552 default:
1553 cpu_fprintf(f, "%s: unimplemented\n", __func__);
1557 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1558 target_ulong eaddr, int rw)
1560 int in_plb, ret;
1562 ctx->raddr = eaddr;
1563 ctx->prot = PAGE_READ | PAGE_EXEC;
1564 ret = 0;
1565 switch (env->mmu_model) {
1566 case POWERPC_MMU_32B:
1567 case POWERPC_MMU_601:
1568 case POWERPC_MMU_SOFT_6xx:
1569 case POWERPC_MMU_SOFT_74xx:
1570 case POWERPC_MMU_SOFT_4xx:
1571 case POWERPC_MMU_REAL:
1572 case POWERPC_MMU_BOOKE:
1573 ctx->prot |= PAGE_WRITE;
1574 break;
1575 #if defined(TARGET_PPC64)
1576 case POWERPC_MMU_620:
1577 case POWERPC_MMU_64B:
1578 case POWERPC_MMU_2_06:
1579 /* Real address are 60 bits long */
1580 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1581 ctx->prot |= PAGE_WRITE;
1582 break;
1583 #endif
1584 case POWERPC_MMU_SOFT_4xx_Z:
1585 if (unlikely(msr_pe != 0)) {
1586 /* 403 family add some particular protections,
1587 * using PBL/PBU registers for accesses with no translation.
1589 in_plb =
1590 /* Check PLB validity */
1591 (env->pb[0] < env->pb[1] &&
1592 /* and address in plb area */
1593 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1594 (env->pb[2] < env->pb[3] &&
1595 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1596 if (in_plb ^ msr_px) {
1597 /* Access in protected area */
1598 if (rw == 1) {
1599 /* Access is not allowed */
1600 ret = -2;
1602 } else {
1603 /* Read-write access is allowed */
1604 ctx->prot |= PAGE_WRITE;
1607 break;
1608 case POWERPC_MMU_MPC8xx:
1609 /* XXX: TODO */
1610 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1611 break;
1612 case POWERPC_MMU_BOOKE206:
1613 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1614 break;
1615 default:
1616 cpu_abort(env, "Unknown or invalid MMU model\n");
1617 return -1;
1620 return ret;
1623 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1624 int rw, int access_type)
1626 int ret;
1628 #if 0
1629 qemu_log("%s\n", __func__);
1630 #endif
1631 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1632 (access_type != ACCESS_CODE && msr_dr == 0)) {
1633 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1634 /* The BookE MMU always performs address translation. The
1635 IS and DS bits only affect the address space. */
1636 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1637 rw, access_type);
1638 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1639 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1640 access_type);
1641 } else {
1642 /* No address translation. */
1643 ret = check_physical(env, ctx, eaddr, rw);
1645 } else {
1646 ret = -1;
1647 switch (env->mmu_model) {
1648 case POWERPC_MMU_32B:
1649 case POWERPC_MMU_601:
1650 case POWERPC_MMU_SOFT_6xx:
1651 case POWERPC_MMU_SOFT_74xx:
1652 /* Try to find a BAT */
1653 if (env->nb_BATs != 0)
1654 ret = get_bat(env, ctx, eaddr, rw, access_type);
1655 #if defined(TARGET_PPC64)
1656 case POWERPC_MMU_620:
1657 case POWERPC_MMU_64B:
1658 case POWERPC_MMU_2_06:
1659 #endif
1660 if (ret < 0) {
1661 /* We didn't match any BAT entry or don't have BATs */
1662 ret = get_segment(env, ctx, eaddr, rw, access_type);
1664 break;
1665 case POWERPC_MMU_SOFT_4xx:
1666 case POWERPC_MMU_SOFT_4xx_Z:
1667 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1668 rw, access_type);
1669 break;
1670 case POWERPC_MMU_BOOKE:
1671 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1672 rw, access_type);
1673 break;
1674 case POWERPC_MMU_BOOKE206:
1675 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1676 access_type);
1677 break;
1678 case POWERPC_MMU_MPC8xx:
1679 /* XXX: TODO */
1680 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1681 break;
1682 case POWERPC_MMU_REAL:
1683 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1684 return -1;
1685 default:
1686 cpu_abort(env, "Unknown or invalid MMU model\n");
1687 return -1;
1690 #if 0
1691 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1692 __func__, eaddr, ret, ctx->raddr);
1693 #endif
1695 return ret;
1698 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1700 mmu_ctx_t ctx;
1702 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1703 return -1;
1705 return ctx.raddr & TARGET_PAGE_MASK;
1708 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1709 int rw)
1711 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1712 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1713 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1714 env->spr[SPR_BOOKE_MAS3] = 0;
1715 env->spr[SPR_BOOKE_MAS6] = 0;
1716 env->spr[SPR_BOOKE_MAS7] = 0;
1718 /* AS */
1719 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1720 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1721 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1724 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1725 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1727 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1728 case MAS4_TIDSELD_PID0:
1729 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1730 break;
1731 case MAS4_TIDSELD_PID1:
1732 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1733 break;
1734 case MAS4_TIDSELD_PID2:
1735 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1736 break;
1739 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1741 /* next victim logic */
1742 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1743 env->last_way++;
1744 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1745 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1748 /* Perform address translation */
1749 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1750 int mmu_idx)
1752 mmu_ctx_t ctx;
1753 int access_type;
1754 int ret = 0;
1756 if (rw == 2) {
1757 /* code access */
1758 rw = 0;
1759 access_type = ACCESS_CODE;
1760 } else {
1761 /* data access */
1762 access_type = env->access_type;
1764 ret = get_physical_address(env, &ctx, address, rw, access_type);
1765 if (ret == 0) {
1766 tlb_set_page(env, address & TARGET_PAGE_MASK,
1767 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1768 mmu_idx, TARGET_PAGE_SIZE);
1769 ret = 0;
1770 } else if (ret < 0) {
1771 LOG_MMU_STATE(env);
1772 if (access_type == ACCESS_CODE) {
1773 switch (ret) {
1774 case -1:
1775 /* No matches in page tables or TLB */
1776 switch (env->mmu_model) {
1777 case POWERPC_MMU_SOFT_6xx:
1778 env->exception_index = POWERPC_EXCP_IFTLB;
1779 env->error_code = 1 << 18;
1780 env->spr[SPR_IMISS] = address;
1781 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1782 goto tlb_miss;
1783 case POWERPC_MMU_SOFT_74xx:
1784 env->exception_index = POWERPC_EXCP_IFTLB;
1785 goto tlb_miss_74xx;
1786 case POWERPC_MMU_SOFT_4xx:
1787 case POWERPC_MMU_SOFT_4xx_Z:
1788 env->exception_index = POWERPC_EXCP_ITLB;
1789 env->error_code = 0;
1790 env->spr[SPR_40x_DEAR] = address;
1791 env->spr[SPR_40x_ESR] = 0x00000000;
1792 break;
1793 case POWERPC_MMU_32B:
1794 case POWERPC_MMU_601:
1795 #if defined(TARGET_PPC64)
1796 case POWERPC_MMU_620:
1797 case POWERPC_MMU_64B:
1798 case POWERPC_MMU_2_06:
1799 #endif
1800 env->exception_index = POWERPC_EXCP_ISI;
1801 env->error_code = 0x40000000;
1802 break;
1803 case POWERPC_MMU_BOOKE206:
1804 booke206_update_mas_tlb_miss(env, address, rw);
1805 /* fall through */
1806 case POWERPC_MMU_BOOKE:
1807 env->exception_index = POWERPC_EXCP_ITLB;
1808 env->error_code = 0;
1809 env->spr[SPR_BOOKE_DEAR] = address;
1810 return -1;
1811 case POWERPC_MMU_MPC8xx:
1812 /* XXX: TODO */
1813 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1814 break;
1815 case POWERPC_MMU_REAL:
1816 cpu_abort(env, "PowerPC in real mode should never raise "
1817 "any MMU exceptions\n");
1818 return -1;
1819 default:
1820 cpu_abort(env, "Unknown or invalid MMU model\n");
1821 return -1;
1823 break;
1824 case -2:
1825 /* Access rights violation */
1826 env->exception_index = POWERPC_EXCP_ISI;
1827 env->error_code = 0x08000000;
1828 break;
1829 case -3:
1830 /* No execute protection violation */
1831 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1832 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1833 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1835 env->exception_index = POWERPC_EXCP_ISI;
1836 env->error_code = 0x10000000;
1837 break;
1838 case -4:
1839 /* Direct store exception */
1840 /* No code fetch is allowed in direct-store areas */
1841 env->exception_index = POWERPC_EXCP_ISI;
1842 env->error_code = 0x10000000;
1843 break;
1844 #if defined(TARGET_PPC64)
1845 case -5:
1846 /* No match in segment table */
1847 if (env->mmu_model == POWERPC_MMU_620) {
1848 env->exception_index = POWERPC_EXCP_ISI;
1849 /* XXX: this might be incorrect */
1850 env->error_code = 0x40000000;
1851 } else {
1852 env->exception_index = POWERPC_EXCP_ISEG;
1853 env->error_code = 0;
1855 break;
1856 #endif
1858 } else {
1859 switch (ret) {
1860 case -1:
1861 /* No matches in page tables or TLB */
1862 switch (env->mmu_model) {
1863 case POWERPC_MMU_SOFT_6xx:
1864 if (rw == 1) {
1865 env->exception_index = POWERPC_EXCP_DSTLB;
1866 env->error_code = 1 << 16;
1867 } else {
1868 env->exception_index = POWERPC_EXCP_DLTLB;
1869 env->error_code = 0;
1871 env->spr[SPR_DMISS] = address;
1872 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1873 tlb_miss:
1874 env->error_code |= ctx.key << 19;
1875 env->spr[SPR_HASH1] = env->htab_base +
1876 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1877 env->spr[SPR_HASH2] = env->htab_base +
1878 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1879 break;
1880 case POWERPC_MMU_SOFT_74xx:
1881 if (rw == 1) {
1882 env->exception_index = POWERPC_EXCP_DSTLB;
1883 } else {
1884 env->exception_index = POWERPC_EXCP_DLTLB;
1886 tlb_miss_74xx:
1887 /* Implement LRU algorithm */
1888 env->error_code = ctx.key << 19;
1889 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1890 ((env->last_way + 1) & (env->nb_ways - 1));
1891 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1892 break;
1893 case POWERPC_MMU_SOFT_4xx:
1894 case POWERPC_MMU_SOFT_4xx_Z:
1895 env->exception_index = POWERPC_EXCP_DTLB;
1896 env->error_code = 0;
1897 env->spr[SPR_40x_DEAR] = address;
1898 if (rw)
1899 env->spr[SPR_40x_ESR] = 0x00800000;
1900 else
1901 env->spr[SPR_40x_ESR] = 0x00000000;
1902 break;
1903 case POWERPC_MMU_32B:
1904 case POWERPC_MMU_601:
1905 #if defined(TARGET_PPC64)
1906 case POWERPC_MMU_620:
1907 case POWERPC_MMU_64B:
1908 case POWERPC_MMU_2_06:
1909 #endif
1910 env->exception_index = POWERPC_EXCP_DSI;
1911 env->error_code = 0;
1912 env->spr[SPR_DAR] = address;
1913 if (rw == 1)
1914 env->spr[SPR_DSISR] = 0x42000000;
1915 else
1916 env->spr[SPR_DSISR] = 0x40000000;
1917 break;
1918 case POWERPC_MMU_MPC8xx:
1919 /* XXX: TODO */
1920 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1921 break;
1922 case POWERPC_MMU_BOOKE206:
1923 booke206_update_mas_tlb_miss(env, address, rw);
1924 /* fall through */
1925 case POWERPC_MMU_BOOKE:
1926 env->exception_index = POWERPC_EXCP_DTLB;
1927 env->error_code = 0;
1928 env->spr[SPR_BOOKE_DEAR] = address;
1929 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1930 return -1;
1931 case POWERPC_MMU_REAL:
1932 cpu_abort(env, "PowerPC in real mode should never raise "
1933 "any MMU exceptions\n");
1934 return -1;
1935 default:
1936 cpu_abort(env, "Unknown or invalid MMU model\n");
1937 return -1;
1939 break;
1940 case -2:
1941 /* Access rights violation */
1942 env->exception_index = POWERPC_EXCP_DSI;
1943 env->error_code = 0;
1944 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1945 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1946 env->spr[SPR_40x_DEAR] = address;
1947 if (rw) {
1948 env->spr[SPR_40x_ESR] |= 0x00800000;
1950 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1951 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1952 env->spr[SPR_BOOKE_DEAR] = address;
1953 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1954 } else {
1955 env->spr[SPR_DAR] = address;
1956 if (rw == 1) {
1957 env->spr[SPR_DSISR] = 0x0A000000;
1958 } else {
1959 env->spr[SPR_DSISR] = 0x08000000;
1962 break;
1963 case -4:
1964 /* Direct store exception */
1965 switch (access_type) {
1966 case ACCESS_FLOAT:
1967 /* Floating point load/store */
1968 env->exception_index = POWERPC_EXCP_ALIGN;
1969 env->error_code = POWERPC_EXCP_ALIGN_FP;
1970 env->spr[SPR_DAR] = address;
1971 break;
1972 case ACCESS_RES:
1973 /* lwarx, ldarx or stwcx. */
1974 env->exception_index = POWERPC_EXCP_DSI;
1975 env->error_code = 0;
1976 env->spr[SPR_DAR] = address;
1977 if (rw == 1)
1978 env->spr[SPR_DSISR] = 0x06000000;
1979 else
1980 env->spr[SPR_DSISR] = 0x04000000;
1981 break;
1982 case ACCESS_EXT:
1983 /* eciwx or ecowx */
1984 env->exception_index = POWERPC_EXCP_DSI;
1985 env->error_code = 0;
1986 env->spr[SPR_DAR] = address;
1987 if (rw == 1)
1988 env->spr[SPR_DSISR] = 0x06100000;
1989 else
1990 env->spr[SPR_DSISR] = 0x04100000;
1991 break;
1992 default:
1993 printf("DSI: invalid exception (%d)\n", ret);
1994 env->exception_index = POWERPC_EXCP_PROGRAM;
1995 env->error_code =
1996 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1997 env->spr[SPR_DAR] = address;
1998 break;
2000 break;
2001 #if defined(TARGET_PPC64)
2002 case -5:
2003 /* No match in segment table */
2004 if (env->mmu_model == POWERPC_MMU_620) {
2005 env->exception_index = POWERPC_EXCP_DSI;
2006 env->error_code = 0;
2007 env->spr[SPR_DAR] = address;
2008 /* XXX: this might be incorrect */
2009 if (rw == 1)
2010 env->spr[SPR_DSISR] = 0x42000000;
2011 else
2012 env->spr[SPR_DSISR] = 0x40000000;
2013 } else {
2014 env->exception_index = POWERPC_EXCP_DSEG;
2015 env->error_code = 0;
2016 env->spr[SPR_DAR] = address;
2018 break;
2019 #endif
2022 #if 0
2023 printf("%s: set exception to %d %02x\n", __func__,
2024 env->exception, env->error_code);
2025 #endif
2026 ret = 1;
2029 return ret;
2032 /*****************************************************************************/
2033 /* BATs management */
2034 #if !defined(FLUSH_ALL_TLBS)
2035 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2036 target_ulong mask)
2038 target_ulong base, end, page;
2040 base = BATu & ~0x0001FFFF;
2041 end = base + mask + 0x00020000;
2042 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2043 TARGET_FMT_lx ")\n", base, end, mask);
2044 for (page = base; page != end; page += TARGET_PAGE_SIZE)
2045 tlb_flush_page(env, page);
2046 LOG_BATS("Flush done\n");
2048 #endif
2050 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2051 target_ulong value)
2053 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2054 nr, ul == 0 ? 'u' : 'l', value, env->nip);
2057 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2059 target_ulong mask;
2061 dump_store_bat(env, 'I', 0, nr, value);
2062 if (env->IBAT[0][nr] != value) {
2063 mask = (value << 15) & 0x0FFE0000UL;
2064 #if !defined(FLUSH_ALL_TLBS)
2065 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2066 #endif
2067 /* When storing valid upper BAT, mask BEPI and BRPN
2068 * and invalidate all TLBs covered by this BAT
2070 mask = (value << 15) & 0x0FFE0000UL;
2071 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2072 (value & ~0x0001FFFFUL & ~mask);
2073 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2074 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2075 #if !defined(FLUSH_ALL_TLBS)
2076 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2077 #else
2078 tlb_flush(env, 1);
2079 #endif
2083 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2085 dump_store_bat(env, 'I', 1, nr, value);
2086 env->IBAT[1][nr] = value;
2089 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2091 target_ulong mask;
2093 dump_store_bat(env, 'D', 0, nr, value);
2094 if (env->DBAT[0][nr] != value) {
2095 /* When storing valid upper BAT, mask BEPI and BRPN
2096 * and invalidate all TLBs covered by this BAT
2098 mask = (value << 15) & 0x0FFE0000UL;
2099 #if !defined(FLUSH_ALL_TLBS)
2100 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2101 #endif
2102 mask = (value << 15) & 0x0FFE0000UL;
2103 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2104 (value & ~0x0001FFFFUL & ~mask);
2105 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2106 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2107 #if !defined(FLUSH_ALL_TLBS)
2108 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2109 #else
2110 tlb_flush(env, 1);
2111 #endif
2115 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2117 dump_store_bat(env, 'D', 1, nr, value);
2118 env->DBAT[1][nr] = value;
2121 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2123 target_ulong mask;
2124 #if defined(FLUSH_ALL_TLBS)
2125 int do_inval;
2126 #endif
2128 dump_store_bat(env, 'I', 0, nr, value);
2129 if (env->IBAT[0][nr] != value) {
2130 #if defined(FLUSH_ALL_TLBS)
2131 do_inval = 0;
2132 #endif
2133 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2134 if (env->IBAT[1][nr] & 0x40) {
2135 /* Invalidate BAT only if it is valid */
2136 #if !defined(FLUSH_ALL_TLBS)
2137 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2138 #else
2139 do_inval = 1;
2140 #endif
2142 /* When storing valid upper BAT, mask BEPI and BRPN
2143 * and invalidate all TLBs covered by this BAT
2145 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2146 (value & ~0x0001FFFFUL & ~mask);
2147 env->DBAT[0][nr] = env->IBAT[0][nr];
2148 if (env->IBAT[1][nr] & 0x40) {
2149 #if !defined(FLUSH_ALL_TLBS)
2150 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2151 #else
2152 do_inval = 1;
2153 #endif
2155 #if defined(FLUSH_ALL_TLBS)
2156 if (do_inval)
2157 tlb_flush(env, 1);
2158 #endif
2162 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2164 target_ulong mask;
2165 #if defined(FLUSH_ALL_TLBS)
2166 int do_inval;
2167 #endif
2169 dump_store_bat(env, 'I', 1, nr, value);
2170 if (env->IBAT[1][nr] != value) {
2171 #if defined(FLUSH_ALL_TLBS)
2172 do_inval = 0;
2173 #endif
2174 if (env->IBAT[1][nr] & 0x40) {
2175 #if !defined(FLUSH_ALL_TLBS)
2176 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2177 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2178 #else
2179 do_inval = 1;
2180 #endif
2182 if (value & 0x40) {
2183 #if !defined(FLUSH_ALL_TLBS)
2184 mask = (value << 17) & 0x0FFE0000UL;
2185 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2186 #else
2187 do_inval = 1;
2188 #endif
2190 env->IBAT[1][nr] = value;
2191 env->DBAT[1][nr] = value;
2192 #if defined(FLUSH_ALL_TLBS)
2193 if (do_inval)
2194 tlb_flush(env, 1);
2195 #endif
2199 /*****************************************************************************/
2200 /* TLB management */
2201 void ppc_tlb_invalidate_all (CPUPPCState *env)
2203 switch (env->mmu_model) {
2204 case POWERPC_MMU_SOFT_6xx:
2205 case POWERPC_MMU_SOFT_74xx:
2206 ppc6xx_tlb_invalidate_all(env);
2207 break;
2208 case POWERPC_MMU_SOFT_4xx:
2209 case POWERPC_MMU_SOFT_4xx_Z:
2210 ppc4xx_tlb_invalidate_all(env);
2211 break;
2212 case POWERPC_MMU_REAL:
2213 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2214 break;
2215 case POWERPC_MMU_MPC8xx:
2216 /* XXX: TODO */
2217 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2218 break;
2219 case POWERPC_MMU_BOOKE:
2220 tlb_flush(env, 1);
2221 break;
2222 case POWERPC_MMU_BOOKE206:
2223 booke206_flush_tlb(env, -1, 0);
2224 break;
2225 case POWERPC_MMU_32B:
2226 case POWERPC_MMU_601:
2227 #if defined(TARGET_PPC64)
2228 case POWERPC_MMU_620:
2229 case POWERPC_MMU_64B:
2230 case POWERPC_MMU_2_06:
2231 #endif /* defined(TARGET_PPC64) */
2232 tlb_flush(env, 1);
2233 break;
2234 default:
2235 /* XXX: TODO */
2236 cpu_abort(env, "Unknown MMU model\n");
2237 break;
2241 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2243 #if !defined(FLUSH_ALL_TLBS)
2244 addr &= TARGET_PAGE_MASK;
2245 switch (env->mmu_model) {
2246 case POWERPC_MMU_SOFT_6xx:
2247 case POWERPC_MMU_SOFT_74xx:
2248 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2249 if (env->id_tlbs == 1)
2250 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2251 break;
2252 case POWERPC_MMU_SOFT_4xx:
2253 case POWERPC_MMU_SOFT_4xx_Z:
2254 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2255 break;
2256 case POWERPC_MMU_REAL:
2257 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2258 break;
2259 case POWERPC_MMU_MPC8xx:
2260 /* XXX: TODO */
2261 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2262 break;
2263 case POWERPC_MMU_BOOKE:
2264 /* XXX: TODO */
2265 cpu_abort(env, "BookE MMU model is not implemented\n");
2266 break;
2267 case POWERPC_MMU_BOOKE206:
2268 /* XXX: TODO */
2269 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2270 break;
2271 case POWERPC_MMU_32B:
2272 case POWERPC_MMU_601:
2273 /* tlbie invalidate TLBs for all segments */
2274 addr &= ~((target_ulong)-1ULL << 28);
2275 /* XXX: this case should be optimized,
2276 * giving a mask to tlb_flush_page
2278 tlb_flush_page(env, addr | (0x0 << 28));
2279 tlb_flush_page(env, addr | (0x1 << 28));
2280 tlb_flush_page(env, addr | (0x2 << 28));
2281 tlb_flush_page(env, addr | (0x3 << 28));
2282 tlb_flush_page(env, addr | (0x4 << 28));
2283 tlb_flush_page(env, addr | (0x5 << 28));
2284 tlb_flush_page(env, addr | (0x6 << 28));
2285 tlb_flush_page(env, addr | (0x7 << 28));
2286 tlb_flush_page(env, addr | (0x8 << 28));
2287 tlb_flush_page(env, addr | (0x9 << 28));
2288 tlb_flush_page(env, addr | (0xA << 28));
2289 tlb_flush_page(env, addr | (0xB << 28));
2290 tlb_flush_page(env, addr | (0xC << 28));
2291 tlb_flush_page(env, addr | (0xD << 28));
2292 tlb_flush_page(env, addr | (0xE << 28));
2293 tlb_flush_page(env, addr | (0xF << 28));
2294 break;
2295 #if defined(TARGET_PPC64)
2296 case POWERPC_MMU_620:
2297 case POWERPC_MMU_64B:
2298 case POWERPC_MMU_2_06:
2299 /* tlbie invalidate TLBs for all segments */
2300 /* XXX: given the fact that there are too many segments to invalidate,
2301 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2302 * we just invalidate all TLBs
2304 tlb_flush(env, 1);
2305 break;
2306 #endif /* defined(TARGET_PPC64) */
2307 default:
2308 /* XXX: TODO */
2309 cpu_abort(env, "Unknown MMU model\n");
2310 break;
2312 #else
2313 ppc_tlb_invalidate_all(env);
2314 #endif
2317 /*****************************************************************************/
2318 /* Special registers manipulation */
2319 #if defined(TARGET_PPC64)
2320 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2322 if (env->asr != value) {
2323 env->asr = value;
2324 tlb_flush(env, 1);
2327 #endif
2329 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2331 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2332 if (env->spr[SPR_SDR1] != value) {
2333 env->spr[SPR_SDR1] = value;
2334 #if defined(TARGET_PPC64)
2335 if (env->mmu_model & POWERPC_MMU_64) {
2336 target_ulong htabsize = value & SDR_64_HTABSIZE;
2338 if (htabsize > 28) {
2339 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2340 " stored in SDR1\n", htabsize);
2341 htabsize = 28;
2343 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2344 env->htab_base = value & SDR_64_HTABORG;
2345 } else
2346 #endif /* defined(TARGET_PPC64) */
2348 /* FIXME: Should check for valid HTABMASK values */
2349 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2350 env->htab_base = value & SDR_32_HTABORG;
2352 tlb_flush(env, 1);
2356 #if defined(TARGET_PPC64)
2357 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2359 // XXX
2360 return 0;
2362 #endif
2364 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2366 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2367 srnum, value, env->sr[srnum]);
2368 #if defined(TARGET_PPC64)
2369 if (env->mmu_model & POWERPC_MMU_64) {
2370 uint64_t rb = 0, rs = 0;
2372 /* ESID = srnum */
2373 rb |= ((uint32_t)srnum & 0xf) << 28;
2374 /* Set the valid bit */
2375 rb |= 1 << 27;
2376 /* Index = ESID */
2377 rb |= (uint32_t)srnum;
2379 /* VSID = VSID */
2380 rs |= (value & 0xfffffff) << 12;
2381 /* flags = flags */
2382 rs |= ((value >> 27) & 0xf) << 8;
2384 ppc_store_slb(env, rb, rs);
2385 } else
2386 #endif
2387 if (env->sr[srnum] != value) {
2388 env->sr[srnum] = value;
2389 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2390 flusing the whole TLB. */
2391 #if !defined(FLUSH_ALL_TLBS) && 0
2393 target_ulong page, end;
2394 /* Invalidate 256 MB of virtual memory */
2395 page = (16 << 20) * srnum;
2396 end = page + (16 << 20);
2397 for (; page != end; page += TARGET_PAGE_SIZE)
2398 tlb_flush_page(env, page);
2400 #else
2401 tlb_flush(env, 1);
2402 #endif
2405 #endif /* !defined (CONFIG_USER_ONLY) */
2407 /* GDBstub can read and write MSR... */
2408 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2410 hreg_store_msr(env, value, 0);
2413 /*****************************************************************************/
2414 /* Exception processing */
2415 #if defined (CONFIG_USER_ONLY)
2416 void do_interrupt (CPUState *env)
2418 env->exception_index = POWERPC_EXCP_NONE;
2419 env->error_code = 0;
2422 void ppc_hw_interrupt (CPUState *env)
2424 env->exception_index = POWERPC_EXCP_NONE;
2425 env->error_code = 0;
2427 #else /* defined (CONFIG_USER_ONLY) */
2428 static inline void dump_syscall(CPUState *env)
2430 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2431 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2432 " nip=" TARGET_FMT_lx "\n",
2433 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2434 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2435 ppc_dump_gpr(env, 6), env->nip);
2438 /* Note that this function should be greatly optimized
2439 * when called with a constant excp, from ppc_hw_interrupt
2441 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2443 target_ulong msr, new_msr, vector;
2444 int srr0, srr1, asrr0, asrr1;
2445 int lpes0, lpes1, lev;
2447 if (0) {
2448 /* XXX: find a suitable condition to enable the hypervisor mode */
2449 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2450 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2451 } else {
2452 /* Those values ensure we won't enter the hypervisor mode */
2453 lpes0 = 0;
2454 lpes1 = 1;
2457 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2458 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2460 /* new srr1 value excluding must-be-zero bits */
2461 msr = env->msr & ~0x783f0000ULL;
2463 /* new interrupt handler msr */
2464 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2466 /* target registers */
2467 srr0 = SPR_SRR0;
2468 srr1 = SPR_SRR1;
2469 asrr0 = -1;
2470 asrr1 = -1;
2472 switch (excp) {
2473 case POWERPC_EXCP_NONE:
2474 /* Should never happen */
2475 return;
2476 case POWERPC_EXCP_CRITICAL: /* Critical input */
2477 switch (excp_model) {
2478 case POWERPC_EXCP_40x:
2479 srr0 = SPR_40x_SRR2;
2480 srr1 = SPR_40x_SRR3;
2481 break;
2482 case POWERPC_EXCP_BOOKE:
2483 srr0 = SPR_BOOKE_CSRR0;
2484 srr1 = SPR_BOOKE_CSRR1;
2485 break;
2486 case POWERPC_EXCP_G2:
2487 break;
2488 default:
2489 goto excp_invalid;
2491 goto store_next;
2492 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2493 if (msr_me == 0) {
2494 /* Machine check exception is not enabled.
2495 * Enter checkstop state.
2497 if (qemu_log_enabled()) {
2498 qemu_log("Machine check while not allowed. "
2499 "Entering checkstop state\n");
2500 } else {
2501 fprintf(stderr, "Machine check while not allowed. "
2502 "Entering checkstop state\n");
2504 env->halted = 1;
2505 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2507 if (0) {
2508 /* XXX: find a suitable condition to enable the hypervisor mode */
2509 new_msr |= (target_ulong)MSR_HVB;
2512 /* machine check exceptions don't have ME set */
2513 new_msr &= ~((target_ulong)1 << MSR_ME);
2515 /* XXX: should also have something loaded in DAR / DSISR */
2516 switch (excp_model) {
2517 case POWERPC_EXCP_40x:
2518 srr0 = SPR_40x_SRR2;
2519 srr1 = SPR_40x_SRR3;
2520 break;
2521 case POWERPC_EXCP_BOOKE:
2522 srr0 = SPR_BOOKE_MCSRR0;
2523 srr1 = SPR_BOOKE_MCSRR1;
2524 asrr0 = SPR_BOOKE_CSRR0;
2525 asrr1 = SPR_BOOKE_CSRR1;
2526 break;
2527 default:
2528 break;
2530 goto store_next;
2531 case POWERPC_EXCP_DSI: /* Data storage exception */
2532 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2533 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2534 if (lpes1 == 0)
2535 new_msr |= (target_ulong)MSR_HVB;
2536 goto store_next;
2537 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2538 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2539 "\n", msr, env->nip);
2540 if (lpes1 == 0)
2541 new_msr |= (target_ulong)MSR_HVB;
2542 msr |= env->error_code;
2543 goto store_next;
2544 case POWERPC_EXCP_EXTERNAL: /* External input */
2545 if (lpes0 == 1)
2546 new_msr |= (target_ulong)MSR_HVB;
2547 goto store_next;
2548 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2549 if (lpes1 == 0)
2550 new_msr |= (target_ulong)MSR_HVB;
2551 /* XXX: this is false */
2552 /* Get rS/rD and rA from faulting opcode */
2553 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2554 goto store_current;
2555 case POWERPC_EXCP_PROGRAM: /* Program exception */
2556 switch (env->error_code & ~0xF) {
2557 case POWERPC_EXCP_FP:
2558 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2559 LOG_EXCP("Ignore floating point exception\n");
2560 env->exception_index = POWERPC_EXCP_NONE;
2561 env->error_code = 0;
2562 return;
2564 if (lpes1 == 0)
2565 new_msr |= (target_ulong)MSR_HVB;
2566 msr |= 0x00100000;
2567 if (msr_fe0 == msr_fe1)
2568 goto store_next;
2569 msr |= 0x00010000;
2570 break;
2571 case POWERPC_EXCP_INVAL:
2572 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2573 if (lpes1 == 0)
2574 new_msr |= (target_ulong)MSR_HVB;
2575 msr |= 0x00080000;
2576 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2577 break;
2578 case POWERPC_EXCP_PRIV:
2579 if (lpes1 == 0)
2580 new_msr |= (target_ulong)MSR_HVB;
2581 msr |= 0x00040000;
2582 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2583 break;
2584 case POWERPC_EXCP_TRAP:
2585 if (lpes1 == 0)
2586 new_msr |= (target_ulong)MSR_HVB;
2587 msr |= 0x00020000;
2588 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2589 break;
2590 default:
2591 /* Should never occur */
2592 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2593 env->error_code);
2594 break;
2596 goto store_current;
2597 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2598 if (lpes1 == 0)
2599 new_msr |= (target_ulong)MSR_HVB;
2600 goto store_current;
2601 case POWERPC_EXCP_SYSCALL: /* System call exception */
2602 dump_syscall(env);
2603 lev = env->error_code;
2604 if ((lev == 1) && cpu_ppc_hypercall) {
2605 cpu_ppc_hypercall(env);
2606 return;
2608 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2609 new_msr |= (target_ulong)MSR_HVB;
2610 goto store_next;
2611 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2612 goto store_current;
2613 case POWERPC_EXCP_DECR: /* Decrementer exception */
2614 if (lpes1 == 0)
2615 new_msr |= (target_ulong)MSR_HVB;
2616 goto store_next;
2617 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2618 /* FIT on 4xx */
2619 LOG_EXCP("FIT exception\n");
2620 goto store_next;
2621 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2622 LOG_EXCP("WDT exception\n");
2623 switch (excp_model) {
2624 case POWERPC_EXCP_BOOKE:
2625 srr0 = SPR_BOOKE_CSRR0;
2626 srr1 = SPR_BOOKE_CSRR1;
2627 break;
2628 default:
2629 break;
2631 goto store_next;
2632 case POWERPC_EXCP_DTLB: /* Data TLB error */
2633 goto store_next;
2634 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2635 goto store_next;
2636 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2637 switch (excp_model) {
2638 case POWERPC_EXCP_BOOKE:
2639 srr0 = SPR_BOOKE_DSRR0;
2640 srr1 = SPR_BOOKE_DSRR1;
2641 asrr0 = SPR_BOOKE_CSRR0;
2642 asrr1 = SPR_BOOKE_CSRR1;
2643 break;
2644 default:
2645 break;
2647 /* XXX: TODO */
2648 cpu_abort(env, "Debug exception is not implemented yet !\n");
2649 goto store_next;
2650 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2651 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2652 goto store_current;
2653 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2654 /* XXX: TODO */
2655 cpu_abort(env, "Embedded floating point data exception "
2656 "is not implemented yet !\n");
2657 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2658 goto store_next;
2659 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2660 /* XXX: TODO */
2661 cpu_abort(env, "Embedded floating point round exception "
2662 "is not implemented yet !\n");
2663 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2664 goto store_next;
2665 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2666 /* XXX: TODO */
2667 cpu_abort(env,
2668 "Performance counter exception is not implemented yet !\n");
2669 goto store_next;
2670 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2671 /* XXX: TODO */
2672 cpu_abort(env,
2673 "Embedded doorbell interrupt is not implemented yet !\n");
2674 goto store_next;
2675 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2676 switch (excp_model) {
2677 case POWERPC_EXCP_BOOKE:
2678 srr0 = SPR_BOOKE_CSRR0;
2679 srr1 = SPR_BOOKE_CSRR1;
2680 break;
2681 default:
2682 break;
2684 /* XXX: TODO */
2685 cpu_abort(env, "Embedded doorbell critical interrupt "
2686 "is not implemented yet !\n");
2687 goto store_next;
2688 case POWERPC_EXCP_RESET: /* System reset exception */
2689 if (msr_pow) {
2690 /* indicate that we resumed from power save mode */
2691 msr |= 0x10000;
2692 } else {
2693 new_msr &= ~((target_ulong)1 << MSR_ME);
2696 if (0) {
2697 /* XXX: find a suitable condition to enable the hypervisor mode */
2698 new_msr |= (target_ulong)MSR_HVB;
2700 goto store_next;
2701 case POWERPC_EXCP_DSEG: /* Data segment exception */
2702 if (lpes1 == 0)
2703 new_msr |= (target_ulong)MSR_HVB;
2704 goto store_next;
2705 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2706 if (lpes1 == 0)
2707 new_msr |= (target_ulong)MSR_HVB;
2708 goto store_next;
2709 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2710 srr0 = SPR_HSRR0;
2711 srr1 = SPR_HSRR1;
2712 new_msr |= (target_ulong)MSR_HVB;
2713 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2714 goto store_next;
2715 case POWERPC_EXCP_TRACE: /* Trace exception */
2716 if (lpes1 == 0)
2717 new_msr |= (target_ulong)MSR_HVB;
2718 goto store_next;
2719 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2720 srr0 = SPR_HSRR0;
2721 srr1 = SPR_HSRR1;
2722 new_msr |= (target_ulong)MSR_HVB;
2723 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2724 goto store_next;
2725 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2726 srr0 = SPR_HSRR0;
2727 srr1 = SPR_HSRR1;
2728 new_msr |= (target_ulong)MSR_HVB;
2729 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2730 goto store_next;
2731 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2732 srr0 = SPR_HSRR0;
2733 srr1 = SPR_HSRR1;
2734 new_msr |= (target_ulong)MSR_HVB;
2735 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2736 goto store_next;
2737 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2738 srr0 = SPR_HSRR0;
2739 srr1 = SPR_HSRR1;
2740 new_msr |= (target_ulong)MSR_HVB;
2741 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2742 goto store_next;
2743 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2744 if (lpes1 == 0)
2745 new_msr |= (target_ulong)MSR_HVB;
2746 goto store_current;
2747 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2748 LOG_EXCP("PIT exception\n");
2749 goto store_next;
2750 case POWERPC_EXCP_IO: /* IO error exception */
2751 /* XXX: TODO */
2752 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2753 goto store_next;
2754 case POWERPC_EXCP_RUNM: /* Run mode exception */
2755 /* XXX: TODO */
2756 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2757 goto store_next;
2758 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2759 /* XXX: TODO */
2760 cpu_abort(env, "602 emulation trap exception "
2761 "is not implemented yet !\n");
2762 goto store_next;
2763 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2764 if (lpes1 == 0) /* XXX: check this */
2765 new_msr |= (target_ulong)MSR_HVB;
2766 switch (excp_model) {
2767 case POWERPC_EXCP_602:
2768 case POWERPC_EXCP_603:
2769 case POWERPC_EXCP_603E:
2770 case POWERPC_EXCP_G2:
2771 goto tlb_miss_tgpr;
2772 case POWERPC_EXCP_7x5:
2773 goto tlb_miss;
2774 case POWERPC_EXCP_74xx:
2775 goto tlb_miss_74xx;
2776 default:
2777 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2778 break;
2780 break;
2781 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2782 if (lpes1 == 0) /* XXX: check this */
2783 new_msr |= (target_ulong)MSR_HVB;
2784 switch (excp_model) {
2785 case POWERPC_EXCP_602:
2786 case POWERPC_EXCP_603:
2787 case POWERPC_EXCP_603E:
2788 case POWERPC_EXCP_G2:
2789 goto tlb_miss_tgpr;
2790 case POWERPC_EXCP_7x5:
2791 goto tlb_miss;
2792 case POWERPC_EXCP_74xx:
2793 goto tlb_miss_74xx;
2794 default:
2795 cpu_abort(env, "Invalid data load TLB miss exception\n");
2796 break;
2798 break;
2799 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2800 if (lpes1 == 0) /* XXX: check this */
2801 new_msr |= (target_ulong)MSR_HVB;
2802 switch (excp_model) {
2803 case POWERPC_EXCP_602:
2804 case POWERPC_EXCP_603:
2805 case POWERPC_EXCP_603E:
2806 case POWERPC_EXCP_G2:
2807 tlb_miss_tgpr:
2808 /* Swap temporary saved registers with GPRs */
2809 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2810 new_msr |= (target_ulong)1 << MSR_TGPR;
2811 hreg_swap_gpr_tgpr(env);
2813 goto tlb_miss;
2814 case POWERPC_EXCP_7x5:
2815 tlb_miss:
2816 #if defined (DEBUG_SOFTWARE_TLB)
2817 if (qemu_log_enabled()) {
2818 const char *es;
2819 target_ulong *miss, *cmp;
2820 int en;
2821 if (excp == POWERPC_EXCP_IFTLB) {
2822 es = "I";
2823 en = 'I';
2824 miss = &env->spr[SPR_IMISS];
2825 cmp = &env->spr[SPR_ICMP];
2826 } else {
2827 if (excp == POWERPC_EXCP_DLTLB)
2828 es = "DL";
2829 else
2830 es = "DS";
2831 en = 'D';
2832 miss = &env->spr[SPR_DMISS];
2833 cmp = &env->spr[SPR_DCMP];
2835 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2836 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2837 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2838 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2839 env->error_code);
2841 #endif
2842 msr |= env->crf[0] << 28;
2843 msr |= env->error_code; /* key, D/I, S/L bits */
2844 /* Set way using a LRU mechanism */
2845 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2846 break;
2847 case POWERPC_EXCP_74xx:
2848 tlb_miss_74xx:
2849 #if defined (DEBUG_SOFTWARE_TLB)
2850 if (qemu_log_enabled()) {
2851 const char *es;
2852 target_ulong *miss, *cmp;
2853 int en;
2854 if (excp == POWERPC_EXCP_IFTLB) {
2855 es = "I";
2856 en = 'I';
2857 miss = &env->spr[SPR_TLBMISS];
2858 cmp = &env->spr[SPR_PTEHI];
2859 } else {
2860 if (excp == POWERPC_EXCP_DLTLB)
2861 es = "DL";
2862 else
2863 es = "DS";
2864 en = 'D';
2865 miss = &env->spr[SPR_TLBMISS];
2866 cmp = &env->spr[SPR_PTEHI];
2868 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2869 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2870 env->error_code);
2872 #endif
2873 msr |= env->error_code; /* key bit */
2874 break;
2875 default:
2876 cpu_abort(env, "Invalid data store TLB miss exception\n");
2877 break;
2879 goto store_next;
2880 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2881 /* XXX: TODO */
2882 cpu_abort(env, "Floating point assist exception "
2883 "is not implemented yet !\n");
2884 goto store_next;
2885 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2886 /* XXX: TODO */
2887 cpu_abort(env, "DABR exception is not implemented yet !\n");
2888 goto store_next;
2889 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2890 /* XXX: TODO */
2891 cpu_abort(env, "IABR exception is not implemented yet !\n");
2892 goto store_next;
2893 case POWERPC_EXCP_SMI: /* System management interrupt */
2894 /* XXX: TODO */
2895 cpu_abort(env, "SMI exception is not implemented yet !\n");
2896 goto store_next;
2897 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2898 /* XXX: TODO */
2899 cpu_abort(env, "Thermal management exception "
2900 "is not implemented yet !\n");
2901 goto store_next;
2902 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2903 if (lpes1 == 0)
2904 new_msr |= (target_ulong)MSR_HVB;
2905 /* XXX: TODO */
2906 cpu_abort(env,
2907 "Performance counter exception is not implemented yet !\n");
2908 goto store_next;
2909 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2910 /* XXX: TODO */
2911 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2912 goto store_next;
2913 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2914 /* XXX: TODO */
2915 cpu_abort(env,
2916 "970 soft-patch exception is not implemented yet !\n");
2917 goto store_next;
2918 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2919 /* XXX: TODO */
2920 cpu_abort(env,
2921 "970 maintenance exception is not implemented yet !\n");
2922 goto store_next;
2923 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2924 /* XXX: TODO */
2925 cpu_abort(env, "Maskable external exception "
2926 "is not implemented yet !\n");
2927 goto store_next;
2928 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2929 /* XXX: TODO */
2930 cpu_abort(env, "Non maskable external exception "
2931 "is not implemented yet !\n");
2932 goto store_next;
2933 default:
2934 excp_invalid:
2935 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2936 break;
2937 store_current:
2938 /* save current instruction location */
2939 env->spr[srr0] = env->nip - 4;
2940 break;
2941 store_next:
2942 /* save next instruction location */
2943 env->spr[srr0] = env->nip;
2944 break;
2946 /* Save MSR */
2947 env->spr[srr1] = msr;
2948 /* If any alternate SRR register are defined, duplicate saved values */
2949 if (asrr0 != -1)
2950 env->spr[asrr0] = env->spr[srr0];
2951 if (asrr1 != -1)
2952 env->spr[asrr1] = env->spr[srr1];
2953 /* If we disactivated any translation, flush TLBs */
2954 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2955 tlb_flush(env, 1);
2957 if (msr_ile) {
2958 new_msr |= (target_ulong)1 << MSR_LE;
2961 /* Jump to handler */
2962 vector = env->excp_vectors[excp];
2963 if (vector == (target_ulong)-1ULL) {
2964 cpu_abort(env, "Raised an exception without defined vector %d\n",
2965 excp);
2967 vector |= env->excp_prefix;
2968 #if defined(TARGET_PPC64)
2969 if (excp_model == POWERPC_EXCP_BOOKE) {
2970 if (!msr_icm) {
2971 vector = (uint32_t)vector;
2972 } else {
2973 new_msr |= (target_ulong)1 << MSR_CM;
2975 } else {
2976 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2977 vector = (uint32_t)vector;
2978 } else {
2979 new_msr |= (target_ulong)1 << MSR_SF;
2982 #endif
2983 /* XXX: we don't use hreg_store_msr here as already have treated
2984 * any special case that could occur. Just store MSR and update hflags
2986 env->msr = new_msr & env->msr_mask;
2987 hreg_compute_hflags(env);
2988 env->nip = vector;
2989 /* Reset exception state */
2990 env->exception_index = POWERPC_EXCP_NONE;
2991 env->error_code = 0;
2993 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2994 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2995 /* XXX: The BookE changes address space when switching modes,
2996 we should probably implement that as different MMU indexes,
2997 but for the moment we do it the slow way and flush all. */
2998 tlb_flush(env, 1);
3002 void do_interrupt (CPUState *env)
3004 powerpc_excp(env, env->excp_model, env->exception_index);
3007 void ppc_hw_interrupt (CPUPPCState *env)
3009 int hdice;
3011 #if 0
3012 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3013 __func__, env, env->pending_interrupts,
3014 env->interrupt_request, (int)msr_me, (int)msr_ee);
3015 #endif
3016 /* External reset */
3017 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3018 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3019 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3020 return;
3022 /* Machine check exception */
3023 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3024 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3025 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3026 return;
3028 #if 0 /* TODO */
3029 /* External debug exception */
3030 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3031 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3032 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3033 return;
3035 #endif
3036 if (0) {
3037 /* XXX: find a suitable condition to enable the hypervisor mode */
3038 hdice = env->spr[SPR_LPCR] & 1;
3039 } else {
3040 hdice = 0;
3042 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3043 /* Hypervisor decrementer exception */
3044 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3045 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3046 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3047 return;
3050 if (msr_ce != 0) {
3051 /* External critical interrupt */
3052 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3053 /* Taking a critical external interrupt does not clear the external
3054 * critical interrupt status
3056 #if 0
3057 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3058 #endif
3059 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3060 return;
3063 if (msr_ee != 0) {
3064 /* Watchdog timer on embedded PowerPC */
3065 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3066 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3067 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3068 return;
3070 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3071 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3072 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3073 return;
3075 /* Fixed interval timer on embedded PowerPC */
3076 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3077 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3078 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3079 return;
3081 /* Programmable interval timer on embedded PowerPC */
3082 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3083 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3084 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3085 return;
3087 /* Decrementer exception */
3088 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3089 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3090 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3091 return;
3093 /* External interrupt */
3094 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3095 /* Taking an external interrupt does not clear the external
3096 * interrupt status
3098 #if 0
3099 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3100 #endif
3101 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3102 return;
3104 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3105 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3106 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3107 return;
3109 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3110 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3111 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3112 return;
3114 /* Thermal interrupt */
3115 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3116 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3117 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3118 return;
3122 #endif /* !CONFIG_USER_ONLY */
3124 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3126 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3127 TARGET_FMT_lx "\n", RA, msr);
3130 void cpu_reset(CPUPPCState *env)
3132 target_ulong msr;
3134 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3135 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3136 log_cpu_state(env, 0);
3139 msr = (target_ulong)0;
3140 if (0) {
3141 /* XXX: find a suitable condition to enable the hypervisor mode */
3142 msr |= (target_ulong)MSR_HVB;
3144 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3145 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3146 msr |= (target_ulong)1 << MSR_EP;
3147 #if defined (DO_SINGLE_STEP) && 0
3148 /* Single step trace mode */
3149 msr |= (target_ulong)1 << MSR_SE;
3150 msr |= (target_ulong)1 << MSR_BE;
3151 #endif
3152 #if defined(CONFIG_USER_ONLY)
3153 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3154 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3155 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3156 msr |= (target_ulong)1 << MSR_PR;
3157 #else
3158 env->excp_prefix = env->hreset_excp_prefix;
3159 env->nip = env->hreset_vector | env->excp_prefix;
3160 if (env->mmu_model != POWERPC_MMU_REAL)
3161 ppc_tlb_invalidate_all(env);
3162 #endif
3163 env->msr = msr & env->msr_mask;
3164 #if defined(TARGET_PPC64)
3165 if (env->mmu_model & POWERPC_MMU_64)
3166 env->msr |= (1ULL << MSR_SF);
3167 #endif
3168 hreg_compute_hflags(env);
3169 env->reserve_addr = (target_ulong)-1ULL;
3170 /* Be sure no exception or interrupt is pending */
3171 env->pending_interrupts = 0;
3172 env->exception_index = POWERPC_EXCP_NONE;
3173 env->error_code = 0;
3174 /* Flush all TLBs */
3175 tlb_flush(env, 1);
3178 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3180 CPUPPCState *env;
3181 const ppc_def_t *def;
3183 def = cpu_ppc_find_by_name(cpu_model);
3184 if (!def)
3185 return NULL;
3187 env = g_malloc0(sizeof(CPUPPCState));
3188 cpu_exec_init(env);
3189 if (tcg_enabled()) {
3190 ppc_translate_init();
3192 env->cpu_model_str = cpu_model;
3193 cpu_ppc_register_internal(env, def);
3195 qemu_init_vcpu(env);
3197 return env;
3200 void cpu_ppc_close (CPUPPCState *env)
3202 /* Should also remove all opcode tables... */
3203 g_free(env);