Use dma_addr_t type for scatter/gather code
[qemu.git] / target-ppc / helper.c
blob137a494201ba4ffa2dcfc0901f5fa09813c2fe60
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 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
1550 switch (env->mmu_model) {
1551 case POWERPC_MMU_BOOKE206:
1552 mmubooke206_dump_mmu(f, cpu_fprintf, env);
1553 break;
1554 default:
1555 cpu_fprintf(f, "%s: unimplemented\n", __func__);
1559 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1560 target_ulong eaddr, int rw)
1562 int in_plb, ret;
1564 ctx->raddr = eaddr;
1565 ctx->prot = PAGE_READ | PAGE_EXEC;
1566 ret = 0;
1567 switch (env->mmu_model) {
1568 case POWERPC_MMU_32B:
1569 case POWERPC_MMU_601:
1570 case POWERPC_MMU_SOFT_6xx:
1571 case POWERPC_MMU_SOFT_74xx:
1572 case POWERPC_MMU_SOFT_4xx:
1573 case POWERPC_MMU_REAL:
1574 case POWERPC_MMU_BOOKE:
1575 ctx->prot |= PAGE_WRITE;
1576 break;
1577 #if defined(TARGET_PPC64)
1578 case POWERPC_MMU_620:
1579 case POWERPC_MMU_64B:
1580 case POWERPC_MMU_2_06:
1581 /* Real address are 60 bits long */
1582 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1583 ctx->prot |= PAGE_WRITE;
1584 break;
1585 #endif
1586 case POWERPC_MMU_SOFT_4xx_Z:
1587 if (unlikely(msr_pe != 0)) {
1588 /* 403 family add some particular protections,
1589 * using PBL/PBU registers for accesses with no translation.
1591 in_plb =
1592 /* Check PLB validity */
1593 (env->pb[0] < env->pb[1] &&
1594 /* and address in plb area */
1595 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1596 (env->pb[2] < env->pb[3] &&
1597 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1598 if (in_plb ^ msr_px) {
1599 /* Access in protected area */
1600 if (rw == 1) {
1601 /* Access is not allowed */
1602 ret = -2;
1604 } else {
1605 /* Read-write access is allowed */
1606 ctx->prot |= PAGE_WRITE;
1609 break;
1610 case POWERPC_MMU_MPC8xx:
1611 /* XXX: TODO */
1612 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1613 break;
1614 case POWERPC_MMU_BOOKE206:
1615 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1616 break;
1617 default:
1618 cpu_abort(env, "Unknown or invalid MMU model\n");
1619 return -1;
1622 return ret;
1625 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1626 int rw, int access_type)
1628 int ret;
1630 #if 0
1631 qemu_log("%s\n", __func__);
1632 #endif
1633 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1634 (access_type != ACCESS_CODE && msr_dr == 0)) {
1635 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1636 /* The BookE MMU always performs address translation. The
1637 IS and DS bits only affect the address space. */
1638 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1639 rw, access_type);
1640 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1641 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1642 access_type);
1643 } else {
1644 /* No address translation. */
1645 ret = check_physical(env, ctx, eaddr, rw);
1647 } else {
1648 ret = -1;
1649 switch (env->mmu_model) {
1650 case POWERPC_MMU_32B:
1651 case POWERPC_MMU_601:
1652 case POWERPC_MMU_SOFT_6xx:
1653 case POWERPC_MMU_SOFT_74xx:
1654 /* Try to find a BAT */
1655 if (env->nb_BATs != 0)
1656 ret = get_bat(env, ctx, eaddr, rw, access_type);
1657 #if defined(TARGET_PPC64)
1658 case POWERPC_MMU_620:
1659 case POWERPC_MMU_64B:
1660 case POWERPC_MMU_2_06:
1661 #endif
1662 if (ret < 0) {
1663 /* We didn't match any BAT entry or don't have BATs */
1664 ret = get_segment(env, ctx, eaddr, rw, access_type);
1666 break;
1667 case POWERPC_MMU_SOFT_4xx:
1668 case POWERPC_MMU_SOFT_4xx_Z:
1669 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1670 rw, access_type);
1671 break;
1672 case POWERPC_MMU_BOOKE:
1673 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1674 rw, access_type);
1675 break;
1676 case POWERPC_MMU_BOOKE206:
1677 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1678 access_type);
1679 break;
1680 case POWERPC_MMU_MPC8xx:
1681 /* XXX: TODO */
1682 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1683 break;
1684 case POWERPC_MMU_REAL:
1685 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1686 return -1;
1687 default:
1688 cpu_abort(env, "Unknown or invalid MMU model\n");
1689 return -1;
1692 #if 0
1693 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1694 __func__, eaddr, ret, ctx->raddr);
1695 #endif
1697 return ret;
1700 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1702 mmu_ctx_t ctx;
1704 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1705 return -1;
1707 return ctx.raddr & TARGET_PAGE_MASK;
1710 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1711 int rw)
1713 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1714 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1715 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1716 env->spr[SPR_BOOKE_MAS3] = 0;
1717 env->spr[SPR_BOOKE_MAS6] = 0;
1718 env->spr[SPR_BOOKE_MAS7] = 0;
1720 /* AS */
1721 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1722 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1723 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1726 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1727 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1729 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1730 case MAS4_TIDSELD_PID0:
1731 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1732 break;
1733 case MAS4_TIDSELD_PID1:
1734 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1735 break;
1736 case MAS4_TIDSELD_PID2:
1737 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1738 break;
1741 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1743 /* next victim logic */
1744 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1745 env->last_way++;
1746 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1747 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1750 /* Perform address translation */
1751 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1752 int mmu_idx)
1754 mmu_ctx_t ctx;
1755 int access_type;
1756 int ret = 0;
1758 if (rw == 2) {
1759 /* code access */
1760 rw = 0;
1761 access_type = ACCESS_CODE;
1762 } else {
1763 /* data access */
1764 access_type = env->access_type;
1766 ret = get_physical_address(env, &ctx, address, rw, access_type);
1767 if (ret == 0) {
1768 tlb_set_page(env, address & TARGET_PAGE_MASK,
1769 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1770 mmu_idx, TARGET_PAGE_SIZE);
1771 ret = 0;
1772 } else if (ret < 0) {
1773 LOG_MMU_STATE(env);
1774 if (access_type == ACCESS_CODE) {
1775 switch (ret) {
1776 case -1:
1777 /* No matches in page tables or TLB */
1778 switch (env->mmu_model) {
1779 case POWERPC_MMU_SOFT_6xx:
1780 env->exception_index = POWERPC_EXCP_IFTLB;
1781 env->error_code = 1 << 18;
1782 env->spr[SPR_IMISS] = address;
1783 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1784 goto tlb_miss;
1785 case POWERPC_MMU_SOFT_74xx:
1786 env->exception_index = POWERPC_EXCP_IFTLB;
1787 goto tlb_miss_74xx;
1788 case POWERPC_MMU_SOFT_4xx:
1789 case POWERPC_MMU_SOFT_4xx_Z:
1790 env->exception_index = POWERPC_EXCP_ITLB;
1791 env->error_code = 0;
1792 env->spr[SPR_40x_DEAR] = address;
1793 env->spr[SPR_40x_ESR] = 0x00000000;
1794 break;
1795 case POWERPC_MMU_32B:
1796 case POWERPC_MMU_601:
1797 #if defined(TARGET_PPC64)
1798 case POWERPC_MMU_620:
1799 case POWERPC_MMU_64B:
1800 case POWERPC_MMU_2_06:
1801 #endif
1802 env->exception_index = POWERPC_EXCP_ISI;
1803 env->error_code = 0x40000000;
1804 break;
1805 case POWERPC_MMU_BOOKE206:
1806 booke206_update_mas_tlb_miss(env, address, rw);
1807 /* fall through */
1808 case POWERPC_MMU_BOOKE:
1809 env->exception_index = POWERPC_EXCP_ITLB;
1810 env->error_code = 0;
1811 env->spr[SPR_BOOKE_DEAR] = address;
1812 return -1;
1813 case POWERPC_MMU_MPC8xx:
1814 /* XXX: TODO */
1815 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1816 break;
1817 case POWERPC_MMU_REAL:
1818 cpu_abort(env, "PowerPC in real mode should never raise "
1819 "any MMU exceptions\n");
1820 return -1;
1821 default:
1822 cpu_abort(env, "Unknown or invalid MMU model\n");
1823 return -1;
1825 break;
1826 case -2:
1827 /* Access rights violation */
1828 env->exception_index = POWERPC_EXCP_ISI;
1829 env->error_code = 0x08000000;
1830 break;
1831 case -3:
1832 /* No execute protection violation */
1833 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1834 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1835 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1837 env->exception_index = POWERPC_EXCP_ISI;
1838 env->error_code = 0x10000000;
1839 break;
1840 case -4:
1841 /* Direct store exception */
1842 /* No code fetch is allowed in direct-store areas */
1843 env->exception_index = POWERPC_EXCP_ISI;
1844 env->error_code = 0x10000000;
1845 break;
1846 #if defined(TARGET_PPC64)
1847 case -5:
1848 /* No match in segment table */
1849 if (env->mmu_model == POWERPC_MMU_620) {
1850 env->exception_index = POWERPC_EXCP_ISI;
1851 /* XXX: this might be incorrect */
1852 env->error_code = 0x40000000;
1853 } else {
1854 env->exception_index = POWERPC_EXCP_ISEG;
1855 env->error_code = 0;
1857 break;
1858 #endif
1860 } else {
1861 switch (ret) {
1862 case -1:
1863 /* No matches in page tables or TLB */
1864 switch (env->mmu_model) {
1865 case POWERPC_MMU_SOFT_6xx:
1866 if (rw == 1) {
1867 env->exception_index = POWERPC_EXCP_DSTLB;
1868 env->error_code = 1 << 16;
1869 } else {
1870 env->exception_index = POWERPC_EXCP_DLTLB;
1871 env->error_code = 0;
1873 env->spr[SPR_DMISS] = address;
1874 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1875 tlb_miss:
1876 env->error_code |= ctx.key << 19;
1877 env->spr[SPR_HASH1] = env->htab_base +
1878 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1879 env->spr[SPR_HASH2] = env->htab_base +
1880 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1881 break;
1882 case POWERPC_MMU_SOFT_74xx:
1883 if (rw == 1) {
1884 env->exception_index = POWERPC_EXCP_DSTLB;
1885 } else {
1886 env->exception_index = POWERPC_EXCP_DLTLB;
1888 tlb_miss_74xx:
1889 /* Implement LRU algorithm */
1890 env->error_code = ctx.key << 19;
1891 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1892 ((env->last_way + 1) & (env->nb_ways - 1));
1893 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1894 break;
1895 case POWERPC_MMU_SOFT_4xx:
1896 case POWERPC_MMU_SOFT_4xx_Z:
1897 env->exception_index = POWERPC_EXCP_DTLB;
1898 env->error_code = 0;
1899 env->spr[SPR_40x_DEAR] = address;
1900 if (rw)
1901 env->spr[SPR_40x_ESR] = 0x00800000;
1902 else
1903 env->spr[SPR_40x_ESR] = 0x00000000;
1904 break;
1905 case POWERPC_MMU_32B:
1906 case POWERPC_MMU_601:
1907 #if defined(TARGET_PPC64)
1908 case POWERPC_MMU_620:
1909 case POWERPC_MMU_64B:
1910 case POWERPC_MMU_2_06:
1911 #endif
1912 env->exception_index = POWERPC_EXCP_DSI;
1913 env->error_code = 0;
1914 env->spr[SPR_DAR] = address;
1915 if (rw == 1)
1916 env->spr[SPR_DSISR] = 0x42000000;
1917 else
1918 env->spr[SPR_DSISR] = 0x40000000;
1919 break;
1920 case POWERPC_MMU_MPC8xx:
1921 /* XXX: TODO */
1922 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1923 break;
1924 case POWERPC_MMU_BOOKE206:
1925 booke206_update_mas_tlb_miss(env, address, rw);
1926 /* fall through */
1927 case POWERPC_MMU_BOOKE:
1928 env->exception_index = POWERPC_EXCP_DTLB;
1929 env->error_code = 0;
1930 env->spr[SPR_BOOKE_DEAR] = address;
1931 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1932 return -1;
1933 case POWERPC_MMU_REAL:
1934 cpu_abort(env, "PowerPC in real mode should never raise "
1935 "any MMU exceptions\n");
1936 return -1;
1937 default:
1938 cpu_abort(env, "Unknown or invalid MMU model\n");
1939 return -1;
1941 break;
1942 case -2:
1943 /* Access rights violation */
1944 env->exception_index = POWERPC_EXCP_DSI;
1945 env->error_code = 0;
1946 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1947 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1948 env->spr[SPR_40x_DEAR] = address;
1949 if (rw) {
1950 env->spr[SPR_40x_ESR] |= 0x00800000;
1952 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1953 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1954 env->spr[SPR_BOOKE_DEAR] = address;
1955 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1956 } else {
1957 env->spr[SPR_DAR] = address;
1958 if (rw == 1) {
1959 env->spr[SPR_DSISR] = 0x0A000000;
1960 } else {
1961 env->spr[SPR_DSISR] = 0x08000000;
1964 break;
1965 case -4:
1966 /* Direct store exception */
1967 switch (access_type) {
1968 case ACCESS_FLOAT:
1969 /* Floating point load/store */
1970 env->exception_index = POWERPC_EXCP_ALIGN;
1971 env->error_code = POWERPC_EXCP_ALIGN_FP;
1972 env->spr[SPR_DAR] = address;
1973 break;
1974 case ACCESS_RES:
1975 /* lwarx, ldarx or stwcx. */
1976 env->exception_index = POWERPC_EXCP_DSI;
1977 env->error_code = 0;
1978 env->spr[SPR_DAR] = address;
1979 if (rw == 1)
1980 env->spr[SPR_DSISR] = 0x06000000;
1981 else
1982 env->spr[SPR_DSISR] = 0x04000000;
1983 break;
1984 case ACCESS_EXT:
1985 /* eciwx or ecowx */
1986 env->exception_index = POWERPC_EXCP_DSI;
1987 env->error_code = 0;
1988 env->spr[SPR_DAR] = address;
1989 if (rw == 1)
1990 env->spr[SPR_DSISR] = 0x06100000;
1991 else
1992 env->spr[SPR_DSISR] = 0x04100000;
1993 break;
1994 default:
1995 printf("DSI: invalid exception (%d)\n", ret);
1996 env->exception_index = POWERPC_EXCP_PROGRAM;
1997 env->error_code =
1998 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1999 env->spr[SPR_DAR] = address;
2000 break;
2002 break;
2003 #if defined(TARGET_PPC64)
2004 case -5:
2005 /* No match in segment table */
2006 if (env->mmu_model == POWERPC_MMU_620) {
2007 env->exception_index = POWERPC_EXCP_DSI;
2008 env->error_code = 0;
2009 env->spr[SPR_DAR] = address;
2010 /* XXX: this might be incorrect */
2011 if (rw == 1)
2012 env->spr[SPR_DSISR] = 0x42000000;
2013 else
2014 env->spr[SPR_DSISR] = 0x40000000;
2015 } else {
2016 env->exception_index = POWERPC_EXCP_DSEG;
2017 env->error_code = 0;
2018 env->spr[SPR_DAR] = address;
2020 break;
2021 #endif
2024 #if 0
2025 printf("%s: set exception to %d %02x\n", __func__,
2026 env->exception, env->error_code);
2027 #endif
2028 ret = 1;
2031 return ret;
2034 /*****************************************************************************/
2035 /* BATs management */
2036 #if !defined(FLUSH_ALL_TLBS)
2037 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2038 target_ulong mask)
2040 target_ulong base, end, page;
2042 base = BATu & ~0x0001FFFF;
2043 end = base + mask + 0x00020000;
2044 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2045 TARGET_FMT_lx ")\n", base, end, mask);
2046 for (page = base; page != end; page += TARGET_PAGE_SIZE)
2047 tlb_flush_page(env, page);
2048 LOG_BATS("Flush done\n");
2050 #endif
2052 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2053 target_ulong value)
2055 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2056 nr, ul == 0 ? 'u' : 'l', value, env->nip);
2059 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2061 target_ulong mask;
2063 dump_store_bat(env, 'I', 0, nr, value);
2064 if (env->IBAT[0][nr] != value) {
2065 mask = (value << 15) & 0x0FFE0000UL;
2066 #if !defined(FLUSH_ALL_TLBS)
2067 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2068 #endif
2069 /* When storing valid upper BAT, mask BEPI and BRPN
2070 * and invalidate all TLBs covered by this BAT
2072 mask = (value << 15) & 0x0FFE0000UL;
2073 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2074 (value & ~0x0001FFFFUL & ~mask);
2075 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2076 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2077 #if !defined(FLUSH_ALL_TLBS)
2078 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2079 #else
2080 tlb_flush(env, 1);
2081 #endif
2085 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2087 dump_store_bat(env, 'I', 1, nr, value);
2088 env->IBAT[1][nr] = value;
2091 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2093 target_ulong mask;
2095 dump_store_bat(env, 'D', 0, nr, value);
2096 if (env->DBAT[0][nr] != value) {
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 #if !defined(FLUSH_ALL_TLBS)
2102 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2103 #endif
2104 mask = (value << 15) & 0x0FFE0000UL;
2105 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2106 (value & ~0x0001FFFFUL & ~mask);
2107 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2108 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2109 #if !defined(FLUSH_ALL_TLBS)
2110 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2111 #else
2112 tlb_flush(env, 1);
2113 #endif
2117 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2119 dump_store_bat(env, 'D', 1, nr, value);
2120 env->DBAT[1][nr] = value;
2123 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2125 target_ulong mask;
2126 #if defined(FLUSH_ALL_TLBS)
2127 int do_inval;
2128 #endif
2130 dump_store_bat(env, 'I', 0, nr, value);
2131 if (env->IBAT[0][nr] != value) {
2132 #if defined(FLUSH_ALL_TLBS)
2133 do_inval = 0;
2134 #endif
2135 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2136 if (env->IBAT[1][nr] & 0x40) {
2137 /* Invalidate BAT only if it is valid */
2138 #if !defined(FLUSH_ALL_TLBS)
2139 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2140 #else
2141 do_inval = 1;
2142 #endif
2144 /* When storing valid upper BAT, mask BEPI and BRPN
2145 * and invalidate all TLBs covered by this BAT
2147 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2148 (value & ~0x0001FFFFUL & ~mask);
2149 env->DBAT[0][nr] = env->IBAT[0][nr];
2150 if (env->IBAT[1][nr] & 0x40) {
2151 #if !defined(FLUSH_ALL_TLBS)
2152 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2153 #else
2154 do_inval = 1;
2155 #endif
2157 #if defined(FLUSH_ALL_TLBS)
2158 if (do_inval)
2159 tlb_flush(env, 1);
2160 #endif
2164 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2166 target_ulong mask;
2167 #if defined(FLUSH_ALL_TLBS)
2168 int do_inval;
2169 #endif
2171 dump_store_bat(env, 'I', 1, nr, value);
2172 if (env->IBAT[1][nr] != value) {
2173 #if defined(FLUSH_ALL_TLBS)
2174 do_inval = 0;
2175 #endif
2176 if (env->IBAT[1][nr] & 0x40) {
2177 #if !defined(FLUSH_ALL_TLBS)
2178 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2179 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2180 #else
2181 do_inval = 1;
2182 #endif
2184 if (value & 0x40) {
2185 #if !defined(FLUSH_ALL_TLBS)
2186 mask = (value << 17) & 0x0FFE0000UL;
2187 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2188 #else
2189 do_inval = 1;
2190 #endif
2192 env->IBAT[1][nr] = value;
2193 env->DBAT[1][nr] = value;
2194 #if defined(FLUSH_ALL_TLBS)
2195 if (do_inval)
2196 tlb_flush(env, 1);
2197 #endif
2201 /*****************************************************************************/
2202 /* TLB management */
2203 void ppc_tlb_invalidate_all (CPUPPCState *env)
2205 switch (env->mmu_model) {
2206 case POWERPC_MMU_SOFT_6xx:
2207 case POWERPC_MMU_SOFT_74xx:
2208 ppc6xx_tlb_invalidate_all(env);
2209 break;
2210 case POWERPC_MMU_SOFT_4xx:
2211 case POWERPC_MMU_SOFT_4xx_Z:
2212 ppc4xx_tlb_invalidate_all(env);
2213 break;
2214 case POWERPC_MMU_REAL:
2215 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2216 break;
2217 case POWERPC_MMU_MPC8xx:
2218 /* XXX: TODO */
2219 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2220 break;
2221 case POWERPC_MMU_BOOKE:
2222 tlb_flush(env, 1);
2223 break;
2224 case POWERPC_MMU_BOOKE206:
2225 booke206_flush_tlb(env, -1, 0);
2226 break;
2227 case POWERPC_MMU_32B:
2228 case POWERPC_MMU_601:
2229 #if defined(TARGET_PPC64)
2230 case POWERPC_MMU_620:
2231 case POWERPC_MMU_64B:
2232 case POWERPC_MMU_2_06:
2233 #endif /* defined(TARGET_PPC64) */
2234 tlb_flush(env, 1);
2235 break;
2236 default:
2237 /* XXX: TODO */
2238 cpu_abort(env, "Unknown MMU model\n");
2239 break;
2243 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2245 #if !defined(FLUSH_ALL_TLBS)
2246 addr &= TARGET_PAGE_MASK;
2247 switch (env->mmu_model) {
2248 case POWERPC_MMU_SOFT_6xx:
2249 case POWERPC_MMU_SOFT_74xx:
2250 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2251 if (env->id_tlbs == 1)
2252 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2253 break;
2254 case POWERPC_MMU_SOFT_4xx:
2255 case POWERPC_MMU_SOFT_4xx_Z:
2256 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2257 break;
2258 case POWERPC_MMU_REAL:
2259 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2260 break;
2261 case POWERPC_MMU_MPC8xx:
2262 /* XXX: TODO */
2263 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2264 break;
2265 case POWERPC_MMU_BOOKE:
2266 /* XXX: TODO */
2267 cpu_abort(env, "BookE MMU model is not implemented\n");
2268 break;
2269 case POWERPC_MMU_BOOKE206:
2270 /* XXX: TODO */
2271 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2272 break;
2273 case POWERPC_MMU_32B:
2274 case POWERPC_MMU_601:
2275 /* tlbie invalidate TLBs for all segments */
2276 addr &= ~((target_ulong)-1ULL << 28);
2277 /* XXX: this case should be optimized,
2278 * giving a mask to tlb_flush_page
2280 tlb_flush_page(env, addr | (0x0 << 28));
2281 tlb_flush_page(env, addr | (0x1 << 28));
2282 tlb_flush_page(env, addr | (0x2 << 28));
2283 tlb_flush_page(env, addr | (0x3 << 28));
2284 tlb_flush_page(env, addr | (0x4 << 28));
2285 tlb_flush_page(env, addr | (0x5 << 28));
2286 tlb_flush_page(env, addr | (0x6 << 28));
2287 tlb_flush_page(env, addr | (0x7 << 28));
2288 tlb_flush_page(env, addr | (0x8 << 28));
2289 tlb_flush_page(env, addr | (0x9 << 28));
2290 tlb_flush_page(env, addr | (0xA << 28));
2291 tlb_flush_page(env, addr | (0xB << 28));
2292 tlb_flush_page(env, addr | (0xC << 28));
2293 tlb_flush_page(env, addr | (0xD << 28));
2294 tlb_flush_page(env, addr | (0xE << 28));
2295 tlb_flush_page(env, addr | (0xF << 28));
2296 break;
2297 #if defined(TARGET_PPC64)
2298 case POWERPC_MMU_620:
2299 case POWERPC_MMU_64B:
2300 case POWERPC_MMU_2_06:
2301 /* tlbie invalidate TLBs for all segments */
2302 /* XXX: given the fact that there are too many segments to invalidate,
2303 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2304 * we just invalidate all TLBs
2306 tlb_flush(env, 1);
2307 break;
2308 #endif /* defined(TARGET_PPC64) */
2309 default:
2310 /* XXX: TODO */
2311 cpu_abort(env, "Unknown MMU model\n");
2312 break;
2314 #else
2315 ppc_tlb_invalidate_all(env);
2316 #endif
2319 /*****************************************************************************/
2320 /* Special registers manipulation */
2321 #if defined(TARGET_PPC64)
2322 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2324 if (env->asr != value) {
2325 env->asr = value;
2326 tlb_flush(env, 1);
2329 #endif
2331 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2333 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2334 if (env->spr[SPR_SDR1] != value) {
2335 env->spr[SPR_SDR1] = value;
2336 #if defined(TARGET_PPC64)
2337 if (env->mmu_model & POWERPC_MMU_64) {
2338 target_ulong htabsize = value & SDR_64_HTABSIZE;
2340 if (htabsize > 28) {
2341 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2342 " stored in SDR1\n", htabsize);
2343 htabsize = 28;
2345 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2346 env->htab_base = value & SDR_64_HTABORG;
2347 } else
2348 #endif /* defined(TARGET_PPC64) */
2350 /* FIXME: Should check for valid HTABMASK values */
2351 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2352 env->htab_base = value & SDR_32_HTABORG;
2354 tlb_flush(env, 1);
2358 #if defined(TARGET_PPC64)
2359 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2361 // XXX
2362 return 0;
2364 #endif
2366 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2368 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2369 srnum, value, env->sr[srnum]);
2370 #if defined(TARGET_PPC64)
2371 if (env->mmu_model & POWERPC_MMU_64) {
2372 uint64_t rb = 0, rs = 0;
2374 /* ESID = srnum */
2375 rb |= ((uint32_t)srnum & 0xf) << 28;
2376 /* Set the valid bit */
2377 rb |= 1 << 27;
2378 /* Index = ESID */
2379 rb |= (uint32_t)srnum;
2381 /* VSID = VSID */
2382 rs |= (value & 0xfffffff) << 12;
2383 /* flags = flags */
2384 rs |= ((value >> 27) & 0xf) << 8;
2386 ppc_store_slb(env, rb, rs);
2387 } else
2388 #endif
2389 if (env->sr[srnum] != value) {
2390 env->sr[srnum] = value;
2391 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2392 flusing the whole TLB. */
2393 #if !defined(FLUSH_ALL_TLBS) && 0
2395 target_ulong page, end;
2396 /* Invalidate 256 MB of virtual memory */
2397 page = (16 << 20) * srnum;
2398 end = page + (16 << 20);
2399 for (; page != end; page += TARGET_PAGE_SIZE)
2400 tlb_flush_page(env, page);
2402 #else
2403 tlb_flush(env, 1);
2404 #endif
2407 #endif /* !defined (CONFIG_USER_ONLY) */
2409 /* GDBstub can read and write MSR... */
2410 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2412 hreg_store_msr(env, value, 0);
2415 /*****************************************************************************/
2416 /* Exception processing */
2417 #if defined (CONFIG_USER_ONLY)
2418 void do_interrupt (CPUState *env)
2420 env->exception_index = POWERPC_EXCP_NONE;
2421 env->error_code = 0;
2424 void ppc_hw_interrupt (CPUState *env)
2426 env->exception_index = POWERPC_EXCP_NONE;
2427 env->error_code = 0;
2429 #else /* defined (CONFIG_USER_ONLY) */
2430 static inline void dump_syscall(CPUState *env)
2432 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2433 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2434 " nip=" TARGET_FMT_lx "\n",
2435 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2436 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2437 ppc_dump_gpr(env, 6), env->nip);
2440 /* Note that this function should be greatly optimized
2441 * when called with a constant excp, from ppc_hw_interrupt
2443 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2445 target_ulong msr, new_msr, vector;
2446 int srr0, srr1, asrr0, asrr1;
2447 int lpes0, lpes1, lev;
2449 if (0) {
2450 /* XXX: find a suitable condition to enable the hypervisor mode */
2451 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2452 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2453 } else {
2454 /* Those values ensure we won't enter the hypervisor mode */
2455 lpes0 = 0;
2456 lpes1 = 1;
2459 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2460 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2462 /* new srr1 value excluding must-be-zero bits */
2463 msr = env->msr & ~0x783f0000ULL;
2465 /* new interrupt handler msr */
2466 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2468 /* target registers */
2469 srr0 = SPR_SRR0;
2470 srr1 = SPR_SRR1;
2471 asrr0 = -1;
2472 asrr1 = -1;
2474 switch (excp) {
2475 case POWERPC_EXCP_NONE:
2476 /* Should never happen */
2477 return;
2478 case POWERPC_EXCP_CRITICAL: /* Critical input */
2479 switch (excp_model) {
2480 case POWERPC_EXCP_40x:
2481 srr0 = SPR_40x_SRR2;
2482 srr1 = SPR_40x_SRR3;
2483 break;
2484 case POWERPC_EXCP_BOOKE:
2485 srr0 = SPR_BOOKE_CSRR0;
2486 srr1 = SPR_BOOKE_CSRR1;
2487 break;
2488 case POWERPC_EXCP_G2:
2489 break;
2490 default:
2491 goto excp_invalid;
2493 goto store_next;
2494 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2495 if (msr_me == 0) {
2496 /* Machine check exception is not enabled.
2497 * Enter checkstop state.
2499 if (qemu_log_enabled()) {
2500 qemu_log("Machine check while not allowed. "
2501 "Entering checkstop state\n");
2502 } else {
2503 fprintf(stderr, "Machine check while not allowed. "
2504 "Entering checkstop state\n");
2506 env->halted = 1;
2507 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2509 if (0) {
2510 /* XXX: find a suitable condition to enable the hypervisor mode */
2511 new_msr |= (target_ulong)MSR_HVB;
2514 /* machine check exceptions don't have ME set */
2515 new_msr &= ~((target_ulong)1 << MSR_ME);
2517 /* XXX: should also have something loaded in DAR / DSISR */
2518 switch (excp_model) {
2519 case POWERPC_EXCP_40x:
2520 srr0 = SPR_40x_SRR2;
2521 srr1 = SPR_40x_SRR3;
2522 break;
2523 case POWERPC_EXCP_BOOKE:
2524 srr0 = SPR_BOOKE_MCSRR0;
2525 srr1 = SPR_BOOKE_MCSRR1;
2526 asrr0 = SPR_BOOKE_CSRR0;
2527 asrr1 = SPR_BOOKE_CSRR1;
2528 break;
2529 default:
2530 break;
2532 goto store_next;
2533 case POWERPC_EXCP_DSI: /* Data storage exception */
2534 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2535 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2536 if (lpes1 == 0)
2537 new_msr |= (target_ulong)MSR_HVB;
2538 goto store_next;
2539 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2540 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2541 "\n", msr, env->nip);
2542 if (lpes1 == 0)
2543 new_msr |= (target_ulong)MSR_HVB;
2544 msr |= env->error_code;
2545 goto store_next;
2546 case POWERPC_EXCP_EXTERNAL: /* External input */
2547 if (lpes0 == 1)
2548 new_msr |= (target_ulong)MSR_HVB;
2549 goto store_next;
2550 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2551 if (lpes1 == 0)
2552 new_msr |= (target_ulong)MSR_HVB;
2553 /* XXX: this is false */
2554 /* Get rS/rD and rA from faulting opcode */
2555 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2556 goto store_current;
2557 case POWERPC_EXCP_PROGRAM: /* Program exception */
2558 switch (env->error_code & ~0xF) {
2559 case POWERPC_EXCP_FP:
2560 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2561 LOG_EXCP("Ignore floating point exception\n");
2562 env->exception_index = POWERPC_EXCP_NONE;
2563 env->error_code = 0;
2564 return;
2566 if (lpes1 == 0)
2567 new_msr |= (target_ulong)MSR_HVB;
2568 msr |= 0x00100000;
2569 if (msr_fe0 == msr_fe1)
2570 goto store_next;
2571 msr |= 0x00010000;
2572 break;
2573 case POWERPC_EXCP_INVAL:
2574 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2575 if (lpes1 == 0)
2576 new_msr |= (target_ulong)MSR_HVB;
2577 msr |= 0x00080000;
2578 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2579 break;
2580 case POWERPC_EXCP_PRIV:
2581 if (lpes1 == 0)
2582 new_msr |= (target_ulong)MSR_HVB;
2583 msr |= 0x00040000;
2584 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2585 break;
2586 case POWERPC_EXCP_TRAP:
2587 if (lpes1 == 0)
2588 new_msr |= (target_ulong)MSR_HVB;
2589 msr |= 0x00020000;
2590 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2591 break;
2592 default:
2593 /* Should never occur */
2594 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2595 env->error_code);
2596 break;
2598 goto store_current;
2599 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2600 if (lpes1 == 0)
2601 new_msr |= (target_ulong)MSR_HVB;
2602 goto store_current;
2603 case POWERPC_EXCP_SYSCALL: /* System call exception */
2604 dump_syscall(env);
2605 lev = env->error_code;
2606 if ((lev == 1) && cpu_ppc_hypercall) {
2607 cpu_ppc_hypercall(env);
2608 return;
2610 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2611 new_msr |= (target_ulong)MSR_HVB;
2612 goto store_next;
2613 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2614 goto store_current;
2615 case POWERPC_EXCP_DECR: /* Decrementer exception */
2616 if (lpes1 == 0)
2617 new_msr |= (target_ulong)MSR_HVB;
2618 goto store_next;
2619 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2620 /* FIT on 4xx */
2621 LOG_EXCP("FIT exception\n");
2622 goto store_next;
2623 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2624 LOG_EXCP("WDT exception\n");
2625 switch (excp_model) {
2626 case POWERPC_EXCP_BOOKE:
2627 srr0 = SPR_BOOKE_CSRR0;
2628 srr1 = SPR_BOOKE_CSRR1;
2629 break;
2630 default:
2631 break;
2633 goto store_next;
2634 case POWERPC_EXCP_DTLB: /* Data TLB error */
2635 goto store_next;
2636 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2637 goto store_next;
2638 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2639 switch (excp_model) {
2640 case POWERPC_EXCP_BOOKE:
2641 srr0 = SPR_BOOKE_DSRR0;
2642 srr1 = SPR_BOOKE_DSRR1;
2643 asrr0 = SPR_BOOKE_CSRR0;
2644 asrr1 = SPR_BOOKE_CSRR1;
2645 break;
2646 default:
2647 break;
2649 /* XXX: TODO */
2650 cpu_abort(env, "Debug exception is not implemented yet !\n");
2651 goto store_next;
2652 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2653 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2654 goto store_current;
2655 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2656 /* XXX: TODO */
2657 cpu_abort(env, "Embedded floating point data exception "
2658 "is not implemented yet !\n");
2659 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2660 goto store_next;
2661 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2662 /* XXX: TODO */
2663 cpu_abort(env, "Embedded floating point round exception "
2664 "is not implemented yet !\n");
2665 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2666 goto store_next;
2667 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2668 /* XXX: TODO */
2669 cpu_abort(env,
2670 "Performance counter exception is not implemented yet !\n");
2671 goto store_next;
2672 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2673 /* XXX: TODO */
2674 cpu_abort(env,
2675 "Embedded doorbell interrupt is not implemented yet !\n");
2676 goto store_next;
2677 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2678 switch (excp_model) {
2679 case POWERPC_EXCP_BOOKE:
2680 srr0 = SPR_BOOKE_CSRR0;
2681 srr1 = SPR_BOOKE_CSRR1;
2682 break;
2683 default:
2684 break;
2686 /* XXX: TODO */
2687 cpu_abort(env, "Embedded doorbell critical interrupt "
2688 "is not implemented yet !\n");
2689 goto store_next;
2690 case POWERPC_EXCP_RESET: /* System reset exception */
2691 if (msr_pow) {
2692 /* indicate that we resumed from power save mode */
2693 msr |= 0x10000;
2694 } else {
2695 new_msr &= ~((target_ulong)1 << MSR_ME);
2698 if (0) {
2699 /* XXX: find a suitable condition to enable the hypervisor mode */
2700 new_msr |= (target_ulong)MSR_HVB;
2702 goto store_next;
2703 case POWERPC_EXCP_DSEG: /* Data segment exception */
2704 if (lpes1 == 0)
2705 new_msr |= (target_ulong)MSR_HVB;
2706 goto store_next;
2707 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2708 if (lpes1 == 0)
2709 new_msr |= (target_ulong)MSR_HVB;
2710 goto store_next;
2711 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2712 srr0 = SPR_HSRR0;
2713 srr1 = SPR_HSRR1;
2714 new_msr |= (target_ulong)MSR_HVB;
2715 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2716 goto store_next;
2717 case POWERPC_EXCP_TRACE: /* Trace exception */
2718 if (lpes1 == 0)
2719 new_msr |= (target_ulong)MSR_HVB;
2720 goto store_next;
2721 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2722 srr0 = SPR_HSRR0;
2723 srr1 = SPR_HSRR1;
2724 new_msr |= (target_ulong)MSR_HVB;
2725 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2726 goto store_next;
2727 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2728 srr0 = SPR_HSRR0;
2729 srr1 = SPR_HSRR1;
2730 new_msr |= (target_ulong)MSR_HVB;
2731 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2732 goto store_next;
2733 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2734 srr0 = SPR_HSRR0;
2735 srr1 = SPR_HSRR1;
2736 new_msr |= (target_ulong)MSR_HVB;
2737 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2738 goto store_next;
2739 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment 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_VPU: /* Vector unavailable exception */
2746 if (lpes1 == 0)
2747 new_msr |= (target_ulong)MSR_HVB;
2748 goto store_current;
2749 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2750 LOG_EXCP("PIT exception\n");
2751 goto store_next;
2752 case POWERPC_EXCP_IO: /* IO error exception */
2753 /* XXX: TODO */
2754 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2755 goto store_next;
2756 case POWERPC_EXCP_RUNM: /* Run mode exception */
2757 /* XXX: TODO */
2758 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2759 goto store_next;
2760 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2761 /* XXX: TODO */
2762 cpu_abort(env, "602 emulation trap exception "
2763 "is not implemented yet !\n");
2764 goto store_next;
2765 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2766 if (lpes1 == 0) /* XXX: check this */
2767 new_msr |= (target_ulong)MSR_HVB;
2768 switch (excp_model) {
2769 case POWERPC_EXCP_602:
2770 case POWERPC_EXCP_603:
2771 case POWERPC_EXCP_603E:
2772 case POWERPC_EXCP_G2:
2773 goto tlb_miss_tgpr;
2774 case POWERPC_EXCP_7x5:
2775 goto tlb_miss;
2776 case POWERPC_EXCP_74xx:
2777 goto tlb_miss_74xx;
2778 default:
2779 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2780 break;
2782 break;
2783 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2784 if (lpes1 == 0) /* XXX: check this */
2785 new_msr |= (target_ulong)MSR_HVB;
2786 switch (excp_model) {
2787 case POWERPC_EXCP_602:
2788 case POWERPC_EXCP_603:
2789 case POWERPC_EXCP_603E:
2790 case POWERPC_EXCP_G2:
2791 goto tlb_miss_tgpr;
2792 case POWERPC_EXCP_7x5:
2793 goto tlb_miss;
2794 case POWERPC_EXCP_74xx:
2795 goto tlb_miss_74xx;
2796 default:
2797 cpu_abort(env, "Invalid data load TLB miss exception\n");
2798 break;
2800 break;
2801 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2802 if (lpes1 == 0) /* XXX: check this */
2803 new_msr |= (target_ulong)MSR_HVB;
2804 switch (excp_model) {
2805 case POWERPC_EXCP_602:
2806 case POWERPC_EXCP_603:
2807 case POWERPC_EXCP_603E:
2808 case POWERPC_EXCP_G2:
2809 tlb_miss_tgpr:
2810 /* Swap temporary saved registers with GPRs */
2811 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2812 new_msr |= (target_ulong)1 << MSR_TGPR;
2813 hreg_swap_gpr_tgpr(env);
2815 goto tlb_miss;
2816 case POWERPC_EXCP_7x5:
2817 tlb_miss:
2818 #if defined (DEBUG_SOFTWARE_TLB)
2819 if (qemu_log_enabled()) {
2820 const char *es;
2821 target_ulong *miss, *cmp;
2822 int en;
2823 if (excp == POWERPC_EXCP_IFTLB) {
2824 es = "I";
2825 en = 'I';
2826 miss = &env->spr[SPR_IMISS];
2827 cmp = &env->spr[SPR_ICMP];
2828 } else {
2829 if (excp == POWERPC_EXCP_DLTLB)
2830 es = "DL";
2831 else
2832 es = "DS";
2833 en = 'D';
2834 miss = &env->spr[SPR_DMISS];
2835 cmp = &env->spr[SPR_DCMP];
2837 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2838 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2839 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2840 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2841 env->error_code);
2843 #endif
2844 msr |= env->crf[0] << 28;
2845 msr |= env->error_code; /* key, D/I, S/L bits */
2846 /* Set way using a LRU mechanism */
2847 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2848 break;
2849 case POWERPC_EXCP_74xx:
2850 tlb_miss_74xx:
2851 #if defined (DEBUG_SOFTWARE_TLB)
2852 if (qemu_log_enabled()) {
2853 const char *es;
2854 target_ulong *miss, *cmp;
2855 int en;
2856 if (excp == POWERPC_EXCP_IFTLB) {
2857 es = "I";
2858 en = 'I';
2859 miss = &env->spr[SPR_TLBMISS];
2860 cmp = &env->spr[SPR_PTEHI];
2861 } else {
2862 if (excp == POWERPC_EXCP_DLTLB)
2863 es = "DL";
2864 else
2865 es = "DS";
2866 en = 'D';
2867 miss = &env->spr[SPR_TLBMISS];
2868 cmp = &env->spr[SPR_PTEHI];
2870 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2871 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2872 env->error_code);
2874 #endif
2875 msr |= env->error_code; /* key bit */
2876 break;
2877 default:
2878 cpu_abort(env, "Invalid data store TLB miss exception\n");
2879 break;
2881 goto store_next;
2882 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2883 /* XXX: TODO */
2884 cpu_abort(env, "Floating point assist exception "
2885 "is not implemented yet !\n");
2886 goto store_next;
2887 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2888 /* XXX: TODO */
2889 cpu_abort(env, "DABR exception is not implemented yet !\n");
2890 goto store_next;
2891 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2892 /* XXX: TODO */
2893 cpu_abort(env, "IABR exception is not implemented yet !\n");
2894 goto store_next;
2895 case POWERPC_EXCP_SMI: /* System management interrupt */
2896 /* XXX: TODO */
2897 cpu_abort(env, "SMI exception is not implemented yet !\n");
2898 goto store_next;
2899 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2900 /* XXX: TODO */
2901 cpu_abort(env, "Thermal management exception "
2902 "is not implemented yet !\n");
2903 goto store_next;
2904 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2905 if (lpes1 == 0)
2906 new_msr |= (target_ulong)MSR_HVB;
2907 /* XXX: TODO */
2908 cpu_abort(env,
2909 "Performance counter exception is not implemented yet !\n");
2910 goto store_next;
2911 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2912 /* XXX: TODO */
2913 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2914 goto store_next;
2915 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2916 /* XXX: TODO */
2917 cpu_abort(env,
2918 "970 soft-patch exception is not implemented yet !\n");
2919 goto store_next;
2920 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2921 /* XXX: TODO */
2922 cpu_abort(env,
2923 "970 maintenance exception is not implemented yet !\n");
2924 goto store_next;
2925 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2926 /* XXX: TODO */
2927 cpu_abort(env, "Maskable external exception "
2928 "is not implemented yet !\n");
2929 goto store_next;
2930 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2931 /* XXX: TODO */
2932 cpu_abort(env, "Non maskable external exception "
2933 "is not implemented yet !\n");
2934 goto store_next;
2935 default:
2936 excp_invalid:
2937 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2938 break;
2939 store_current:
2940 /* save current instruction location */
2941 env->spr[srr0] = env->nip - 4;
2942 break;
2943 store_next:
2944 /* save next instruction location */
2945 env->spr[srr0] = env->nip;
2946 break;
2948 /* Save MSR */
2949 env->spr[srr1] = msr;
2950 /* If any alternate SRR register are defined, duplicate saved values */
2951 if (asrr0 != -1)
2952 env->spr[asrr0] = env->spr[srr0];
2953 if (asrr1 != -1)
2954 env->spr[asrr1] = env->spr[srr1];
2955 /* If we disactivated any translation, flush TLBs */
2956 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2957 tlb_flush(env, 1);
2959 if (msr_ile) {
2960 new_msr |= (target_ulong)1 << MSR_LE;
2963 /* Jump to handler */
2964 vector = env->excp_vectors[excp];
2965 if (vector == (target_ulong)-1ULL) {
2966 cpu_abort(env, "Raised an exception without defined vector %d\n",
2967 excp);
2969 vector |= env->excp_prefix;
2970 #if defined(TARGET_PPC64)
2971 if (excp_model == POWERPC_EXCP_BOOKE) {
2972 if (!msr_icm) {
2973 vector = (uint32_t)vector;
2974 } else {
2975 new_msr |= (target_ulong)1 << MSR_CM;
2977 } else {
2978 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2979 vector = (uint32_t)vector;
2980 } else {
2981 new_msr |= (target_ulong)1 << MSR_SF;
2984 #endif
2985 /* XXX: we don't use hreg_store_msr here as already have treated
2986 * any special case that could occur. Just store MSR and update hflags
2988 env->msr = new_msr & env->msr_mask;
2989 hreg_compute_hflags(env);
2990 env->nip = vector;
2991 /* Reset exception state */
2992 env->exception_index = POWERPC_EXCP_NONE;
2993 env->error_code = 0;
2995 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
2996 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
2997 /* XXX: The BookE changes address space when switching modes,
2998 we should probably implement that as different MMU indexes,
2999 but for the moment we do it the slow way and flush all. */
3000 tlb_flush(env, 1);
3004 void do_interrupt (CPUState *env)
3006 powerpc_excp(env, env->excp_model, env->exception_index);
3009 void ppc_hw_interrupt (CPUPPCState *env)
3011 int hdice;
3013 #if 0
3014 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3015 __func__, env, env->pending_interrupts,
3016 env->interrupt_request, (int)msr_me, (int)msr_ee);
3017 #endif
3018 /* External reset */
3019 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3020 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3021 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3022 return;
3024 /* Machine check exception */
3025 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3026 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3027 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3028 return;
3030 #if 0 /* TODO */
3031 /* External debug exception */
3032 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3033 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3034 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3035 return;
3037 #endif
3038 if (0) {
3039 /* XXX: find a suitable condition to enable the hypervisor mode */
3040 hdice = env->spr[SPR_LPCR] & 1;
3041 } else {
3042 hdice = 0;
3044 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3045 /* Hypervisor decrementer exception */
3046 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3047 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3048 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3049 return;
3052 if (msr_ce != 0) {
3053 /* External critical interrupt */
3054 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3055 /* Taking a critical external interrupt does not clear the external
3056 * critical interrupt status
3058 #if 0
3059 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3060 #endif
3061 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3062 return;
3065 if (msr_ee != 0) {
3066 /* Watchdog timer on embedded PowerPC */
3067 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3068 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3069 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3070 return;
3072 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3073 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3074 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3075 return;
3077 /* Fixed interval timer on embedded PowerPC */
3078 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3079 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3080 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3081 return;
3083 /* Programmable interval timer on embedded PowerPC */
3084 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3085 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3086 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3087 return;
3089 /* Decrementer exception */
3090 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3091 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3092 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3093 return;
3095 /* External interrupt */
3096 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3097 /* Taking an external interrupt does not clear the external
3098 * interrupt status
3100 #if 0
3101 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3102 #endif
3103 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3104 return;
3106 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3107 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3108 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3109 return;
3111 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3112 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3113 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3114 return;
3116 /* Thermal interrupt */
3117 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3118 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3119 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3120 return;
3124 #endif /* !CONFIG_USER_ONLY */
3126 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3128 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3129 TARGET_FMT_lx "\n", RA, msr);
3132 void cpu_reset(CPUPPCState *env)
3134 target_ulong msr;
3136 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3137 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3138 log_cpu_state(env, 0);
3141 msr = (target_ulong)0;
3142 if (0) {
3143 /* XXX: find a suitable condition to enable the hypervisor mode */
3144 msr |= (target_ulong)MSR_HVB;
3146 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3147 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3148 msr |= (target_ulong)1 << MSR_EP;
3149 #if defined (DO_SINGLE_STEP) && 0
3150 /* Single step trace mode */
3151 msr |= (target_ulong)1 << MSR_SE;
3152 msr |= (target_ulong)1 << MSR_BE;
3153 #endif
3154 #if defined(CONFIG_USER_ONLY)
3155 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3156 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3157 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3158 msr |= (target_ulong)1 << MSR_PR;
3159 #else
3160 env->excp_prefix = env->hreset_excp_prefix;
3161 env->nip = env->hreset_vector | env->excp_prefix;
3162 if (env->mmu_model != POWERPC_MMU_REAL)
3163 ppc_tlb_invalidate_all(env);
3164 #endif
3165 env->msr = msr & env->msr_mask;
3166 #if defined(TARGET_PPC64)
3167 if (env->mmu_model & POWERPC_MMU_64)
3168 env->msr |= (1ULL << MSR_SF);
3169 #endif
3170 hreg_compute_hflags(env);
3171 env->reserve_addr = (target_ulong)-1ULL;
3172 /* Be sure no exception or interrupt is pending */
3173 env->pending_interrupts = 0;
3174 env->exception_index = POWERPC_EXCP_NONE;
3175 env->error_code = 0;
3176 /* Flush all TLBs */
3177 tlb_flush(env, 1);
3180 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3182 CPUPPCState *env;
3183 const ppc_def_t *def;
3185 def = cpu_ppc_find_by_name(cpu_model);
3186 if (!def)
3187 return NULL;
3189 env = g_malloc0(sizeof(CPUPPCState));
3190 cpu_exec_init(env);
3191 if (tcg_enabled()) {
3192 ppc_translate_init();
3194 /* Adjust cpu index for SMT */
3195 #if !defined(CONFIG_USER_ONLY)
3196 if (kvm_enabled()) {
3197 int smt = kvmppc_smt_threads();
3199 env->cpu_index = (env->cpu_index / smp_threads)*smt
3200 + (env->cpu_index % smp_threads);
3202 #endif /* !CONFIG_USER_ONLY */
3203 env->cpu_model_str = cpu_model;
3204 cpu_ppc_register_internal(env, def);
3206 qemu_init_vcpu(env);
3208 return env;
3211 void cpu_ppc_close (CPUPPCState *env)
3213 /* Should also remove all opcode tables... */
3214 g_free(env);