Add POWER7 support for ppc
[qemu-kvm.git] / target-ppc / helper.c
blob278bee4f174e1dbd66d0be60049babd82c5ee380
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>
24 #include <signal.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "helper_regs.h"
29 #include "qemu-common.h"
30 #include "kvm.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, int is_softmmu)
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[nr].tlb6;
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[nr].tlb6;
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[nr].tlb6;
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[nr].tlb6;
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[best].tlb6.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 pte0 = ldq_phys(env->htab_base + pteg_off + (i * 16));
593 pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
595 /* We have a TLB that saves 4K pages, so let's
596 * split a huge page to 4k chunks */
597 if (target_page_bits != TARGET_PAGE_BITS)
598 pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
599 & TARGET_PAGE_MASK;
601 r = pte64_check(ctx, pte0, pte1, h, rw, type);
602 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
603 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
604 pteg_base + (i * 16), pte0, pte1, (int)(pte0 & 1), h,
605 (int)((pte0 >> 1) & 1), ctx->ptem);
606 } else
607 #endif
609 pte0 = ldl_phys(env->htab_base + pteg_off + (i * 8));
610 pte1 = ldl_phys(env->htab_base + pteg_off + (i * 8) + 4);
611 r = pte32_check(ctx, pte0, pte1, h, rw, type);
612 LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
613 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
614 pteg_base + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
615 (int)((pte0 >> 6) & 1), ctx->ptem);
617 switch (r) {
618 case -3:
619 /* PTE inconsistency */
620 return -1;
621 case -2:
622 /* Access violation */
623 ret = -2;
624 good = i;
625 break;
626 case -1:
627 default:
628 /* No PTE match */
629 break;
630 case 0:
631 /* access granted */
632 /* XXX: we should go on looping to check all PTEs consistency
633 * but if we can speed-up the whole thing as the
634 * result would be undefined if PTEs are not consistent.
636 ret = 0;
637 good = i;
638 goto done;
641 if (good != -1) {
642 done:
643 LOG_MMU("found PTE at addr " TARGET_FMT_lx " prot=%01x ret=%d\n",
644 ctx->raddr, ctx->prot, ret);
645 /* Update page flags */
646 pte1 = ctx->raddr;
647 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
648 #if defined(TARGET_PPC64)
649 if (is_64b) {
650 stq_phys_notdirty(env->htab_base + pteg_off + (good * 16) + 8,
651 pte1);
652 } else
653 #endif
655 stl_phys_notdirty(env->htab_base + pteg_off + (good * 8) + 4,
656 pte1);
661 return ret;
664 static inline int find_pte(CPUState *env, mmu_ctx_t *ctx, int h, int rw,
665 int type, int target_page_bits)
667 #if defined(TARGET_PPC64)
668 if (env->mmu_model & POWERPC_MMU_64)
669 return _find_pte(env, ctx, 1, h, rw, type, target_page_bits);
670 #endif
672 return _find_pte(env, ctx, 0, h, rw, type, target_page_bits);
675 #if defined(TARGET_PPC64)
676 static inline ppc_slb_t *slb_lookup(CPUPPCState *env, target_ulong eaddr)
678 uint64_t esid_256M, esid_1T;
679 int n;
681 LOG_SLB("%s: eaddr " TARGET_FMT_lx "\n", __func__, eaddr);
683 esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
684 esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
686 for (n = 0; n < env->slb_nr; n++) {
687 ppc_slb_t *slb = &env->slb[n];
689 LOG_SLB("%s: slot %d %016" PRIx64 " %016"
690 PRIx64 "\n", __func__, n, slb->esid, slb->vsid);
691 /* We check for 1T matches on all MMUs here - if the MMU
692 * doesn't have 1T segment support, we will have prevented 1T
693 * entries from being inserted in the slbmte code. */
694 if (((slb->esid == esid_256M) &&
695 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_256M))
696 || ((slb->esid == esid_1T) &&
697 ((slb->vsid & SLB_VSID_B) == SLB_VSID_B_1T))) {
698 return slb;
702 return NULL;
705 void ppc_slb_invalidate_all (CPUPPCState *env)
707 int n, do_invalidate;
709 do_invalidate = 0;
710 /* XXX: Warning: slbia never invalidates the first segment */
711 for (n = 1; n < env->slb_nr; n++) {
712 ppc_slb_t *slb = &env->slb[n];
714 if (slb->esid & SLB_ESID_V) {
715 slb->esid &= ~SLB_ESID_V;
716 /* XXX: given the fact that segment size is 256 MB or 1TB,
717 * and we still don't have a tlb_flush_mask(env, n, mask)
718 * in Qemu, we just invalidate all TLBs
720 do_invalidate = 1;
723 if (do_invalidate)
724 tlb_flush(env, 1);
727 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
729 ppc_slb_t *slb;
731 slb = slb_lookup(env, T0);
732 if (!slb) {
733 return;
736 if (slb->esid & SLB_ESID_V) {
737 slb->esid &= ~SLB_ESID_V;
739 /* XXX: given the fact that segment size is 256 MB or 1TB,
740 * and we still don't have a tlb_flush_mask(env, n, mask)
741 * in Qemu, we just invalidate all TLBs
743 tlb_flush(env, 1);
747 int ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
749 int slot = rb & 0xfff;
750 ppc_slb_t *slb = &env->slb[slot];
752 if (rb & (0x1000 - env->slb_nr)) {
753 return -1; /* Reserved bits set or slot too high */
755 if (rs & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
756 return -1; /* Bad segment size */
758 if ((rs & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
759 return -1; /* 1T segment on MMU that doesn't support it */
762 /* Mask out the slot number as we store the entry */
763 slb->esid = rb & (SLB_ESID_ESID | SLB_ESID_V);
764 slb->vsid = rs;
766 LOG_SLB("%s: %d " TARGET_FMT_lx " - " TARGET_FMT_lx " => %016" PRIx64
767 " %016" PRIx64 "\n", __func__, slot, rb, rs,
768 slb->esid, slb->vsid);
770 return 0;
773 int ppc_load_slb_esid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
775 int slot = rb & 0xfff;
776 ppc_slb_t *slb = &env->slb[slot];
778 if (slot >= env->slb_nr) {
779 return -1;
782 *rt = slb->esid;
783 return 0;
786 int ppc_load_slb_vsid (CPUPPCState *env, target_ulong rb, target_ulong *rt)
788 int slot = rb & 0xfff;
789 ppc_slb_t *slb = &env->slb[slot];
791 if (slot >= env->slb_nr) {
792 return -1;
795 *rt = slb->vsid;
796 return 0;
798 #endif /* defined(TARGET_PPC64) */
800 /* Perform segment based translation */
801 static inline int get_segment(CPUState *env, mmu_ctx_t *ctx,
802 target_ulong eaddr, int rw, int type)
804 target_phys_addr_t hash;
805 target_ulong vsid;
806 int ds, pr, target_page_bits;
807 int ret, ret2;
809 pr = msr_pr;
810 ctx->eaddr = eaddr;
811 #if defined(TARGET_PPC64)
812 if (env->mmu_model & POWERPC_MMU_64) {
813 ppc_slb_t *slb;
814 target_ulong pageaddr;
815 int segment_bits;
817 LOG_MMU("Check SLBs\n");
818 slb = slb_lookup(env, eaddr);
819 if (!slb) {
820 return -5;
823 if (slb->vsid & SLB_VSID_B) {
824 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT_1T;
825 segment_bits = 40;
826 } else {
827 vsid = (slb->vsid & SLB_VSID_VSID) >> SLB_VSID_SHIFT;
828 segment_bits = 28;
831 target_page_bits = (slb->vsid & SLB_VSID_L)
832 ? TARGET_PAGE_BITS_16M : TARGET_PAGE_BITS;
833 ctx->key = !!(pr ? (slb->vsid & SLB_VSID_KP)
834 : (slb->vsid & SLB_VSID_KS));
835 ds = 0;
836 ctx->nx = !!(slb->vsid & SLB_VSID_N);
838 pageaddr = eaddr & ((1ULL << segment_bits)
839 - (1ULL << target_page_bits));
840 if (slb->vsid & SLB_VSID_B) {
841 hash = vsid ^ (vsid << 25) ^ (pageaddr >> target_page_bits);
842 } else {
843 hash = vsid ^ (pageaddr >> target_page_bits);
845 /* Only 5 bits of the page index are used in the AVPN */
846 ctx->ptem = (slb->vsid & SLB_VSID_PTEM) |
847 ((pageaddr >> 16) & ((1ULL << segment_bits) - 0x80));
848 } else
849 #endif /* defined(TARGET_PPC64) */
851 target_ulong sr, pgidx;
853 sr = env->sr[eaddr >> 28];
854 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
855 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
856 ds = sr & 0x80000000 ? 1 : 0;
857 ctx->nx = sr & 0x10000000 ? 1 : 0;
858 vsid = sr & 0x00FFFFFF;
859 target_page_bits = TARGET_PAGE_BITS;
860 LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
861 TARGET_FMT_lx " lr=" TARGET_FMT_lx
862 " ir=%d dr=%d pr=%d %d t=%d\n",
863 eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
864 (int)msr_dr, pr != 0 ? 1 : 0, rw, type);
865 pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
866 hash = vsid ^ pgidx;
867 ctx->ptem = (vsid << 7) | (pgidx >> 10);
869 LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
870 ctx->key, ds, ctx->nx, vsid);
871 ret = -1;
872 if (!ds) {
873 /* Check if instruction fetch is allowed, if needed */
874 if (type != ACCESS_CODE || ctx->nx == 0) {
875 /* Page address translation */
876 LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
877 " hash " TARGET_FMT_plx "\n",
878 env->htab_base, env->htab_mask, hash);
879 ctx->hash[0] = hash;
880 ctx->hash[1] = ~hash;
882 /* Initialize real address with an invalid value */
883 ctx->raddr = (target_phys_addr_t)-1ULL;
884 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
885 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
886 /* Software TLB search */
887 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
888 } else {
889 LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
890 " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
891 " hash=" TARGET_FMT_plx "\n",
892 env->htab_base, env->htab_mask, vsid, ctx->ptem,
893 ctx->hash[0]);
894 /* Primary table lookup */
895 ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
896 if (ret < 0) {
897 /* Secondary table lookup */
898 if (eaddr != 0xEFFFFFFF)
899 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
900 " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
901 " hash=" TARGET_FMT_plx " pg_addr="
902 TARGET_FMT_plx "\n", env->htab_base,
903 env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
904 ret2 = find_pte(env, ctx, 1, rw, type,
905 target_page_bits);
906 if (ret2 != -1)
907 ret = ret2;
910 #if defined (DUMP_PAGE_TABLES)
911 if (qemu_log_enabled()) {
912 target_phys_addr_t curaddr;
913 uint32_t a0, a1, a2, a3;
914 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
915 "\n", sdr, mask + 0x80);
916 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
917 curaddr += 16) {
918 a0 = ldl_phys(curaddr);
919 a1 = ldl_phys(curaddr + 4);
920 a2 = ldl_phys(curaddr + 8);
921 a3 = ldl_phys(curaddr + 12);
922 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
923 qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
924 curaddr, a0, a1, a2, a3);
928 #endif
929 } else {
930 LOG_MMU("No access allowed\n");
931 ret = -3;
933 } else {
934 LOG_MMU("direct store...\n");
935 /* Direct-store segment : absolutely *BUGGY* for now */
936 switch (type) {
937 case ACCESS_INT:
938 /* Integer load/store : only access allowed */
939 break;
940 case ACCESS_CODE:
941 /* No code fetch is allowed in direct-store areas */
942 return -4;
943 case ACCESS_FLOAT:
944 /* Floating point load/store */
945 return -4;
946 case ACCESS_RES:
947 /* lwarx, ldarx or srwcx. */
948 return -4;
949 case ACCESS_CACHE:
950 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
951 /* Should make the instruction do no-op.
952 * As it already do no-op, it's quite easy :-)
954 ctx->raddr = eaddr;
955 return 0;
956 case ACCESS_EXT:
957 /* eciwx or ecowx */
958 return -4;
959 default:
960 qemu_log("ERROR: instruction should not need "
961 "address translation\n");
962 return -4;
964 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
965 ctx->raddr = eaddr;
966 ret = 2;
967 } else {
968 ret = -2;
972 return ret;
975 /* Generic TLB check function for embedded PowerPC implementations */
976 static inline int ppcemb_tlb_check(CPUState *env, ppcemb_tlb_t *tlb,
977 target_phys_addr_t *raddrp,
978 target_ulong address, uint32_t pid, int ext,
979 int i)
981 target_ulong mask;
983 /* Check valid flag */
984 if (!(tlb->prot & PAGE_VALID)) {
985 return -1;
987 mask = ~(tlb->size - 1);
988 LOG_SWTLB("%s: TLB %d address " TARGET_FMT_lx " PID %u <=> " TARGET_FMT_lx
989 " " TARGET_FMT_lx " %u\n", __func__, i, address, pid, tlb->EPN,
990 mask, (uint32_t)tlb->PID);
991 /* Check PID */
992 if (tlb->PID != 0 && tlb->PID != pid)
993 return -1;
994 /* Check effective address */
995 if ((address & mask) != tlb->EPN)
996 return -1;
997 *raddrp = (tlb->RPN & mask) | (address & ~mask);
998 #if (TARGET_PHYS_ADDR_BITS >= 36)
999 if (ext) {
1000 /* Extend the physical address to 36 bits */
1001 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1003 #endif
1005 return 0;
1008 /* Generic TLB search function for PowerPC embedded implementations */
1009 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1011 ppcemb_tlb_t *tlb;
1012 target_phys_addr_t raddr;
1013 int i, ret;
1015 /* Default return value is no match */
1016 ret = -1;
1017 for (i = 0; i < env->nb_tlb; i++) {
1018 tlb = &env->tlb[i].tlbe;
1019 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1020 ret = i;
1021 break;
1025 return ret;
1028 /* Helpers specific to PowerPC 40x implementations */
1029 static inline void ppc4xx_tlb_invalidate_all(CPUState *env)
1031 ppcemb_tlb_t *tlb;
1032 int i;
1034 for (i = 0; i < env->nb_tlb; i++) {
1035 tlb = &env->tlb[i].tlbe;
1036 tlb->prot &= ~PAGE_VALID;
1038 tlb_flush(env, 1);
1041 static inline void ppc4xx_tlb_invalidate_virt(CPUState *env,
1042 target_ulong eaddr, uint32_t pid)
1044 #if !defined(FLUSH_ALL_TLBS)
1045 ppcemb_tlb_t *tlb;
1046 target_phys_addr_t raddr;
1047 target_ulong page, end;
1048 int i;
1050 for (i = 0; i < env->nb_tlb; i++) {
1051 tlb = &env->tlb[i].tlbe;
1052 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1053 end = tlb->EPN + tlb->size;
1054 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1055 tlb_flush_page(env, page);
1056 tlb->prot &= ~PAGE_VALID;
1057 break;
1060 #else
1061 ppc4xx_tlb_invalidate_all(env);
1062 #endif
1065 static int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1066 target_ulong address, int rw, int access_type)
1068 ppcemb_tlb_t *tlb;
1069 target_phys_addr_t raddr;
1070 int i, ret, zsel, zpr, pr;
1072 ret = -1;
1073 raddr = (target_phys_addr_t)-1ULL;
1074 pr = msr_pr;
1075 for (i = 0; i < env->nb_tlb; i++) {
1076 tlb = &env->tlb[i].tlbe;
1077 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1078 env->spr[SPR_40x_PID], 0, i) < 0)
1079 continue;
1080 zsel = (tlb->attr >> 4) & 0xF;
1081 zpr = (env->spr[SPR_40x_ZPR] >> (30 - (2 * zsel))) & 0x3;
1082 LOG_SWTLB("%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1083 __func__, i, zsel, zpr, rw, tlb->attr);
1084 /* Check execute enable bit */
1085 switch (zpr) {
1086 case 0x2:
1087 if (pr != 0)
1088 goto check_perms;
1089 /* No break here */
1090 case 0x3:
1091 /* All accesses granted */
1092 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1093 ret = 0;
1094 break;
1095 case 0x0:
1096 if (pr != 0) {
1097 /* Raise Zone protection fault. */
1098 env->spr[SPR_40x_ESR] = 1 << 22;
1099 ctx->prot = 0;
1100 ret = -2;
1101 break;
1103 /* No break here */
1104 case 0x1:
1105 check_perms:
1106 /* Check from TLB entry */
1107 ctx->prot = tlb->prot;
1108 ret = check_prot(ctx->prot, rw, access_type);
1109 if (ret == -2)
1110 env->spr[SPR_40x_ESR] = 0;
1111 break;
1113 if (ret >= 0) {
1114 ctx->raddr = raddr;
1115 LOG_SWTLB("%s: access granted " TARGET_FMT_lx " => " TARGET_FMT_plx
1116 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1117 ret);
1118 return 0;
1121 LOG_SWTLB("%s: access refused " TARGET_FMT_lx " => " TARGET_FMT_plx
1122 " %d %d\n", __func__, address, raddr, ctx->prot, ret);
1124 return ret;
1127 void store_40x_sler (CPUPPCState *env, uint32_t val)
1129 /* XXX: TO BE FIXED */
1130 if (val != 0x00000000) {
1131 cpu_abort(env, "Little-endian regions are not supported by now\n");
1133 env->spr[SPR_405_SLER] = val;
1136 static int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1137 target_ulong address, int rw,
1138 int access_type)
1140 ppcemb_tlb_t *tlb;
1141 target_phys_addr_t raddr;
1142 int i, prot, ret;
1144 ret = -1;
1145 raddr = (target_phys_addr_t)-1ULL;
1146 for (i = 0; i < env->nb_tlb; i++) {
1147 tlb = &env->tlb[i].tlbe;
1148 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1149 env->spr[SPR_BOOKE_PID], 1, i) < 0)
1150 continue;
1151 if (msr_pr != 0)
1152 prot = tlb->prot & 0xF;
1153 else
1154 prot = (tlb->prot >> 4) & 0xF;
1155 /* Check the address space */
1156 if (access_type == ACCESS_CODE) {
1157 if (msr_ir != (tlb->attr & 1))
1158 continue;
1159 ctx->prot = prot;
1160 if (prot & PAGE_EXEC) {
1161 ret = 0;
1162 break;
1164 ret = -3;
1165 } else {
1166 if (msr_dr != (tlb->attr & 1))
1167 continue;
1168 ctx->prot = prot;
1169 if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1170 ret = 0;
1171 break;
1173 ret = -2;
1176 if (ret >= 0)
1177 ctx->raddr = raddr;
1179 return ret;
1182 static inline int check_physical(CPUState *env, mmu_ctx_t *ctx,
1183 target_ulong eaddr, int rw)
1185 int in_plb, ret;
1187 ctx->raddr = eaddr;
1188 ctx->prot = PAGE_READ | PAGE_EXEC;
1189 ret = 0;
1190 switch (env->mmu_model) {
1191 case POWERPC_MMU_32B:
1192 case POWERPC_MMU_601:
1193 case POWERPC_MMU_SOFT_6xx:
1194 case POWERPC_MMU_SOFT_74xx:
1195 case POWERPC_MMU_SOFT_4xx:
1196 case POWERPC_MMU_REAL:
1197 case POWERPC_MMU_BOOKE:
1198 ctx->prot |= PAGE_WRITE;
1199 break;
1200 #if defined(TARGET_PPC64)
1201 case POWERPC_MMU_620:
1202 case POWERPC_MMU_64B:
1203 case POWERPC_MMU_2_06:
1204 /* Real address are 60 bits long */
1205 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1206 ctx->prot |= PAGE_WRITE;
1207 break;
1208 #endif
1209 case POWERPC_MMU_SOFT_4xx_Z:
1210 if (unlikely(msr_pe != 0)) {
1211 /* 403 family add some particular protections,
1212 * using PBL/PBU registers for accesses with no translation.
1214 in_plb =
1215 /* Check PLB validity */
1216 (env->pb[0] < env->pb[1] &&
1217 /* and address in plb area */
1218 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1219 (env->pb[2] < env->pb[3] &&
1220 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1221 if (in_plb ^ msr_px) {
1222 /* Access in protected area */
1223 if (rw == 1) {
1224 /* Access is not allowed */
1225 ret = -2;
1227 } else {
1228 /* Read-write access is allowed */
1229 ctx->prot |= PAGE_WRITE;
1232 break;
1233 case POWERPC_MMU_MPC8xx:
1234 /* XXX: TODO */
1235 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1236 break;
1237 case POWERPC_MMU_BOOKE_FSL:
1238 /* XXX: TODO */
1239 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1240 break;
1241 default:
1242 cpu_abort(env, "Unknown or invalid MMU model\n");
1243 return -1;
1246 return ret;
1249 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1250 int rw, int access_type)
1252 int ret;
1254 #if 0
1255 qemu_log("%s\n", __func__);
1256 #endif
1257 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1258 (access_type != ACCESS_CODE && msr_dr == 0)) {
1259 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1260 /* The BookE MMU always performs address translation. The
1261 IS and DS bits only affect the address space. */
1262 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1263 rw, access_type);
1264 } else {
1265 /* No address translation. */
1266 ret = check_physical(env, ctx, eaddr, rw);
1268 } else {
1269 ret = -1;
1270 switch (env->mmu_model) {
1271 case POWERPC_MMU_32B:
1272 case POWERPC_MMU_601:
1273 case POWERPC_MMU_SOFT_6xx:
1274 case POWERPC_MMU_SOFT_74xx:
1275 /* Try to find a BAT */
1276 if (env->nb_BATs != 0)
1277 ret = get_bat(env, ctx, eaddr, rw, access_type);
1278 #if defined(TARGET_PPC64)
1279 case POWERPC_MMU_620:
1280 case POWERPC_MMU_64B:
1281 case POWERPC_MMU_2_06:
1282 #endif
1283 if (ret < 0) {
1284 /* We didn't match any BAT entry or don't have BATs */
1285 ret = get_segment(env, ctx, eaddr, rw, access_type);
1287 break;
1288 case POWERPC_MMU_SOFT_4xx:
1289 case POWERPC_MMU_SOFT_4xx_Z:
1290 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1291 rw, access_type);
1292 break;
1293 case POWERPC_MMU_BOOKE:
1294 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1295 rw, access_type);
1296 break;
1297 case POWERPC_MMU_MPC8xx:
1298 /* XXX: TODO */
1299 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1300 break;
1301 case POWERPC_MMU_BOOKE_FSL:
1302 /* XXX: TODO */
1303 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1304 return -1;
1305 case POWERPC_MMU_REAL:
1306 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1307 return -1;
1308 default:
1309 cpu_abort(env, "Unknown or invalid MMU model\n");
1310 return -1;
1313 #if 0
1314 qemu_log("%s address " TARGET_FMT_lx " => %d " TARGET_FMT_plx "\n",
1315 __func__, eaddr, ret, ctx->raddr);
1316 #endif
1318 return ret;
1321 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1323 mmu_ctx_t ctx;
1325 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1326 return -1;
1328 return ctx.raddr & TARGET_PAGE_MASK;
1331 /* Perform address translation */
1332 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1333 int mmu_idx, int is_softmmu)
1335 mmu_ctx_t ctx;
1336 int access_type;
1337 int ret = 0;
1339 if (rw == 2) {
1340 /* code access */
1341 rw = 0;
1342 access_type = ACCESS_CODE;
1343 } else {
1344 /* data access */
1345 access_type = env->access_type;
1347 ret = get_physical_address(env, &ctx, address, rw, access_type);
1348 if (ret == 0) {
1349 tlb_set_page(env, address & TARGET_PAGE_MASK,
1350 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1351 mmu_idx, TARGET_PAGE_SIZE);
1352 ret = 0;
1353 } else if (ret < 0) {
1354 LOG_MMU_STATE(env);
1355 if (access_type == ACCESS_CODE) {
1356 switch (ret) {
1357 case -1:
1358 /* No matches in page tables or TLB */
1359 switch (env->mmu_model) {
1360 case POWERPC_MMU_SOFT_6xx:
1361 env->exception_index = POWERPC_EXCP_IFTLB;
1362 env->error_code = 1 << 18;
1363 env->spr[SPR_IMISS] = address;
1364 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1365 goto tlb_miss;
1366 case POWERPC_MMU_SOFT_74xx:
1367 env->exception_index = POWERPC_EXCP_IFTLB;
1368 goto tlb_miss_74xx;
1369 case POWERPC_MMU_SOFT_4xx:
1370 case POWERPC_MMU_SOFT_4xx_Z:
1371 env->exception_index = POWERPC_EXCP_ITLB;
1372 env->error_code = 0;
1373 env->spr[SPR_40x_DEAR] = address;
1374 env->spr[SPR_40x_ESR] = 0x00000000;
1375 break;
1376 case POWERPC_MMU_32B:
1377 case POWERPC_MMU_601:
1378 #if defined(TARGET_PPC64)
1379 case POWERPC_MMU_620:
1380 case POWERPC_MMU_64B:
1381 case POWERPC_MMU_2_06:
1382 #endif
1383 env->exception_index = POWERPC_EXCP_ISI;
1384 env->error_code = 0x40000000;
1385 break;
1386 case POWERPC_MMU_BOOKE:
1387 env->exception_index = POWERPC_EXCP_ITLB;
1388 env->error_code = 0;
1389 env->spr[SPR_BOOKE_DEAR] = address;
1390 return -1;
1391 case POWERPC_MMU_BOOKE_FSL:
1392 /* XXX: TODO */
1393 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1394 return -1;
1395 case POWERPC_MMU_MPC8xx:
1396 /* XXX: TODO */
1397 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1398 break;
1399 case POWERPC_MMU_REAL:
1400 cpu_abort(env, "PowerPC in real mode should never raise "
1401 "any MMU exceptions\n");
1402 return -1;
1403 default:
1404 cpu_abort(env, "Unknown or invalid MMU model\n");
1405 return -1;
1407 break;
1408 case -2:
1409 /* Access rights violation */
1410 env->exception_index = POWERPC_EXCP_ISI;
1411 env->error_code = 0x08000000;
1412 break;
1413 case -3:
1414 /* No execute protection violation */
1415 if (env->mmu_model == POWERPC_MMU_BOOKE) {
1416 env->spr[SPR_BOOKE_ESR] = 0x00000000;
1418 env->exception_index = POWERPC_EXCP_ISI;
1419 env->error_code = 0x10000000;
1420 break;
1421 case -4:
1422 /* Direct store exception */
1423 /* No code fetch is allowed in direct-store areas */
1424 env->exception_index = POWERPC_EXCP_ISI;
1425 env->error_code = 0x10000000;
1426 break;
1427 #if defined(TARGET_PPC64)
1428 case -5:
1429 /* No match in segment table */
1430 if (env->mmu_model == POWERPC_MMU_620) {
1431 env->exception_index = POWERPC_EXCP_ISI;
1432 /* XXX: this might be incorrect */
1433 env->error_code = 0x40000000;
1434 } else {
1435 env->exception_index = POWERPC_EXCP_ISEG;
1436 env->error_code = 0;
1438 break;
1439 #endif
1441 } else {
1442 switch (ret) {
1443 case -1:
1444 /* No matches in page tables or TLB */
1445 switch (env->mmu_model) {
1446 case POWERPC_MMU_SOFT_6xx:
1447 if (rw == 1) {
1448 env->exception_index = POWERPC_EXCP_DSTLB;
1449 env->error_code = 1 << 16;
1450 } else {
1451 env->exception_index = POWERPC_EXCP_DLTLB;
1452 env->error_code = 0;
1454 env->spr[SPR_DMISS] = address;
1455 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1456 tlb_miss:
1457 env->error_code |= ctx.key << 19;
1458 env->spr[SPR_HASH1] = env->htab_base +
1459 get_pteg_offset(env, ctx.hash[0], HASH_PTE_SIZE_32);
1460 env->spr[SPR_HASH2] = env->htab_base +
1461 get_pteg_offset(env, ctx.hash[1], HASH_PTE_SIZE_32);
1462 break;
1463 case POWERPC_MMU_SOFT_74xx:
1464 if (rw == 1) {
1465 env->exception_index = POWERPC_EXCP_DSTLB;
1466 } else {
1467 env->exception_index = POWERPC_EXCP_DLTLB;
1469 tlb_miss_74xx:
1470 /* Implement LRU algorithm */
1471 env->error_code = ctx.key << 19;
1472 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1473 ((env->last_way + 1) & (env->nb_ways - 1));
1474 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1475 break;
1476 case POWERPC_MMU_SOFT_4xx:
1477 case POWERPC_MMU_SOFT_4xx_Z:
1478 env->exception_index = POWERPC_EXCP_DTLB;
1479 env->error_code = 0;
1480 env->spr[SPR_40x_DEAR] = address;
1481 if (rw)
1482 env->spr[SPR_40x_ESR] = 0x00800000;
1483 else
1484 env->spr[SPR_40x_ESR] = 0x00000000;
1485 break;
1486 case POWERPC_MMU_32B:
1487 case POWERPC_MMU_601:
1488 #if defined(TARGET_PPC64)
1489 case POWERPC_MMU_620:
1490 case POWERPC_MMU_64B:
1491 case POWERPC_MMU_2_06:
1492 #endif
1493 env->exception_index = POWERPC_EXCP_DSI;
1494 env->error_code = 0;
1495 env->spr[SPR_DAR] = address;
1496 if (rw == 1)
1497 env->spr[SPR_DSISR] = 0x42000000;
1498 else
1499 env->spr[SPR_DSISR] = 0x40000000;
1500 break;
1501 case POWERPC_MMU_MPC8xx:
1502 /* XXX: TODO */
1503 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1504 break;
1505 case POWERPC_MMU_BOOKE:
1506 env->exception_index = POWERPC_EXCP_DTLB;
1507 env->error_code = 0;
1508 env->spr[SPR_BOOKE_DEAR] = address;
1509 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1510 return -1;
1511 case POWERPC_MMU_BOOKE_FSL:
1512 /* XXX: TODO */
1513 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1514 return -1;
1515 case POWERPC_MMU_REAL:
1516 cpu_abort(env, "PowerPC in real mode should never raise "
1517 "any MMU exceptions\n");
1518 return -1;
1519 default:
1520 cpu_abort(env, "Unknown or invalid MMU model\n");
1521 return -1;
1523 break;
1524 case -2:
1525 /* Access rights violation */
1526 env->exception_index = POWERPC_EXCP_DSI;
1527 env->error_code = 0;
1528 if (env->mmu_model == POWERPC_MMU_SOFT_4xx
1529 || env->mmu_model == POWERPC_MMU_SOFT_4xx_Z) {
1530 env->spr[SPR_40x_DEAR] = address;
1531 if (rw) {
1532 env->spr[SPR_40x_ESR] |= 0x00800000;
1534 } else if (env->mmu_model == POWERPC_MMU_BOOKE) {
1535 env->spr[SPR_BOOKE_DEAR] = address;
1536 env->spr[SPR_BOOKE_ESR] = rw ? 1 << ESR_ST : 0;
1537 } else {
1538 env->spr[SPR_DAR] = address;
1539 if (rw == 1) {
1540 env->spr[SPR_DSISR] = 0x0A000000;
1541 } else {
1542 env->spr[SPR_DSISR] = 0x08000000;
1545 break;
1546 case -4:
1547 /* Direct store exception */
1548 switch (access_type) {
1549 case ACCESS_FLOAT:
1550 /* Floating point load/store */
1551 env->exception_index = POWERPC_EXCP_ALIGN;
1552 env->error_code = POWERPC_EXCP_ALIGN_FP;
1553 env->spr[SPR_DAR] = address;
1554 break;
1555 case ACCESS_RES:
1556 /* lwarx, ldarx or stwcx. */
1557 env->exception_index = POWERPC_EXCP_DSI;
1558 env->error_code = 0;
1559 env->spr[SPR_DAR] = address;
1560 if (rw == 1)
1561 env->spr[SPR_DSISR] = 0x06000000;
1562 else
1563 env->spr[SPR_DSISR] = 0x04000000;
1564 break;
1565 case ACCESS_EXT:
1566 /* eciwx or ecowx */
1567 env->exception_index = POWERPC_EXCP_DSI;
1568 env->error_code = 0;
1569 env->spr[SPR_DAR] = address;
1570 if (rw == 1)
1571 env->spr[SPR_DSISR] = 0x06100000;
1572 else
1573 env->spr[SPR_DSISR] = 0x04100000;
1574 break;
1575 default:
1576 printf("DSI: invalid exception (%d)\n", ret);
1577 env->exception_index = POWERPC_EXCP_PROGRAM;
1578 env->error_code =
1579 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1580 env->spr[SPR_DAR] = address;
1581 break;
1583 break;
1584 #if defined(TARGET_PPC64)
1585 case -5:
1586 /* No match in segment table */
1587 if (env->mmu_model == POWERPC_MMU_620) {
1588 env->exception_index = POWERPC_EXCP_DSI;
1589 env->error_code = 0;
1590 env->spr[SPR_DAR] = address;
1591 /* XXX: this might be incorrect */
1592 if (rw == 1)
1593 env->spr[SPR_DSISR] = 0x42000000;
1594 else
1595 env->spr[SPR_DSISR] = 0x40000000;
1596 } else {
1597 env->exception_index = POWERPC_EXCP_DSEG;
1598 env->error_code = 0;
1599 env->spr[SPR_DAR] = address;
1601 break;
1602 #endif
1605 #if 0
1606 printf("%s: set exception to %d %02x\n", __func__,
1607 env->exception, env->error_code);
1608 #endif
1609 ret = 1;
1612 return ret;
1615 /*****************************************************************************/
1616 /* BATs management */
1617 #if !defined(FLUSH_ALL_TLBS)
1618 static inline void do_invalidate_BAT(CPUPPCState *env, target_ulong BATu,
1619 target_ulong mask)
1621 target_ulong base, end, page;
1623 base = BATu & ~0x0001FFFF;
1624 end = base + mask + 0x00020000;
1625 LOG_BATS("Flush BAT from " TARGET_FMT_lx " to " TARGET_FMT_lx " ("
1626 TARGET_FMT_lx ")\n", base, end, mask);
1627 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1628 tlb_flush_page(env, page);
1629 LOG_BATS("Flush done\n");
1631 #endif
1633 static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
1634 target_ulong value)
1636 LOG_BATS("Set %cBAT%d%c to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", ID,
1637 nr, ul == 0 ? 'u' : 'l', value, env->nip);
1640 void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1642 target_ulong mask;
1644 dump_store_bat(env, 'I', 0, nr, value);
1645 if (env->IBAT[0][nr] != value) {
1646 mask = (value << 15) & 0x0FFE0000UL;
1647 #if !defined(FLUSH_ALL_TLBS)
1648 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1649 #endif
1650 /* When storing valid upper BAT, mask BEPI and BRPN
1651 * and invalidate all TLBs covered by this BAT
1653 mask = (value << 15) & 0x0FFE0000UL;
1654 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1655 (value & ~0x0001FFFFUL & ~mask);
1656 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1657 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1658 #if !defined(FLUSH_ALL_TLBS)
1659 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1660 #else
1661 tlb_flush(env, 1);
1662 #endif
1666 void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1668 dump_store_bat(env, 'I', 1, nr, value);
1669 env->IBAT[1][nr] = value;
1672 void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1674 target_ulong mask;
1676 dump_store_bat(env, 'D', 0, nr, value);
1677 if (env->DBAT[0][nr] != value) {
1678 /* When storing valid upper BAT, mask BEPI and BRPN
1679 * and invalidate all TLBs covered by this BAT
1681 mask = (value << 15) & 0x0FFE0000UL;
1682 #if !defined(FLUSH_ALL_TLBS)
1683 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1684 #endif
1685 mask = (value << 15) & 0x0FFE0000UL;
1686 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1687 (value & ~0x0001FFFFUL & ~mask);
1688 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1689 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1690 #if !defined(FLUSH_ALL_TLBS)
1691 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1692 #else
1693 tlb_flush(env, 1);
1694 #endif
1698 void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1700 dump_store_bat(env, 'D', 1, nr, value);
1701 env->DBAT[1][nr] = value;
1704 void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1706 target_ulong mask;
1707 #if defined(FLUSH_ALL_TLBS)
1708 int do_inval;
1709 #endif
1711 dump_store_bat(env, 'I', 0, nr, value);
1712 if (env->IBAT[0][nr] != value) {
1713 #if defined(FLUSH_ALL_TLBS)
1714 do_inval = 0;
1715 #endif
1716 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1717 if (env->IBAT[1][nr] & 0x40) {
1718 /* Invalidate BAT only if it is valid */
1719 #if !defined(FLUSH_ALL_TLBS)
1720 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1721 #else
1722 do_inval = 1;
1723 #endif
1725 /* When storing valid upper BAT, mask BEPI and BRPN
1726 * and invalidate all TLBs covered by this BAT
1728 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1729 (value & ~0x0001FFFFUL & ~mask);
1730 env->DBAT[0][nr] = env->IBAT[0][nr];
1731 if (env->IBAT[1][nr] & 0x40) {
1732 #if !defined(FLUSH_ALL_TLBS)
1733 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1734 #else
1735 do_inval = 1;
1736 #endif
1738 #if defined(FLUSH_ALL_TLBS)
1739 if (do_inval)
1740 tlb_flush(env, 1);
1741 #endif
1745 void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1747 target_ulong mask;
1748 #if defined(FLUSH_ALL_TLBS)
1749 int do_inval;
1750 #endif
1752 dump_store_bat(env, 'I', 1, nr, value);
1753 if (env->IBAT[1][nr] != value) {
1754 #if defined(FLUSH_ALL_TLBS)
1755 do_inval = 0;
1756 #endif
1757 if (env->IBAT[1][nr] & 0x40) {
1758 #if !defined(FLUSH_ALL_TLBS)
1759 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1760 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1761 #else
1762 do_inval = 1;
1763 #endif
1765 if (value & 0x40) {
1766 #if !defined(FLUSH_ALL_TLBS)
1767 mask = (value << 17) & 0x0FFE0000UL;
1768 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1769 #else
1770 do_inval = 1;
1771 #endif
1773 env->IBAT[1][nr] = value;
1774 env->DBAT[1][nr] = value;
1775 #if defined(FLUSH_ALL_TLBS)
1776 if (do_inval)
1777 tlb_flush(env, 1);
1778 #endif
1782 /*****************************************************************************/
1783 /* TLB management */
1784 void ppc_tlb_invalidate_all (CPUPPCState *env)
1786 switch (env->mmu_model) {
1787 case POWERPC_MMU_SOFT_6xx:
1788 case POWERPC_MMU_SOFT_74xx:
1789 ppc6xx_tlb_invalidate_all(env);
1790 break;
1791 case POWERPC_MMU_SOFT_4xx:
1792 case POWERPC_MMU_SOFT_4xx_Z:
1793 ppc4xx_tlb_invalidate_all(env);
1794 break;
1795 case POWERPC_MMU_REAL:
1796 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1797 break;
1798 case POWERPC_MMU_MPC8xx:
1799 /* XXX: TODO */
1800 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1801 break;
1802 case POWERPC_MMU_BOOKE:
1803 tlb_flush(env, 1);
1804 break;
1805 case POWERPC_MMU_BOOKE_FSL:
1806 /* XXX: TODO */
1807 if (!kvm_enabled())
1808 cpu_abort(env, "BookE MMU model is not implemented\n");
1809 break;
1810 case POWERPC_MMU_32B:
1811 case POWERPC_MMU_601:
1812 #if defined(TARGET_PPC64)
1813 case POWERPC_MMU_620:
1814 case POWERPC_MMU_64B:
1815 case POWERPC_MMU_2_06:
1816 #endif /* defined(TARGET_PPC64) */
1817 tlb_flush(env, 1);
1818 break;
1819 default:
1820 /* XXX: TODO */
1821 cpu_abort(env, "Unknown MMU model\n");
1822 break;
1826 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1828 #if !defined(FLUSH_ALL_TLBS)
1829 addr &= TARGET_PAGE_MASK;
1830 switch (env->mmu_model) {
1831 case POWERPC_MMU_SOFT_6xx:
1832 case POWERPC_MMU_SOFT_74xx:
1833 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1834 if (env->id_tlbs == 1)
1835 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1836 break;
1837 case POWERPC_MMU_SOFT_4xx:
1838 case POWERPC_MMU_SOFT_4xx_Z:
1839 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1840 break;
1841 case POWERPC_MMU_REAL:
1842 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1843 break;
1844 case POWERPC_MMU_MPC8xx:
1845 /* XXX: TODO */
1846 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1847 break;
1848 case POWERPC_MMU_BOOKE:
1849 /* XXX: TODO */
1850 cpu_abort(env, "BookE MMU model is not implemented\n");
1851 break;
1852 case POWERPC_MMU_BOOKE_FSL:
1853 /* XXX: TODO */
1854 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1855 break;
1856 case POWERPC_MMU_32B:
1857 case POWERPC_MMU_601:
1858 /* tlbie invalidate TLBs for all segments */
1859 addr &= ~((target_ulong)-1ULL << 28);
1860 /* XXX: this case should be optimized,
1861 * giving a mask to tlb_flush_page
1863 tlb_flush_page(env, addr | (0x0 << 28));
1864 tlb_flush_page(env, addr | (0x1 << 28));
1865 tlb_flush_page(env, addr | (0x2 << 28));
1866 tlb_flush_page(env, addr | (0x3 << 28));
1867 tlb_flush_page(env, addr | (0x4 << 28));
1868 tlb_flush_page(env, addr | (0x5 << 28));
1869 tlb_flush_page(env, addr | (0x6 << 28));
1870 tlb_flush_page(env, addr | (0x7 << 28));
1871 tlb_flush_page(env, addr | (0x8 << 28));
1872 tlb_flush_page(env, addr | (0x9 << 28));
1873 tlb_flush_page(env, addr | (0xA << 28));
1874 tlb_flush_page(env, addr | (0xB << 28));
1875 tlb_flush_page(env, addr | (0xC << 28));
1876 tlb_flush_page(env, addr | (0xD << 28));
1877 tlb_flush_page(env, addr | (0xE << 28));
1878 tlb_flush_page(env, addr | (0xF << 28));
1879 break;
1880 #if defined(TARGET_PPC64)
1881 case POWERPC_MMU_620:
1882 case POWERPC_MMU_64B:
1883 case POWERPC_MMU_2_06:
1884 /* tlbie invalidate TLBs for all segments */
1885 /* XXX: given the fact that there are too many segments to invalidate,
1886 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
1887 * we just invalidate all TLBs
1889 tlb_flush(env, 1);
1890 break;
1891 #endif /* defined(TARGET_PPC64) */
1892 default:
1893 /* XXX: TODO */
1894 cpu_abort(env, "Unknown MMU model\n");
1895 break;
1897 #else
1898 ppc_tlb_invalidate_all(env);
1899 #endif
1902 /*****************************************************************************/
1903 /* Special registers manipulation */
1904 #if defined(TARGET_PPC64)
1905 void ppc_store_asr (CPUPPCState *env, target_ulong value)
1907 if (env->asr != value) {
1908 env->asr = value;
1909 tlb_flush(env, 1);
1912 #endif
1914 void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
1916 LOG_MMU("%s: " TARGET_FMT_lx "\n", __func__, value);
1917 if (env->spr[SPR_SDR1] != value) {
1918 env->spr[SPR_SDR1] = value;
1919 #if defined(TARGET_PPC64)
1920 if (env->mmu_model & POWERPC_MMU_64) {
1921 target_ulong htabsize = value & SDR_64_HTABSIZE;
1923 if (htabsize > 28) {
1924 fprintf(stderr, "Invalid HTABSIZE 0x" TARGET_FMT_lx
1925 " stored in SDR1\n", htabsize);
1926 htabsize = 28;
1928 env->htab_mask = (1ULL << (htabsize + 18)) - 1;
1929 env->htab_base = value & SDR_64_HTABORG;
1930 } else
1931 #endif /* defined(TARGET_PPC64) */
1933 /* FIXME: Should check for valid HTABMASK values */
1934 env->htab_mask = ((value & SDR_32_HTABMASK) << 16) | 0xFFFF;
1935 env->htab_base = value & SDR_32_HTABORG;
1937 tlb_flush(env, 1);
1941 #if defined(TARGET_PPC64)
1942 target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
1944 // XXX
1945 return 0;
1947 #endif
1949 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
1951 LOG_MMU("%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
1952 srnum, value, env->sr[srnum]);
1953 #if defined(TARGET_PPC64)
1954 if (env->mmu_model & POWERPC_MMU_64) {
1955 uint64_t rb = 0, rs = 0;
1957 /* ESID = srnum */
1958 rb |= ((uint32_t)srnum & 0xf) << 28;
1959 /* Set the valid bit */
1960 rb |= 1 << 27;
1961 /* Index = ESID */
1962 rb |= (uint32_t)srnum;
1964 /* VSID = VSID */
1965 rs |= (value & 0xfffffff) << 12;
1966 /* flags = flags */
1967 rs |= ((value >> 27) & 0xf) << 9;
1969 ppc_store_slb(env, rb, rs);
1970 } else
1971 #endif
1972 if (env->sr[srnum] != value) {
1973 env->sr[srnum] = value;
1974 /* Invalidating 256MB of virtual memory in 4kB pages is way longer than
1975 flusing the whole TLB. */
1976 #if !defined(FLUSH_ALL_TLBS) && 0
1978 target_ulong page, end;
1979 /* Invalidate 256 MB of virtual memory */
1980 page = (16 << 20) * srnum;
1981 end = page + (16 << 20);
1982 for (; page != end; page += TARGET_PAGE_SIZE)
1983 tlb_flush_page(env, page);
1985 #else
1986 tlb_flush(env, 1);
1987 #endif
1990 #endif /* !defined (CONFIG_USER_ONLY) */
1992 /* GDBstub can read and write MSR... */
1993 void ppc_store_msr (CPUPPCState *env, target_ulong value)
1995 hreg_store_msr(env, value, 0);
1998 /*****************************************************************************/
1999 /* Exception processing */
2000 #if defined (CONFIG_USER_ONLY)
2001 void do_interrupt (CPUState *env)
2003 env->exception_index = POWERPC_EXCP_NONE;
2004 env->error_code = 0;
2007 void ppc_hw_interrupt (CPUState *env)
2009 env->exception_index = POWERPC_EXCP_NONE;
2010 env->error_code = 0;
2012 #else /* defined (CONFIG_USER_ONLY) */
2013 static inline void dump_syscall(CPUState *env)
2015 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
2016 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
2017 " nip=" TARGET_FMT_lx "\n",
2018 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
2019 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
2020 ppc_dump_gpr(env, 6), env->nip);
2023 /* Note that this function should be greatly optimized
2024 * when called with a constant excp, from ppc_hw_interrupt
2026 static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
2028 target_ulong msr, new_msr, vector;
2029 int srr0, srr1, asrr0, asrr1;
2030 int lpes0, lpes1, lev;
2032 if (0) {
2033 /* XXX: find a suitable condition to enable the hypervisor mode */
2034 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2035 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2036 } else {
2037 /* Those values ensure we won't enter the hypervisor mode */
2038 lpes0 = 0;
2039 lpes1 = 1;
2042 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
2043 " => %08x (%02x)\n", env->nip, excp, env->error_code);
2045 /* new srr1 value excluding must-be-zero bits */
2046 msr = env->msr & ~0x783f0000ULL;
2048 /* new interrupt handler msr */
2049 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
2051 /* target registers */
2052 srr0 = SPR_SRR0;
2053 srr1 = SPR_SRR1;
2054 asrr0 = -1;
2055 asrr1 = -1;
2057 switch (excp) {
2058 case POWERPC_EXCP_NONE:
2059 /* Should never happen */
2060 return;
2061 case POWERPC_EXCP_CRITICAL: /* Critical input */
2062 switch (excp_model) {
2063 case POWERPC_EXCP_40x:
2064 srr0 = SPR_40x_SRR2;
2065 srr1 = SPR_40x_SRR3;
2066 break;
2067 case POWERPC_EXCP_BOOKE:
2068 srr0 = SPR_BOOKE_CSRR0;
2069 srr1 = SPR_BOOKE_CSRR1;
2070 break;
2071 case POWERPC_EXCP_G2:
2072 break;
2073 default:
2074 goto excp_invalid;
2076 goto store_next;
2077 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2078 if (msr_me == 0) {
2079 /* Machine check exception is not enabled.
2080 * Enter checkstop state.
2082 if (qemu_log_enabled()) {
2083 qemu_log("Machine check while not allowed. "
2084 "Entering checkstop state\n");
2085 } else {
2086 fprintf(stderr, "Machine check while not allowed. "
2087 "Entering checkstop state\n");
2089 env->halted = 1;
2090 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2092 if (0) {
2093 /* XXX: find a suitable condition to enable the hypervisor mode */
2094 new_msr |= (target_ulong)MSR_HVB;
2097 /* machine check exceptions don't have ME set */
2098 new_msr &= ~((target_ulong)1 << MSR_ME);
2100 /* XXX: should also have something loaded in DAR / DSISR */
2101 switch (excp_model) {
2102 case POWERPC_EXCP_40x:
2103 srr0 = SPR_40x_SRR2;
2104 srr1 = SPR_40x_SRR3;
2105 break;
2106 case POWERPC_EXCP_BOOKE:
2107 srr0 = SPR_BOOKE_MCSRR0;
2108 srr1 = SPR_BOOKE_MCSRR1;
2109 asrr0 = SPR_BOOKE_CSRR0;
2110 asrr1 = SPR_BOOKE_CSRR1;
2111 break;
2112 default:
2113 break;
2115 goto store_next;
2116 case POWERPC_EXCP_DSI: /* Data storage exception */
2117 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
2118 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2119 if (lpes1 == 0)
2120 new_msr |= (target_ulong)MSR_HVB;
2121 goto store_next;
2122 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2123 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
2124 "\n", msr, env->nip);
2125 if (lpes1 == 0)
2126 new_msr |= (target_ulong)MSR_HVB;
2127 msr |= env->error_code;
2128 goto store_next;
2129 case POWERPC_EXCP_EXTERNAL: /* External input */
2130 if (lpes0 == 1)
2131 new_msr |= (target_ulong)MSR_HVB;
2132 goto store_next;
2133 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2134 if (lpes1 == 0)
2135 new_msr |= (target_ulong)MSR_HVB;
2136 /* XXX: this is false */
2137 /* Get rS/rD and rA from faulting opcode */
2138 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2139 goto store_current;
2140 case POWERPC_EXCP_PROGRAM: /* Program exception */
2141 switch (env->error_code & ~0xF) {
2142 case POWERPC_EXCP_FP:
2143 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2144 LOG_EXCP("Ignore floating point exception\n");
2145 env->exception_index = POWERPC_EXCP_NONE;
2146 env->error_code = 0;
2147 return;
2149 if (lpes1 == 0)
2150 new_msr |= (target_ulong)MSR_HVB;
2151 msr |= 0x00100000;
2152 if (msr_fe0 == msr_fe1)
2153 goto store_next;
2154 msr |= 0x00010000;
2155 break;
2156 case POWERPC_EXCP_INVAL:
2157 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
2158 if (lpes1 == 0)
2159 new_msr |= (target_ulong)MSR_HVB;
2160 msr |= 0x00080000;
2161 break;
2162 case POWERPC_EXCP_PRIV:
2163 if (lpes1 == 0)
2164 new_msr |= (target_ulong)MSR_HVB;
2165 msr |= 0x00040000;
2166 break;
2167 case POWERPC_EXCP_TRAP:
2168 if (lpes1 == 0)
2169 new_msr |= (target_ulong)MSR_HVB;
2170 msr |= 0x00020000;
2171 break;
2172 default:
2173 /* Should never occur */
2174 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2175 env->error_code);
2176 break;
2178 goto store_current;
2179 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2180 if (lpes1 == 0)
2181 new_msr |= (target_ulong)MSR_HVB;
2182 goto store_current;
2183 case POWERPC_EXCP_SYSCALL: /* System call exception */
2184 dump_syscall(env);
2185 lev = env->error_code;
2186 if ((lev == 1) && cpu_ppc_hypercall) {
2187 cpu_ppc_hypercall(env);
2188 return;
2190 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2191 new_msr |= (target_ulong)MSR_HVB;
2192 goto store_next;
2193 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2194 goto store_current;
2195 case POWERPC_EXCP_DECR: /* Decrementer exception */
2196 if (lpes1 == 0)
2197 new_msr |= (target_ulong)MSR_HVB;
2198 goto store_next;
2199 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2200 /* FIT on 4xx */
2201 LOG_EXCP("FIT exception\n");
2202 goto store_next;
2203 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2204 LOG_EXCP("WDT exception\n");
2205 switch (excp_model) {
2206 case POWERPC_EXCP_BOOKE:
2207 srr0 = SPR_BOOKE_CSRR0;
2208 srr1 = SPR_BOOKE_CSRR1;
2209 break;
2210 default:
2211 break;
2213 goto store_next;
2214 case POWERPC_EXCP_DTLB: /* Data TLB error */
2215 goto store_next;
2216 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2217 goto store_next;
2218 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2219 switch (excp_model) {
2220 case POWERPC_EXCP_BOOKE:
2221 srr0 = SPR_BOOKE_DSRR0;
2222 srr1 = SPR_BOOKE_DSRR1;
2223 asrr0 = SPR_BOOKE_CSRR0;
2224 asrr1 = SPR_BOOKE_CSRR1;
2225 break;
2226 default:
2227 break;
2229 /* XXX: TODO */
2230 cpu_abort(env, "Debug exception is not implemented yet !\n");
2231 goto store_next;
2232 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2233 goto store_current;
2234 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2235 /* XXX: TODO */
2236 cpu_abort(env, "Embedded floating point data exception "
2237 "is not implemented yet !\n");
2238 goto store_next;
2239 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2240 /* XXX: TODO */
2241 cpu_abort(env, "Embedded floating point round exception "
2242 "is not implemented yet !\n");
2243 goto store_next;
2244 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2245 /* XXX: TODO */
2246 cpu_abort(env,
2247 "Performance counter exception is not implemented yet !\n");
2248 goto store_next;
2249 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2250 /* XXX: TODO */
2251 cpu_abort(env,
2252 "Embedded doorbell interrupt is not implemented yet !\n");
2253 goto store_next;
2254 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2255 switch (excp_model) {
2256 case POWERPC_EXCP_BOOKE:
2257 srr0 = SPR_BOOKE_CSRR0;
2258 srr1 = SPR_BOOKE_CSRR1;
2259 break;
2260 default:
2261 break;
2263 /* XXX: TODO */
2264 cpu_abort(env, "Embedded doorbell critical interrupt "
2265 "is not implemented yet !\n");
2266 goto store_next;
2267 case POWERPC_EXCP_RESET: /* System reset exception */
2268 if (msr_pow) {
2269 /* indicate that we resumed from power save mode */
2270 msr |= 0x10000;
2271 } else {
2272 new_msr &= ~((target_ulong)1 << MSR_ME);
2275 if (0) {
2276 /* XXX: find a suitable condition to enable the hypervisor mode */
2277 new_msr |= (target_ulong)MSR_HVB;
2279 goto store_next;
2280 case POWERPC_EXCP_DSEG: /* Data segment exception */
2281 if (lpes1 == 0)
2282 new_msr |= (target_ulong)MSR_HVB;
2283 goto store_next;
2284 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2285 if (lpes1 == 0)
2286 new_msr |= (target_ulong)MSR_HVB;
2287 goto store_next;
2288 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2289 srr0 = SPR_HSRR0;
2290 srr1 = SPR_HSRR1;
2291 new_msr |= (target_ulong)MSR_HVB;
2292 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2293 goto store_next;
2294 case POWERPC_EXCP_TRACE: /* Trace exception */
2295 if (lpes1 == 0)
2296 new_msr |= (target_ulong)MSR_HVB;
2297 goto store_next;
2298 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2299 srr0 = SPR_HSRR0;
2300 srr1 = SPR_HSRR1;
2301 new_msr |= (target_ulong)MSR_HVB;
2302 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2303 goto store_next;
2304 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2305 srr0 = SPR_HSRR0;
2306 srr1 = SPR_HSRR1;
2307 new_msr |= (target_ulong)MSR_HVB;
2308 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2309 goto store_next;
2310 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2311 srr0 = SPR_HSRR0;
2312 srr1 = SPR_HSRR1;
2313 new_msr |= (target_ulong)MSR_HVB;
2314 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2315 goto store_next;
2316 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2317 srr0 = SPR_HSRR0;
2318 srr1 = SPR_HSRR1;
2319 new_msr |= (target_ulong)MSR_HVB;
2320 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
2321 goto store_next;
2322 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2323 if (lpes1 == 0)
2324 new_msr |= (target_ulong)MSR_HVB;
2325 goto store_current;
2326 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2327 LOG_EXCP("PIT exception\n");
2328 goto store_next;
2329 case POWERPC_EXCP_IO: /* IO error exception */
2330 /* XXX: TODO */
2331 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2332 goto store_next;
2333 case POWERPC_EXCP_RUNM: /* Run mode exception */
2334 /* XXX: TODO */
2335 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2336 goto store_next;
2337 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2338 /* XXX: TODO */
2339 cpu_abort(env, "602 emulation trap exception "
2340 "is not implemented yet !\n");
2341 goto store_next;
2342 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2343 if (lpes1 == 0) /* XXX: check this */
2344 new_msr |= (target_ulong)MSR_HVB;
2345 switch (excp_model) {
2346 case POWERPC_EXCP_602:
2347 case POWERPC_EXCP_603:
2348 case POWERPC_EXCP_603E:
2349 case POWERPC_EXCP_G2:
2350 goto tlb_miss_tgpr;
2351 case POWERPC_EXCP_7x5:
2352 goto tlb_miss;
2353 case POWERPC_EXCP_74xx:
2354 goto tlb_miss_74xx;
2355 default:
2356 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2357 break;
2359 break;
2360 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2361 if (lpes1 == 0) /* XXX: check this */
2362 new_msr |= (target_ulong)MSR_HVB;
2363 switch (excp_model) {
2364 case POWERPC_EXCP_602:
2365 case POWERPC_EXCP_603:
2366 case POWERPC_EXCP_603E:
2367 case POWERPC_EXCP_G2:
2368 goto tlb_miss_tgpr;
2369 case POWERPC_EXCP_7x5:
2370 goto tlb_miss;
2371 case POWERPC_EXCP_74xx:
2372 goto tlb_miss_74xx;
2373 default:
2374 cpu_abort(env, "Invalid data load TLB miss exception\n");
2375 break;
2377 break;
2378 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2379 if (lpes1 == 0) /* XXX: check this */
2380 new_msr |= (target_ulong)MSR_HVB;
2381 switch (excp_model) {
2382 case POWERPC_EXCP_602:
2383 case POWERPC_EXCP_603:
2384 case POWERPC_EXCP_603E:
2385 case POWERPC_EXCP_G2:
2386 tlb_miss_tgpr:
2387 /* Swap temporary saved registers with GPRs */
2388 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2389 new_msr |= (target_ulong)1 << MSR_TGPR;
2390 hreg_swap_gpr_tgpr(env);
2392 goto tlb_miss;
2393 case POWERPC_EXCP_7x5:
2394 tlb_miss:
2395 #if defined (DEBUG_SOFTWARE_TLB)
2396 if (qemu_log_enabled()) {
2397 const char *es;
2398 target_ulong *miss, *cmp;
2399 int en;
2400 if (excp == POWERPC_EXCP_IFTLB) {
2401 es = "I";
2402 en = 'I';
2403 miss = &env->spr[SPR_IMISS];
2404 cmp = &env->spr[SPR_ICMP];
2405 } else {
2406 if (excp == POWERPC_EXCP_DLTLB)
2407 es = "DL";
2408 else
2409 es = "DS";
2410 en = 'D';
2411 miss = &env->spr[SPR_DMISS];
2412 cmp = &env->spr[SPR_DCMP];
2414 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2415 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
2416 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2417 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2418 env->error_code);
2420 #endif
2421 msr |= env->crf[0] << 28;
2422 msr |= env->error_code; /* key, D/I, S/L bits */
2423 /* Set way using a LRU mechanism */
2424 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2425 break;
2426 case POWERPC_EXCP_74xx:
2427 tlb_miss_74xx:
2428 #if defined (DEBUG_SOFTWARE_TLB)
2429 if (qemu_log_enabled()) {
2430 const char *es;
2431 target_ulong *miss, *cmp;
2432 int en;
2433 if (excp == POWERPC_EXCP_IFTLB) {
2434 es = "I";
2435 en = 'I';
2436 miss = &env->spr[SPR_TLBMISS];
2437 cmp = &env->spr[SPR_PTEHI];
2438 } else {
2439 if (excp == POWERPC_EXCP_DLTLB)
2440 es = "DL";
2441 else
2442 es = "DS";
2443 en = 'D';
2444 miss = &env->spr[SPR_TLBMISS];
2445 cmp = &env->spr[SPR_PTEHI];
2447 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
2448 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
2449 env->error_code);
2451 #endif
2452 msr |= env->error_code; /* key bit */
2453 break;
2454 default:
2455 cpu_abort(env, "Invalid data store TLB miss exception\n");
2456 break;
2458 goto store_next;
2459 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2460 /* XXX: TODO */
2461 cpu_abort(env, "Floating point assist exception "
2462 "is not implemented yet !\n");
2463 goto store_next;
2464 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2465 /* XXX: TODO */
2466 cpu_abort(env, "DABR exception is not implemented yet !\n");
2467 goto store_next;
2468 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2469 /* XXX: TODO */
2470 cpu_abort(env, "IABR exception is not implemented yet !\n");
2471 goto store_next;
2472 case POWERPC_EXCP_SMI: /* System management interrupt */
2473 /* XXX: TODO */
2474 cpu_abort(env, "SMI exception is not implemented yet !\n");
2475 goto store_next;
2476 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2477 /* XXX: TODO */
2478 cpu_abort(env, "Thermal management exception "
2479 "is not implemented yet !\n");
2480 goto store_next;
2481 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2482 if (lpes1 == 0)
2483 new_msr |= (target_ulong)MSR_HVB;
2484 /* XXX: TODO */
2485 cpu_abort(env,
2486 "Performance counter exception is not implemented yet !\n");
2487 goto store_next;
2488 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2489 /* XXX: TODO */
2490 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2491 goto store_next;
2492 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2493 /* XXX: TODO */
2494 cpu_abort(env,
2495 "970 soft-patch exception is not implemented yet !\n");
2496 goto store_next;
2497 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2498 /* XXX: TODO */
2499 cpu_abort(env,
2500 "970 maintenance exception is not implemented yet !\n");
2501 goto store_next;
2502 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2503 /* XXX: TODO */
2504 cpu_abort(env, "Maskable external exception "
2505 "is not implemented yet !\n");
2506 goto store_next;
2507 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2508 /* XXX: TODO */
2509 cpu_abort(env, "Non maskable external exception "
2510 "is not implemented yet !\n");
2511 goto store_next;
2512 default:
2513 excp_invalid:
2514 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2515 break;
2516 store_current:
2517 /* save current instruction location */
2518 env->spr[srr0] = env->nip - 4;
2519 break;
2520 store_next:
2521 /* save next instruction location */
2522 env->spr[srr0] = env->nip;
2523 break;
2525 /* Save MSR */
2526 env->spr[srr1] = msr;
2527 /* If any alternate SRR register are defined, duplicate saved values */
2528 if (asrr0 != -1)
2529 env->spr[asrr0] = env->spr[srr0];
2530 if (asrr1 != -1)
2531 env->spr[asrr1] = env->spr[srr1];
2532 /* If we disactivated any translation, flush TLBs */
2533 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2534 tlb_flush(env, 1);
2536 if (msr_ile) {
2537 new_msr |= (target_ulong)1 << MSR_LE;
2540 /* Jump to handler */
2541 vector = env->excp_vectors[excp];
2542 if (vector == (target_ulong)-1ULL) {
2543 cpu_abort(env, "Raised an exception without defined vector %d\n",
2544 excp);
2546 vector |= env->excp_prefix;
2547 #if defined(TARGET_PPC64)
2548 if (excp_model == POWERPC_EXCP_BOOKE) {
2549 if (!msr_icm) {
2550 vector = (uint32_t)vector;
2551 } else {
2552 new_msr |= (target_ulong)1 << MSR_CM;
2554 } else {
2555 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
2556 vector = (uint32_t)vector;
2557 } else {
2558 new_msr |= (target_ulong)1 << MSR_SF;
2561 #endif
2562 /* XXX: we don't use hreg_store_msr here as already have treated
2563 * any special case that could occur. Just store MSR and update hflags
2565 env->msr = new_msr & env->msr_mask;
2566 hreg_compute_hflags(env);
2567 env->nip = vector;
2568 /* Reset exception state */
2569 env->exception_index = POWERPC_EXCP_NONE;
2570 env->error_code = 0;
2572 if (env->mmu_model == POWERPC_MMU_BOOKE) {
2573 /* XXX: The BookE changes address space when switching modes,
2574 we should probably implement that as different MMU indexes,
2575 but for the moment we do it the slow way and flush all. */
2576 tlb_flush(env, 1);
2580 void do_interrupt (CPUState *env)
2582 powerpc_excp(env, env->excp_model, env->exception_index);
2585 void ppc_hw_interrupt (CPUPPCState *env)
2587 int hdice;
2589 #if 0
2590 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
2591 __func__, env, env->pending_interrupts,
2592 env->interrupt_request, (int)msr_me, (int)msr_ee);
2593 #endif
2594 /* External reset */
2595 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2596 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2597 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2598 return;
2600 /* Machine check exception */
2601 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2602 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2603 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2604 return;
2606 #if 0 /* TODO */
2607 /* External debug exception */
2608 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2609 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2610 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2611 return;
2613 #endif
2614 if (0) {
2615 /* XXX: find a suitable condition to enable the hypervisor mode */
2616 hdice = env->spr[SPR_LPCR] & 1;
2617 } else {
2618 hdice = 0;
2620 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2621 /* Hypervisor decrementer exception */
2622 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2623 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2624 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2625 return;
2628 if (msr_ce != 0) {
2629 /* External critical interrupt */
2630 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2631 /* Taking a critical external interrupt does not clear the external
2632 * critical interrupt status
2634 #if 0
2635 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2636 #endif
2637 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2638 return;
2641 if (msr_ee != 0) {
2642 /* Watchdog timer on embedded PowerPC */
2643 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2644 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2645 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2646 return;
2648 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2649 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2650 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2651 return;
2653 /* Fixed interval timer on embedded PowerPC */
2654 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2655 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2656 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2657 return;
2659 /* Programmable interval timer on embedded PowerPC */
2660 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2661 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2662 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2663 return;
2665 /* Decrementer exception */
2666 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2667 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2668 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2669 return;
2671 /* External interrupt */
2672 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2673 /* Taking an external interrupt does not clear the external
2674 * interrupt status
2676 #if 0
2677 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2678 #endif
2679 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2680 return;
2682 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2683 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2684 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2685 return;
2687 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2688 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2689 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2690 return;
2692 /* Thermal interrupt */
2693 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2694 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2695 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2696 return;
2700 #endif /* !CONFIG_USER_ONLY */
2702 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2704 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
2705 TARGET_FMT_lx "\n", RA, msr);
2708 void cpu_reset(CPUPPCState *env)
2710 target_ulong msr;
2712 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
2713 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
2714 log_cpu_state(env, 0);
2717 msr = (target_ulong)0;
2718 if (0) {
2719 /* XXX: find a suitable condition to enable the hypervisor mode */
2720 msr |= (target_ulong)MSR_HVB;
2722 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2723 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2724 msr |= (target_ulong)1 << MSR_EP;
2725 #if defined (DO_SINGLE_STEP) && 0
2726 /* Single step trace mode */
2727 msr |= (target_ulong)1 << MSR_SE;
2728 msr |= (target_ulong)1 << MSR_BE;
2729 #endif
2730 #if defined(CONFIG_USER_ONLY)
2731 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2732 msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
2733 msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
2734 msr |= (target_ulong)1 << MSR_PR;
2735 #else
2736 env->excp_prefix = env->hreset_excp_prefix;
2737 env->nip = env->hreset_vector | env->excp_prefix;
2738 if (env->mmu_model != POWERPC_MMU_REAL)
2739 ppc_tlb_invalidate_all(env);
2740 #endif
2741 env->msr = msr & env->msr_mask;
2742 #if defined(TARGET_PPC64)
2743 if (env->mmu_model & POWERPC_MMU_64)
2744 env->msr |= (1ULL << MSR_SF);
2745 #endif
2746 hreg_compute_hflags(env);
2747 env->reserve_addr = (target_ulong)-1ULL;
2748 /* Be sure no exception or interrupt is pending */
2749 env->pending_interrupts = 0;
2750 env->exception_index = POWERPC_EXCP_NONE;
2751 env->error_code = 0;
2752 /* Flush all TLBs */
2753 tlb_flush(env, 1);
2756 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2758 CPUPPCState *env;
2759 const ppc_def_t *def;
2761 def = cpu_ppc_find_by_name(cpu_model);
2762 if (!def)
2763 return NULL;
2765 env = qemu_mallocz(sizeof(CPUPPCState));
2766 cpu_exec_init(env);
2767 ppc_translate_init();
2768 env->cpu_model_str = cpu_model;
2769 cpu_ppc_register_internal(env, def);
2771 qemu_init_vcpu(env);
2773 return env;
2776 void cpu_ppc_close (CPUPPCState *env)
2778 /* Should also remove all opcode tables... */
2779 qemu_free(env);