spice: set spice uuid and name
[qemu/ar7.git] / target-ppc / helper.c
blob39dcc273e5c417df9688893eb6c0bc8408082bad
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/>.
20 #include "cpu.h"
21 #include "helper_regs.h"
22 #include "kvm.h"
23 #include "kvm_ppc.h"
24 #include "cpus.h"
26 //#define DEBUG_MMU
27 //#define DEBUG_BATS
28 //#define DEBUG_SLB
29 //#define DEBUG_SOFTWARE_TLB
30 //#define DUMP_PAGE_TABLES
31 //#define DEBUG_EXCEPTIONS
32 //#define FLUSH_ALL_TLBS
34 #ifdef DEBUG_MMU
35 # define LOG_MMU(...) qemu_log(__VA_ARGS__)
36 # define LOG_MMU_STATE(env) log_cpu_state((env), 0)
37 #else
38 # define LOG_MMU(...) do { } while (0)
39 # define LOG_MMU_STATE(...) do { } while (0)
40 #endif
43 #ifdef DEBUG_SOFTWARE_TLB
44 # define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
45 #else
46 # define LOG_SWTLB(...) do { } while (0)
47 #endif
49 #ifdef DEBUG_BATS
50 # define LOG_BATS(...) qemu_log(__VA_ARGS__)
51 #else
52 # define LOG_BATS(...) do { } while (0)
53 #endif
55 #ifdef DEBUG_SLB
56 # define LOG_SLB(...) qemu_log(__VA_ARGS__)
57 #else
58 # define LOG_SLB(...) do { } while (0)
59 #endif
61 #ifdef DEBUG_EXCEPTIONS
62 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
63 #else
64 # define LOG_EXCP(...) do { } while (0)
65 #endif
67 /*****************************************************************************/
68 /* PowerPC Hypercall emulation */
70 void (*cpu_ppc_hypercall)(CPUPPCState *);
72 /*****************************************************************************/
73 /* PowerPC MMU emulation */
75 #if defined(CONFIG_USER_ONLY)
76 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
77 int mmu_idx)
79 int exception, error_code;
81 if (rw == 2) {
82 exception = POWERPC_EXCP_ISI;
83 error_code = 0x40000000;
84 } else {
85 exception = POWERPC_EXCP_DSI;
86 error_code = 0x40000000;
87 if (rw)
88 error_code |= 0x02000000;
89 env->spr[SPR_DAR] = address;
90 env->spr[SPR_DSISR] = error_code;
92 env->exception_index = exception;
93 env->error_code = error_code;
95 return 1;
98 #else
99 /* Common routines used by software and hardware TLBs emulation */
100 static inline int pte_is_valid(target_ulong pte0)
102 return pte0 & 0x80000000 ? 1 : 0;
105 static inline void pte_invalidate(target_ulong *pte0)
107 *pte0 &= ~0x80000000;
110 #if defined(TARGET_PPC64)
111 static inline int pte64_is_valid(target_ulong pte0)
113 return pte0 & 0x0000000000000001ULL ? 1 : 0;
116 static inline void pte64_invalidate(target_ulong *pte0)
118 *pte0 &= ~0x0000000000000001ULL;
120 #endif
122 #define PTE_PTEM_MASK 0x7FFFFFBF
123 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
124 #if defined(TARGET_PPC64)
125 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
126 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
127 #endif
129 static inline int pp_check(int key, int pp, int nx)
131 int access;
133 /* Compute access rights */
134 /* When pp is 3/7, the result is undefined. Set it to noaccess */
135 access = 0;
136 if (key == 0) {
137 switch (pp) {
138 case 0x0:
139 case 0x1:
140 case 0x2:
141 access |= PAGE_WRITE;
142 /* No break here */
143 case 0x3:
144 case 0x6:
145 access |= PAGE_READ;
146 break;
148 } else {
149 switch (pp) {
150 case 0x0:
151 case 0x6:
152 access = 0;
153 break;
154 case 0x1:
155 case 0x3:
156 access = PAGE_READ;
157 break;
158 case 0x2:
159 access = PAGE_READ | PAGE_WRITE;
160 break;
163 if (nx == 0)
164 access |= PAGE_EXEC;
166 return access;
169 static inline int check_prot(int prot, int rw, int access_type)
171 int ret;
173 if (access_type == ACCESS_CODE) {
174 if (prot & PAGE_EXEC)
175 ret = 0;
176 else
177 ret = -2;
178 } else if (rw) {
179 if (prot & PAGE_WRITE)
180 ret = 0;
181 else
182 ret = -2;
183 } else {
184 if (prot & PAGE_READ)
185 ret = 0;
186 else
187 ret = -2;
190 return ret;
193 static inline int _pte_check(mmu_ctx_t *ctx, int is_64b, target_ulong pte0,
194 target_ulong pte1, int h, int rw, int type)
196 target_ulong ptem, mmask;
197 int access, ret, pteh, ptev, pp;
199 ret = -1;
200 /* Check validity and table match */
201 #if defined(TARGET_PPC64)
202 if (is_64b) {
203 ptev = pte64_is_valid(pte0);
204 pteh = (pte0 >> 1) & 1;
205 } else
206 #endif
208 ptev = pte_is_valid(pte0);
209 pteh = (pte0 >> 6) & 1;
211 if (ptev && h == pteh) {
212 /* Check vsid & api */
213 #if defined(TARGET_PPC64)
214 if (is_64b) {
215 ptem = pte0 & PTE64_PTEM_MASK;
216 mmask = PTE64_CHECK_MASK;
217 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
218 ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
219 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
220 } else
221 #endif
223 ptem = pte0 & PTE_PTEM_MASK;
224 mmask = PTE_CHECK_MASK;
225 pp = pte1 & 0x00000003;
227 if (ptem == ctx->ptem) {
228 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
229 /* all matches should have equal RPN, WIMG & PP */
230 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
231 qemu_log("Bad RPN/WIMG/PP\n");
232 return -3;
235 /* Compute access rights */
236 access = pp_check(ctx->key, pp, ctx->nx);
237 /* Keep the matching PTE informations */
238 ctx->raddr = pte1;
239 ctx->prot = access;
240 ret = check_prot(ctx->prot, rw, type);
241 if (ret == 0) {
242 /* Access granted */
243 LOG_MMU("PTE access granted !\n");
244 } else {
245 /* Access right violation */
246 LOG_MMU("PTE access rejected\n");
251 return ret;
254 static inline int pte32_check(mmu_ctx_t *ctx, target_ulong pte0,
255 target_ulong pte1, int h, int rw, int type)
257 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
260 #if defined(TARGET_PPC64)
261 static inline int pte64_check(mmu_ctx_t *ctx, target_ulong pte0,
262 target_ulong pte1, int h, int rw, int type)
264 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
266 #endif
268 static inline int pte_update_flags(mmu_ctx_t *ctx, target_ulong *pte1p,
269 int ret, int rw)
271 int store = 0;
273 /* Update page flags */
274 if (!(*pte1p & 0x00000100)) {
275 /* Update accessed flag */
276 *pte1p |= 0x00000100;
277 store = 1;
279 if (!(*pte1p & 0x00000080)) {
280 if (rw == 1 && ret == 0) {
281 /* Update changed flag */
282 *pte1p |= 0x00000080;
283 store = 1;
284 } else {
285 /* Force page fault for first write access */
286 ctx->prot &= ~PAGE_WRITE;
290 return store;
293 /* Software driven TLB helpers */
294 static inline int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr, int way,
295 int is_code)
297 int nr;
299 /* Select TLB num in a way from address */
300 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
301 /* Select TLB way */
302 nr += env->tlb_per_way * way;
303 /* 6xx have separate TLBs for instructions and data */
304 if (is_code && env->id_tlbs == 1)
305 nr += env->nb_tlb;
307 return nr;
310 static inline void ppc6xx_tlb_invalidate_all(CPUPPCState *env)
312 ppc6xx_tlb_t *tlb;
313 int nr, max;
315 //LOG_SWTLB("Invalidate all TLBs\n");
316 /* Invalidate all defined software TLB */
317 max = env->nb_tlb;
318 if (env->id_tlbs == 1)
319 max *= 2;
320 for (nr = 0; nr < max; nr++) {
321 tlb = &env->tlb.tlb6[nr];
322 pte_invalidate(&tlb->pte0);
324 tlb_flush(env, 1);
327 static inline void __ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
328 target_ulong eaddr,
329 int is_code, int match_epn)
331 #if !defined(FLUSH_ALL_TLBS)
332 ppc6xx_tlb_t *tlb;
333 int way, nr;
335 /* Invalidate ITLB + DTLB, all ways */
336 for (way = 0; way < env->nb_ways; way++) {
337 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
338 tlb = &env->tlb.tlb6[nr];
339 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
340 LOG_SWTLB("TLB invalidate %d/%d " TARGET_FMT_lx "\n", nr,
341 env->nb_tlb, eaddr);
342 pte_invalidate(&tlb->pte0);
343 tlb_flush_page(env, tlb->EPN);
346 #else
347 /* XXX: PowerPC specification say this is valid as well */
348 ppc6xx_tlb_invalidate_all(env);
349 #endif
352 static inline void ppc6xx_tlb_invalidate_virt(CPUPPCState *env,
353 target_ulong eaddr, int is_code)
355 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
358 void ppc6xx_tlb_store (CPUPPCState *env, target_ulong EPN, int way, int is_code,
359 target_ulong pte0, target_ulong pte1)
361 ppc6xx_tlb_t *tlb;
362 int nr;
364 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
365 tlb = &env->tlb.tlb6[nr];
366 LOG_SWTLB("Set TLB %d/%d EPN " TARGET_FMT_lx " PTE0 " TARGET_FMT_lx
367 " PTE1 " TARGET_FMT_lx "\n", nr, env->nb_tlb, EPN, pte0, pte1);
368 /* Invalidate any pending reference in Qemu for this virtual address */
369 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
370 tlb->pte0 = pte0;
371 tlb->pte1 = pte1;
372 tlb->EPN = EPN;
373 /* Store last way for LRU mechanism */
374 env->last_way = way;
377 static inline int ppc6xx_tlb_check(CPUPPCState *env, mmu_ctx_t *ctx,
378 target_ulong eaddr, int rw, int access_type)
380 ppc6xx_tlb_t *tlb;
381 int nr, best, way;
382 int ret;
384 best = -1;
385 ret = -1; /* No TLB found */
386 for (way = 0; way < env->nb_ways; way++) {
387 nr = ppc6xx_tlb_getnum(env, eaddr, way,
388 access_type == ACCESS_CODE ? 1 : 0);
389 tlb = &env->tlb.tlb6[nr];
390 /* This test "emulates" the PTE index match for hardware TLBs */
391 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
392 LOG_SWTLB("TLB %d/%d %s [" TARGET_FMT_lx " " TARGET_FMT_lx
393 "] <> " TARGET_FMT_lx "\n", nr, env->nb_tlb,
394 pte_is_valid(tlb->pte0) ? "valid" : "inval",
395 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
396 continue;
398 LOG_SWTLB("TLB %d/%d %s " TARGET_FMT_lx " <> " TARGET_FMT_lx " "
399 TARGET_FMT_lx " %c %c\n", nr, env->nb_tlb,
400 pte_is_valid(tlb->pte0) ? "valid" : "inval",
401 tlb->EPN, eaddr, tlb->pte1,
402 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
403 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
404 case -3:
405 /* TLB inconsistency */
406 return -1;
407 case -2:
408 /* Access violation */
409 ret = -2;
410 best = nr;
411 break;
412 case -1:
413 default:
414 /* No match */
415 break;
416 case 0:
417 /* access granted */
418 /* XXX: we should go on looping to check all TLBs consistency
419 * but we can speed-up the whole thing as the
420 * result would be undefined if TLBs are not consistent.
422 ret = 0;
423 best = nr;
424 goto done;
427 if (best != -1) {
428 done:
429 LOG_SWTLB("found TLB at addr " TARGET_FMT_plx " prot=%01x ret=%d\n",
430 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
431 /* Update page flags */
432 pte_update_flags(ctx, &env->tlb.tlb6[best].pte1, ret, rw);
435 return ret;
438 /* Perform BAT hit & translation */
439 static inline void bat_size_prot(CPUPPCState *env, target_ulong *blp, int *validp,
440 int *protp, target_ulong *BATu,
441 target_ulong *BATl)
443 target_ulong bl;
444 int pp, valid, prot;
446 bl = (*BATu & 0x00001FFC) << 15;
447 valid = 0;
448 prot = 0;
449 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
450 ((msr_pr != 0) && (*BATu & 0x00000001))) {
451 valid = 1;
452 pp = *BATl & 0x00000003;
453 if (pp != 0) {
454 prot = PAGE_READ | PAGE_EXEC;
455 if (pp == 0x2)
456 prot |= PAGE_WRITE;
459 *blp = bl;
460 *validp = valid;
461 *protp = prot;
464 static inline void bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
465 int *validp, int *protp,
466 target_ulong *BATu, target_ulong *BATl)
468 target_ulong bl;
469 int key, pp, valid, prot;
471 bl = (*BATl & 0x0000003F) << 17;
472 LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
473 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
474 prot = 0;
475 valid = (*BATl >> 6) & 1;
476 if (valid) {
477 pp = *BATu & 0x00000003;
478 if (msr_pr == 0)
479 key = (*BATu >> 3) & 1;
480 else
481 key = (*BATu >> 2) & 1;
482 prot = pp_check(key, pp, 0);
484 *blp = bl;
485 *validp = valid;
486 *protp = prot;
489 static inline int get_bat(CPUPPCState *env, mmu_ctx_t *ctx, target_ulong virtual,
490 int rw, int type)
492 target_ulong *BATlt, *BATut, *BATu, *BATl;
493 target_ulong BEPIl, BEPIu, bl;
494 int i, valid, prot;
495 int ret = -1;
497 LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
498 type == ACCESS_CODE ? 'I' : 'D', virtual);
499 switch (type) {
500 case ACCESS_CODE:
501 BATlt = env->IBAT[1];
502 BATut = env->IBAT[0];
503 break;
504 default:
505 BATlt = env->DBAT[1];
506 BATut = env->DBAT[0];
507 break;
509 for (i = 0; i < env->nb_BATs; i++) {
510 BATu = &BATut[i];
511 BATl = &BATlt[i];
512 BEPIu = *BATu & 0xF0000000;
513 BEPIl = *BATu & 0x0FFE0000;
514 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
515 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
516 } else {
517 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
519 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
520 " BATl " TARGET_FMT_lx "\n", __func__,
521 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
522 if ((virtual & 0xF0000000) == BEPIu &&
523 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
524 /* BAT matches */
525 if (valid != 0) {
526 /* Get physical address */
527 ctx->raddr = (*BATl & 0xF0000000) |
528 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
529 (virtual & 0x0001F000);
530 /* Compute access rights */
531 ctx->prot = prot;
532 ret = check_prot(ctx->prot, rw, type);
533 if (ret == 0)
534 LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
535 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
536 ctx->prot & PAGE_WRITE ? 'W' : '-');
537 break;
541 if (ret < 0) {
542 #if defined(DEBUG_BATS)
543 if (qemu_log_enabled()) {
544 LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
545 for (i = 0; i < 4; i++) {
546 BATu = &BATut[i];
547 BATl = &BATlt[i];
548 BEPIu = *BATu & 0xF0000000;
549 BEPIl = *BATu & 0x0FFE0000;
550 bl = (*BATu & 0x00001FFC) << 15;
551 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
552 " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
553 TARGET_FMT_lx " " TARGET_FMT_lx "\n",
554 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
555 *BATu, *BATl, BEPIu, BEPIl, bl);
558 #endif
560 /* No hit */
561 return ret;
564 static inline target_phys_addr_t get_pteg_offset(CPUPPCState *env,
565 target_phys_addr_t hash,
566 int pte_size)
568 return (hash * pte_size * 8) & env->htab_mask;
571 /* PTE table lookup */
572 static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
573 int rw, int type, int target_page_bits)
575 target_phys_addr_t pteg_off;
576 target_ulong pte0, pte1;
577 int i, good = -1;
578 int ret, r;
580 ret = -1; /* No entry found */
581 pteg_off = get_pteg_offset(env, ctx->hash[h],
582 is_64b ? HASH_PTE_SIZE_64 : HASH_PTE_SIZE_32);
583 for (i = 0; i < 8; i++) {
584 #if defined(TARGET_PPC64)
585 if (is_64b) {
586 if (env->external_htab) {
587 pte0 = ldq_p(env->external_htab + pteg_off + (i * 16));
588 pte1 = ldq_p(env->external_htab + pteg_off + (i * 16) + 8);
589 } else {
590 pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
591 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
594 r = pte64_check(ctx, pte0, pte1, h, rw, type);
595 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
596 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
597 pteg_off + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
598 (int)((pte0 >> 1) & 1), ctx->ptem);
599 } else
600 #endif
602 if (env->external_htab) {
603 pte0 = ldl_p(env->external_htab + pteg_off + (i * 8));
604 pte1 = ldl_p(env->external_htab + pteg_off + (i * 8) + 4);
605 } else {
606 pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
607 pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
609 r = pte32_check(ctx, pte0, pte1, h, rw, type);
610 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
611 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
612 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
613 (int)((pte0 >> 6) & 1), ctx->ptem);
615 switch (r) {
616 case -3:
617 /* PTE inconsistency */
618 return -1;
619 case -2:
620 /* Access violation */
621 ret = -2;
622 good = i;
623 break;
624 case -1:
625 default:
626 /* No PTE match */
627 break;
628 case 0:
629 /* access granted */
630 /* XXX: we should go on looping to check all PTEs consistency
631 * but if we can speed-up the whole thing as the
632 * result would be undefined if PTEs are not consistent.
634 ret = 0;
635 good = i;
636 goto done;
639 if (good != -1) {
640 done:
641 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
642 ctx->raddr, ctx->prot, ret);
643 /* Update page flags */
644 pte1 = ctx->raddr;
645 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
646 #if defined(TARGET_PPC64)
647 if (is_64b) {
648 if (env->external_htab) {
649 stq_p(env->external_htab + pteg_off + (good * 16) + 8,
650 pte1);
651 } else {
652 stq_phys_notdirty(env->htab_base + pteg_off +
653 (good * 16) + 8, pte1);
655 } else
656 #endif
658 if (env->external_htab) {
659 stl_p(env->external_htab + pteg_off + (good * 8) + 4,
660 pte1);
661 } else {
662 stl_phys_notdirty(env->htab_base + pteg_off +
663 (good * 8) + 4, pte1);
669 /* We have a TLB that saves 4K pages, so let's
670 * split a huge page to 4k chunks */
671 if (target_page_bits != TARGET_PAGE_BITS) {
672 ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
673 & TARGET_PAGE_MASK;
675 return ret;
678 static inline int find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int h, int rw,
679 int type, int target_page_bits)
681 #if defined(TARGET_PPC64)
682 if (env->mmu_model & POWERPC_MMU_64)
683 return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
684 #endif
686 return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
689 #if defined(TARGET_PPC64)
690 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
692 uint64_t esid_256M, esid_1T;
693 int n;
695 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
697 esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
698 esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
700 for (n = 0; n < env->slb_nr; n++) {
701 ppc_slb_t *slb = &env->slb[n];
703 LOG_SLB("%s: slot %d %016" PRIx64 " %016"
704 PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
705 /* We check for 1T matches on all MMUs here - if the MMU
706 * doesn't have 1T segment support, we will have prevented 1T
707 * entries from being inserted in the slbmte code. */
708 if (((slb->esid == esid_256M) &&
709 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
710 || ((slb->esid == esid_1T) &&
711 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
712 return slb;
716 return NULL;
719 void ppc_slb_invalidate_all (CPUPPCState *env)
721 int n, do_invalidate;
723 do_invalidate = 0;
724 /* XXX: Warning: slbia never invalidates the first segment */
725 for (n = 1; n < env->slb_nr; n++) {
726 ppc_slb_t *slb = &env->slb[n];
728 if (slb->esid & SLB_ESID_V) {
729 slb->esid &= ~SLB_ESID_V;
730 /* XXX: given the fact that segment size is 256 MB or 1TB,
731 * and we still don't have a tlb_flush_mask(env, n, mask)
732 * in Qemu, we just invalidate all TLBs
734 do_invalidate = 1;
737 if (do_invalidate)
738 tlb_flush(env, 1);
741 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
743 ppc_slb_t *slb;
745 slb = slb_lookup(env, T0);
746 if (!slb) {
747 return;
750 if (slb->esid & SLB_ESID_V) {
751 slb->esid &= ~SLB_ESID_V;
753 /* XXX: given the fact that segment size is 256 MB or 1TB,
754 * and we still don't have a tlb_flush_mask(env, n, mask)
755 * in Qemu, we just invalidate all TLBs
757 tlb_flush(env, 1);
761 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
763 int slot = rb & 0xfff;
764 ppc_slb_t *slb = &env->slb[slot];
766 if (rb & (0x1000 - env->slb_nr)) {
767 return -1; /* Reserved bits set or slot too high */
769 if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
770 return -1; /* Bad segment size */
772 if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
773 return -1; /* 1T segment on MMU that doesn't support it */
776 /* Mask out the slot number as we store the entry */
777 slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
778 slb->vsid = rs;
780 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
781 " %016" PRIx64 "\n", __func__, slot, rb, rs,
782 slb->esid, slb->vsid);
784 return 0;
787 int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
789 int slot = rb & 0xfff;
790 ppc_slb_t *slb = &env->slb[slot];
792 if (slot >= env->slb_nr) {
793 return -1;
796 *rt = slb->esid;
797 return 0;
800 int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
802 int slot = rb & 0xfff;
803 ppc_slb_t *slb = &env->slb[slot];
805 if (slot >= env->slb_nr) {
806 return -1;
809 *rt = slb->vsid;
810 return 0;
812 #endif /* defined(TARGET_PPC64) */
814 /* Perform segment based translation */
815 static inline int get_segment(CPUPPCState *env, mmu_ctx_t *ctx,
816 target_ulong eaddr, int rw, int type)
818 target_phys_addr_t hash;
819 target_ulong vsid;
820 int ds, pr, target_page_bits;
821 int ret, ret2;
823 pr = msr_pr;
824 ctx->eaddr = eaddr;
825 #if defined(TARGET_PPC64)
826 if (env->mmu_model & POWERPC_MMU_64) {
827 ppc_slb_t *slb;
828 target_ulong pageaddr;
829 int segment_bits;
831 LOG_MMU("Check SLBs\n");
832 slb = slb_lookup(env, eaddr);
833 if (!slb) {
834 return -5;
837 if (slb->vsid & SLB_VSID_B) {
838 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
839 segment_bits = 40;
840 } else {
841 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
842 segment_bits = 28;
845 target_page_bits = (slb->vsid & SLB_VSID_L)
846 ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
847 ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
848 : (slb->vsid & SLB_VSID_KS));
849 ds = 0;
850 ctx->nx = !!(slb->vsid & SLB_VSID_N);
852 pageaddr = eaddr & ((1ULL << segment_bits)
853 - (1ULL << target_page_bits));
854 if (slb->vsid & SLB_VSID_B) {
855 hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
856 } else {
857 hash = vsid ^ (pageaddr >> target_page_bits);
859 /* Only 5 bits of the page index are used in the AVPN */
860 ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
861 ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
862 } else
863 #endif /* defined(TARGET_PPC64) */
865 target_ulong sr, pgidx;
867 sr = env->sr[eaddr >> 28];
868 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
869 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
870 ds = sr & 0x80000000 ? 1 : 0;
871 ctx->nx = sr & 0x10000000 ? 1 : 0;
872 vsid = sr & 0x00FFFFFF;
873 target_page_bits = TARGET_PAGE_BITS;
874 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
875 TARGET_FMT_lx " lr=" TARGET_FMT_lx
876 " ir=%d dr=%d pr=%d %d t=%d\n",
877 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
878 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
879 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
880 hash = vsid ^ pgidx;
881 ctx->ptem = (vsid << 7) | (pgidx >> 10);
883 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
884 ctx->key, ds, ctx->nx, vsid);
885 ret = -1;
886 if (!ds) {
887 /* Check if instruction fetch is allowed, if needed */
888 if (type != ACCESS_CODE || ctx->nx == 0) {
889 /* Page address translation */
890 LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
891 " hash " TARGET_FMT_plx "\n",
892 env->htab_base, env->htab_mask, hash);
893 ctx->hash[0] = hash;
894 ctx->hash[1] = ~hash;
896 /* Initialize real address with an invalid value */
897 ctx->raddr = (target_phys_addr_t)-1ULL;
898 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
899 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
900 /* Software TLB search */
901 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
902 } else {
903 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
904 " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
905 " hash=" TARGET_FMT_plx "\n",
906 env->htab_base, env->htab_mask, vsid, ctx->ptem,
907 ctx->hash[0]);
908 /* Primary table lookup */
909 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
910 if (ret < 0) {
911 /* Secondary table lookup */
912 if (eaddr != 0xEFFFFFFF)
913 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
914 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
915 " hash=" TARGET_FMT_plx "\n", env->htab_base,
916 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
917 ret2 = find_pte(env, ctx, 1, rw, type,
918 target_page_bits);
919 if (ret2 != -1)
920 ret = ret2;
923 #if defined (DUMP_PAGE_TABLES)
924 if (qemu_log_enabled()) {
925 target_phys_addr_t curaddr;
926 uint32_t a0, a1, a2, a3;
927 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
928 "\n", sdr, mask + 0x80);
929 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
930 curaddr += 16) {
931 a0 = ldl_phys(curaddr);
932 a1 = ldl_phys(curaddr + 4);
933 a2 = ldl_phys(curaddr + 8);
934 a3 = ldl_phys(curaddr + 12);
935 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
936 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
937 curaddr, a0, a1, a2, a3);
941 #endif
942 } else {
943 LOG_MMU("No access allowed\n");
944 ret = -3;
946 } else {
947 target_ulong sr;
948 LOG_MMU("direct store...\n");
949 /* Direct-store segment : absolutely *BUGGY* for now */
951 /* Direct-store implies a 32-bit MMU.
952 * Check the Segment Register's bus unit ID (BUID).
954 sr = env->sr[eaddr >> 28];
955 if ((sr & 0x1FF00000) >> 20 == 0x07f) {
956 /* Memory-forced I/O controller interface access */
957 /* If T=1 and BUID=x'07F', the 601 performs a memory access
958 * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
960 ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
961 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
962 return 0;
965 switch (type) {
966 case ACCESS_INT:
967 /* Integer load/store : only access allowed */
968 break;
969 case ACCESS_CODE:
970 /* No code fetch is allowed in direct-store areas */
971 return -4;
972 case ACCESS_FLOAT:
973 /* Floating point load/store */
974 return -4;
975 case ACCESS_RES:
976 /* lwarx, ldarx or srwcx. */
977 return -4;
978 case ACCESS_CACHE:
979 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
980 /* Should make the instruction do no-op.
981 * As it already do no-op, it's quite easy :-)
983 ctx->raddr = eaddr;
984 return 0;
985 case ACCESS_EXT:
986 /* eciwx or ecowx */
987 return -4;
988 default:
989 qemu_log("ERROR: instruction should not need "
990 "address translation\n");
991 return -4;
993 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
994 ctx->raddr = eaddr;
995 ret = 2;
996 } else {
997 ret = -2;
1001 return ret;
1004 /* Generic TLB check function for embedded PowerPC implementations */
1005 int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
1006 target_phys_addr_t *raddrp,
1007 target_ulong address, uint32_t pid, int ext,
1008 int i)
1010 target_ulong mask;
1012 /* Check valid flag */
1013 if (!(tlb->prot & PAGE_VALID)) {
1014 return -1;
1016 mask = ~(tlb->size - 1);
1017 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
1018 " " TARGET_FMT_lx " %u %x\n", __func__, i, address, pid, tlb->EPN,
1019 mask, (uint32_t)tlb->PID, tlb->prot);
1020 /* Check PID */
1021 if (tlb->PID != 0 && tlb->PID != pid)
1022 return -1;
1023 /* Check effective address */
1024 if ((address & mask) != tlb->EPN)
1025 return -1;
1026 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1027 #if (TARGET_PHYS_ADDR_BITS >= 36)
1028 if (ext) {
1029 /* Extend the physical address to 36 bits */
1030 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1032 #endif
1034 return 0;
1037 /* Generic TLB search function for PowerPC embedded implementations */
1038 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1040 ppcemb_tlb_t *tlb;
1041 target_phys_addr_t raddr;
1042 int i, ret;
1044 /* Default return value is no match */
1045 ret = -1;
1046 for (i = 0; i < env->nb_tlb; i++) {
1047 tlb = &env->tlb.tlbe[i];
1048 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1049 ret = i;
1050 break;
1054 return ret;
1057 /* Helpers specific to PowerPC 40x implementations */
1058 static inline void ppc4xx_tlb_invalidate_all(CPUPPCState *env)
1060 ppcemb_tlb_t *tlb;
1061 int i;
1063 for (i = 0; i < env->nb_tlb; i++) {
1064 tlb = &env->tlb.tlbe[i];
1065 tlb->prot &= ~PAGE_VALID;
1067 tlb_flush(env, 1);
1070 static inline void ppc4xx_tlb_invalidate_virt(CPUPPCState *env,
1071 target_ulong eaddr, uint32_t pid)
1073 #if !defined(FLUSH_ALL_TLBS)
1074 ppcemb_tlb_t *tlb;
1075 target_phys_addr_t raddr;
1076 target_ulong page, end;
1077 int i;
1079 for (i = 0; i < env->nb_tlb; i++) {
1080 tlb = &env->tlb.tlbe[i];
1081 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1082 end = tlb->EPN + tlb->size;
1083 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1084 tlb_flush_page(env, page);
1085 tlb->prot &= ~PAGE_VALID;
1086 break;
1089 #else
1090 ppc4xx_tlb_invalidate_all(env);
1091 #endif
1094 static int mmu40x_get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx,
1095 target_ulong address, int rw, int access_type)
1097 ppcemb_tlb_t *tlb;
1098 target_phys_addr_t raddr;
1099 int i, ret, zsel, zpr, pr;
1101 ret = -1;
1102 raddr = (target_phys_addr_t)-1ULL;
1103 pr = msr_pr;
1104 for (i = 0; i < env->nb_tlb; i++) {
1105 tlb = &env->tlb.tlbe[i];
1106 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1107 env->spr[SPR_40x_PID], 0, i) < 0)
1108 continue;
1109 zsel = (tlb->attr >> 4) & 0xF;
1110 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1111 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1112 __func__, i, zsel, zpr, rw, tlb->attr);
1113 /* Check execute enable bit */
1114 switch (zpr) {
1115 case 0x2:
1116 if (pr != 0)
1117 goto check_perms;
1118 /* No break here */
1119 case 0x3:
1120 /* All accesses granted */
1121 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1122 ret = 0;
1123 break;
1124 case 0x0:
1125 if (pr != 0) {
1126 /* Raise Zone protection fault. */
1127 env->spr[SPR_40x_ESR] = 1 << 22;
1128 ctx->prot = 0;
1129 ret = -2;
1130 break;
1132 /* No break here */
1133 case 0x1:
1134 check_perms:
1135 /* Check from TLB entry */
1136 ctx->prot = tlb->prot;
1137 ret = check_prot(ctx->prot, rw, access_type);
1138 if (ret == -2)
1139 env->spr[SPR_40x_ESR] = 0;
1140 break;
1142 if (ret >= 0) {
1143 ctx->raddr = raddr;
1144 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1145 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1146 ret);
1147 return 0;
1150 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1151 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1153 return ret;
1156 void store_40x_sler (CPUPPCState *env, uint32_t val)
1158 /* XXX: TO BE FIXED */
1159 if (val != 0x00000000) {
1160 cpu_abort(env, "Little-endian regions are not supported by now\n");
1162 env->spr[SPR_405_SLER] = val;
1165 static inline int mmubooke_check_tlb (CPUPPCState *env, ppcemb_tlb_t *tlb,
1166 target_phys_addr_t *raddr, int *prot,
1167 target_ulong address, int rw,
1168 int access_type, int i)
1170 int ret, _prot;
1172 if (ppcemb_tlb_check(env, tlb, raddr, address,
1173 env->spr[SPR_BOOKE_PID],
1174 !env->nb_pids, i) >= 0) {
1175 goto found_tlb;
1178 if (env->spr[SPR_BOOKE_PID1] &&
1179 ppcemb_tlb_check(env, tlb, raddr, address,
1180 env->spr[SPR_BOOKE_PID1], 0, i) >= 0) {
1181 goto found_tlb;
1184 if (env->spr[SPR_BOOKE_PID2] &&
1185 ppcemb_tlb_check(env, tlb, raddr, address,
1186 env->spr[SPR_BOOKE_PID2], 0, i) >= 0) {
1187 goto found_tlb;
1190 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1191 return -1;
1193 found_tlb:
1195 if (msr_pr != 0) {
1196 _prot = tlb->prot & 0xF;
1197 } else {
1198 _prot = (tlb->prot >> 4) & 0xF;
1201 /* Check the address space */
1202 if (access_type == ACCESS_CODE) {
1203 if (msr_ir != (tlb->attr & 1)) {
1204 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1205 return -1;
1208 *prot = _prot;
1209 if (_prot & PAGE_EXEC) {
1210 LOG_SWTLB("%s: good TLB!\n", __func__);
1211 return 0;
1214 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1215 ret = -3;
1216 } else {
1217 if (msr_dr != (tlb->attr & 1)) {
1218 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1219 return -1;
1222 *prot = _prot;
1223 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1224 LOG_SWTLB("%s: found TLB!\n", __func__);
1225 return 0;
1228 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1229 ret = -2;
1232 return ret;
1235 static int mmubooke_get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx,
1236 target_ulong address, int rw,
1237 int access_type)
1239 ppcemb_tlb_t *tlb;
1240 target_phys_addr_t raddr;
1241 int i, ret;
1243 ret = -1;
1244 raddr = (target_phys_addr_t)-1ULL;
1245 for (i = 0; i < env->nb_tlb; i++) {
1246 tlb = &env->tlb.tlbe[i];
1247 ret = mmubooke_check_tlb(env, tlb, &raddr, &ctx->prot, address, rw,
1248 access_type, i);
1249 if (!ret) {
1250 break;
1254 if (ret >= 0) {
1255 ctx->raddr = raddr;
1256 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1257 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1258 ret);
1259 } else {
1260 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1261 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1264 return ret;
1267 void booke206_flush_tlb(CPUPPCState *env, int flags, const int check_iprot)
1269 int tlb_size;
1270 int i, j;
1271 ppcmas_tlb_t *tlb = env->tlb.tlbm;
1273 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1274 if (flags & (1 << i)) {
1275 tlb_size = booke206_tlb_size(env, i);
1276 for (j = 0; j < tlb_size; j++) {
1277 if (!check_iprot || !(tlb[j].mas1 & MAS1_IPROT)) {
1278 tlb[j].mas1 &= ~MAS1_VALID;
1282 tlb += booke206_tlb_size(env, i);
1285 tlb_flush(env, 1);
1288 target_phys_addr_t booke206_tlb_to_page_size(CPUPPCState *env, ppcmas_tlb_t *tlb)
1290 int tlbm_size;
1292 tlbm_size = (tlb->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1294 return 1024ULL << tlbm_size;
1297 /* TLB check function for MAS based SoftTLBs */
1298 int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
1299 target_phys_addr_t *raddrp,
1300 target_ulong address, uint32_t pid)
1302 target_ulong mask;
1303 uint32_t tlb_pid;
1305 /* Check valid flag */
1306 if (!(tlb->mas1 & MAS1_VALID)) {
1307 return -1;
1310 mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
1311 LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
1312 PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
1313 __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
1314 tlb->mas8);
1316 /* Check PID */
1317 tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
1318 if (tlb_pid != 0 && tlb_pid != pid) {
1319 return -1;
1322 /* Check effective address */
1323 if ((address & mask) != (tlb->mas2 & MAS2_EPN_MASK)) {
1324 return -1;
1327 if (raddrp) {
1328 *raddrp = (tlb->mas7_3 & mask) | (address & ~mask);
1331 return 0;
1334 static int mmubooke206_check_tlb(CPUPPCState *env, ppcmas_tlb_t *tlb,
1335 target_phys_addr_t *raddr, int *prot,
1336 target_ulong address, int rw,
1337 int access_type)
1339 int ret;
1340 int _prot = 0;
1342 if (ppcmas_tlb_check(env, tlb, raddr, address,
1343 env->spr[SPR_BOOKE_PID]) >= 0) {
1344 goto found_tlb;
1347 if (env->spr[SPR_BOOKE_PID1] &&
1348 ppcmas_tlb_check(env, tlb, raddr, address,
1349 env->spr[SPR_BOOKE_PID1]) >= 0) {
1350 goto found_tlb;
1353 if (env->spr[SPR_BOOKE_PID2] &&
1354 ppcmas_tlb_check(env, tlb, raddr, address,
1355 env->spr[SPR_BOOKE_PID2]) >= 0) {
1356 goto found_tlb;
1359 LOG_SWTLB("%s: TLB entry not found\n", __func__);
1360 return -1;
1362 found_tlb:
1364 if (msr_pr != 0) {
1365 if (tlb->mas7_3 & MAS3_UR) {
1366 _prot |= PAGE_READ;
1368 if (tlb->mas7_3 & MAS3_UW) {
1369 _prot |= PAGE_WRITE;
1371 if (tlb->mas7_3 & MAS3_UX) {
1372 _prot |= PAGE_EXEC;
1374 } else {
1375 if (tlb->mas7_3 & MAS3_SR) {
1376 _prot |= PAGE_READ;
1378 if (tlb->mas7_3 & MAS3_SW) {
1379 _prot |= PAGE_WRITE;
1381 if (tlb->mas7_3 & MAS3_SX) {
1382 _prot |= PAGE_EXEC;
1386 /* Check the address space and permissions */
1387 if (access_type == ACCESS_CODE) {
1388 if (msr_ir != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1389 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1390 return -1;
1393 *prot = _prot;
1394 if (_prot & PAGE_EXEC) {
1395 LOG_SWTLB("%s: good TLB!\n", __func__);
1396 return 0;
1399 LOG_SWTLB("%s: no PAGE_EXEC: %x\n", __func__, _prot);
1400 ret = -3;
1401 } else {
1402 if (msr_dr != ((tlb->mas1 & MAS1_TS) >> MAS1_TS_SHIFT)) {
1403 LOG_SWTLB("%s: AS doesn't match\n", __func__);
1404 return -1;
1407 *prot = _prot;
1408 if ((!rw && _prot & PAGE_READ) || (rw && (_prot & PAGE_WRITE))) {
1409 LOG_SWTLB("%s: found TLB!\n", __func__);
1410 return 0;
1413 LOG_SWTLB("%s: PAGE_READ/WRITE doesn't match: %x\n", __func__, _prot);
1414 ret = -2;
1417 return ret;
1420 static int mmubooke206_get_physical_address(CPUPPCState *env, mmu_ctx_t *ctx,
1421 target_ulong address, int rw,
1422 int access_type)
1424 ppcmas_tlb_t *tlb;
1425 target_phys_addr_t raddr;
1426 int i, j, ret;
1428 ret = -1;
1429 raddr = (target_phys_addr_t)-1ULL;
1431 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1432 int ways = booke206_tlb_ways(env, i);
1434 for (j = 0; j < ways; j++) {
1435 tlb = booke206_get_tlbm(env, i, address, j);
1436 if (!tlb) {
1437 continue;
1439 ret = mmubooke206_check_tlb(env, tlb, &raddr, &ctx->prot, address,
1440 rw, access_type);
1441 if (ret != -1) {
1442 goto found_tlb;
1447 found_tlb:
1449 if (ret >= 0) {
1450 ctx->raddr = raddr;
1451 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1452 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1453 ret);
1454 } else {
1455 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1456 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1459 return ret;
1462 static const char *book3e_tsize_to_str[32] = {
1463 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K",
1464 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M",
1465 "1G", "2G", "4G", "8G", "16G", "32G", "64G", "128G", "256G", "512G",
1466 "1T", "2T"
1469 static void mmubooke206_dump_one_tlb(FILE *f, fprintf_function cpu_fprintf,
1470 CPUPPCState *env, int tlbn, int offset,
1471 int tlbsize)
1473 ppcmas_tlb_t *entry;
1474 int i;
1476 cpu_fprintf(f, "\nTLB%d:\n", tlbn);
1477 cpu_fprintf(f, "Effective Physical Size TID TS SRWX URWX WIMGE U0123\n");
1479 entry = &env->tlb.tlbm[offset];
1480 for (i = 0; i < tlbsize; i++, entry++) {
1481 target_phys_addr_t ea, pa, size;
1482 int tsize;
1484 if (!(entry->mas1 & MAS1_VALID)) {
1485 continue;
1488 tsize = (entry->mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
1489 size = 1024ULL << tsize;
1490 ea = entry->mas2 & ~(size - 1);
1491 pa = entry->mas7_3 & ~(size - 1);
1493 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",
1494 (uint64_t)ea, (uint64_t)pa,
1495 book3e_tsize_to_str[tsize],
1496 (entry->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT,
1497 (entry->mas1 & MAS1_TS) >> MAS1_TS_SHIFT,
1498 entry->mas7_3 & MAS3_SR ? 'R' : '-',
1499 entry->mas7_3 & MAS3_SW ? 'W' : '-',
1500 entry->mas7_3 & MAS3_SX ? 'X' : '-',
1501 entry->mas7_3 & MAS3_UR ? 'R' : '-',
1502 entry->mas7_3 & MAS3_UW ? 'W' : '-',
1503 entry->mas7_3 & MAS3_UX ? 'X' : '-',
1504 entry->mas2 & MAS2_W ? 'W' : '-',
1505 entry->mas2 & MAS2_I ? 'I' : '-',
1506 entry->mas2 & MAS2_M ? 'M' : '-',
1507 entry->mas2 & MAS2_G ? 'G' : '-',
1508 entry->mas2 & MAS2_E ? 'E' : '-',
1509 entry->mas7_3 & MAS3_U0 ? '0' : '-',
1510 entry->mas7_3 & MAS3_U1 ? '1' : '-',
1511 entry->mas7_3 & MAS3_U2 ? '2' : '-',
1512 entry->mas7_3 & MAS3_U3 ? '3' : '-');
1516 static void mmubooke206_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1517 CPUPPCState *env)
1519 int offset = 0;
1520 int i;
1522 if (kvm_enabled() && !env->kvm_sw_tlb) {
1523 cpu_fprintf(f, "Cannot access KVM TLB\n");
1524 return;
1527 for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
1528 int size = booke206_tlb_size(env, i);
1530 if (size == 0) {
1531 continue;
1534 mmubooke206_dump_one_tlb(f, cpu_fprintf, env, i, offset, size);
1535 offset += size;
1539 #if defined(TARGET_PPC64)
1540 static void mmubooks_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
1541 CPUPPCState *env)
1543 int i;
1544 uint64_t slbe, slbv;
1546 cpu_synchronize_state(env);
1548 cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
1549 for (i = 0; i < env->slb_nr; i++) {
1550 slbe = env->slb[i].esid;
1551 slbv = env->slb[i].vsid;
1552 if (slbe == 0 && slbv == 0) {
1553 continue;
1555 cpu_fprintf(f, "%d\t0x%016" PRIx64 "\t0x%016" PRIx64 "\n",
1556 i, slbe, slbv);
1559 #endif
1561 void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
1563 switch (env->mmu_model) {
1564 case POWERPC_MMU_BOOKE206:
1565 mmubooke206_dump_mmu(f, cpu_fprintf, env);
1566 break;
1567 #if defined(TARGET_PPC64)
1568 case POWERPC_MMU_64B:
1569 case POWERPC_MMU_2_06:
1570 mmubooks_dump_mmu(f, cpu_fprintf, env);
1571 break;
1572 #endif
1573 default:
1574 cpu_fprintf(f, "%s: unimplemented\n", __func__);
1578 static inline int check_physical(CPUPPCState *env, mmu_ctx_t *ctx,
1579 target_ulong eaddr, int rw)
1581 int in_plb, ret;
1583 ctx->raddr = eaddr;
1584 ctx->prot = PAGE_READ | PAGE_EXEC;
1585 ret = 0;
1586 switch (env->mmu_model) {
1587 case POWERPC_MMU_32B:
1588 case POWERPC_MMU_601:
1589 case POWERPC_MMU_SOFT_6xx:
1590 case POWERPC_MMU_SOFT_74xx:
1591 case POWERPC_MMU_SOFT_4xx:
1592 case POWERPC_MMU_REAL:
1593 case POWERPC_MMU_BOOKE:
1594 ctx->prot |= PAGE_WRITE;
1595 break;
1596 #if defined(TARGET_PPC64)
1597 case POWERPC_MMU_620:
1598 case POWERPC_MMU_64B:
1599 case POWERPC_MMU_2_06:
1600 /* Real address are 60 bits long */
1601 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1602 ctx->prot |= PAGE_WRITE;
1603 break;
1604 #endif
1605 case POWERPC_MMU_SOFT_4xx_Z:
1606 if (unlikely(msr_pe != 0)) {
1607 /* 403 family add some particular protections,
1608 * using PBL/PBU registers for accesses with no translation.
1610 in_plb =
1611 /* Check PLB validity */
1612 (env->pb[0] < env->pb[1] &&
1613 /* and address in plb area */
1614 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1615 (env->pb[2] < env->pb[3] &&
1616 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1617 if (in_plb ^ msr_px) {
1618 /* Access in protected area */
1619 if (rw == 1) {
1620 /* Access is not allowed */
1621 ret = -2;
1623 } else {
1624 /* Read-write access is allowed */
1625 ctx->prot |= PAGE_WRITE;
1628 break;
1629 case POWERPC_MMU_MPC8xx:
1630 /* XXX: TODO */
1631 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1632 break;
1633 case POWERPC_MMU_BOOKE206:
1634 cpu_abort(env, "BookE 2.06 MMU doesn't have physical real mode\n");
1635 break;
1636 default:
1637 cpu_abort(env, "Unknown or invalid MMU model\n");
1638 return -1;
1641 return ret;
1644 int get_physical_address (CPUPPCState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1645 int rw, int access_type)
1647 int ret;
1649 #if 0
1650 qemu_log("%s\n", __func__);
1651 #endif
1652 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1653 (access_type != ACCESS_CODE && msr_dr == 0)) {
1654 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1655 /* The BookE MMU always performs address translation. The
1656 IS and DS bits only affect the address space. */
1657 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1658 rw, access_type);
1659 } else if (env->mmu_model == POWERPC_MMU_BOOKE206) {
1660 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1661 access_type);
1662 } else {
1663 /* No address translation. */
1664 ret = check_physical(env, ctx, eaddr, rw);
1666 } else {
1667 ret = -1;
1668 switch (env->mmu_model) {
1669 case POWERPC_MMU_32B:
1670 case POWERPC_MMU_601:
1671 case POWERPC_MMU_SOFT_6xx:
1672 case POWERPC_MMU_SOFT_74xx:
1673 /* Try to find a BAT */
1674 if (env->nb_BATs != 0)
1675 ret = get_bat(env, ctx, eaddr, rw, access_type);
1676 #if defined(TARGET_PPC64)
1677 case POWERPC_MMU_620:
1678 case POWERPC_MMU_64B:
1679 case POWERPC_MMU_2_06:
1680 #endif
1681 if (ret < 0) {
1682 /* We didn't match any BAT entry or don't have BATs */
1683 ret = get_segment(env, ctx, eaddr, rw, access_type);
1685 break;
1686 case POWERPC_MMU_SOFT_4xx:
1687 case POWERPC_MMU_SOFT_4xx_Z:
1688 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1689 rw, access_type);
1690 break;
1691 case POWERPC_MMU_BOOKE:
1692 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1693 rw, access_type);
1694 break;
1695 case POWERPC_MMU_BOOKE206:
1696 ret = mmubooke206_get_physical_address(env, ctx, eaddr, rw,
1697 access_type);
1698 break;
1699 case POWERPC_MMU_MPC8xx:
1700 /* XXX: TODO */
1701 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1702 break;
1703 case POWERPC_MMU_REAL:
1704 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1705 return -1;
1706 default:
1707 cpu_abort(env, "Unknown or invalid MMU model\n");
1708 return -1;
1711 #if 0
1712 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1713 __func__, eaddr, ret, ctx->raddr);
1714 #endif
1716 return ret;
1719 target_phys_addr_t cpu_get_phys_page_debug (CPUPPCState *env, target_ulong addr)
1721 mmu_ctx_t ctx;
1723 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1724 return -1;
1726 return ctx.raddr & TARGET_PAGE_MASK;
1729 static void booke206_update_mas_tlb_miss(CPUPPCState *env, target_ulong address,
1730 int rw)
1732 env->spr[SPR_BOOKE_MAS0] = env->spr[SPR_BOOKE_MAS4] & MAS4_TLBSELD_MASK;
1733 env->spr[SPR_BOOKE_MAS1] = env->spr[SPR_BOOKE_MAS4] & MAS4_TSIZED_MASK;
1734 env->spr[SPR_BOOKE_MAS2] = env->spr[SPR_BOOKE_MAS4] & MAS4_WIMGED_MASK;
1735 env->spr[SPR_BOOKE_MAS3] = 0;
1736 env->spr[SPR_BOOKE_MAS6] = 0;
1737 env->spr[SPR_BOOKE_MAS7] = 0;
1739 /* AS */
1740 if (((rw == 2) && msr_ir) || ((rw != 2) && msr_dr)) {
1741 env->spr[SPR_BOOKE_MAS1] |= MAS1_TS;
1742 env->spr[SPR_BOOKE_MAS6] |= MAS6_SAS;
1745 env->spr[SPR_BOOKE_MAS1] |= MAS1_VALID;
1746 env->spr[SPR_BOOKE_MAS2] |= address & MAS2_EPN_MASK;
1748 switch (env->spr[SPR_BOOKE_MAS4] & MAS4_TIDSELD_PIDZ) {
1749 case MAS4_TIDSELD_PID0:
1750 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID] << MAS1_TID_SHIFT;
1751 break;
1752 case MAS4_TIDSELD_PID1:
1753 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID1] << MAS1_TID_SHIFT;
1754 break;
1755 case MAS4_TIDSELD_PID2:
1756 env->spr[SPR_BOOKE_MAS1] |= env->spr[SPR_BOOKE_PID2] << MAS1_TID_SHIFT;
1757 break;
1760 env->spr[SPR_BOOKE_MAS6] |= env->spr[SPR_BOOKE_PID] << 16;
1762 /* next victim logic */
1763 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_ESEL_SHIFT;
1764 env->last_way++;
1765 env->last_way &= booke206_tlb_ways(env, 0) - 1;
1766 env->spr[SPR_BOOKE_MAS0] |= env->last_way << MAS0_NV_SHIFT;
1769 /* Perform address translation */
1770 int cpu_ppc_handle_mmu_fault (CPUPPCState *env, target_ulong address, int rw,
1771 int mmu_idx)
1773 mmu_ctx_t ctx;
1774 int access_type;
1775 int ret = 0;
1777 if (rw == 2) {
1778 /* code access */
1779 rw = 0;
1780 access_type = ACCESS_CODE;
1781 } else {
1782 /* data access */
1783 access_type = env->access_type;
1785 ret = get_physical_address(env, &ctx, address, rw, access_type);
1786 if (ret == 0) {
1787 tlb_set_page(env, address & TARGET_PAGE_MASK,
1788 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1789 mmu_idx, TARGET_PAGE_SIZE);
1790 ret = 0;
1791 } else if (ret < 0) {
1792 LOG_MMU_STATE(env);
1793 if (access_type == ACCESS_CODE) {
1794 switch (ret) {
1795 case -1:
1796 /* No matches in page tables or TLB */
1797 switch (env->mmu_model) {
1798 case POWERPC_MMU_SOFT_6xx:
1799 env->exception_index = POWERPC_EXCP_IFTLB;
1800 env->error_code = 1 << 18;
1801 env->spr[SPR_IMISS] = address;
1802 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1803 goto tlb_miss;
1804 case POWERPC_MMU_SOFT_74xx:
1805 env->exception_index = POWERPC_EXCP_IFTLB;
1806 goto tlb_miss_74xx;
1807 case POWERPC_MMU_SOFT_4xx:
1808 case POWERPC_MMU_SOFT_4xx_Z:
1809 env->exception_index = POWERPC_EXCP_ITLB;
1810 env->error_code = 0;
1811 env->spr[SPR_40x_DEAR] = address;
1812 env->spr[SPR_40x_ESR] = 0x00000000;
1813 break;
1814 case POWERPC_MMU_32B:
1815 case POWERPC_MMU_601:
1816 #if defined(TARGET_PPC64)
1817 case POWERPC_MMU_620:
1818 case POWERPC_MMU_64B:
1819 case POWERPC_MMU_2_06:
1820 #endif
1821 env->exception_index = POWERPC_EXCP_ISI;
1822 env->error_code = 0x40000000;
1823 break;
1824 case POWERPC_MMU_BOOKE206:
1825 booke206_update_mas_tlb_miss(env, address, rw);
1826 /* fall through */
1827 case POWERPC_MMU_BOOKE:
1828 env->exception_index = POWERPC_EXCP_ITLB;
1829 env->error_code = 0;
1830 env->spr[SPR_BOOKE_DEAR] = address;
1831 return -1;
1832 case POWERPC_MMU_MPC8xx:
1833 /* XXX: TODO */
1834 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1835 break;
1836 case POWERPC_MMU_REAL:
1837 cpu_abort(env, "PowerPC in real mode should never raise "
1838 "any MMU exceptions\n");
1839 return -1;
1840 default:
1841 cpu_abort(env, "Unknown or invalid MMU model\n");
1842 return -1;
1844 break;
1845 case -2:
1846 /* Access rights violation */
1847 env->exception_index = POWERPC_EXCP_ISI;
1848 env->error_code = 0x08000000;
1849 break;
1850 case -3:
1851 /* No execute protection violation */
1852 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1853 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1854 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1856 env->exception_index = POWERPC_EXCP_ISI;
1857 env->error_code = 0x10000000;
1858 break;
1859 case -4:
1860 /* Direct store exception */
1861 /* No code fetch is allowed in direct-store areas */
1862 env->exception_index = POWERPC_EXCP_ISI;
1863 env->error_code = 0x10000000;
1864 break;
1865 #if defined(TARGET_PPC64)
1866 case -5:
1867 /* No match in segment table */
1868 if (env->mmu_model == POWERPC_MMU_620) {
1869 env->exception_index = POWERPC_EXCP_ISI;
1870 /* XXX: this might be incorrect */
1871 env->error_code = 0x40000000;
1872 } else {
1873 env->exception_index = POWERPC_EXCP_ISEG;
1874 env->error_code = 0;
1876 break;
1877 #endif
1879 } else {
1880 switch (ret) {
1881 case -1:
1882 /* No matches in page tables or TLB */
1883 switch (env->mmu_model) {
1884 case POWERPC_MMU_SOFT_6xx:
1885 if (rw == 1) {
1886 env->exception_index = POWERPC_EXCP_DSTLB;
1887 env->error_code = 1 << 16;
1888 } else {
1889 env->exception_index = POWERPC_EXCP_DLTLB;
1890 env->error_code = 0;
1892 env->spr[SPR_DMISS] = address;
1893 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1894 tlb_miss:
1895 env->error_code |= ctx.key << 19;
1896 env->spr[SPR_HASH1] = env->htab_base +
1897 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1898 env->spr[SPR_HASH2] = env->htab_base +
1899 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1900 break;
1901 case POWERPC_MMU_SOFT_74xx:
1902 if (rw == 1) {
1903 env->exception_index = POWERPC_EXCP_DSTLB;
1904 } else {
1905 env->exception_index = POWERPC_EXCP_DLTLB;
1907 tlb_miss_74xx:
1908 /* Implement LRU algorithm */
1909 env->error_code = ctx.key << 19;
1910 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1911 ((env->last_way + 1) & (env->nb_ways - 1));
1912 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1913 break;
1914 case POWERPC_MMU_SOFT_4xx:
1915 case POWERPC_MMU_SOFT_4xx_Z:
1916 env->exception_index = POWERPC_EXCP_DTLB;
1917 env->error_code = 0;
1918 env->spr[SPR_40x_DEAR] = address;
1919 if (rw)
1920 env->spr[SPR_40x_ESR] = 0x00800000;
1921 else
1922 env->spr[SPR_40x_ESR] = 0x00000000;
1923 break;
1924 case POWERPC_MMU_32B:
1925 case POWERPC_MMU_601:
1926 #if defined(TARGET_PPC64)
1927 case POWERPC_MMU_620:
1928 case POWERPC_MMU_64B:
1929 case POWERPC_MMU_2_06:
1930 #endif
1931 env->exception_index = POWERPC_EXCP_DSI;
1932 env->error_code = 0;
1933 env->spr[SPR_DAR] = address;
1934 if (rw == 1)
1935 env->spr[SPR_DSISR] = 0x42000000;
1936 else
1937 env->spr[SPR_DSISR] = 0x40000000;
1938 break;
1939 case POWERPC_MMU_MPC8xx:
1940 /* XXX: TODO */
1941 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1942 break;
1943 case POWERPC_MMU_BOOKE206:
1944 booke206_update_mas_tlb_miss(env, address, rw);
1945 /* fall through */
1946 case POWERPC_MMU_BOOKE:
1947 env->exception_index = POWERPC_EXCP_DTLB;
1948 env->error_code = 0;
1949 env->spr[SPR_BOOKE_DEAR] = address;
1950 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1951 return -1;
1952 case POWERPC_MMU_REAL:
1953 cpu_abort(env, "PowerPC in real mode should never raise "
1954 "any MMU exceptions\n");
1955 return -1;
1956 default:
1957 cpu_abort(env, "Unknown or invalid MMU model\n");
1958 return -1;
1960 break;
1961 case -2:
1962 /* Access rights violation */
1963 env->exception_index = POWERPC_EXCP_DSI;
1964 env->error_code = 0;
1965 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1966 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1967 env->spr[SPR_40x_DEAR] = address;
1968 if (rw) {
1969 env->spr[SPR_40x_ESR] |= 0x00800000;
1971 } else if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
1972 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
1973 env->spr[SPR_BOOKE_DEAR] = address;
1974 env->spr[SPR_BOOKE_ESR] = rw ? ESR_ST : 0;
1975 } else {
1976 env->spr[SPR_DAR] = address;
1977 if (rw == 1) {
1978 env->spr[SPR_DSISR] = 0x0A000000;
1979 } else {
1980 env->spr[SPR_DSISR] = 0x08000000;
1983 break;
1984 case -4:
1985 /* Direct store exception */
1986 switch (access_type) {
1987 case ACCESS_FLOAT:
1988 /* Floating point load/store */
1989 env->exception_index = POWERPC_EXCP_ALIGN;
1990 env->error_code = POWERPC_EXCP_ALIGN_FP;
1991 env->spr[SPR_DAR] = address;
1992 break;
1993 case ACCESS_RES:
1994 /* lwarx, ldarx or stwcx. */
1995 env->exception_index = POWERPC_EXCP_DSI;
1996 env->error_code = 0;
1997 env->spr[SPR_DAR] = address;
1998 if (rw == 1)
1999 env->spr[SPR_DSISR] = 0x06000000;
2000 else
2001 env->spr[SPR_DSISR] = 0x04000000;
2002 break;
2003 case ACCESS_EXT:
2004 /* eciwx or ecowx */
2005 env->exception_index = POWERPC_EXCP_DSI;
2006 env->error_code = 0;
2007 env->spr[SPR_DAR] = address;
2008 if (rw == 1)
2009 env->spr[SPR_DSISR] = 0x06100000;
2010 else
2011 env->spr[SPR_DSISR] = 0x04100000;
2012 break;
2013 default:
2014 printf("DSI: invalid exception (%d)\n", ret);
2015 env->exception_index = POWERPC_EXCP_PROGRAM;
2016 env->error_code =
2017 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
2018 env->spr[SPR_DAR] = address;
2019 break;
2021 break;
2022 #if defined(TARGET_PPC64)
2023 case -5:
2024 /* No match in segment table */
2025 if (env->mmu_model == POWERPC_MMU_620) {
2026 env->exception_index = POWERPC_EXCP_DSI;
2027 env->error_code = 0;
2028 env->spr[SPR_DAR] = address;
2029 /* XXX: this might be incorrect */
2030 if (rw == 1)
2031 env->spr[SPR_DSISR] = 0x42000000;
2032 else
2033 env->spr[SPR_DSISR] = 0x40000000;
2034 } else {
2035 env->exception_index = POWERPC_EXCP_DSEG;
2036 env->error_code = 0;
2037 env->spr[SPR_DAR] = address;
2039 break;
2040 #endif
2043 #if 0
2044 printf("%s: set exception to %d %02x\n", __func__,
2045 env->exception, env->error_code);
2046 #endif
2047 ret = 1;
2050 return ret;
2053 /*****************************************************************************/
2054 /* BATs management */
2055 #if !defined(FLUSH_ALL_TLBS)
2056 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
2057 target_ulong mask)
2059 target_ulong base, end, page;
2061 base = BATu & ~0x0001FFFF;
2062 end = base + mask + 0x00020000;
2063 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
2064 TARGET_FMT_lx ")\n", base, end, mask);
2065 for (page = base; page != end; page += TARGET_PAGE_SIZE)
2066 tlb_flush_page(env, page);
2067 LOG_BATS("Flush done\n");
2069 #endif
2071 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
2072 target_ulong value)
2074 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
2075 nr, ul == 0 ? 'u' : 'l', value, env->nip);
2078 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
2080 target_ulong mask;
2082 dump_store_bat(env, 'I', 0, nr, value);
2083 if (env->IBAT[0][nr] != value) {
2084 mask = (value << 15) & 0x0FFE0000UL;
2085 #if !defined(FLUSH_ALL_TLBS)
2086 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2087 #endif
2088 /* When storing valid upper BAT, mask BEPI and BRPN
2089 * and invalidate all TLBs covered by this BAT
2091 mask = (value << 15) & 0x0FFE0000UL;
2092 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2093 (value & ~0x0001FFFFUL & ~mask);
2094 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
2095 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
2096 #if !defined(FLUSH_ALL_TLBS)
2097 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2098 #else
2099 tlb_flush(env, 1);
2100 #endif
2104 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
2106 dump_store_bat(env, 'I', 1, nr, value);
2107 env->IBAT[1][nr] = value;
2110 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
2112 target_ulong mask;
2114 dump_store_bat(env, 'D', 0, nr, value);
2115 if (env->DBAT[0][nr] != value) {
2116 /* When storing valid upper BAT, mask BEPI and BRPN
2117 * and invalidate all TLBs covered by this BAT
2119 mask = (value << 15) & 0x0FFE0000UL;
2120 #if !defined(FLUSH_ALL_TLBS)
2121 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2122 #endif
2123 mask = (value << 15) & 0x0FFE0000UL;
2124 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
2125 (value & ~0x0001FFFFUL & ~mask);
2126 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
2127 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
2128 #if !defined(FLUSH_ALL_TLBS)
2129 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
2130 #else
2131 tlb_flush(env, 1);
2132 #endif
2136 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
2138 dump_store_bat(env, 'D', 1, nr, value);
2139 env->DBAT[1][nr] = value;
2142 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
2144 target_ulong mask;
2145 #if defined(FLUSH_ALL_TLBS)
2146 int do_inval;
2147 #endif
2149 dump_store_bat(env, 'I', 0, nr, value);
2150 if (env->IBAT[0][nr] != value) {
2151 #if defined(FLUSH_ALL_TLBS)
2152 do_inval = 0;
2153 #endif
2154 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2155 if (env->IBAT[1][nr] & 0x40) {
2156 /* Invalidate BAT only if it is valid */
2157 #if !defined(FLUSH_ALL_TLBS)
2158 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2159 #else
2160 do_inval = 1;
2161 #endif
2163 /* When storing valid upper BAT, mask BEPI and BRPN
2164 * and invalidate all TLBs covered by this BAT
2166 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
2167 (value & ~0x0001FFFFUL & ~mask);
2168 env->DBAT[0][nr] = env->IBAT[0][nr];
2169 if (env->IBAT[1][nr] & 0x40) {
2170 #if !defined(FLUSH_ALL_TLBS)
2171 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2172 #else
2173 do_inval = 1;
2174 #endif
2176 #if defined(FLUSH_ALL_TLBS)
2177 if (do_inval)
2178 tlb_flush(env, 1);
2179 #endif
2183 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
2185 target_ulong mask;
2186 #if defined(FLUSH_ALL_TLBS)
2187 int do_inval;
2188 #endif
2190 dump_store_bat(env, 'I', 1, nr, value);
2191 if (env->IBAT[1][nr] != value) {
2192 #if defined(FLUSH_ALL_TLBS)
2193 do_inval = 0;
2194 #endif
2195 if (env->IBAT[1][nr] & 0x40) {
2196 #if !defined(FLUSH_ALL_TLBS)
2197 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
2198 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2199 #else
2200 do_inval = 1;
2201 #endif
2203 if (value & 0x40) {
2204 #if !defined(FLUSH_ALL_TLBS)
2205 mask = (value << 17) & 0x0FFE0000UL;
2206 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
2207 #else
2208 do_inval = 1;
2209 #endif
2211 env->IBAT[1][nr] = value;
2212 env->DBAT[1][nr] = value;
2213 #if defined(FLUSH_ALL_TLBS)
2214 if (do_inval)
2215 tlb_flush(env, 1);
2216 #endif
2220 /*****************************************************************************/
2221 /* TLB management */
2222 void ppc_tlb_invalidate_all (CPUPPCState *env)
2224 switch (env->mmu_model) {
2225 case POWERPC_MMU_SOFT_6xx:
2226 case POWERPC_MMU_SOFT_74xx:
2227 ppc6xx_tlb_invalidate_all(env);
2228 break;
2229 case POWERPC_MMU_SOFT_4xx:
2230 case POWERPC_MMU_SOFT_4xx_Z:
2231 ppc4xx_tlb_invalidate_all(env);
2232 break;
2233 case POWERPC_MMU_REAL:
2234 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2235 break;
2236 case POWERPC_MMU_MPC8xx:
2237 /* XXX: TODO */
2238 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2239 break;
2240 case POWERPC_MMU_BOOKE:
2241 tlb_flush(env, 1);
2242 break;
2243 case POWERPC_MMU_BOOKE206:
2244 booke206_flush_tlb(env, -1, 0);
2245 break;
2246 case POWERPC_MMU_32B:
2247 case POWERPC_MMU_601:
2248 #if defined(TARGET_PPC64)
2249 case POWERPC_MMU_620:
2250 case POWERPC_MMU_64B:
2251 case POWERPC_MMU_2_06:
2252 #endif /* defined(TARGET_PPC64) */
2253 tlb_flush(env, 1);
2254 break;
2255 default:
2256 /* XXX: TODO */
2257 cpu_abort(env, "Unknown MMU model\n");
2258 break;
2262 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
2264 #if !defined(FLUSH_ALL_TLBS)
2265 addr &= TARGET_PAGE_MASK;
2266 switch (env->mmu_model) {
2267 case POWERPC_MMU_SOFT_6xx:
2268 case POWERPC_MMU_SOFT_74xx:
2269 ppc6xx_tlb_invalidate_virt(env, addr, 0);
2270 if (env->id_tlbs == 1)
2271 ppc6xx_tlb_invalidate_virt(env, addr, 1);
2272 break;
2273 case POWERPC_MMU_SOFT_4xx:
2274 case POWERPC_MMU_SOFT_4xx_Z:
2275 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
2276 break;
2277 case POWERPC_MMU_REAL:
2278 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
2279 break;
2280 case POWERPC_MMU_MPC8xx:
2281 /* XXX: TODO */
2282 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2283 break;
2284 case POWERPC_MMU_BOOKE:
2285 /* XXX: TODO */
2286 cpu_abort(env, "BookE MMU model is not implemented\n");
2287 break;
2288 case POWERPC_MMU_BOOKE206:
2289 /* XXX: TODO */
2290 cpu_abort(env, "BookE 2.06 MMU model is not implemented\n");
2291 break;
2292 case POWERPC_MMU_32B:
2293 case POWERPC_MMU_601:
2294 /* tlbie invalidate TLBs for all segments */
2295 addr &= ~((target_ulong)-1ULL << 28);
2296 /* XXX: this case should be optimized,
2297 * giving a mask to tlb_flush_page
2299 tlb_flush_page(env, addr | (0x0 << 28));
2300 tlb_flush_page(env, addr | (0x1 << 28));
2301 tlb_flush_page(env, addr | (0x2 << 28));
2302 tlb_flush_page(env, addr | (0x3 << 28));
2303 tlb_flush_page(env, addr | (0x4 << 28));
2304 tlb_flush_page(env, addr | (0x5 << 28));
2305 tlb_flush_page(env, addr | (0x6 << 28));
2306 tlb_flush_page(env, addr | (0x7 << 28));
2307 tlb_flush_page(env, addr | (0x8 << 28));
2308 tlb_flush_page(env, addr | (0x9 << 28));
2309 tlb_flush_page(env, addr | (0xA << 28));
2310 tlb_flush_page(env, addr | (0xB << 28));
2311 tlb_flush_page(env, addr | (0xC << 28));
2312 tlb_flush_page(env, addr | (0xD << 28));
2313 tlb_flush_page(env, addr | (0xE << 28));
2314 tlb_flush_page(env, addr | (0xF << 28));
2315 break;
2316 #if defined(TARGET_PPC64)
2317 case POWERPC_MMU_620:
2318 case POWERPC_MMU_64B:
2319 case POWERPC_MMU_2_06:
2320 /* tlbie invalidate TLBs for all segments */
2321 /* XXX: given the fact that there are too many segments to invalidate,
2322 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2323 * we just invalidate all TLBs
2325 tlb_flush(env, 1);
2326 break;
2327 #endif /* defined(TARGET_PPC64) */
2328 default:
2329 /* XXX: TODO */
2330 cpu_abort(env, "Unknown MMU model\n");
2331 break;
2333 #else
2334 ppc_tlb_invalidate_all(env);
2335 #endif
2338 /*****************************************************************************/
2339 /* Special registers manipulation */
2340 #if defined(TARGET_PPC64)
2341 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2343 if (env->asr != value) {
2344 env->asr = value;
2345 tlb_flush(env, 1);
2348 #endif
2350 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
2352 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
2353 if (env->spr[SPR_SDR1] != value) {
2354 env->spr[SPR_SDR1] = value;
2355 #if defined(TARGET_PPC64)
2356 if (env->mmu_model & POWERPC_MMU_64) {
2357 target_ulong htabsize = value & SDR_64_HTABSIZE;
2359 if (htabsize > 28) {
2360 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
2361 " stored in SDR1\n", htabsize);
2362 htabsize = 28;
2364 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
2365 env->htab_base = value & SDR_64_HTABORG;
2366 } else
2367 #endif /* defined(TARGET_PPC64) */
2369 /* FIXME: Should check for valid HTABMASK values */
2370 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
2371 env->htab_base = value & SDR_32_HTABORG;
2373 tlb_flush(env, 1);
2377 #if defined(TARGET_PPC64)
2378 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
2380 // XXX
2381 return 0;
2383 #endif
2385 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2387 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
2388 srnum, value, env->sr[srnum]);
2389 #if defined(TARGET_PPC64)
2390 if (env->mmu_model & POWERPC_MMU_64) {
2391 uint64_t rb = 0, rs = 0;
2393 /* ESID = srnum */
2394 rb |= ((uint32_t)srnum & 0xf) << 28;
2395 /* Set the valid bit */
2396 rb |= 1 << 27;
2397 /* Index = ESID */
2398 rb |= (uint32_t)srnum;
2400 /* VSID = VSID */
2401 rs |= (value & 0xfffffff) << 12;
2402 /* flags = flags */
2403 rs |= ((value >> 27) & 0xf) << 8;
2405 ppc_store_slb(env, rb, rs);
2406 } else
2407 #endif
2408 if (env->sr[srnum] != value) {
2409 env->sr[srnum] = value;
2410 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
2411 flusing the whole TLB. */
2412 #if !defined(FLUSH_ALL_TLBS) && 0
2414 target_ulong page, end;
2415 /* Invalidate 256 MB of virtual memory */
2416 page = (16 << 20) * srnum;
2417 end = page + (16 << 20);
2418 for (; page != end; page += TARGET_PAGE_SIZE)
2419 tlb_flush_page(env, page);
2421 #else
2422 tlb_flush(env, 1);
2423 #endif
2426 #endif /* !defined (CONFIG_USER_ONLY) */
2428 /* GDBstub can read and write MSR... */
2429 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2431 hreg_store_msr(env, value, 0);
2434 /*****************************************************************************/
2435 /* Exception processing */
2436 #if defined (CONFIG_USER_ONLY)
2437 void do_interrupt (CPUPPCState *env)
2439 env->exception_index = POWERPC_EXCP_NONE;
2440 env->error_code = 0;
2443 void ppc_hw_interrupt (CPUPPCState *env)
2445 env->exception_index = POWERPC_EXCP_NONE;
2446 env->error_code = 0;
2448 #else /* defined (CONFIG_USER_ONLY) */
2449 static inline void dump_syscall(CPUPPCState *env)
2451 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2452 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2453 " nip=" TARGET_FMT_lx "\n",
2454 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2455 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2456 ppc_dump_gpr(env, 6), env->nip);
2459 /* Note that this function should be greatly optimized
2460 * when called with a constant excp, from ppc_hw_interrupt
2462 static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
2464 target_ulong msr, new_msr, vector;
2465 int srr0, srr1, asrr0, asrr1;
2466 int lpes0, lpes1, lev;
2468 if (0) {
2469 /* XXX: find a suitable condition to enable the hypervisor mode */
2470 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2471 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2472 } else {
2473 /* Those values ensure we won't enter the hypervisor mode */
2474 lpes0 = 0;
2475 lpes1 = 1;
2478 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2479 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2481 /* new srr1 value excluding must-be-zero bits */
2482 msr = env->msr & ~0x783f0000ULL;
2484 /* new interrupt handler msr */
2485 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2487 /* target registers */
2488 srr0 = SPR_SRR0;
2489 srr1 = SPR_SRR1;
2490 asrr0 = -1;
2491 asrr1 = -1;
2493 switch (excp) {
2494 case POWERPC_EXCP_NONE:
2495 /* Should never happen */
2496 return;
2497 case POWERPC_EXCP_CRITICAL: /* Critical input */
2498 switch (excp_model) {
2499 case POWERPC_EXCP_40x:
2500 srr0 = SPR_40x_SRR2;
2501 srr1 = SPR_40x_SRR3;
2502 break;
2503 case POWERPC_EXCP_BOOKE:
2504 srr0 = SPR_BOOKE_CSRR0;
2505 srr1 = SPR_BOOKE_CSRR1;
2506 break;
2507 case POWERPC_EXCP_G2:
2508 break;
2509 default:
2510 goto excp_invalid;
2512 goto store_next;
2513 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2514 if (msr_me == 0) {
2515 /* Machine check exception is not enabled.
2516 * Enter checkstop state.
2518 if (qemu_log_enabled()) {
2519 qemu_log("Machine check while not allowed. "
2520 "Entering checkstop state\n");
2521 } else {
2522 fprintf(stderr, "Machine check while not allowed. "
2523 "Entering checkstop state\n");
2525 env->halted = 1;
2526 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2528 if (0) {
2529 /* XXX: find a suitable condition to enable the hypervisor mode */
2530 new_msr |= (target_ulong)MSR_HVB;
2533 /* machine check exceptions don't have ME set */
2534 new_msr &= ~((target_ulong)1 << MSR_ME);
2536 /* XXX: should also have something loaded in DAR / DSISR */
2537 switch (excp_model) {
2538 case POWERPC_EXCP_40x:
2539 srr0 = SPR_40x_SRR2;
2540 srr1 = SPR_40x_SRR3;
2541 break;
2542 case POWERPC_EXCP_BOOKE:
2543 srr0 = SPR_BOOKE_MCSRR0;
2544 srr1 = SPR_BOOKE_MCSRR1;
2545 asrr0 = SPR_BOOKE_CSRR0;
2546 asrr1 = SPR_BOOKE_CSRR1;
2547 break;
2548 default:
2549 break;
2551 goto store_next;
2552 case POWERPC_EXCP_DSI: /* Data storage exception */
2553 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2554 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2555 if (lpes1 == 0)
2556 new_msr |= (target_ulong)MSR_HVB;
2557 goto store_next;
2558 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2559 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2560 "\n", msr, env->nip);
2561 if (lpes1 == 0)
2562 new_msr |= (target_ulong)MSR_HVB;
2563 msr |= env->error_code;
2564 goto store_next;
2565 case POWERPC_EXCP_EXTERNAL: /* External input */
2566 if (lpes0 == 1)
2567 new_msr |= (target_ulong)MSR_HVB;
2568 goto store_next;
2569 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2570 if (lpes1 == 0)
2571 new_msr |= (target_ulong)MSR_HVB;
2572 /* XXX: this is false */
2573 /* Get rS/rD and rA from faulting opcode */
2574 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2575 goto store_current;
2576 case POWERPC_EXCP_PROGRAM: /* Program exception */
2577 switch (env->error_code & ~0xF) {
2578 case POWERPC_EXCP_FP:
2579 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2580 LOG_EXCP("Ignore floating point exception\n");
2581 env->exception_index = POWERPC_EXCP_NONE;
2582 env->error_code = 0;
2583 return;
2585 if (lpes1 == 0)
2586 new_msr |= (target_ulong)MSR_HVB;
2587 msr |= 0x00100000;
2588 if (msr_fe0 == msr_fe1)
2589 goto store_next;
2590 msr |= 0x00010000;
2591 break;
2592 case POWERPC_EXCP_INVAL:
2593 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2594 if (lpes1 == 0)
2595 new_msr |= (target_ulong)MSR_HVB;
2596 msr |= 0x00080000;
2597 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
2598 break;
2599 case POWERPC_EXCP_PRIV:
2600 if (lpes1 == 0)
2601 new_msr |= (target_ulong)MSR_HVB;
2602 msr |= 0x00040000;
2603 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
2604 break;
2605 case POWERPC_EXCP_TRAP:
2606 if (lpes1 == 0)
2607 new_msr |= (target_ulong)MSR_HVB;
2608 msr |= 0x00020000;
2609 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
2610 break;
2611 default:
2612 /* Should never occur */
2613 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2614 env->error_code);
2615 break;
2617 goto store_current;
2618 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2619 if (lpes1 == 0)
2620 new_msr |= (target_ulong)MSR_HVB;
2621 goto store_current;
2622 case POWERPC_EXCP_SYSCALL: /* System call exception */
2623 dump_syscall(env);
2624 lev = env->error_code;
2625 if ((lev == 1) && cpu_ppc_hypercall) {
2626 cpu_ppc_hypercall(env);
2627 return;
2629 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2630 new_msr |= (target_ulong)MSR_HVB;
2631 goto store_next;
2632 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2633 goto store_current;
2634 case POWERPC_EXCP_DECR: /* Decrementer exception */
2635 if (lpes1 == 0)
2636 new_msr |= (target_ulong)MSR_HVB;
2637 goto store_next;
2638 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2639 /* FIT on 4xx */
2640 LOG_EXCP("FIT exception\n");
2641 goto store_next;
2642 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2643 LOG_EXCP("WDT exception\n");
2644 switch (excp_model) {
2645 case POWERPC_EXCP_BOOKE:
2646 srr0 = SPR_BOOKE_CSRR0;
2647 srr1 = SPR_BOOKE_CSRR1;
2648 break;
2649 default:
2650 break;
2652 goto store_next;
2653 case POWERPC_EXCP_DTLB: /* Data TLB error */
2654 goto store_next;
2655 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2656 goto store_next;
2657 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2658 switch (excp_model) {
2659 case POWERPC_EXCP_BOOKE:
2660 srr0 = SPR_BOOKE_DSRR0;
2661 srr1 = SPR_BOOKE_DSRR1;
2662 asrr0 = SPR_BOOKE_CSRR0;
2663 asrr1 = SPR_BOOKE_CSRR1;
2664 break;
2665 default:
2666 break;
2668 /* XXX: TODO */
2669 cpu_abort(env, "Debug exception is not implemented yet !\n");
2670 goto store_next;
2671 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2672 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2673 goto store_current;
2674 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2675 /* XXX: TODO */
2676 cpu_abort(env, "Embedded floating point data exception "
2677 "is not implemented yet !\n");
2678 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2679 goto store_next;
2680 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2681 /* XXX: TODO */
2682 cpu_abort(env, "Embedded floating point round exception "
2683 "is not implemented yet !\n");
2684 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
2685 goto store_next;
2686 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2687 /* XXX: TODO */
2688 cpu_abort(env,
2689 "Performance counter exception is not implemented yet !\n");
2690 goto store_next;
2691 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2692 goto store_next;
2693 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2694 srr0 = SPR_BOOKE_CSRR0;
2695 srr1 = SPR_BOOKE_CSRR1;
2696 goto store_next;
2697 case POWERPC_EXCP_RESET: /* System reset exception */
2698 if (msr_pow) {
2699 /* indicate that we resumed from power save mode */
2700 msr |= 0x10000;
2701 } else {
2702 new_msr &= ~((target_ulong)1 << MSR_ME);
2705 if (0) {
2706 /* XXX: find a suitable condition to enable the hypervisor mode */
2707 new_msr |= (target_ulong)MSR_HVB;
2709 goto store_next;
2710 case POWERPC_EXCP_DSEG: /* Data segment exception */
2711 if (lpes1 == 0)
2712 new_msr |= (target_ulong)MSR_HVB;
2713 goto store_next;
2714 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2715 if (lpes1 == 0)
2716 new_msr |= (target_ulong)MSR_HVB;
2717 goto store_next;
2718 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2719 srr0 = SPR_HSRR0;
2720 srr1 = SPR_HSRR1;
2721 new_msr |= (target_ulong)MSR_HVB;
2722 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2723 goto store_next;
2724 case POWERPC_EXCP_TRACE: /* Trace exception */
2725 if (lpes1 == 0)
2726 new_msr |= (target_ulong)MSR_HVB;
2727 goto store_next;
2728 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2729 srr0 = SPR_HSRR0;
2730 srr1 = SPR_HSRR1;
2731 new_msr |= (target_ulong)MSR_HVB;
2732 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2733 goto store_next;
2734 case POWERPC_EXCP_HISI: /* Hypervisor instruction 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_HDSEG: /* Hypervisor data segment 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_HISEG: /* Hypervisor instruction 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_VPU: /* Vector unavailable exception */
2753 if (lpes1 == 0)
2754 new_msr |= (target_ulong)MSR_HVB;
2755 goto store_current;
2756 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2757 LOG_EXCP("PIT exception\n");
2758 goto store_next;
2759 case POWERPC_EXCP_IO: /* IO error exception */
2760 /* XXX: TODO */
2761 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2762 goto store_next;
2763 case POWERPC_EXCP_RUNM: /* Run mode exception */
2764 /* XXX: TODO */
2765 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2766 goto store_next;
2767 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2768 /* XXX: TODO */
2769 cpu_abort(env, "602 emulation trap exception "
2770 "is not implemented yet !\n");
2771 goto store_next;
2772 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2773 if (lpes1 == 0) /* XXX: check this */
2774 new_msr |= (target_ulong)MSR_HVB;
2775 switch (excp_model) {
2776 case POWERPC_EXCP_602:
2777 case POWERPC_EXCP_603:
2778 case POWERPC_EXCP_603E:
2779 case POWERPC_EXCP_G2:
2780 goto tlb_miss_tgpr;
2781 case POWERPC_EXCP_7x5:
2782 goto tlb_miss;
2783 case POWERPC_EXCP_74xx:
2784 goto tlb_miss_74xx;
2785 default:
2786 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2787 break;
2789 break;
2790 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2791 if (lpes1 == 0) /* XXX: check this */
2792 new_msr |= (target_ulong)MSR_HVB;
2793 switch (excp_model) {
2794 case POWERPC_EXCP_602:
2795 case POWERPC_EXCP_603:
2796 case POWERPC_EXCP_603E:
2797 case POWERPC_EXCP_G2:
2798 goto tlb_miss_tgpr;
2799 case POWERPC_EXCP_7x5:
2800 goto tlb_miss;
2801 case POWERPC_EXCP_74xx:
2802 goto tlb_miss_74xx;
2803 default:
2804 cpu_abort(env, "Invalid data load TLB miss exception\n");
2805 break;
2807 break;
2808 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2809 if (lpes1 == 0) /* XXX: check this */
2810 new_msr |= (target_ulong)MSR_HVB;
2811 switch (excp_model) {
2812 case POWERPC_EXCP_602:
2813 case POWERPC_EXCP_603:
2814 case POWERPC_EXCP_603E:
2815 case POWERPC_EXCP_G2:
2816 tlb_miss_tgpr:
2817 /* Swap temporary saved registers with GPRs */
2818 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2819 new_msr |= (target_ulong)1 << MSR_TGPR;
2820 hreg_swap_gpr_tgpr(env);
2822 goto tlb_miss;
2823 case POWERPC_EXCP_7x5:
2824 tlb_miss:
2825 #if defined (DEBUG_SOFTWARE_TLB)
2826 if (qemu_log_enabled()) {
2827 const char *es;
2828 target_ulong *miss, *cmp;
2829 int en;
2830 if (excp == POWERPC_EXCP_IFTLB) {
2831 es = "I";
2832 en = 'I';
2833 miss = &env->spr[SPR_IMISS];
2834 cmp = &env->spr[SPR_ICMP];
2835 } else {
2836 if (excp == POWERPC_EXCP_DLTLB)
2837 es = "DL";
2838 else
2839 es = "DS";
2840 en = 'D';
2841 miss = &env->spr[SPR_DMISS];
2842 cmp = &env->spr[SPR_DCMP];
2844 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2845 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2846 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2847 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2848 env->error_code);
2850 #endif
2851 msr |= env->crf[0] << 28;
2852 msr |= env->error_code; /* key, D/I, S/L bits */
2853 /* Set way using a LRU mechanism */
2854 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2855 break;
2856 case POWERPC_EXCP_74xx:
2857 tlb_miss_74xx:
2858 #if defined (DEBUG_SOFTWARE_TLB)
2859 if (qemu_log_enabled()) {
2860 const char *es;
2861 target_ulong *miss, *cmp;
2862 int en;
2863 if (excp == POWERPC_EXCP_IFTLB) {
2864 es = "I";
2865 en = 'I';
2866 miss = &env->spr[SPR_TLBMISS];
2867 cmp = &env->spr[SPR_PTEHI];
2868 } else {
2869 if (excp == POWERPC_EXCP_DLTLB)
2870 es = "DL";
2871 else
2872 es = "DS";
2873 en = 'D';
2874 miss = &env->spr[SPR_TLBMISS];
2875 cmp = &env->spr[SPR_PTEHI];
2877 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2878 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2879 env->error_code);
2881 #endif
2882 msr |= env->error_code; /* key bit */
2883 break;
2884 default:
2885 cpu_abort(env, "Invalid data store TLB miss exception\n");
2886 break;
2888 goto store_next;
2889 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2890 /* XXX: TODO */
2891 cpu_abort(env, "Floating point assist exception "
2892 "is not implemented yet !\n");
2893 goto store_next;
2894 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2895 /* XXX: TODO */
2896 cpu_abort(env, "DABR exception is not implemented yet !\n");
2897 goto store_next;
2898 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2899 /* XXX: TODO */
2900 cpu_abort(env, "IABR exception is not implemented yet !\n");
2901 goto store_next;
2902 case POWERPC_EXCP_SMI: /* System management interrupt */
2903 /* XXX: TODO */
2904 cpu_abort(env, "SMI exception is not implemented yet !\n");
2905 goto store_next;
2906 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2907 /* XXX: TODO */
2908 cpu_abort(env, "Thermal management exception "
2909 "is not implemented yet !\n");
2910 goto store_next;
2911 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2912 if (lpes1 == 0)
2913 new_msr |= (target_ulong)MSR_HVB;
2914 /* XXX: TODO */
2915 cpu_abort(env,
2916 "Performance counter exception is not implemented yet !\n");
2917 goto store_next;
2918 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2919 /* XXX: TODO */
2920 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2921 goto store_next;
2922 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2923 /* XXX: TODO */
2924 cpu_abort(env,
2925 "970 soft-patch exception is not implemented yet !\n");
2926 goto store_next;
2927 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2928 /* XXX: TODO */
2929 cpu_abort(env,
2930 "970 maintenance exception is not implemented yet !\n");
2931 goto store_next;
2932 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2933 /* XXX: TODO */
2934 cpu_abort(env, "Maskable external exception "
2935 "is not implemented yet !\n");
2936 goto store_next;
2937 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2938 /* XXX: TODO */
2939 cpu_abort(env, "Non maskable external exception "
2940 "is not implemented yet !\n");
2941 goto store_next;
2942 default:
2943 excp_invalid:
2944 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2945 break;
2946 store_current:
2947 /* save current instruction location */
2948 env->spr[srr0] = env->nip - 4;
2949 break;
2950 store_next:
2951 /* save next instruction location */
2952 env->spr[srr0] = env->nip;
2953 break;
2955 /* Save MSR */
2956 env->spr[srr1] = msr;
2957 /* If any alternate SRR register are defined, duplicate saved values */
2958 if (asrr0 != -1)
2959 env->spr[asrr0] = env->spr[srr0];
2960 if (asrr1 != -1)
2961 env->spr[asrr1] = env->spr[srr1];
2962 /* If we disactivated any translation, flush TLBs */
2963 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2964 tlb_flush(env, 1);
2966 if (msr_ile) {
2967 new_msr |= (target_ulong)1 << MSR_LE;
2970 /* Jump to handler */
2971 vector = env->excp_vectors[excp];
2972 if (vector == (target_ulong)-1ULL) {
2973 cpu_abort(env, "Raised an exception without defined vector %d\n",
2974 excp);
2976 vector |= env->excp_prefix;
2977 #if defined(TARGET_PPC64)
2978 if (excp_model == POWERPC_EXCP_BOOKE) {
2979 if (!msr_icm) {
2980 vector = (uint32_t)vector;
2981 } else {
2982 new_msr |= (target_ulong)1 << MSR_CM;
2984 } else {
2985 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2986 vector = (uint32_t)vector;
2987 } else {
2988 new_msr |= (target_ulong)1 << MSR_SF;
2991 #endif
2992 /* XXX: we don't use hreg_store_msr here as already have treated
2993 * any special case that could occur. Just store MSR and update hflags
2995 env->msr = new_msr & env->msr_mask;
2996 hreg_compute_hflags(env);
2997 env->nip = vector;
2998 /* Reset exception state */
2999 env->exception_index = POWERPC_EXCP_NONE;
3000 env->error_code = 0;
3002 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
3003 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
3004 /* XXX: The BookE changes address space when switching modes,
3005 we should probably implement that as different MMU indexes,
3006 but for the moment we do it the slow way and flush all. */
3007 tlb_flush(env, 1);
3011 void do_interrupt (CPUPPCState *env)
3013 powerpc_excp(env, env->excp_model, env->exception_index);
3016 void ppc_hw_interrupt (CPUPPCState *env)
3018 int hdice;
3020 #if 0
3021 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
3022 __func__, env, env->pending_interrupts,
3023 env->interrupt_request, (int)msr_me, (int)msr_ee);
3024 #endif
3025 /* External reset */
3026 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
3027 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
3028 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
3029 return;
3031 /* Machine check exception */
3032 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
3033 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
3034 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
3035 return;
3037 #if 0 /* TODO */
3038 /* External debug exception */
3039 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
3040 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
3041 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
3042 return;
3044 #endif
3045 if (0) {
3046 /* XXX: find a suitable condition to enable the hypervisor mode */
3047 hdice = env->spr[SPR_LPCR] & 1;
3048 } else {
3049 hdice = 0;
3051 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
3052 /* Hypervisor decrementer exception */
3053 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
3054 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
3055 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
3056 return;
3059 if (msr_ce != 0) {
3060 /* External critical interrupt */
3061 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
3062 /* Taking a critical external interrupt does not clear the external
3063 * critical interrupt status
3065 #if 0
3066 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
3067 #endif
3068 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
3069 return;
3072 if (msr_ee != 0) {
3073 /* Watchdog timer on embedded PowerPC */
3074 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
3075 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
3076 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
3077 return;
3079 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
3080 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
3081 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
3082 return;
3084 /* Fixed interval timer on embedded PowerPC */
3085 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
3086 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
3087 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
3088 return;
3090 /* Programmable interval timer on embedded PowerPC */
3091 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
3092 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
3093 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
3094 return;
3096 /* Decrementer exception */
3097 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
3098 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
3099 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
3100 return;
3102 /* External interrupt */
3103 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
3104 /* Taking an external interrupt does not clear the external
3105 * interrupt status
3107 #if 0
3108 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
3109 #endif
3110 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
3111 return;
3113 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
3114 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
3115 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
3116 return;
3118 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
3119 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
3120 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
3121 return;
3123 /* Thermal interrupt */
3124 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
3125 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
3126 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
3127 return;
3131 #endif /* !CONFIG_USER_ONLY */
3133 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
3135 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
3136 TARGET_FMT_lx "\n", RA, msr);
3139 void cpu_state_reset(CPUPPCState *env)
3141 target_ulong msr;
3143 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
3144 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
3145 log_cpu_state(env, 0);
3148 msr = (target_ulong)0;
3149 if (0) {
3150 /* XXX: find a suitable condition to enable the hypervisor mode */
3151 msr |= (target_ulong)MSR_HVB;
3153 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
3154 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
3155 msr |= (target_ulong)1 << MSR_EP;
3156 #if defined (DO_SINGLE_STEP) && 0
3157 /* Single step trace mode */
3158 msr |= (target_ulong)1 << MSR_SE;
3159 msr |= (target_ulong)1 << MSR_BE;
3160 #endif
3161 #if defined(CONFIG_USER_ONLY)
3162 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
3163 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
3164 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
3165 msr |= (target_ulong)1 << MSR_PR;
3166 #else
3167 env->excp_prefix = env->hreset_excp_prefix;
3168 env->nip = env->hreset_vector | env->excp_prefix;
3169 if (env->mmu_model != POWERPC_MMU_REAL)
3170 ppc_tlb_invalidate_all(env);
3171 #endif
3172 env->msr = msr & env->msr_mask;
3173 #if defined(TARGET_PPC64)
3174 if (env->mmu_model & POWERPC_MMU_64)
3175 env->msr |= (1ULL << MSR_SF);
3176 #endif
3177 hreg_compute_hflags(env);
3178 env->reserve_addr = (target_ulong)-1ULL;
3179 /* Be sure no exception or interrupt is pending */
3180 env->pending_interrupts = 0;
3181 env->exception_index = POWERPC_EXCP_NONE;
3182 env->error_code = 0;
3183 /* Flush all TLBs */
3184 tlb_flush(env, 1);
3187 CPUPPCState *cpu_ppc_init (const char *cpu_model)
3189 CPUPPCState *env;
3190 const ppc_def_t *def;
3192 def = cpu_ppc_find_by_name(cpu_model);
3193 if (!def)
3194 return NULL;
3196 env = g_malloc0(sizeof(CPUPPCState));
3197 cpu_exec_init(env);
3198 if (tcg_enabled()) {
3199 ppc_translate_init();
3201 /* Adjust cpu index for SMT */
3202 #if !defined(CONFIG_USER_ONLY)
3203 if (kvm_enabled()) {
3204 int smt = kvmppc_smt_threads();
3206 env->cpu_index = (env->cpu_index / smp_threads)*smt
3207 + (env->cpu_index % smp_threads);
3209 #endif /* !CONFIG_USER_ONLY */
3210 env->cpu_model_str = cpu_model;
3211 cpu_ppc_register_internal(env, def);
3213 qemu_init_vcpu(env);
3215 return env;
3218 void cpu_ppc_close (CPUPPCState *env)
3220 /* Should also remove all opcode tables... */
3221 g_free(env);