kvm: Set cpu_single_env only once
[qemu-kvm.git] / target-ppc / helper.c
blob928fbcf3cbe99206ea80a927b63134abd03912f2
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 int tlbm_size;
1298 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1300 return 1024ULL << tlbm_size;
1303 /* TLB check function for MAS based SoftTLBs */
1304 int ppcmas_tlb_check(CPUState *env, ppcmas_tlb_t *tlb,
1305 target_phys_addr_t *raddrp,
1306 target_ulong address, uint32_t pid)
1308 target_ulong mask;
1309 uint32_t tlb_pid;
1311 /* Check valid flag */
1312 if (!(tlb->mas1 & MAS1_VALID)) {
1313 return -1;
1316 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1317 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
1318 PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
1319 __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
1320 tlb->mas8);
1322 /* Check PID */
1323 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
1324 if (tlb_pid != 0 && tlb_pid != pid) {
1325 return -1;
1328 /* Check effective address */
1329 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
1330 return -1;
1333 if (raddrp) {
1334 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
1337 return 0;
1340 static int mmubooke206_check_tlb(CPUState *env, ppcmas_tlb_t *tlb,
1341 target_phys_addr_t *raddr, int *prot,
1342 target_ulong address, int rw,
1343 int access_type)
1345 int ret;
1346 int _prot = 0;
1348 if (ppcmas_tlb_check(env, tlb, raddr, address,
1349 env->spr[SPR_BOOKE_PID]) >= 0) {
1350 goto found_tlb;
1353 if (env->spr[SPR_BOOKE_PID1] &&
1354 ppcmas_tlb_check(env, tlb, raddr, address,
1355 env->spr[SPR_BOOKE_PID1]) >= 0) {
1356 goto found_tlb;
1359 if (env->spr[SPR_BOOKE_PID2] &&
1360 ppcmas_tlb_check(env, tlb, raddr, address,
1361 env->spr[SPR_BOOKE_PID2]) >= 0) {
1362 goto found_tlb;
1365 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1366 return -1;
1368 found_tlb:
1370 if (msr_pr != 0) {
1371 if (tlb->mas7_3 & MAS3_UR) {
1372 _prot |= PAGE_READ;
1374 if (tlb->mas7_3 & MAS3_UW) {
1375 _prot |= PAGE_WRITE;
1377 if (tlb->mas7_3 & MAS3_UX) {
1378 _prot |= PAGE_EXEC;
1380 } else {
1381 if (tlb->mas7_3 & MAS3_SR) {
1382 _prot |= PAGE_READ;
1384 if (tlb->mas7_3 & MAS3_SW) {
1385 _prot |= PAGE_WRITE;
1387 if (tlb->mas7_3 & MAS3_SX) {
1388 _prot |= PAGE_EXEC;
1392 /* Check the address space and permissions */
1393 if (access_type == ACCESS_CODE) {
1394 if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1395 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1396 return -1;
1399 *prot = _prot;
1400 if (_prot & PAGE_EXEC) {
1401 LOG_SWTLB("%s: good TLB!\n", __func__);
1402 return 0;
1405 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1406 ret = -3;
1407 } else {
1408 if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1409 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1410 return -1;
1413 *prot = _prot;
1414 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1415 LOG_SWTLB("%s: found TLB!\n", __func__);
1416 return 0;
1419 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1420 ret = -2;
1423 return ret;
1426 static int mmubooke206_get_physical_address(CPUState *env, mmu_ctx_t *ctx,
1427 target_ulong address, int rw,
1428 int access_type)
1430 ppcmas_tlb_t *tlb;
1431 target_phys_addr_t raddr;
1432 int i, j, ret;
1434 ret = -1;
1435 raddr = (target_phys_addr_t)-1ULL;
1437 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1438 int ways = booke206_tlb_ways(env, i);
1440 for (j = 0; j < ways; j++) {
1441 tlb = booke206_get_tlbm(env, i, address, j);
1442 if (!tlb) {
1443 continue;
1445 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1446 rw, access_type);
1447 if (ret != -1) {
1448 goto found_tlb;
1453 found_tlb:
1455 if (ret >= 0) {
1456 ctx->raddr = raddr;
1457 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1458 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1459 ret);
1460 } else {
1461 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1462 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1465 return ret;
1468 static const char *book3e_tsize_to_str[32] = {
1469 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1470 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1471 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1472 "1T", "2T"
1475 static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1476 CPUState *env, int tlbn, int offset,
1477 int tlbsize)
1479 ppcmas_tlb_t *entry;
1480 int i;
1482 cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1483 cpu_fprintf(f, "Effective Physical Size TID TS SRWX URWX WIMGE U0123\n");
1485 entry = &env->tlb.tlbm[offset];
1486 for (i = 0; i < tlbsize; i++, entry++) {
1487 target_phys_addr_t ea, pa, size;
1488 int tsize;
1490 if (!(entry->mas1 & MAS1_VALID)) {
1491 continue;
1494 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1495 size = 1024ULL << tsize;
1496 ea = entry->mas2 & ~(size - 1);
1497 pa = entry->mas7_3 & ~(size - 1);
1499 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",
1500 (uint64_t)ea, (uint64_t)pa,
1501 book3e_tsize_to_str[tsize],
1502 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1503 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1504 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1505 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1506 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1507 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1508 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1509 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1510 entry->mas2 & MAS2_W ? 'W' : '-',
1511 entry->mas2 & MAS2_I ? 'I' : '-',
1512 entry->mas2 & MAS2_M ? 'M' : '-',
1513 entry->mas2 & MAS2_G ? 'G' : '-',
1514 entry->mas2 & MAS2_E ? 'E' : '-',
1515 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1516 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1517 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1518 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1522 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1523 CPUState *env)
1525 int offset = 0;
1526 int i;
1528 if (kvm_enabled() && !env->kvm_sw_tlb) {
1529 cpu_fprintf(f, "Cannot access KVM TLB\n");
1530 return;
1533 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1534 int size = booke206_tlb_size(env, i);
1536 if (size == 0) {
1537 continue;
1540 mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1541 offset += size;
1545 #if defined(TARGET_PPC64)
1546 static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1547 CPUState *env)
1549 int i;
1550 uint64_t slbe, slbv;
1552 cpu_synchronize_state(env);
1554 cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
1555 for (i = 0; i < env->slb_nr; i++) {
1556 slbe = env->slb[i].esid;
1557 slbv = env->slb[i].vsid;
1558 if (slbe == 0 && slbv == 0) {
1559 continue;
1561 cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
1562 i, slbe, slbv);
1565 #endif
1567 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
1569 switch (env->mmu_model) {
1570 case POWERPC_MMU_BOOKE206:
1571 mmubooke206_dump_mmu(f, cpu_fprintf, env);
1572 break;
1573 #if defined(TARGET_PPC64)
1574 case POWERPC_MMU_64B:
1575 case POWERPC_MMU_2_06:
1576 mmubooks_dump_mmu(f, cpu_fprintf, env);
1577 break;
1578 #endif
1579 default:
1580 cpu_fprintf(f, "%s: unimplemented\n", __func__);
1584 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1585 target_ulong eaddr, int rw)
1587 int in_plb, ret;
1589 ctx->raddr = eaddr;
1590 ctx->prot = PAGE_READ | PAGE_EXEC;
1591 ret = 0;
1592 switch (env->mmu_model) {
1593 case POWERPC_MMU_32B:
1594 case POWERPC_MMU_601:
1595 case POWERPC_MMU_SOFT_6xx:
1596 case POWERPC_MMU_SOFT_74xx:
1597 case POWERPC_MMU_SOFT_4xx:
1598 case POWERPC_MMU_REAL:
1599 case POWERPC_MMU_BOOKE:
1600 ctx->prot |= PAGE_WRITE;
1601 break;
1602 #if defined(TARGET_PPC64)
1603 case POWERPC_MMU_620:
1604 case POWERPC_MMU_64B:
1605 case POWERPC_MMU_2_06:
1606 /* Real address are 60 bits long */
1607 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1608 ctx->prot |= PAGE_WRITE;
1609 break;
1610 #endif
1611 case POWERPC_MMU_SOFT_4xx_Z:
1612 if (unlikely(msr_pe != 0)) {
1613 /* 403 family add some particular protections,
1614 * using PBL/PBU registers for accesses with no translation.
1616 in_plb =
1617 /* Check PLB validity */
1618 (env->pb[0] < env->pb[1] &&
1619 /* and address in plb area */
1620 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1621 (env->pb[2] < env->pb[3] &&
1622 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1623 if (in_plb ^ msr_px) {
1624 /* Access in protected area */
1625 if (rw == 1) {
1626 /* Access is not allowed */
1627 ret = -2;
1629 } else {
1630 /* Read-write access is allowed */
1631 ctx->prot |= PAGE_WRITE;
1634 break;
1635 case POWERPC_MMU_MPC8xx:
1636 /* XXX: TODO */
1637 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1638 break;
1639 case POWERPC_MMU_BOOKE206:
1640 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1641 break;
1642 default:
1643 cpu_abort(env, "Unknown or invalid MMU model\n");
1644 return -1;
1647 return ret;
1650 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1651 int rw, int access_type)
1653 int ret;
1655 #if 0
1656 qemu_log("%s\n", __func__);
1657 #endif
1658 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1659 (access_type != ACCESS_CODE && msr_dr == 0)) {
1660 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1661 /* The BookE MMU always performs address translation. The
1662 IS and DS bits only affect the address space. */
1663 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1664 rw, access_type);
1665 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1666 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1667 access_type);
1668 } else {
1669 /* No address translation. */
1670 ret = check_physical(env, ctx, eaddr, rw);
1672 } else {
1673 ret = -1;
1674 switch (env->mmu_model) {
1675 case POWERPC_MMU_32B:
1676 case POWERPC_MMU_601:
1677 case POWERPC_MMU_SOFT_6xx:
1678 case POWERPC_MMU_SOFT_74xx:
1679 /* Try to find a BAT */
1680 if (env->nb_BATs != 0)
1681 ret = get_bat(env, ctx, eaddr, rw, access_type);
1682 #if defined(TARGET_PPC64)
1683 case POWERPC_MMU_620:
1684 case POWERPC_MMU_64B:
1685 case POWERPC_MMU_2_06:
1686 #endif
1687 if (ret < 0) {
1688 /* We didn't match any BAT entry or don't have BATs */
1689 ret = get_segment(env, ctx, eaddr, rw, access_type);
1691 break;
1692 case POWERPC_MMU_SOFT_4xx:
1693 case POWERPC_MMU_SOFT_4xx_Z:
1694 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1695 rw, access_type);
1696 break;
1697 case POWERPC_MMU_BOOKE:
1698 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1699 rw, access_type);
1700 break;
1701 case POWERPC_MMU_BOOKE206:
1702 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1703 access_type);
1704 break;
1705 case POWERPC_MMU_MPC8xx:
1706 /* XXX: TODO */
1707 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1708 break;
1709 case POWERPC_MMU_REAL:
1710 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1711 return -1;
1712 default:
1713 cpu_abort(env, "Unknown or invalid MMU model\n");
1714 return -1;
1717 #if 0
1718 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1719 __func__, eaddr, ret, ctx->raddr);
1720 #endif
1722 return ret;
1725 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1727 mmu_ctx_t ctx;
1729 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1730 return -1;
1732 return ctx.raddr & TARGET_PAGE_MASK;
1735 static void booke206_update_mas_tlb_miss(CPUState *env, target_ulong address,
1736 int rw)
1738 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1739 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1740 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1741 env->spr[SPR_BOOKE_MAS3] = 0;
1742 env->spr[SPR_BOOKE_MAS6] = 0;
1743 env->spr[SPR_BOOKE_MAS7] = 0;
1745 /* AS */
1746 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1747 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1748 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1751 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1752 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1754 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1755 case MAS4_TIDSELD_PID0:
1756 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1757 break;
1758 case MAS4_TIDSELD_PID1:
1759 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1760 break;
1761 case MAS4_TIDSELD_PID2:
1762 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1763 break;
1766 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1768 /* next victim logic */
1769 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1770 env->last_way++;
1771 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1772 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1775 /* Perform address translation */
1776 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1777 int mmu_idx)
1779 mmu_ctx_t ctx;
1780 int access_type;
1781 int ret = 0;
1783 if (rw == 2) {
1784 /* code access */
1785 rw = 0;
1786 access_type = ACCESS_CODE;
1787 } else {
1788 /* data access */
1789 access_type = env->access_type;
1791 ret = get_physical_address(env, &ctx, address, rw, access_type);
1792 if (ret == 0) {
1793 tlb_set_page(env, address & TARGET_PAGE_MASK,
1794 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1795 mmu_idx, TARGET_PAGE_SIZE);
1796 ret = 0;
1797 } else if (ret < 0) {
1798 LOG_MMU_STATE(env);
1799 if (access_type == ACCESS_CODE) {
1800 switch (ret) {
1801 case -1:
1802 /* No matches in page tables or TLB */
1803 switch (env->mmu_model) {
1804 case POWERPC_MMU_SOFT_6xx:
1805 env->exception_index = POWERPC_EXCP_IFTLB;
1806 env->error_code = 1 << 18;
1807 env->spr[SPR_IMISS] = address;
1808 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1809 goto tlb_miss;
1810 case POWERPC_MMU_SOFT_74xx:
1811 env->exception_index = POWERPC_EXCP_IFTLB;
1812 goto tlb_miss_74xx;
1813 case POWERPC_MMU_SOFT_4xx:
1814 case POWERPC_MMU_SOFT_4xx_Z:
1815 env->exception_index = POWERPC_EXCP_ITLB;
1816 env->error_code = 0;
1817 env->spr[SPR_40x_DEAR] = address;
1818 env->spr[SPR_40x_ESR] = 0x00000000;
1819 break;
1820 case POWERPC_MMU_32B:
1821 case POWERPC_MMU_601:
1822 #if defined(TARGET_PPC64)
1823 case POWERPC_MMU_620:
1824 case POWERPC_MMU_64B:
1825 case POWERPC_MMU_2_06:
1826 #endif
1827 env->exception_index = POWERPC_EXCP_ISI;
1828 env->error_code = 0x40000000;
1829 break;
1830 case POWERPC_MMU_BOOKE206:
1831 booke206_update_mas_tlb_miss(env, address, rw);
1832 /* fall through */
1833 case POWERPC_MMU_BOOKE:
1834 env->exception_index = POWERPC_EXCP_ITLB;
1835 env->error_code = 0;
1836 env->spr[SPR_BOOKE_DEAR] = address;
1837 return -1;
1838 case POWERPC_MMU_MPC8xx:
1839 /* XXX: TODO */
1840 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1841 break;
1842 case POWERPC_MMU_REAL:
1843 cpu_abort(env, "PowerPC in real mode should never raise "
1844 "any MMU exceptions\n");
1845 return -1;
1846 default:
1847 cpu_abort(env, "Unknown or invalid MMU model\n");
1848 return -1;
1850 break;
1851 case -2:
1852 /* Access rights violation */
1853 env->exception_index = POWERPC_EXCP_ISI;
1854 env->error_code = 0x08000000;
1855 break;
1856 case -3:
1857 /* No execute protection violation */
1858 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1859 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1860 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1862 env->exception_index = POWERPC_EXCP_ISI;
1863 env->error_code = 0x10000000;
1864 break;
1865 case -4:
1866 /* Direct store exception */
1867 /* No code fetch is allowed in direct-store areas */
1868 env->exception_index = POWERPC_EXCP_ISI;
1869 env->error_code = 0x10000000;
1870 break;
1871 #if defined(TARGET_PPC64)
1872 case -5:
1873 /* No match in segment table */
1874 if (env->mmu_model == POWERPC_MMU_620) {
1875 env->exception_index = POWERPC_EXCP_ISI;
1876 /* XXX: this might be incorrect */
1877 env->error_code = 0x40000000;
1878 } else {
1879 env->exception_index = POWERPC_EXCP_ISEG;
1880 env->error_code = 0;
1882 break;
1883 #endif
1885 } else {
1886 switch (ret) {
1887 case -1:
1888 /* No matches in page tables or TLB */
1889 switch (env->mmu_model) {
1890 case POWERPC_MMU_SOFT_6xx:
1891 if (rw == 1) {
1892 env->exception_index = POWERPC_EXCP_DSTLB;
1893 env->error_code = 1 << 16;
1894 } else {
1895 env->exception_index = POWERPC_EXCP_DLTLB;
1896 env->error_code = 0;
1898 env->spr[SPR_DMISS] = address;
1899 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1900 tlb_miss:
1901 env->error_code |= ctx.key << 19;
1902 env->spr[SPR_HASH1] = env->htab_base +
1903 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1904 env->spr[SPR_HASH2] = env->htab_base +
1905 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1906 break;
1907 case POWERPC_MMU_SOFT_74xx:
1908 if (rw == 1) {
1909 env->exception_index = POWERPC_EXCP_DSTLB;
1910 } else {
1911 env->exception_index = POWERPC_EXCP_DLTLB;
1913 tlb_miss_74xx:
1914 /* Implement LRU algorithm */
1915 env->error_code = ctx.key << 19;
1916 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1917 ((env->last_way + 1) & (env->nb_ways - 1));
1918 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1919 break;
1920 case POWERPC_MMU_SOFT_4xx:
1921 case POWERPC_MMU_SOFT_4xx_Z:
1922 env->exception_index = POWERPC_EXCP_DTLB;
1923 env->error_code = 0;
1924 env->spr[SPR_40x_DEAR] = address;
1925 if (rw)
1926 env->spr[SPR_40x_ESR] = 0x00800000;
1927 else
1928 env->spr[SPR_40x_ESR] = 0x00000000;
1929 break;
1930 case POWERPC_MMU_32B:
1931 case POWERPC_MMU_601:
1932 #if defined(TARGET_PPC64)
1933 case POWERPC_MMU_620:
1934 case POWERPC_MMU_64B:
1935 case POWERPC_MMU_2_06:
1936 #endif
1937 env->exception_index = POWERPC_EXCP_DSI;
1938 env->error_code = 0;
1939 env->spr[SPR_DAR] = address;
1940 if (rw == 1)
1941 env->spr[SPR_DSISR] = 0x42000000;
1942 else
1943 env->spr[SPR_DSISR] = 0x40000000;
1944 break;
1945 case POWERPC_MMU_MPC8xx:
1946 /* XXX: TODO */
1947 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1948 break;
1949 case POWERPC_MMU_BOOKE206:
1950 booke206_update_mas_tlb_miss(env, address, rw);
1951 /* fall through */
1952 case POWERPC_MMU_BOOKE:
1953 env->exception_index = POWERPC_EXCP_DTLB;
1954 env->error_code = 0;
1955 env->spr[SPR_BOOKE_DEAR] = address;
1956 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1957 return -1;
1958 case POWERPC_MMU_REAL:
1959 cpu_abort(env, "PowerPC in real mode should never raise "
1960 "any MMU exceptions\n");
1961 return -1;
1962 default:
1963 cpu_abort(env, "Unknown or invalid MMU model\n");
1964 return -1;
1966 break;
1967 case -2:
1968 /* Access rights violation */
1969 env->exception_index = POWERPC_EXCP_DSI;
1970 env->error_code = 0;
1971 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1972 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1973 env->spr[SPR_40x_DEAR] = address;
1974 if (rw) {
1975 env->spr[SPR_40x_ESR] |= 0x00800000;
1977 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1978 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1979 env->spr[SPR_BOOKE_DEAR] = address;
1980 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1981 } else {
1982 env->spr[SPR_DAR] = address;
1983 if (rw == 1) {
1984 env->spr[SPR_DSISR] = 0x0A000000;
1985 } else {
1986 env->spr[SPR_DSISR] = 0x08000000;
1989 break;
1990 case -4:
1991 /* Direct store exception */
1992 switch (access_type) {
1993 case ACCESS_FLOAT:
1994 /* Floating point load/store */
1995 env->exception_index = POWERPC_EXCP_ALIGN;
1996 env->error_code = POWERPC_EXCP_ALIGN_FP;
1997 env->spr[SPR_DAR] = address;
1998 break;
1999 case ACCESS_RES:
2000 /* lwarx, ldarx or stwcx. */
2001 env->exception_index = POWERPC_EXCP_DSI;
2002 env->error_code = 0;
2003 env->spr[SPR_DAR] = address;
2004 if (rw == 1)
2005 env->spr[SPR_DSISR] = 0x06000000;
2006 else
2007 env->spr[SPR_DSISR] = 0x04000000;
2008 break;
2009 case ACCESS_EXT:
2010 /* eciwx or ecowx */
2011 env->exception_index = POWERPC_EXCP_DSI;
2012 env->error_code = 0;
2013 env->spr[SPR_DAR] = address;
2014 if (rw == 1)
2015 env->spr[SPR_DSISR] = 0x06100000;
2016 else
2017 env->spr[SPR_DSISR] = 0x04100000;
2018 break;
2019 default:
2020 printf("DSI: invalid exception (%d)\n", ret);
2021 env->exception_index = POWERPC_EXCP_PROGRAM;
2022 env->error_code =
2023 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
2024 env->spr[SPR_DAR] = address;
2025 break;
2027 break;
2028 #if defined(TARGET_PPC64)
2029 case -5:
2030 /* No match in segment table */
2031 if (env->mmu_model == POWERPC_MMU_620) {
2032 env->exception_index = POWERPC_EXCP_DSI;
2033 env->error_code = 0;
2034 env->spr[SPR_DAR] = address;
2035 /* XXX: this might be incorrect */
2036 if (rw == 1)
2037 env->spr[SPR_DSISR] = 0x42000000;
2038 else
2039 env->spr[SPR_DSISR] = 0x40000000;
2040 } else {
2041 env->exception_index = POWERPC_EXCP_DSEG;
2042 env->error_code = 0;
2043 env->spr[SPR_DAR] = address;
2045 break;
2046 #endif
2049 #if 0
2050 printf("%s: set exception to %d %02x\n", __func__,
2051 env->exception, env->error_code);
2052 #endif
2053 ret = 1;
2056 return ret;
2059 /*****************************************************************************/
2060 /* BATs management */
2061 #if !defined(FLUSH_ALL_TLBS)
2062 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2063 target_ulong mask)
2065 target_ulong base, end, page;
2067 base = BATu & ~0x0001FFFF;
2068 end = base + mask + 0x00020000;
2069 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2070 TARGET_FMT_lx ")\n", base, end, mask);
2071 for (page = base; page != end; page += TARGET_PAGE_SIZE)
2072 tlb_flush_page(env, page);
2073 LOG_BATS("Flush done\n");
2075 #endif
2077 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2078 target_ulong value)
2080 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2081 nr, ul == 0 ? 'u' : 'l', value, env->nip);
2084 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2086 target_ulong mask;
2088 dump_store_bat(env, 'I', 0, nr, value);
2089 if (env->IBAT[0][nr] != value) {
2090 mask = (value << 15) & 0x0FFE0000UL;
2091 #if !defined(FLUSH_ALL_TLBS)
2092 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2093 #endif
2094 /* When storing valid upper BAT, mask BEPI and BRPN
2095 * and invalidate all TLBs covered by this BAT
2097 mask = (value << 15) & 0x0FFE0000UL;
2098 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2099 (value & ~0x0001FFFFUL & ~mask);
2100 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2101 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2102 #if !defined(FLUSH_ALL_TLBS)
2103 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2104 #else
2105 tlb_flush(env, 1);
2106 #endif
2110 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2112 dump_store_bat(env, 'I', 1, nr, value);
2113 env->IBAT[1][nr] = value;
2116 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2118 target_ulong mask;
2120 dump_store_bat(env, 'D', 0, nr, value);
2121 if (env->DBAT[0][nr] != value) {
2122 /* When storing valid upper BAT, mask BEPI and BRPN
2123 * and invalidate all TLBs covered by this BAT
2125 mask = (value << 15) & 0x0FFE0000UL;
2126 #if !defined(FLUSH_ALL_TLBS)
2127 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2128 #endif
2129 mask = (value << 15) & 0x0FFE0000UL;
2130 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2131 (value & ~0x0001FFFFUL & ~mask);
2132 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2133 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2134 #if !defined(FLUSH_ALL_TLBS)
2135 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2136 #else
2137 tlb_flush(env, 1);
2138 #endif
2142 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2144 dump_store_bat(env, 'D', 1, nr, value);
2145 env->DBAT[1][nr] = value;
2148 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2150 target_ulong mask;
2151 #if defined(FLUSH_ALL_TLBS)
2152 int do_inval;
2153 #endif
2155 dump_store_bat(env, 'I', 0, nr, value);
2156 if (env->IBAT[0][nr] != value) {
2157 #if defined(FLUSH_ALL_TLBS)
2158 do_inval = 0;
2159 #endif
2160 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2161 if (env->IBAT[1][nr] & 0x40) {
2162 /* Invalidate BAT only if it is valid */
2163 #if !defined(FLUSH_ALL_TLBS)
2164 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2165 #else
2166 do_inval = 1;
2167 #endif
2169 /* When storing valid upper BAT, mask BEPI and BRPN
2170 * and invalidate all TLBs covered by this BAT
2172 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2173 (value & ~0x0001FFFFUL & ~mask);
2174 env->DBAT[0][nr] = env->IBAT[0][nr];
2175 if (env->IBAT[1][nr] & 0x40) {
2176 #if !defined(FLUSH_ALL_TLBS)
2177 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2178 #else
2179 do_inval = 1;
2180 #endif
2182 #if defined(FLUSH_ALL_TLBS)
2183 if (do_inval)
2184 tlb_flush(env, 1);
2185 #endif
2189 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2191 target_ulong mask;
2192 #if defined(FLUSH_ALL_TLBS)
2193 int do_inval;
2194 #endif
2196 dump_store_bat(env, 'I', 1, nr, value);
2197 if (env->IBAT[1][nr] != value) {
2198 #if defined(FLUSH_ALL_TLBS)
2199 do_inval = 0;
2200 #endif
2201 if (env->IBAT[1][nr] & 0x40) {
2202 #if !defined(FLUSH_ALL_TLBS)
2203 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2204 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2205 #else
2206 do_inval = 1;
2207 #endif
2209 if (value & 0x40) {
2210 #if !defined(FLUSH_ALL_TLBS)
2211 mask = (value << 17) & 0x0FFE0000UL;
2212 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2213 #else
2214 do_inval = 1;
2215 #endif
2217 env->IBAT[1][nr] = value;
2218 env->DBAT[1][nr] = value;
2219 #if defined(FLUSH_ALL_TLBS)
2220 if (do_inval)
2221 tlb_flush(env, 1);
2222 #endif
2226 /*****************************************************************************/
2227 /* TLB management */
2228 void ppc_tlb_invalidate_all (CPUPPCState *env)
2230 switch (env->mmu_model) {
2231 case POWERPC_MMU_SOFT_6xx:
2232 case POWERPC_MMU_SOFT_74xx:
2233 ppc6xx_tlb_invalidate_all(env);
2234 break;
2235 case POWERPC_MMU_SOFT_4xx:
2236 case POWERPC_MMU_SOFT_4xx_Z:
2237 ppc4xx_tlb_invalidate_all(env);
2238 break;
2239 case POWERPC_MMU_REAL:
2240 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2241 break;
2242 case POWERPC_MMU_MPC8xx:
2243 /* XXX: TODO */
2244 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2245 break;
2246 case POWERPC_MMU_BOOKE:
2247 tlb_flush(env, 1);
2248 break;
2249 case POWERPC_MMU_BOOKE206:
2250 booke206_flush_tlb(env, -1, 0);
2251 break;
2252 case POWERPC_MMU_32B:
2253 case POWERPC_MMU_601:
2254 #if defined(TARGET_PPC64)
2255 case POWERPC_MMU_620:
2256 case POWERPC_MMU_64B:
2257 case POWERPC_MMU_2_06:
2258 #endif /* defined(TARGET_PPC64) */
2259 tlb_flush(env, 1);
2260 break;
2261 default:
2262 /* XXX: TODO */
2263 cpu_abort(env, "Unknown MMU model\n");
2264 break;
2268 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2270 #if !defined(FLUSH_ALL_TLBS)
2271 addr &= TARGET_PAGE_MASK;
2272 switch (env->mmu_model) {
2273 case POWERPC_MMU_SOFT_6xx:
2274 case POWERPC_MMU_SOFT_74xx:
2275 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2276 if (env->id_tlbs == 1)
2277 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2278 break;
2279 case POWERPC_MMU_SOFT_4xx:
2280 case POWERPC_MMU_SOFT_4xx_Z:
2281 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2282 break;
2283 case POWERPC_MMU_REAL:
2284 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2285 break;
2286 case POWERPC_MMU_MPC8xx:
2287 /* XXX: TODO */
2288 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2289 break;
2290 case POWERPC_MMU_BOOKE:
2291 /* XXX: TODO */
2292 cpu_abort(env, "BookE MMU model is not implemented\n");
2293 break;
2294 case POWERPC_MMU_BOOKE206:
2295 /* XXX: TODO */
2296 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2297 break;
2298 case POWERPC_MMU_32B:
2299 case POWERPC_MMU_601:
2300 /* tlbie invalidate TLBs for all segments */
2301 addr &= ~((target_ulong)-1ULL << 28);
2302 /* XXX: this case should be optimized,
2303 * giving a mask to tlb_flush_page
2305 tlb_flush_page(env, addr | (0x0 << 28));
2306 tlb_flush_page(env, addr | (0x1 << 28));
2307 tlb_flush_page(env, addr | (0x2 << 28));
2308 tlb_flush_page(env, addr | (0x3 << 28));
2309 tlb_flush_page(env, addr | (0x4 << 28));
2310 tlb_flush_page(env, addr | (0x5 << 28));
2311 tlb_flush_page(env, addr | (0x6 << 28));
2312 tlb_flush_page(env, addr | (0x7 << 28));
2313 tlb_flush_page(env, addr | (0x8 << 28));
2314 tlb_flush_page(env, addr | (0x9 << 28));
2315 tlb_flush_page(env, addr | (0xA << 28));
2316 tlb_flush_page(env, addr | (0xB << 28));
2317 tlb_flush_page(env, addr | (0xC << 28));
2318 tlb_flush_page(env, addr | (0xD << 28));
2319 tlb_flush_page(env, addr | (0xE << 28));
2320 tlb_flush_page(env, addr | (0xF << 28));
2321 break;
2322 #if defined(TARGET_PPC64)
2323 case POWERPC_MMU_620:
2324 case POWERPC_MMU_64B:
2325 case POWERPC_MMU_2_06:
2326 /* tlbie invalidate TLBs for all segments */
2327 /* XXX: given the fact that there are too many segments to invalidate,
2328 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2329 * we just invalidate all TLBs
2331 tlb_flush(env, 1);
2332 break;
2333 #endif /* defined(TARGET_PPC64) */
2334 default:
2335 /* XXX: TODO */
2336 cpu_abort(env, "Unknown MMU model\n");
2337 break;
2339 #else
2340 ppc_tlb_invalidate_all(env);
2341 #endif
2344 /*****************************************************************************/
2345 /* Special registers manipulation */
2346 #if defined(TARGET_PPC64)
2347 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2349 if (env->asr != value) {
2350 env->asr = value;
2351 tlb_flush(env, 1);
2354 #endif
2356 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2358 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2359 if (env->spr[SPR_SDR1] != value) {
2360 env->spr[SPR_SDR1] = value;
2361 #if defined(TARGET_PPC64)
2362 if (env->mmu_model & POWERPC_MMU_64) {
2363 target_ulong htabsize = value & SDR_64_HTABSIZE;
2365 if (htabsize > 28) {
2366 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2367 " stored in SDR1\n", htabsize);
2368 htabsize = 28;
2370 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2371 env->htab_base = value & SDR_64_HTABORG;
2372 } else
2373 #endif /* defined(TARGET_PPC64) */
2375 /* FIXME: Should check for valid HTABMASK values */
2376 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2377 env->htab_base = value & SDR_32_HTABORG;
2379 tlb_flush(env, 1);
2383 #if defined(TARGET_PPC64)
2384 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2386 // XXX
2387 return 0;
2389 #endif
2391 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2393 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2394 srnum, value, env->sr[srnum]);
2395 #if defined(TARGET_PPC64)
2396 if (env->mmu_model & POWERPC_MMU_64) {
2397 uint64_t rb = 0, rs = 0;
2399 /* ESID = srnum */
2400 rb |= ((uint32_t)srnum & 0xf) << 28;
2401 /* Set the valid bit */
2402 rb |= 1 << 27;
2403 /* Index = ESID */
2404 rb |= (uint32_t)srnum;
2406 /* VSID = VSID */
2407 rs |= (value & 0xfffffff) << 12;
2408 /* flags = flags */
2409 rs |= ((value >> 27) & 0xf) << 8;
2411 ppc_store_slb(env, rb, rs);
2412 } else
2413 #endif
2414 if (env->sr[srnum] != value) {
2415 env->sr[srnum] = value;
2416 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2417 flusing the whole TLB. */
2418 #if !defined(FLUSH_ALL_TLBS) && 0
2420 target_ulong page, end;
2421 /* Invalidate 256 MB of virtual memory */
2422 page = (16 << 20) * srnum;
2423 end = page + (16 << 20);
2424 for (; page != end; page += TARGET_PAGE_SIZE)
2425 tlb_flush_page(env, page);
2427 #else
2428 tlb_flush(env, 1);
2429 #endif
2432 #endif /* !defined (CONFIG_USER_ONLY) */
2434 /* GDBstub can read and write MSR... */
2435 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2437 hreg_store_msr(env, value, 0);
2440 /*****************************************************************************/
2441 /* Exception processing */
2442 #if defined (CONFIG_USER_ONLY)
2443 void do_interrupt (CPUState *env)
2445 env->exception_index = POWERPC_EXCP_NONE;
2446 env->error_code = 0;
2449 void ppc_hw_interrupt (CPUState *env)
2451 env->exception_index = POWERPC_EXCP_NONE;
2452 env->error_code = 0;
2454 #else /* defined (CONFIG_USER_ONLY) */
2455 static inline void dump_syscall(CPUState *env)
2457 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2458 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2459 " nip=" TARGET_FMT_lx "\n",
2460 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2461 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2462 ppc_dump_gpr(env, 6), env->nip);
2465 /* Note that this function should be greatly optimized
2466 * when called with a constant excp, from ppc_hw_interrupt
2468 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2470 target_ulong msr, new_msr, vector;
2471 int srr0, srr1, asrr0, asrr1;
2472 int lpes0, lpes1, lev;
2474 if (0) {
2475 /* XXX: find a suitable condition to enable the hypervisor mode */
2476 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2477 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2478 } else {
2479 /* Those values ensure we won't enter the hypervisor mode */
2480 lpes0 = 0;
2481 lpes1 = 1;
2484 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2485 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2487 /* new srr1 value excluding must-be-zero bits */
2488 msr = env->msr & ~0x783f0000ULL;
2490 /* new interrupt handler msr */
2491 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2493 /* target registers */
2494 srr0 = SPR_SRR0;
2495 srr1 = SPR_SRR1;
2496 asrr0 = -1;
2497 asrr1 = -1;
2499 switch (excp) {
2500 case POWERPC_EXCP_NONE:
2501 /* Should never happen */
2502 return;
2503 case POWERPC_EXCP_CRITICAL: /* Critical input */
2504 switch (excp_model) {
2505 case POWERPC_EXCP_40x:
2506 srr0 = SPR_40x_SRR2;
2507 srr1 = SPR_40x_SRR3;
2508 break;
2509 case POWERPC_EXCP_BOOKE:
2510 srr0 = SPR_BOOKE_CSRR0;
2511 srr1 = SPR_BOOKE_CSRR1;
2512 break;
2513 case POWERPC_EXCP_G2:
2514 break;
2515 default:
2516 goto excp_invalid;
2518 goto store_next;
2519 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2520 if (msr_me == 0) {
2521 /* Machine check exception is not enabled.
2522 * Enter checkstop state.
2524 if (qemu_log_enabled()) {
2525 qemu_log("Machine check while not allowed. "
2526 "Entering checkstop state\n");
2527 } else {
2528 fprintf(stderr, "Machine check while not allowed. "
2529 "Entering checkstop state\n");
2531 env->halted = 1;
2532 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2534 if (0) {
2535 /* XXX: find a suitable condition to enable the hypervisor mode */
2536 new_msr |= (target_ulong)MSR_HVB;
2539 /* machine check exceptions don't have ME set */
2540 new_msr &= ~((target_ulong)1 << MSR_ME);
2542 /* XXX: should also have something loaded in DAR / DSISR */
2543 switch (excp_model) {
2544 case POWERPC_EXCP_40x:
2545 srr0 = SPR_40x_SRR2;
2546 srr1 = SPR_40x_SRR3;
2547 break;
2548 case POWERPC_EXCP_BOOKE:
2549 srr0 = SPR_BOOKE_MCSRR0;
2550 srr1 = SPR_BOOKE_MCSRR1;
2551 asrr0 = SPR_BOOKE_CSRR0;
2552 asrr1 = SPR_BOOKE_CSRR1;
2553 break;
2554 default:
2555 break;
2557 goto store_next;
2558 case POWERPC_EXCP_DSI: /* Data storage exception */
2559 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2560 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2561 if (lpes1 == 0)
2562 new_msr |= (target_ulong)MSR_HVB;
2563 goto store_next;
2564 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2565 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2566 "\n", msr, env->nip);
2567 if (lpes1 == 0)
2568 new_msr |= (target_ulong)MSR_HVB;
2569 msr |= env->error_code;
2570 goto store_next;
2571 case POWERPC_EXCP_EXTERNAL: /* External input */
2572 if (lpes0 == 1)
2573 new_msr |= (target_ulong)MSR_HVB;
2574 goto store_next;
2575 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2576 if (lpes1 == 0)
2577 new_msr |= (target_ulong)MSR_HVB;
2578 /* XXX: this is false */
2579 /* Get rS/rD and rA from faulting opcode */
2580 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2581 goto store_current;
2582 case POWERPC_EXCP_PROGRAM: /* Program exception */
2583 switch (env->error_code & ~0xF) {
2584 case POWERPC_EXCP_FP:
2585 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2586 LOG_EXCP("Ignore floating point exception\n");
2587 env->exception_index = POWERPC_EXCP_NONE;
2588 env->error_code = 0;
2589 return;
2591 if (lpes1 == 0)
2592 new_msr |= (target_ulong)MSR_HVB;
2593 msr |= 0x00100000;
2594 if (msr_fe0 == msr_fe1)
2595 goto store_next;
2596 msr |= 0x00010000;
2597 break;
2598 case POWERPC_EXCP_INVAL:
2599 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2600 if (lpes1 == 0)
2601 new_msr |= (target_ulong)MSR_HVB;
2602 msr |= 0x00080000;
2603 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2604 break;
2605 case POWERPC_EXCP_PRIV:
2606 if (lpes1 == 0)
2607 new_msr |= (target_ulong)MSR_HVB;
2608 msr |= 0x00040000;
2609 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2610 break;
2611 case POWERPC_EXCP_TRAP:
2612 if (lpes1 == 0)
2613 new_msr |= (target_ulong)MSR_HVB;
2614 msr |= 0x00020000;
2615 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2616 break;
2617 default:
2618 /* Should never occur */
2619 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2620 env->error_code);
2621 break;
2623 goto store_current;
2624 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2625 if (lpes1 == 0)
2626 new_msr |= (target_ulong)MSR_HVB;
2627 goto store_current;
2628 case POWERPC_EXCP_SYSCALL: /* System call exception */
2629 dump_syscall(env);
2630 lev = env->error_code;
2631 if ((lev == 1) && cpu_ppc_hypercall) {
2632 cpu_ppc_hypercall(env);
2633 return;
2635 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2636 new_msr |= (target_ulong)MSR_HVB;
2637 goto store_next;
2638 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2639 goto store_current;
2640 case POWERPC_EXCP_DECR: /* Decrementer exception */
2641 if (lpes1 == 0)
2642 new_msr |= (target_ulong)MSR_HVB;
2643 goto store_next;
2644 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2645 /* FIT on 4xx */
2646 LOG_EXCP("FIT exception\n");
2647 goto store_next;
2648 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2649 LOG_EXCP("WDT exception\n");
2650 switch (excp_model) {
2651 case POWERPC_EXCP_BOOKE:
2652 srr0 = SPR_BOOKE_CSRR0;
2653 srr1 = SPR_BOOKE_CSRR1;
2654 break;
2655 default:
2656 break;
2658 goto store_next;
2659 case POWERPC_EXCP_DTLB: /* Data TLB error */
2660 goto store_next;
2661 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2662 goto store_next;
2663 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2664 switch (excp_model) {
2665 case POWERPC_EXCP_BOOKE:
2666 srr0 = SPR_BOOKE_DSRR0;
2667 srr1 = SPR_BOOKE_DSRR1;
2668 asrr0 = SPR_BOOKE_CSRR0;
2669 asrr1 = SPR_BOOKE_CSRR1;
2670 break;
2671 default:
2672 break;
2674 /* XXX: TODO */
2675 cpu_abort(env, "Debug exception is not implemented yet !\n");
2676 goto store_next;
2677 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2678 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2679 goto store_current;
2680 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2681 /* XXX: TODO */
2682 cpu_abort(env, "Embedded floating point data exception "
2683 "is not implemented yet !\n");
2684 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2685 goto store_next;
2686 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2687 /* XXX: TODO */
2688 cpu_abort(env, "Embedded floating point round exception "
2689 "is not implemented yet !\n");
2690 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2691 goto store_next;
2692 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2693 /* XXX: TODO */
2694 cpu_abort(env,
2695 "Performance counter exception is not implemented yet !\n");
2696 goto store_next;
2697 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2698 goto store_next;
2699 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2700 srr0 = SPR_BOOKE_CSRR0;
2701 srr1 = SPR_BOOKE_CSRR1;
2702 goto store_next;
2703 case POWERPC_EXCP_RESET: /* System reset exception */
2704 if (msr_pow) {
2705 /* indicate that we resumed from power save mode */
2706 msr |= 0x10000;
2707 } else {
2708 new_msr &= ~((target_ulong)1 << MSR_ME);
2711 if (0) {
2712 /* XXX: find a suitable condition to enable the hypervisor mode */
2713 new_msr |= (target_ulong)MSR_HVB;
2715 goto store_next;
2716 case POWERPC_EXCP_DSEG: /* Data segment exception */
2717 if (lpes1 == 0)
2718 new_msr |= (target_ulong)MSR_HVB;
2719 goto store_next;
2720 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2721 if (lpes1 == 0)
2722 new_msr |= (target_ulong)MSR_HVB;
2723 goto store_next;
2724 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2725 srr0 = SPR_HSRR0;
2726 srr1 = SPR_HSRR1;
2727 new_msr |= (target_ulong)MSR_HVB;
2728 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2729 goto store_next;
2730 case POWERPC_EXCP_TRACE: /* Trace exception */
2731 if (lpes1 == 0)
2732 new_msr |= (target_ulong)MSR_HVB;
2733 goto store_next;
2734 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2735 srr0 = SPR_HSRR0;
2736 srr1 = SPR_HSRR1;
2737 new_msr |= (target_ulong)MSR_HVB;
2738 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2739 goto store_next;
2740 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2741 srr0 = SPR_HSRR0;
2742 srr1 = SPR_HSRR1;
2743 new_msr |= (target_ulong)MSR_HVB;
2744 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2745 goto store_next;
2746 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2747 srr0 = SPR_HSRR0;
2748 srr1 = SPR_HSRR1;
2749 new_msr |= (target_ulong)MSR_HVB;
2750 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2751 goto store_next;
2752 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2753 srr0 = SPR_HSRR0;
2754 srr1 = SPR_HSRR1;
2755 new_msr |= (target_ulong)MSR_HVB;
2756 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2757 goto store_next;
2758 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2759 if (lpes1 == 0)
2760 new_msr |= (target_ulong)MSR_HVB;
2761 goto store_current;
2762 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2763 LOG_EXCP("PIT exception\n");
2764 goto store_next;
2765 case POWERPC_EXCP_IO: /* IO error exception */
2766 /* XXX: TODO */
2767 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2768 goto store_next;
2769 case POWERPC_EXCP_RUNM: /* Run mode exception */
2770 /* XXX: TODO */
2771 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2772 goto store_next;
2773 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2774 /* XXX: TODO */
2775 cpu_abort(env, "602 emulation trap exception "
2776 "is not implemented yet !\n");
2777 goto store_next;
2778 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2779 if (lpes1 == 0) /* XXX: check this */
2780 new_msr |= (target_ulong)MSR_HVB;
2781 switch (excp_model) {
2782 case POWERPC_EXCP_602:
2783 case POWERPC_EXCP_603:
2784 case POWERPC_EXCP_603E:
2785 case POWERPC_EXCP_G2:
2786 goto tlb_miss_tgpr;
2787 case POWERPC_EXCP_7x5:
2788 goto tlb_miss;
2789 case POWERPC_EXCP_74xx:
2790 goto tlb_miss_74xx;
2791 default:
2792 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2793 break;
2795 break;
2796 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2797 if (lpes1 == 0) /* XXX: check this */
2798 new_msr |= (target_ulong)MSR_HVB;
2799 switch (excp_model) {
2800 case POWERPC_EXCP_602:
2801 case POWERPC_EXCP_603:
2802 case POWERPC_EXCP_603E:
2803 case POWERPC_EXCP_G2:
2804 goto tlb_miss_tgpr;
2805 case POWERPC_EXCP_7x5:
2806 goto tlb_miss;
2807 case POWERPC_EXCP_74xx:
2808 goto tlb_miss_74xx;
2809 default:
2810 cpu_abort(env, "Invalid data load TLB miss exception\n");
2811 break;
2813 break;
2814 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2815 if (lpes1 == 0) /* XXX: check this */
2816 new_msr |= (target_ulong)MSR_HVB;
2817 switch (excp_model) {
2818 case POWERPC_EXCP_602:
2819 case POWERPC_EXCP_603:
2820 case POWERPC_EXCP_603E:
2821 case POWERPC_EXCP_G2:
2822 tlb_miss_tgpr:
2823 /* Swap temporary saved registers with GPRs */
2824 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2825 new_msr |= (target_ulong)1 << MSR_TGPR;
2826 hreg_swap_gpr_tgpr(env);
2828 goto tlb_miss;
2829 case POWERPC_EXCP_7x5:
2830 tlb_miss:
2831 #if defined (DEBUG_SOFTWARE_TLB)
2832 if (qemu_log_enabled()) {
2833 const char *es;
2834 target_ulong *miss, *cmp;
2835 int en;
2836 if (excp == POWERPC_EXCP_IFTLB) {
2837 es = "I";
2838 en = 'I';
2839 miss = &env->spr[SPR_IMISS];
2840 cmp = &env->spr[SPR_ICMP];
2841 } else {
2842 if (excp == POWERPC_EXCP_DLTLB)
2843 es = "DL";
2844 else
2845 es = "DS";
2846 en = 'D';
2847 miss = &env->spr[SPR_DMISS];
2848 cmp = &env->spr[SPR_DCMP];
2850 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2851 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2852 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2853 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2854 env->error_code);
2856 #endif
2857 msr |= env->crf[0] << 28;
2858 msr |= env->error_code; /* key, D/I, S/L bits */
2859 /* Set way using a LRU mechanism */
2860 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2861 break;
2862 case POWERPC_EXCP_74xx:
2863 tlb_miss_74xx:
2864 #if defined (DEBUG_SOFTWARE_TLB)
2865 if (qemu_log_enabled()) {
2866 const char *es;
2867 target_ulong *miss, *cmp;
2868 int en;
2869 if (excp == POWERPC_EXCP_IFTLB) {
2870 es = "I";
2871 en = 'I';
2872 miss = &env->spr[SPR_TLBMISS];
2873 cmp = &env->spr[SPR_PTEHI];
2874 } else {
2875 if (excp == POWERPC_EXCP_DLTLB)
2876 es = "DL";
2877 else
2878 es = "DS";
2879 en = 'D';
2880 miss = &env->spr[SPR_TLBMISS];
2881 cmp = &env->spr[SPR_PTEHI];
2883 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2884 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2885 env->error_code);
2887 #endif
2888 msr |= env->error_code; /* key bit */
2889 break;
2890 default:
2891 cpu_abort(env, "Invalid data store TLB miss exception\n");
2892 break;
2894 goto store_next;
2895 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2896 /* XXX: TODO */
2897 cpu_abort(env, "Floating point assist exception "
2898 "is not implemented yet !\n");
2899 goto store_next;
2900 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2901 /* XXX: TODO */
2902 cpu_abort(env, "DABR exception is not implemented yet !\n");
2903 goto store_next;
2904 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2905 /* XXX: TODO */
2906 cpu_abort(env, "IABR exception is not implemented yet !\n");
2907 goto store_next;
2908 case POWERPC_EXCP_SMI: /* System management interrupt */
2909 /* XXX: TODO */
2910 cpu_abort(env, "SMI exception is not implemented yet !\n");
2911 goto store_next;
2912 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2913 /* XXX: TODO */
2914 cpu_abort(env, "Thermal management exception "
2915 "is not implemented yet !\n");
2916 goto store_next;
2917 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2918 if (lpes1 == 0)
2919 new_msr |= (target_ulong)MSR_HVB;
2920 /* XXX: TODO */
2921 cpu_abort(env,
2922 "Performance counter exception is not implemented yet !\n");
2923 goto store_next;
2924 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2925 /* XXX: TODO */
2926 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2927 goto store_next;
2928 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2929 /* XXX: TODO */
2930 cpu_abort(env,
2931 "970 soft-patch exception is not implemented yet !\n");
2932 goto store_next;
2933 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2934 /* XXX: TODO */
2935 cpu_abort(env,
2936 "970 maintenance exception is not implemented yet !\n");
2937 goto store_next;
2938 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2939 /* XXX: TODO */
2940 cpu_abort(env, "Maskable external exception "
2941 "is not implemented yet !\n");
2942 goto store_next;
2943 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2944 /* XXX: TODO */
2945 cpu_abort(env, "Non maskable external exception "
2946 "is not implemented yet !\n");
2947 goto store_next;
2948 default:
2949 excp_invalid:
2950 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2951 break;
2952 store_current:
2953 /* save current instruction location */
2954 env->spr[srr0] = env->nip - 4;
2955 break;
2956 store_next:
2957 /* save next instruction location */
2958 env->spr[srr0] = env->nip;
2959 break;
2961 /* Save MSR */
2962 env->spr[srr1] = msr;
2963 /* If any alternate SRR register are defined, duplicate saved values */
2964 if (asrr0 != -1)
2965 env->spr[asrr0] = env->spr[srr0];
2966 if (asrr1 != -1)
2967 env->spr[asrr1] = env->spr[srr1];
2968 /* If we disactivated any translation, flush TLBs */
2969 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2970 tlb_flush(env, 1);
2972 if (msr_ile) {
2973 new_msr |= (target_ulong)1 << MSR_LE;
2976 /* Jump to handler */
2977 vector = env->excp_vectors[excp];
2978 if (vector == (target_ulong)-1ULL) {
2979 cpu_abort(env, "Raised an exception without defined vector %d\n",
2980 excp);
2982 vector |= env->excp_prefix;
2983 #if defined(TARGET_PPC64)
2984 if (excp_model == POWERPC_EXCP_BOOKE) {
2985 if (!msr_icm) {
2986 vector = (uint32_t)vector;
2987 } else {
2988 new_msr |= (target_ulong)1 << MSR_CM;
2990 } else {
2991 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2992 vector = (uint32_t)vector;
2993 } else {
2994 new_msr |= (target_ulong)1 << MSR_SF;
2997 #endif
2998 /* XXX: we don't use hreg_store_msr here as already have treated
2999 * any special case that could occur. Just store MSR and update hflags
3001 env->msr = new_msr & env->msr_mask;
3002 hreg_compute_hflags(env);
3003 env->nip = vector;
3004 /* Reset exception state */
3005 env->exception_index = POWERPC_EXCP_NONE;
3006 env->error_code = 0;
3008 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
3009 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
3010 /* XXX: The BookE changes address space when switching modes,
3011 we should probably implement that as different MMU indexes,
3012 but for the moment we do it the slow way and flush all. */
3013 tlb_flush(env, 1);
3017 void do_interrupt (CPUState *env)
3019 powerpc_excp(env, env->excp_model, env->exception_index);
3022 void ppc_hw_interrupt (CPUPPCState *env)
3024 int hdice;
3026 #if 0
3027 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3028 __func__, env, env->pending_interrupts,
3029 env->interrupt_request, (int)msr_me, (int)msr_ee);
3030 #endif
3031 /* External reset */
3032 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3033 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3034 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3035 return;
3037 /* Machine check exception */
3038 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3039 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3040 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3041 return;
3043 #if 0 /* TODO */
3044 /* External debug exception */
3045 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3046 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3047 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3048 return;
3050 #endif
3051 if (0) {
3052 /* XXX: find a suitable condition to enable the hypervisor mode */
3053 hdice = env->spr[SPR_LPCR] & 1;
3054 } else {
3055 hdice = 0;
3057 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3058 /* Hypervisor decrementer exception */
3059 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3060 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3061 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3062 return;
3065 if (msr_ce != 0) {
3066 /* External critical interrupt */
3067 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3068 /* Taking a critical external interrupt does not clear the external
3069 * critical interrupt status
3071 #if 0
3072 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3073 #endif
3074 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3075 return;
3078 if (msr_ee != 0) {
3079 /* Watchdog timer on embedded PowerPC */
3080 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3081 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3082 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3083 return;
3085 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3086 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3087 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3088 return;
3090 /* Fixed interval timer on embedded PowerPC */
3091 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3092 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3093 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3094 return;
3096 /* Programmable interval timer on embedded PowerPC */
3097 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3098 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3099 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3100 return;
3102 /* Decrementer exception */
3103 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3104 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3105 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3106 return;
3108 /* External interrupt */
3109 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3110 /* Taking an external interrupt does not clear the external
3111 * interrupt status
3113 #if 0
3114 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3115 #endif
3116 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3117 return;
3119 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3120 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3121 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3122 return;
3124 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3125 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3126 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3127 return;
3129 /* Thermal interrupt */
3130 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3131 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3132 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3133 return;
3137 #endif /* !CONFIG_USER_ONLY */
3139 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3141 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3142 TARGET_FMT_lx "\n", RA, msr);
3145 void cpu_reset(CPUPPCState *env)
3147 target_ulong msr;
3149 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3150 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3151 log_cpu_state(env, 0);
3154 msr = (target_ulong)0;
3155 if (0) {
3156 /* XXX: find a suitable condition to enable the hypervisor mode */
3157 msr |= (target_ulong)MSR_HVB;
3159 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3160 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3161 msr |= (target_ulong)1 << MSR_EP;
3162 #if defined (DO_SINGLE_STEP) && 0
3163 /* Single step trace mode */
3164 msr |= (target_ulong)1 << MSR_SE;
3165 msr |= (target_ulong)1 << MSR_BE;
3166 #endif
3167 #if defined(CONFIG_USER_ONLY)
3168 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3169 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3170 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3171 msr |= (target_ulong)1 << MSR_PR;
3172 #else
3173 env->excp_prefix = env->hreset_excp_prefix;
3174 env->nip = env->hreset_vector | env->excp_prefix;
3175 if (env->mmu_model != POWERPC_MMU_REAL)
3176 ppc_tlb_invalidate_all(env);
3177 #endif
3178 env->msr = msr & env->msr_mask;
3179 #if defined(TARGET_PPC64)
3180 if (env->mmu_model & POWERPC_MMU_64)
3181 env->msr |= (1ULL << MSR_SF);
3182 #endif
3183 hreg_compute_hflags(env);
3184 env->reserve_addr = (target_ulong)-1ULL;
3185 /* Be sure no exception or interrupt is pending */
3186 env->pending_interrupts = 0;
3187 env->exception_index = POWERPC_EXCP_NONE;
3188 env->error_code = 0;
3189 /* Flush all TLBs */
3190 tlb_flush(env, 1);
3193 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3195 CPUPPCState *env;
3196 const ppc_def_t *def;
3198 def = cpu_ppc_find_by_name(cpu_model);
3199 if (!def)
3200 return NULL;
3202 env = g_malloc0(sizeof(CPUPPCState));
3203 cpu_exec_init(env);
3204 if (tcg_enabled()) {
3205 ppc_translate_init();
3207 /* Adjust cpu index for SMT */
3208 #if !defined(CONFIG_USER_ONLY)
3209 if (kvm_enabled()) {
3210 int smt = kvmppc_smt_threads();
3212 env->cpu_index = (env->cpu_index / smp_threads)*smt
3213 + (env->cpu_index % smp_threads);
3215 #endif /* !CONFIG_USER_ONLY */
3216 env->cpu_model_str = cpu_model;
3217 cpu_ppc_register_internal(env, def);
3219 qemu_init_vcpu(env);
3221 return env;
3224 void cpu_ppc_close (CPUPPCState *env)
3226 /* Should also remove all opcode tables... */
3227 g_free(env);