Change -drive parsing so that paths don't have to be double-escaped (Laurent Vivier...
[qemu/qemu_0_9_1_stable.git] / target-ppc / helper.c
bloba808454a201e2bd664cb8470348044a5641fe835
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
25 #include <signal.h>
26 #include <assert.h>
28 #include "cpu.h"
29 #include "exec-all.h"
30 #include "helper_regs.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 /*****************************************************************************/
41 /* PowerPC MMU emulation */
43 #if defined(CONFIG_USER_ONLY)
44 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
45 int mmu_idx, int is_softmmu)
47 int exception, error_code;
49 if (rw == 2) {
50 exception = POWERPC_EXCP_ISI;
51 error_code = 0x40000000;
52 } else {
53 exception = POWERPC_EXCP_DSI;
54 error_code = 0x40000000;
55 if (rw)
56 error_code |= 0x02000000;
57 env->spr[SPR_DAR] = address;
58 env->spr[SPR_DSISR] = error_code;
60 env->exception_index = exception;
61 env->error_code = error_code;
63 return 1;
66 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
68 return addr;
71 #else
72 /* Common routines used by software and hardware TLBs emulation */
73 static always_inline int pte_is_valid (target_ulong pte0)
75 return pte0 & 0x80000000 ? 1 : 0;
78 static always_inline void pte_invalidate (target_ulong *pte0)
80 *pte0 &= ~0x80000000;
83 #if defined(TARGET_PPC64)
84 static always_inline int pte64_is_valid (target_ulong pte0)
86 return pte0 & 0x0000000000000001ULL ? 1 : 0;
89 static always_inline void pte64_invalidate (target_ulong *pte0)
91 *pte0 &= ~0x0000000000000001ULL;
93 #endif
95 #define PTE_PTEM_MASK 0x7FFFFFBF
96 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
97 #if defined(TARGET_PPC64)
98 #define PTE64_PTEM_MASK 0xFFFFFFFFFFFFFF80ULL
99 #define PTE64_CHECK_MASK (TARGET_PAGE_MASK | 0x7F)
100 #endif
102 static always_inline int pp_check (int key, int pp, int nx)
104 int access;
106 /* Compute access rights */
107 /* When pp is 3/7, the result is undefined. Set it to noaccess */
108 access = 0;
109 if (key == 0) {
110 switch (pp) {
111 case 0x0:
112 case 0x1:
113 case 0x2:
114 access |= PAGE_WRITE;
115 /* No break here */
116 case 0x3:
117 case 0x6:
118 access |= PAGE_READ;
119 break;
121 } else {
122 switch (pp) {
123 case 0x0:
124 case 0x6:
125 access = 0;
126 break;
127 case 0x1:
128 case 0x3:
129 access = PAGE_READ;
130 break;
131 case 0x2:
132 access = PAGE_READ | PAGE_WRITE;
133 break;
136 if (nx == 0)
137 access |= PAGE_EXEC;
139 return access;
142 static always_inline int check_prot (int prot, int rw, int access_type)
144 int ret;
146 if (access_type == ACCESS_CODE) {
147 if (prot & PAGE_EXEC)
148 ret = 0;
149 else
150 ret = -2;
151 } else if (rw) {
152 if (prot & PAGE_WRITE)
153 ret = 0;
154 else
155 ret = -2;
156 } else {
157 if (prot & PAGE_READ)
158 ret = 0;
159 else
160 ret = -2;
163 return ret;
166 static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
167 target_ulong pte0, target_ulong pte1,
168 int h, int rw, int type)
170 target_ulong ptem, mmask;
171 int access, ret, pteh, ptev, pp;
173 access = 0;
174 ret = -1;
175 /* Check validity and table match */
176 #if defined(TARGET_PPC64)
177 if (is_64b) {
178 ptev = pte64_is_valid(pte0);
179 pteh = (pte0 >> 1) & 1;
180 } else
181 #endif
183 ptev = pte_is_valid(pte0);
184 pteh = (pte0 >> 6) & 1;
186 if (ptev && h == pteh) {
187 /* Check vsid & api */
188 #if defined(TARGET_PPC64)
189 if (is_64b) {
190 ptem = pte0 & PTE64_PTEM_MASK;
191 mmask = PTE64_CHECK_MASK;
192 pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
193 ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
194 ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit */
195 } else
196 #endif
198 ptem = pte0 & PTE_PTEM_MASK;
199 mmask = PTE_CHECK_MASK;
200 pp = pte1 & 0x00000003;
202 if (ptem == ctx->ptem) {
203 if (ctx->raddr != (target_phys_addr_t)-1ULL) {
204 /* all matches should have equal RPN, WIMG & PP */
205 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
206 if (loglevel != 0)
207 fprintf(logfile, "Bad RPN/WIMG/PP\n");
208 return -3;
211 /* Compute access rights */
212 access = pp_check(ctx->key, pp, ctx->nx);
213 /* Keep the matching PTE informations */
214 ctx->raddr = pte1;
215 ctx->prot = access;
216 ret = check_prot(ctx->prot, rw, type);
217 if (ret == 0) {
218 /* Access granted */
219 #if defined (DEBUG_MMU)
220 if (loglevel != 0)
221 fprintf(logfile, "PTE access granted !\n");
222 #endif
223 } else {
224 /* Access right violation */
225 #if defined (DEBUG_MMU)
226 if (loglevel != 0)
227 fprintf(logfile, "PTE access rejected\n");
228 #endif
233 return ret;
236 static always_inline int pte32_check (mmu_ctx_t *ctx,
237 target_ulong pte0, target_ulong pte1,
238 int h, int rw, int type)
240 return _pte_check(ctx, 0, pte0, pte1, h, rw, type);
243 #if defined(TARGET_PPC64)
244 static always_inline int pte64_check (mmu_ctx_t *ctx,
245 target_ulong pte0, target_ulong pte1,
246 int h, int rw, int type)
248 return _pte_check(ctx, 1, pte0, pte1, h, rw, type);
250 #endif
252 static always_inline int pte_update_flags (mmu_ctx_t *ctx, target_ulong *pte1p,
253 int ret, int rw)
255 int store = 0;
257 /* Update page flags */
258 if (!(*pte1p & 0x00000100)) {
259 /* Update accessed flag */
260 *pte1p |= 0x00000100;
261 store = 1;
263 if (!(*pte1p & 0x00000080)) {
264 if (rw == 1 && ret == 0) {
265 /* Update changed flag */
266 *pte1p |= 0x00000080;
267 store = 1;
268 } else {
269 /* Force page fault for first write access */
270 ctx->prot &= ~PAGE_WRITE;
274 return store;
277 /* Software driven TLB helpers */
278 static always_inline int ppc6xx_tlb_getnum (CPUState *env, target_ulong eaddr,
279 int way, int is_code)
281 int nr;
283 /* Select TLB num in a way from address */
284 nr = (eaddr >> TARGET_PAGE_BITS) & (env->tlb_per_way - 1);
285 /* Select TLB way */
286 nr += env->tlb_per_way * way;
287 /* 6xx have separate TLBs for instructions and data */
288 if (is_code && env->id_tlbs == 1)
289 nr += env->nb_tlb;
291 return nr;
294 static always_inline void ppc6xx_tlb_invalidate_all (CPUState *env)
296 ppc6xx_tlb_t *tlb;
297 int nr, max;
299 #if defined (DEBUG_SOFTWARE_TLB) && 0
300 if (loglevel != 0) {
301 fprintf(logfile, "Invalidate all TLBs\n");
303 #endif
304 /* Invalidate all defined software TLB */
305 max = env->nb_tlb;
306 if (env->id_tlbs == 1)
307 max *= 2;
308 for (nr = 0; nr < max; nr++) {
309 tlb = &env->tlb[nr].tlb6;
310 pte_invalidate(&tlb->pte0);
312 tlb_flush(env, 1);
315 static always_inline void __ppc6xx_tlb_invalidate_virt (CPUState *env,
316 target_ulong eaddr,
317 int is_code,
318 int match_epn)
320 #if !defined(FLUSH_ALL_TLBS)
321 ppc6xx_tlb_t *tlb;
322 int way, nr;
324 /* Invalidate ITLB + DTLB, all ways */
325 for (way = 0; way < env->nb_ways; way++) {
326 nr = ppc6xx_tlb_getnum(env, eaddr, way, is_code);
327 tlb = &env->tlb[nr].tlb6;
328 if (pte_is_valid(tlb->pte0) && (match_epn == 0 || eaddr == tlb->EPN)) {
329 #if defined (DEBUG_SOFTWARE_TLB)
330 if (loglevel != 0) {
331 fprintf(logfile, "TLB invalidate %d/%d " ADDRX "\n",
332 nr, env->nb_tlb, eaddr);
334 #endif
335 pte_invalidate(&tlb->pte0);
336 tlb_flush_page(env, tlb->EPN);
339 #else
340 /* XXX: PowerPC specification say this is valid as well */
341 ppc6xx_tlb_invalidate_all(env);
342 #endif
345 static always_inline void ppc6xx_tlb_invalidate_virt (CPUState *env,
346 target_ulong eaddr,
347 int is_code)
349 __ppc6xx_tlb_invalidate_virt(env, eaddr, is_code, 0);
352 void ppc6xx_tlb_store (CPUState *env, target_ulong EPN, int way, int is_code,
353 target_ulong pte0, target_ulong pte1)
355 ppc6xx_tlb_t *tlb;
356 int nr;
358 nr = ppc6xx_tlb_getnum(env, EPN, way, is_code);
359 tlb = &env->tlb[nr].tlb6;
360 #if defined (DEBUG_SOFTWARE_TLB)
361 if (loglevel != 0) {
362 fprintf(logfile, "Set TLB %d/%d EPN " ADDRX " PTE0 " ADDRX
363 " PTE1 " ADDRX "\n", nr, env->nb_tlb, EPN, pte0, pte1);
365 #endif
366 /* Invalidate any pending reference in Qemu for this virtual address */
367 __ppc6xx_tlb_invalidate_virt(env, EPN, is_code, 1);
368 tlb->pte0 = pte0;
369 tlb->pte1 = pte1;
370 tlb->EPN = EPN;
371 /* Store last way for LRU mechanism */
372 env->last_way = way;
375 static always_inline int ppc6xx_tlb_check (CPUState *env, mmu_ctx_t *ctx,
376 target_ulong eaddr, int rw,
377 int access_type)
379 ppc6xx_tlb_t *tlb;
380 int nr, best, way;
381 int ret;
383 best = -1;
384 ret = -1; /* No TLB found */
385 for (way = 0; way < env->nb_ways; way++) {
386 nr = ppc6xx_tlb_getnum(env, eaddr, way,
387 access_type == ACCESS_CODE ? 1 : 0);
388 tlb = &env->tlb[nr].tlb6;
389 /* This test "emulates" the PTE index match for hardware TLBs */
390 if ((eaddr & TARGET_PAGE_MASK) != tlb->EPN) {
391 #if defined (DEBUG_SOFTWARE_TLB)
392 if (loglevel != 0) {
393 fprintf(logfile, "TLB %d/%d %s [" ADDRX " " ADDRX
394 "] <> " ADDRX "\n",
395 nr, env->nb_tlb,
396 pte_is_valid(tlb->pte0) ? "valid" : "inval",
397 tlb->EPN, tlb->EPN + TARGET_PAGE_SIZE, eaddr);
399 #endif
400 continue;
402 #if defined (DEBUG_SOFTWARE_TLB)
403 if (loglevel != 0) {
404 fprintf(logfile, "TLB %d/%d %s " ADDRX " <> " ADDRX " " ADDRX
405 " %c %c\n",
406 nr, env->nb_tlb,
407 pte_is_valid(tlb->pte0) ? "valid" : "inval",
408 tlb->EPN, eaddr, tlb->pte1,
409 rw ? 'S' : 'L', access_type == ACCESS_CODE ? 'I' : 'D');
411 #endif
412 switch (pte32_check(ctx, tlb->pte0, tlb->pte1, 0, rw, access_type)) {
413 case -3:
414 /* TLB inconsistency */
415 return -1;
416 case -2:
417 /* Access violation */
418 ret = -2;
419 best = nr;
420 break;
421 case -1:
422 default:
423 /* No match */
424 break;
425 case 0:
426 /* access granted */
427 /* XXX: we should go on looping to check all TLBs consistency
428 * but we can speed-up the whole thing as the
429 * result would be undefined if TLBs are not consistent.
431 ret = 0;
432 best = nr;
433 goto done;
436 if (best != -1) {
437 done:
438 #if defined (DEBUG_SOFTWARE_TLB)
439 if (loglevel != 0) {
440 fprintf(logfile, "found TLB at addr " PADDRX " prot=%01x ret=%d\n",
441 ctx->raddr & TARGET_PAGE_MASK, ctx->prot, ret);
443 #endif
444 /* Update page flags */
445 pte_update_flags(ctx, &env->tlb[best].tlb6.pte1, ret, rw);
448 return ret;
451 /* Perform BAT hit & translation */
452 static always_inline void bat_size_prot (CPUState *env, target_ulong *blp,
453 int *validp, int *protp,
454 target_ulong *BATu, target_ulong *BATl)
456 target_ulong bl;
457 int pp, valid, prot;
459 bl = (*BATu & 0x00001FFC) << 15;
460 valid = 0;
461 prot = 0;
462 if (((msr_pr == 0) && (*BATu & 0x00000002)) ||
463 ((msr_pr != 0) && (*BATu & 0x00000001))) {
464 valid = 1;
465 pp = *BATl & 0x00000003;
466 if (pp != 0) {
467 prot = PAGE_READ | PAGE_EXEC;
468 if (pp == 0x2)
469 prot |= PAGE_WRITE;
472 *blp = bl;
473 *validp = valid;
474 *protp = prot;
477 static always_inline void bat_601_size_prot (CPUState *env,target_ulong *blp,
478 int *validp, int *protp,
479 target_ulong *BATu,
480 target_ulong *BATl)
482 target_ulong bl;
483 int key, pp, valid, prot;
485 bl = (*BATl & 0x0000003F) << 17;
486 #if defined (DEBUG_BATS)
487 if (loglevel != 0) {
488 fprintf(logfile, "b %02x ==> bl " ADDRX " msk " ADDRX "\n",
489 (uint8_t)(*BATl & 0x0000003F), bl, ~bl);
491 #endif
492 prot = 0;
493 valid = (*BATl >> 6) & 1;
494 if (valid) {
495 pp = *BATu & 0x00000003;
496 if (msr_pr == 0)
497 key = (*BATu >> 3) & 1;
498 else
499 key = (*BATu >> 2) & 1;
500 prot = pp_check(key, pp, 0);
502 *blp = bl;
503 *validp = valid;
504 *protp = prot;
507 static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
508 target_ulong virtual, int rw, int type)
510 target_ulong *BATlt, *BATut, *BATu, *BATl;
511 target_ulong base, BEPIl, BEPIu, bl;
512 int i, valid, prot;
513 int ret = -1;
515 #if defined (DEBUG_BATS)
516 if (loglevel != 0) {
517 fprintf(logfile, "%s: %cBAT v " ADDRX "\n", __func__,
518 type == ACCESS_CODE ? 'I' : 'D', virtual);
520 #endif
521 switch (type) {
522 case ACCESS_CODE:
523 BATlt = env->IBAT[1];
524 BATut = env->IBAT[0];
525 break;
526 default:
527 BATlt = env->DBAT[1];
528 BATut = env->DBAT[0];
529 break;
531 base = virtual & 0xFFFC0000;
532 for (i = 0; i < env->nb_BATs; i++) {
533 BATu = &BATut[i];
534 BATl = &BATlt[i];
535 BEPIu = *BATu & 0xF0000000;
536 BEPIl = *BATu & 0x0FFE0000;
537 if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
538 bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
539 } else {
540 bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
542 #if defined (DEBUG_BATS)
543 if (loglevel != 0) {
544 fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
545 " BATl " ADDRX "\n", __func__,
546 type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
548 #endif
549 if ((virtual & 0xF0000000) == BEPIu &&
550 ((virtual & 0x0FFE0000) & ~bl) == BEPIl) {
551 /* BAT matches */
552 if (valid != 0) {
553 /* Get physical address */
554 ctx->raddr = (*BATl & 0xF0000000) |
555 ((virtual & 0x0FFE0000 & bl) | (*BATl & 0x0FFE0000)) |
556 (virtual & 0x0001F000);
557 /* Compute access rights */
558 ctx->prot = prot;
559 ret = check_prot(ctx->prot, rw, type);
560 #if defined (DEBUG_BATS)
561 if (ret == 0 && loglevel != 0) {
562 fprintf(logfile, "BAT %d match: r " PADDRX " prot=%c%c\n",
563 i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
564 ctx->prot & PAGE_WRITE ? 'W' : '-');
566 #endif
567 break;
571 if (ret < 0) {
572 #if defined (DEBUG_BATS)
573 if (loglevel != 0) {
574 fprintf(logfile, "no BAT match for " ADDRX ":\n", virtual);
575 for (i = 0; i < 4; i++) {
576 BATu = &BATut[i];
577 BATl = &BATlt[i];
578 BEPIu = *BATu & 0xF0000000;
579 BEPIl = *BATu & 0x0FFE0000;
580 bl = (*BATu & 0x00001FFC) << 15;
581 fprintf(logfile, "%s: %cBAT%d v " ADDRX " BATu " ADDRX
582 " BATl " ADDRX " \n\t" ADDRX " " ADDRX " " ADDRX "\n",
583 __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
584 *BATu, *BATl, BEPIu, BEPIl, bl);
587 #endif
590 /* No hit */
591 return ret;
594 /* PTE table lookup */
595 static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
596 int rw, int type)
598 target_ulong base, pte0, pte1;
599 int i, good = -1;
600 int ret, r;
602 ret = -1; /* No entry found */
603 base = ctx->pg_addr[h];
604 for (i = 0; i < 8; i++) {
605 #if defined(TARGET_PPC64)
606 if (is_64b) {
607 pte0 = ldq_phys(base + (i * 16));
608 pte1 = ldq_phys(base + (i * 16) + 8);
609 r = pte64_check(ctx, pte0, pte1, h, rw, type);
610 #if defined (DEBUG_MMU)
611 if (loglevel != 0) {
612 fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
613 " %d %d %d " ADDRX "\n",
614 base + (i * 16), pte0, pte1,
615 (int)(pte0 & 1), h, (int)((pte0 >> 1) & 1),
616 ctx->ptem);
618 #endif
619 } else
620 #endif
622 pte0 = ldl_phys(base + (i * 8));
623 pte1 = ldl_phys(base + (i * 8) + 4);
624 r = pte32_check(ctx, pte0, pte1, h, rw, type);
625 #if defined (DEBUG_MMU)
626 if (loglevel != 0) {
627 fprintf(logfile, "Load pte from " ADDRX " => " ADDRX " " ADDRX
628 " %d %d %d " ADDRX "\n",
629 base + (i * 8), pte0, pte1,
630 (int)(pte0 >> 31), h, (int)((pte0 >> 6) & 1),
631 ctx->ptem);
633 #endif
635 switch (r) {
636 case -3:
637 /* PTE inconsistency */
638 return -1;
639 case -2:
640 /* Access violation */
641 ret = -2;
642 good = i;
643 break;
644 case -1:
645 default:
646 /* No PTE match */
647 break;
648 case 0:
649 /* access granted */
650 /* XXX: we should go on looping to check all PTEs consistency
651 * but if we can speed-up the whole thing as the
652 * result would be undefined if PTEs are not consistent.
654 ret = 0;
655 good = i;
656 goto done;
659 if (good != -1) {
660 done:
661 #if defined (DEBUG_MMU)
662 if (loglevel != 0) {
663 fprintf(logfile, "found PTE at addr " PADDRX " prot=%01x ret=%d\n",
664 ctx->raddr, ctx->prot, ret);
666 #endif
667 /* Update page flags */
668 pte1 = ctx->raddr;
669 if (pte_update_flags(ctx, &pte1, ret, rw) == 1) {
670 #if defined(TARGET_PPC64)
671 if (is_64b) {
672 stq_phys_notdirty(base + (good * 16) + 8, pte1);
673 } else
674 #endif
676 stl_phys_notdirty(base + (good * 8) + 4, pte1);
681 return ret;
684 static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
686 return _find_pte(ctx, 0, h, rw, type);
689 #if defined(TARGET_PPC64)
690 static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
692 return _find_pte(ctx, 1, h, rw, type);
694 #endif
696 static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
697 int h, int rw, int type)
699 #if defined(TARGET_PPC64)
700 if (env->mmu_model & POWERPC_MMU_64)
701 return find_pte64(ctx, h, rw, type);
702 #endif
704 return find_pte32(ctx, h, rw, type);
707 #if defined(TARGET_PPC64)
708 static always_inline int slb_is_valid (uint64_t slb64)
710 return slb64 & 0x0000000008000000ULL ? 1 : 0;
713 static always_inline void slb_invalidate (uint64_t *slb64)
715 *slb64 &= ~0x0000000008000000ULL;
718 static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
719 target_ulong *vsid,
720 target_ulong *page_mask, int *attr)
722 target_phys_addr_t sr_base;
723 target_ulong mask;
724 uint64_t tmp64;
725 uint32_t tmp;
726 int n, ret;
728 ret = -5;
729 sr_base = env->spr[SPR_ASR];
730 #if defined(DEBUG_SLB)
731 if (loglevel != 0) {
732 fprintf(logfile, "%s: eaddr " ADDRX " base " PADDRX "\n",
733 __func__, eaddr, sr_base);
735 #endif
736 mask = 0x0000000000000000ULL; /* Avoid gcc warning */
737 for (n = 0; n < env->slb_nr; n++) {
738 tmp64 = ldq_phys(sr_base);
739 tmp = ldl_phys(sr_base + 8);
740 #if defined(DEBUG_SLB)
741 if (loglevel != 0) {
742 fprintf(logfile, "%s: seg %d " PADDRX " %016" PRIx64 " %08"
743 PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
745 #endif
746 if (slb_is_valid(tmp64)) {
747 /* SLB entry is valid */
748 switch (tmp64 & 0x0000000006000000ULL) {
749 case 0x0000000000000000ULL:
750 /* 256 MB segment */
751 mask = 0xFFFFFFFFF0000000ULL;
752 break;
753 case 0x0000000002000000ULL:
754 /* 1 TB segment */
755 mask = 0xFFFF000000000000ULL;
756 break;
757 case 0x0000000004000000ULL:
758 case 0x0000000006000000ULL:
759 /* Reserved => segment is invalid */
760 continue;
762 if ((eaddr & mask) == (tmp64 & mask)) {
763 /* SLB match */
764 *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
765 *page_mask = ~mask;
766 *attr = tmp & 0xFF;
767 ret = n;
768 break;
771 sr_base += 12;
774 return ret;
777 void ppc_slb_invalidate_all (CPUPPCState *env)
779 target_phys_addr_t sr_base;
780 uint64_t tmp64;
781 int n, do_invalidate;
783 do_invalidate = 0;
784 sr_base = env->spr[SPR_ASR];
785 /* XXX: Warning: slbia never invalidates the first segment */
786 for (n = 1; n < env->slb_nr; n++) {
787 tmp64 = ldq_phys(sr_base);
788 if (slb_is_valid(tmp64)) {
789 slb_invalidate(&tmp64);
790 stq_phys(sr_base, tmp64);
791 /* XXX: given the fact that segment size is 256 MB or 1TB,
792 * and we still don't have a tlb_flush_mask(env, n, mask)
793 * in Qemu, we just invalidate all TLBs
795 do_invalidate = 1;
797 sr_base += 12;
799 if (do_invalidate)
800 tlb_flush(env, 1);
803 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
805 target_phys_addr_t sr_base;
806 target_ulong vsid, page_mask;
807 uint64_t tmp64;
808 int attr;
809 int n;
811 n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
812 if (n >= 0) {
813 sr_base = env->spr[SPR_ASR];
814 sr_base += 12 * n;
815 tmp64 = ldq_phys(sr_base);
816 if (slb_is_valid(tmp64)) {
817 slb_invalidate(&tmp64);
818 stq_phys(sr_base, tmp64);
819 /* XXX: given the fact that segment size is 256 MB or 1TB,
820 * and we still don't have a tlb_flush_mask(env, n, mask)
821 * in Qemu, we just invalidate all TLBs
823 tlb_flush(env, 1);
828 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
830 target_phys_addr_t sr_base;
831 target_ulong rt;
832 uint64_t tmp64;
833 uint32_t tmp;
835 sr_base = env->spr[SPR_ASR];
836 sr_base += 12 * slb_nr;
837 tmp64 = ldq_phys(sr_base);
838 tmp = ldl_phys(sr_base + 8);
839 if (tmp64 & 0x0000000008000000ULL) {
840 /* SLB entry is valid */
841 /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
842 rt = tmp >> 8; /* 65:88 => 40:63 */
843 rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
844 /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
845 rt |= ((tmp >> 4) & 0xF) << 27;
846 } else {
847 rt = 0;
849 #if defined(DEBUG_SLB)
850 if (loglevel != 0) {
851 fprintf(logfile, "%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
852 ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
854 #endif
856 return rt;
859 void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
861 target_phys_addr_t sr_base;
862 uint64_t tmp64;
863 uint32_t tmp;
865 sr_base = env->spr[SPR_ASR];
866 sr_base += 12 * slb_nr;
867 /* Copy Rs bits 37:63 to SLB 62:88 */
868 tmp = rs << 8;
869 tmp64 = (rs >> 24) & 0x7;
870 /* Copy Rs bits 33:36 to SLB 89:92 */
871 tmp |= ((rs >> 27) & 0xF) << 4;
872 /* Set the valid bit */
873 tmp64 |= 1 << 27;
874 /* Set ESID */
875 tmp64 |= (uint32_t)slb_nr << 28;
876 #if defined(DEBUG_SLB)
877 if (loglevel != 0) {
878 fprintf(logfile, "%s: %d " ADDRX " => " PADDRX " %016" PRIx64
879 " %08" PRIx32 "\n", __func__,
880 slb_nr, rs, sr_base, tmp64, tmp);
882 #endif
883 /* Write SLB entry to memory */
884 stq_phys(sr_base, tmp64);
885 stl_phys(sr_base + 8, tmp);
887 #endif /* defined(TARGET_PPC64) */
889 /* Perform segment based translation */
890 static always_inline target_phys_addr_t get_pgaddr (target_phys_addr_t sdr1,
891 int sdr_sh,
892 target_phys_addr_t hash,
893 target_phys_addr_t mask)
895 return (sdr1 & ((target_phys_addr_t)(-1ULL) << sdr_sh)) | (hash & mask);
898 static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
899 target_ulong eaddr, int rw, int type)
901 target_phys_addr_t sdr, hash, mask, sdr_mask, htab_mask;
902 target_ulong sr, vsid, vsid_mask, pgidx, page_mask;
903 #if defined(TARGET_PPC64)
904 int attr;
905 #endif
906 int ds, vsid_sh, sdr_sh, pr;
907 int ret, ret2;
909 pr = msr_pr;
910 #if defined(TARGET_PPC64)
911 if (env->mmu_model & POWERPC_MMU_64) {
912 #if defined (DEBUG_MMU)
913 if (loglevel != 0) {
914 fprintf(logfile, "Check SLBs\n");
916 #endif
917 ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
918 if (ret < 0)
919 return ret;
920 ctx->key = ((attr & 0x40) && (pr != 0)) ||
921 ((attr & 0x80) && (pr == 0)) ? 1 : 0;
922 ds = 0;
923 ctx->nx = attr & 0x20 ? 1 : 0;
924 vsid_mask = 0x00003FFFFFFFFF80ULL;
925 vsid_sh = 7;
926 sdr_sh = 18;
927 sdr_mask = 0x3FF80;
928 } else
929 #endif /* defined(TARGET_PPC64) */
931 sr = env->sr[eaddr >> 28];
932 page_mask = 0x0FFFFFFF;
933 ctx->key = (((sr & 0x20000000) && (pr != 0)) ||
934 ((sr & 0x40000000) && (pr == 0))) ? 1 : 0;
935 ds = sr & 0x80000000 ? 1 : 0;
936 ctx->nx = sr & 0x10000000 ? 1 : 0;
937 vsid = sr & 0x00FFFFFF;
938 vsid_mask = 0x01FFFFC0;
939 vsid_sh = 6;
940 sdr_sh = 16;
941 sdr_mask = 0xFFC0;
942 #if defined (DEBUG_MMU)
943 if (loglevel != 0) {
944 fprintf(logfile, "Check segment v=" ADDRX " %d " ADDRX
945 " nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
946 eaddr, (int)(eaddr >> 28), sr, env->nip,
947 env->lr, (int)msr_ir, (int)msr_dr, pr != 0 ? 1 : 0,
948 rw, type);
950 #endif
952 #if defined (DEBUG_MMU)
953 if (loglevel != 0) {
954 fprintf(logfile, "pte segment: key=%d ds %d nx %d vsid " ADDRX "\n",
955 ctx->key, ds, ctx->nx, vsid);
957 #endif
958 ret = -1;
959 if (!ds) {
960 /* Check if instruction fetch is allowed, if needed */
961 if (type != ACCESS_CODE || ctx->nx == 0) {
962 /* Page address translation */
963 /* Primary table address */
964 sdr = env->sdr1;
965 pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
966 #if defined(TARGET_PPC64)
967 if (env->mmu_model & POWERPC_MMU_64) {
968 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
969 /* XXX: this is false for 1 TB segments */
970 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
971 } else
972 #endif
974 htab_mask = sdr & 0x000001FF;
975 hash = ((vsid ^ pgidx) << vsid_sh) & vsid_mask;
977 mask = (htab_mask << sdr_sh) | sdr_mask;
978 #if defined (DEBUG_MMU)
979 if (loglevel != 0) {
980 fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
981 " mask " PADDRX " " ADDRX "\n",
982 sdr, sdr_sh, hash, mask, page_mask);
984 #endif
985 ctx->pg_addr[0] = get_pgaddr(sdr, sdr_sh, hash, mask);
986 /* Secondary table address */
987 hash = (~hash) & vsid_mask;
988 #if defined (DEBUG_MMU)
989 if (loglevel != 0) {
990 fprintf(logfile, "sdr " PADDRX " sh %d hash " PADDRX
991 " mask " PADDRX "\n",
992 sdr, sdr_sh, hash, mask);
994 #endif
995 ctx->pg_addr[1] = get_pgaddr(sdr, sdr_sh, hash, mask);
996 #if defined(TARGET_PPC64)
997 if (env->mmu_model & POWERPC_MMU_64) {
998 /* Only 5 bits of the page index are used in the AVPN */
999 ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
1000 } else
1001 #endif
1003 ctx->ptem = (vsid << 7) | (pgidx >> 10);
1005 /* Initialize real address with an invalid value */
1006 ctx->raddr = (target_phys_addr_t)-1ULL;
1007 if (unlikely(env->mmu_model == POWERPC_MMU_SOFT_6xx ||
1008 env->mmu_model == POWERPC_MMU_SOFT_74xx)) {
1009 /* Software TLB search */
1010 ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
1011 } else {
1012 #if defined (DEBUG_MMU)
1013 if (loglevel != 0) {
1014 fprintf(logfile, "0 sdr1=" PADDRX " vsid=" ADDRX " "
1015 "api=" ADDRX " hash=" PADDRX
1016 " pg_addr=" PADDRX "\n",
1017 sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
1019 #endif
1020 /* Primary table lookup */
1021 ret = find_pte(env, ctx, 0, rw, type);
1022 if (ret < 0) {
1023 /* Secondary table lookup */
1024 #if defined (DEBUG_MMU)
1025 if (eaddr != 0xEFFFFFFF && loglevel != 0) {
1026 fprintf(logfile, "1 sdr1=" PADDRX " vsid=" ADDRX " "
1027 "api=" ADDRX " hash=" PADDRX
1028 " pg_addr=" PADDRX "\n",
1029 sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
1031 #endif
1032 ret2 = find_pte(env, ctx, 1, rw, type);
1033 if (ret2 != -1)
1034 ret = ret2;
1037 #if defined (DUMP_PAGE_TABLES)
1038 if (loglevel != 0) {
1039 target_phys_addr_t curaddr;
1040 uint32_t a0, a1, a2, a3;
1041 fprintf(logfile, "Page table: " PADDRX " len " PADDRX "\n",
1042 sdr, mask + 0x80);
1043 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
1044 curaddr += 16) {
1045 a0 = ldl_phys(curaddr);
1046 a1 = ldl_phys(curaddr + 4);
1047 a2 = ldl_phys(curaddr + 8);
1048 a3 = ldl_phys(curaddr + 12);
1049 if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
1050 fprintf(logfile, PADDRX ": %08x %08x %08x %08x\n",
1051 curaddr, a0, a1, a2, a3);
1055 #endif
1056 } else {
1057 #if defined (DEBUG_MMU)
1058 if (loglevel != 0)
1059 fprintf(logfile, "No access allowed\n");
1060 #endif
1061 ret = -3;
1063 } else {
1064 #if defined (DEBUG_MMU)
1065 if (loglevel != 0)
1066 fprintf(logfile, "direct store...\n");
1067 #endif
1068 /* Direct-store segment : absolutely *BUGGY* for now */
1069 switch (type) {
1070 case ACCESS_INT:
1071 /* Integer load/store : only access allowed */
1072 break;
1073 case ACCESS_CODE:
1074 /* No code fetch is allowed in direct-store areas */
1075 return -4;
1076 case ACCESS_FLOAT:
1077 /* Floating point load/store */
1078 return -4;
1079 case ACCESS_RES:
1080 /* lwarx, ldarx or srwcx. */
1081 return -4;
1082 case ACCESS_CACHE:
1083 /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
1084 /* Should make the instruction do no-op.
1085 * As it already do no-op, it's quite easy :-)
1087 ctx->raddr = eaddr;
1088 return 0;
1089 case ACCESS_EXT:
1090 /* eciwx or ecowx */
1091 return -4;
1092 default:
1093 if (logfile) {
1094 fprintf(logfile, "ERROR: instruction should not need "
1095 "address translation\n");
1097 return -4;
1099 if ((rw == 1 || ctx->key != 1) && (rw == 0 || ctx->key != 0)) {
1100 ctx->raddr = eaddr;
1101 ret = 2;
1102 } else {
1103 ret = -2;
1107 return ret;
1110 /* Generic TLB check function for embedded PowerPC implementations */
1111 static always_inline int ppcemb_tlb_check (CPUState *env, ppcemb_tlb_t *tlb,
1112 target_phys_addr_t *raddrp,
1113 target_ulong address,
1114 uint32_t pid, int ext, int i)
1116 target_ulong mask;
1118 /* Check valid flag */
1119 if (!(tlb->prot & PAGE_VALID)) {
1120 if (loglevel != 0)
1121 fprintf(logfile, "%s: TLB %d not valid\n", __func__, i);
1122 return -1;
1124 mask = ~(tlb->size - 1);
1125 #if defined (DEBUG_SOFTWARE_TLB)
1126 if (loglevel != 0) {
1127 fprintf(logfile, "%s: TLB %d address " ADDRX " PID %u <=> " ADDRX
1128 " " ADDRX " %u\n",
1129 __func__, i, address, pid, tlb->EPN, mask, (uint32_t)tlb->PID);
1131 #endif
1132 /* Check PID */
1133 if (tlb->PID != 0 && tlb->PID != pid)
1134 return -1;
1135 /* Check effective address */
1136 if ((address & mask) != tlb->EPN)
1137 return -1;
1138 *raddrp = (tlb->RPN & mask) | (address & ~mask);
1139 #if (TARGET_PHYS_ADDR_BITS >= 36)
1140 if (ext) {
1141 /* Extend the physical address to 36 bits */
1142 *raddrp |= (target_phys_addr_t)(tlb->RPN & 0xF) << 32;
1144 #endif
1146 return 0;
1149 /* Generic TLB search function for PowerPC embedded implementations */
1150 int ppcemb_tlb_search (CPUPPCState *env, target_ulong address, uint32_t pid)
1152 ppcemb_tlb_t *tlb;
1153 target_phys_addr_t raddr;
1154 int i, ret;
1156 /* Default return value is no match */
1157 ret = -1;
1158 for (i = 0; i < env->nb_tlb; i++) {
1159 tlb = &env->tlb[i].tlbe;
1160 if (ppcemb_tlb_check(env, tlb, &raddr, address, pid, 0, i) == 0) {
1161 ret = i;
1162 break;
1166 return ret;
1169 /* Helpers specific to PowerPC 40x implementations */
1170 static always_inline void ppc4xx_tlb_invalidate_all (CPUState *env)
1172 ppcemb_tlb_t *tlb;
1173 int i;
1175 for (i = 0; i < env->nb_tlb; i++) {
1176 tlb = &env->tlb[i].tlbe;
1177 tlb->prot &= ~PAGE_VALID;
1179 tlb_flush(env, 1);
1182 static always_inline void ppc4xx_tlb_invalidate_virt (CPUState *env,
1183 target_ulong eaddr,
1184 uint32_t pid)
1186 #if !defined(FLUSH_ALL_TLBS)
1187 ppcemb_tlb_t *tlb;
1188 target_phys_addr_t raddr;
1189 target_ulong page, end;
1190 int i;
1192 for (i = 0; i < env->nb_tlb; i++) {
1193 tlb = &env->tlb[i].tlbe;
1194 if (ppcemb_tlb_check(env, tlb, &raddr, eaddr, pid, 0, i) == 0) {
1195 end = tlb->EPN + tlb->size;
1196 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
1197 tlb_flush_page(env, page);
1198 tlb->prot &= ~PAGE_VALID;
1199 break;
1202 #else
1203 ppc4xx_tlb_invalidate_all(env);
1204 #endif
1207 int mmu40x_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1208 target_ulong address, int rw, int access_type)
1210 ppcemb_tlb_t *tlb;
1211 target_phys_addr_t raddr;
1212 int i, ret, zsel, zpr, pr;
1214 ret = -1;
1215 raddr = (target_phys_addr_t)-1ULL;
1216 pr = msr_pr;
1217 for (i = 0; i < env->nb_tlb; i++) {
1218 tlb = &env->tlb[i].tlbe;
1219 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1220 env->spr[SPR_40x_PID], 0, i) < 0)
1221 continue;
1222 zsel = (tlb->attr >> 4) & 0xF;
1223 zpr = (env->spr[SPR_40x_ZPR] >> (28 - (2 * zsel))) & 0x3;
1224 #if defined (DEBUG_SOFTWARE_TLB)
1225 if (loglevel != 0) {
1226 fprintf(logfile, "%s: TLB %d zsel %d zpr %d rw %d attr %08x\n",
1227 __func__, i, zsel, zpr, rw, tlb->attr);
1229 #endif
1230 /* Check execute enable bit */
1231 switch (zpr) {
1232 case 0x2:
1233 if (pr != 0)
1234 goto check_perms;
1235 /* No break here */
1236 case 0x3:
1237 /* All accesses granted */
1238 ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
1239 ret = 0;
1240 break;
1241 case 0x0:
1242 if (pr != 0) {
1243 ctx->prot = 0;
1244 ret = -2;
1245 break;
1247 /* No break here */
1248 case 0x1:
1249 check_perms:
1250 /* Check from TLB entry */
1251 /* XXX: there is a problem here or in the TLB fill code... */
1252 ctx->prot = tlb->prot;
1253 ctx->prot |= PAGE_EXEC;
1254 ret = check_prot(ctx->prot, rw, access_type);
1255 break;
1257 if (ret >= 0) {
1258 ctx->raddr = raddr;
1259 #if defined (DEBUG_SOFTWARE_TLB)
1260 if (loglevel != 0) {
1261 fprintf(logfile, "%s: access granted " ADDRX " => " PADDRX
1262 " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
1263 ret);
1265 #endif
1266 return 0;
1269 #if defined (DEBUG_SOFTWARE_TLB)
1270 if (loglevel != 0) {
1271 fprintf(logfile, "%s: access refused " ADDRX " => " PADDRX
1272 " %d %d\n", __func__, address, raddr, ctx->prot,
1273 ret);
1275 #endif
1277 return ret;
1280 void store_40x_sler (CPUPPCState *env, uint32_t val)
1282 /* XXX: TO BE FIXED */
1283 if (val != 0x00000000) {
1284 cpu_abort(env, "Little-endian regions are not supported by now\n");
1286 env->spr[SPR_405_SLER] = val;
1289 int mmubooke_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
1290 target_ulong address, int rw,
1291 int access_type)
1293 ppcemb_tlb_t *tlb;
1294 target_phys_addr_t raddr;
1295 int i, prot, ret;
1297 ret = -1;
1298 raddr = (target_phys_addr_t)-1ULL;
1299 for (i = 0; i < env->nb_tlb; i++) {
1300 tlb = &env->tlb[i].tlbe;
1301 if (ppcemb_tlb_check(env, tlb, &raddr, address,
1302 env->spr[SPR_BOOKE_PID], 1, i) < 0)
1303 continue;
1304 if (msr_pr != 0)
1305 prot = tlb->prot & 0xF;
1306 else
1307 prot = (tlb->prot >> 4) & 0xF;
1308 /* Check the address space */
1309 if (access_type == ACCESS_CODE) {
1310 if (msr_ir != (tlb->attr & 1))
1311 continue;
1312 ctx->prot = prot;
1313 if (prot & PAGE_EXEC) {
1314 ret = 0;
1315 break;
1317 ret = -3;
1318 } else {
1319 if (msr_dr != (tlb->attr & 1))
1320 continue;
1321 ctx->prot = prot;
1322 if ((!rw && prot & PAGE_READ) || (rw && (prot & PAGE_WRITE))) {
1323 ret = 0;
1324 break;
1326 ret = -2;
1329 if (ret >= 0)
1330 ctx->raddr = raddr;
1332 return ret;
1335 static always_inline int check_physical (CPUState *env, mmu_ctx_t *ctx,
1336 target_ulong eaddr, int rw)
1338 int in_plb, ret;
1340 ctx->raddr = eaddr;
1341 ctx->prot = PAGE_READ | PAGE_EXEC;
1342 ret = 0;
1343 switch (env->mmu_model) {
1344 case POWERPC_MMU_32B:
1345 case POWERPC_MMU_601:
1346 case POWERPC_MMU_SOFT_6xx:
1347 case POWERPC_MMU_SOFT_74xx:
1348 case POWERPC_MMU_SOFT_4xx:
1349 case POWERPC_MMU_REAL:
1350 case POWERPC_MMU_BOOKE:
1351 ctx->prot |= PAGE_WRITE;
1352 break;
1353 #if defined(TARGET_PPC64)
1354 case POWERPC_MMU_620:
1355 case POWERPC_MMU_64B:
1356 /* Real address are 60 bits long */
1357 ctx->raddr &= 0x0FFFFFFFFFFFFFFFULL;
1358 ctx->prot |= PAGE_WRITE;
1359 break;
1360 #endif
1361 case POWERPC_MMU_SOFT_4xx_Z:
1362 if (unlikely(msr_pe != 0)) {
1363 /* 403 family add some particular protections,
1364 * using PBL/PBU registers for accesses with no translation.
1366 in_plb =
1367 /* Check PLB validity */
1368 (env->pb[0] < env->pb[1] &&
1369 /* and address in plb area */
1370 eaddr >= env->pb[0] && eaddr < env->pb[1]) ||
1371 (env->pb[2] < env->pb[3] &&
1372 eaddr >= env->pb[2] && eaddr < env->pb[3]) ? 1 : 0;
1373 if (in_plb ^ msr_px) {
1374 /* Access in protected area */
1375 if (rw == 1) {
1376 /* Access is not allowed */
1377 ret = -2;
1379 } else {
1380 /* Read-write access is allowed */
1381 ctx->prot |= PAGE_WRITE;
1384 break;
1385 case POWERPC_MMU_MPC8xx:
1386 /* XXX: TODO */
1387 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1388 break;
1389 case POWERPC_MMU_BOOKE_FSL:
1390 /* XXX: TODO */
1391 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1392 break;
1393 default:
1394 cpu_abort(env, "Unknown or invalid MMU model\n");
1395 return -1;
1398 return ret;
1401 int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
1402 int rw, int access_type)
1404 int ret;
1406 #if 0
1407 if (loglevel != 0) {
1408 fprintf(logfile, "%s\n", __func__);
1410 #endif
1411 if ((access_type == ACCESS_CODE && msr_ir == 0) ||
1412 (access_type != ACCESS_CODE && msr_dr == 0)) {
1413 /* No address translation */
1414 ret = check_physical(env, ctx, eaddr, rw);
1415 } else {
1416 ret = -1;
1417 switch (env->mmu_model) {
1418 case POWERPC_MMU_32B:
1419 case POWERPC_MMU_601:
1420 case POWERPC_MMU_SOFT_6xx:
1421 case POWERPC_MMU_SOFT_74xx:
1422 #if defined(TARGET_PPC64)
1423 case POWERPC_MMU_620:
1424 case POWERPC_MMU_64B:
1425 #endif
1426 /* Try to find a BAT */
1427 if (env->nb_BATs != 0)
1428 ret = get_bat(env, ctx, eaddr, rw, access_type);
1429 if (ret < 0) {
1430 /* We didn't match any BAT entry or don't have BATs */
1431 ret = get_segment(env, ctx, eaddr, rw, access_type);
1433 break;
1434 case POWERPC_MMU_SOFT_4xx:
1435 case POWERPC_MMU_SOFT_4xx_Z:
1436 ret = mmu40x_get_physical_address(env, ctx, eaddr,
1437 rw, access_type);
1438 break;
1439 case POWERPC_MMU_BOOKE:
1440 ret = mmubooke_get_physical_address(env, ctx, eaddr,
1441 rw, access_type);
1442 break;
1443 case POWERPC_MMU_MPC8xx:
1444 /* XXX: TODO */
1445 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1446 break;
1447 case POWERPC_MMU_BOOKE_FSL:
1448 /* XXX: TODO */
1449 cpu_abort(env, "BookE FSL MMU model not implemented\n");
1450 return -1;
1451 case POWERPC_MMU_REAL:
1452 cpu_abort(env, "PowerPC in real mode do not do any translation\n");
1453 return -1;
1454 default:
1455 cpu_abort(env, "Unknown or invalid MMU model\n");
1456 return -1;
1459 #if 0
1460 if (loglevel != 0) {
1461 fprintf(logfile, "%s address " ADDRX " => %d " PADDRX "\n",
1462 __func__, eaddr, ret, ctx->raddr);
1464 #endif
1466 return ret;
1469 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
1471 mmu_ctx_t ctx;
1473 if (unlikely(get_physical_address(env, &ctx, addr, 0, ACCESS_INT) != 0))
1474 return -1;
1476 return ctx.raddr & TARGET_PAGE_MASK;
1479 /* Perform address translation */
1480 int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
1481 int mmu_idx, int is_softmmu)
1483 mmu_ctx_t ctx;
1484 int access_type;
1485 int ret = 0;
1487 if (rw == 2) {
1488 /* code access */
1489 rw = 0;
1490 access_type = ACCESS_CODE;
1491 } else {
1492 /* data access */
1493 /* XXX: put correct access by using cpu_restore_state()
1494 correctly */
1495 access_type = ACCESS_INT;
1496 // access_type = env->access_type;
1498 ret = get_physical_address(env, &ctx, address, rw, access_type);
1499 if (ret == 0) {
1500 ret = tlb_set_page_exec(env, address & TARGET_PAGE_MASK,
1501 ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
1502 mmu_idx, is_softmmu);
1503 } else if (ret < 0) {
1504 #if defined (DEBUG_MMU)
1505 if (loglevel != 0)
1506 cpu_dump_state(env, logfile, fprintf, 0);
1507 #endif
1508 if (access_type == ACCESS_CODE) {
1509 switch (ret) {
1510 case -1:
1511 /* No matches in page tables or TLB */
1512 switch (env->mmu_model) {
1513 case POWERPC_MMU_SOFT_6xx:
1514 env->exception_index = POWERPC_EXCP_IFTLB;
1515 env->error_code = 1 << 18;
1516 env->spr[SPR_IMISS] = address;
1517 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
1518 goto tlb_miss;
1519 case POWERPC_MMU_SOFT_74xx:
1520 env->exception_index = POWERPC_EXCP_IFTLB;
1521 goto tlb_miss_74xx;
1522 case POWERPC_MMU_SOFT_4xx:
1523 case POWERPC_MMU_SOFT_4xx_Z:
1524 env->exception_index = POWERPC_EXCP_ITLB;
1525 env->error_code = 0;
1526 env->spr[SPR_40x_DEAR] = address;
1527 env->spr[SPR_40x_ESR] = 0x00000000;
1528 break;
1529 case POWERPC_MMU_32B:
1530 case POWERPC_MMU_601:
1531 #if defined(TARGET_PPC64)
1532 case POWERPC_MMU_620:
1533 case POWERPC_MMU_64B:
1534 #endif
1535 env->exception_index = POWERPC_EXCP_ISI;
1536 env->error_code = 0x40000000;
1537 break;
1538 case POWERPC_MMU_BOOKE:
1539 /* XXX: TODO */
1540 cpu_abort(env, "BookE MMU model is not implemented\n");
1541 return -1;
1542 case POWERPC_MMU_BOOKE_FSL:
1543 /* XXX: TODO */
1544 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1545 return -1;
1546 case POWERPC_MMU_MPC8xx:
1547 /* XXX: TODO */
1548 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1549 break;
1550 case POWERPC_MMU_REAL:
1551 cpu_abort(env, "PowerPC in real mode should never raise "
1552 "any MMU exceptions\n");
1553 return -1;
1554 default:
1555 cpu_abort(env, "Unknown or invalid MMU model\n");
1556 return -1;
1558 break;
1559 case -2:
1560 /* Access rights violation */
1561 env->exception_index = POWERPC_EXCP_ISI;
1562 env->error_code = 0x08000000;
1563 break;
1564 case -3:
1565 /* No execute protection violation */
1566 env->exception_index = POWERPC_EXCP_ISI;
1567 env->error_code = 0x10000000;
1568 break;
1569 case -4:
1570 /* Direct store exception */
1571 /* No code fetch is allowed in direct-store areas */
1572 env->exception_index = POWERPC_EXCP_ISI;
1573 env->error_code = 0x10000000;
1574 break;
1575 #if defined(TARGET_PPC64)
1576 case -5:
1577 /* No match in segment table */
1578 if (env->mmu_model == POWERPC_MMU_620) {
1579 env->exception_index = POWERPC_EXCP_ISI;
1580 /* XXX: this might be incorrect */
1581 env->error_code = 0x40000000;
1582 } else {
1583 env->exception_index = POWERPC_EXCP_ISEG;
1584 env->error_code = 0;
1586 break;
1587 #endif
1589 } else {
1590 switch (ret) {
1591 case -1:
1592 /* No matches in page tables or TLB */
1593 switch (env->mmu_model) {
1594 case POWERPC_MMU_SOFT_6xx:
1595 if (rw == 1) {
1596 env->exception_index = POWERPC_EXCP_DSTLB;
1597 env->error_code = 1 << 16;
1598 } else {
1599 env->exception_index = POWERPC_EXCP_DLTLB;
1600 env->error_code = 0;
1602 env->spr[SPR_DMISS] = address;
1603 env->spr[SPR_DCMP] = 0x80000000 | ctx.ptem;
1604 tlb_miss:
1605 env->error_code |= ctx.key << 19;
1606 env->spr[SPR_HASH1] = ctx.pg_addr[0];
1607 env->spr[SPR_HASH2] = ctx.pg_addr[1];
1608 break;
1609 case POWERPC_MMU_SOFT_74xx:
1610 if (rw == 1) {
1611 env->exception_index = POWERPC_EXCP_DSTLB;
1612 } else {
1613 env->exception_index = POWERPC_EXCP_DLTLB;
1615 tlb_miss_74xx:
1616 /* Implement LRU algorithm */
1617 env->error_code = ctx.key << 19;
1618 env->spr[SPR_TLBMISS] = (address & ~((target_ulong)0x3)) |
1619 ((env->last_way + 1) & (env->nb_ways - 1));
1620 env->spr[SPR_PTEHI] = 0x80000000 | ctx.ptem;
1621 break;
1622 case POWERPC_MMU_SOFT_4xx:
1623 case POWERPC_MMU_SOFT_4xx_Z:
1624 env->exception_index = POWERPC_EXCP_DTLB;
1625 env->error_code = 0;
1626 env->spr[SPR_40x_DEAR] = address;
1627 if (rw)
1628 env->spr[SPR_40x_ESR] = 0x00800000;
1629 else
1630 env->spr[SPR_40x_ESR] = 0x00000000;
1631 break;
1632 case POWERPC_MMU_32B:
1633 case POWERPC_MMU_601:
1634 #if defined(TARGET_PPC64)
1635 case POWERPC_MMU_620:
1636 case POWERPC_MMU_64B:
1637 #endif
1638 env->exception_index = POWERPC_EXCP_DSI;
1639 env->error_code = 0;
1640 env->spr[SPR_DAR] = address;
1641 if (rw == 1)
1642 env->spr[SPR_DSISR] = 0x42000000;
1643 else
1644 env->spr[SPR_DSISR] = 0x40000000;
1645 break;
1646 case POWERPC_MMU_MPC8xx:
1647 /* XXX: TODO */
1648 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1649 break;
1650 case POWERPC_MMU_BOOKE:
1651 /* XXX: TODO */
1652 cpu_abort(env, "BookE MMU model is not implemented\n");
1653 return -1;
1654 case POWERPC_MMU_BOOKE_FSL:
1655 /* XXX: TODO */
1656 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
1657 return -1;
1658 case POWERPC_MMU_REAL:
1659 cpu_abort(env, "PowerPC in real mode should never raise "
1660 "any MMU exceptions\n");
1661 return -1;
1662 default:
1663 cpu_abort(env, "Unknown or invalid MMU model\n");
1664 return -1;
1666 break;
1667 case -2:
1668 /* Access rights violation */
1669 env->exception_index = POWERPC_EXCP_DSI;
1670 env->error_code = 0;
1671 env->spr[SPR_DAR] = address;
1672 if (rw == 1)
1673 env->spr[SPR_DSISR] = 0x0A000000;
1674 else
1675 env->spr[SPR_DSISR] = 0x08000000;
1676 break;
1677 case -4:
1678 /* Direct store exception */
1679 switch (access_type) {
1680 case ACCESS_FLOAT:
1681 /* Floating point load/store */
1682 env->exception_index = POWERPC_EXCP_ALIGN;
1683 env->error_code = POWERPC_EXCP_ALIGN_FP;
1684 env->spr[SPR_DAR] = address;
1685 break;
1686 case ACCESS_RES:
1687 /* lwarx, ldarx or stwcx. */
1688 env->exception_index = POWERPC_EXCP_DSI;
1689 env->error_code = 0;
1690 env->spr[SPR_DAR] = address;
1691 if (rw == 1)
1692 env->spr[SPR_DSISR] = 0x06000000;
1693 else
1694 env->spr[SPR_DSISR] = 0x04000000;
1695 break;
1696 case ACCESS_EXT:
1697 /* eciwx or ecowx */
1698 env->exception_index = POWERPC_EXCP_DSI;
1699 env->error_code = 0;
1700 env->spr[SPR_DAR] = address;
1701 if (rw == 1)
1702 env->spr[SPR_DSISR] = 0x06100000;
1703 else
1704 env->spr[SPR_DSISR] = 0x04100000;
1705 break;
1706 default:
1707 printf("DSI: invalid exception (%d)\n", ret);
1708 env->exception_index = POWERPC_EXCP_PROGRAM;
1709 env->error_code =
1710 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
1711 env->spr[SPR_DAR] = address;
1712 break;
1714 break;
1715 #if defined(TARGET_PPC64)
1716 case -5:
1717 /* No match in segment table */
1718 if (env->mmu_model == POWERPC_MMU_620) {
1719 env->exception_index = POWERPC_EXCP_DSI;
1720 env->error_code = 0;
1721 env->spr[SPR_DAR] = address;
1722 /* XXX: this might be incorrect */
1723 if (rw == 1)
1724 env->spr[SPR_DSISR] = 0x42000000;
1725 else
1726 env->spr[SPR_DSISR] = 0x40000000;
1727 } else {
1728 env->exception_index = POWERPC_EXCP_DSEG;
1729 env->error_code = 0;
1730 env->spr[SPR_DAR] = address;
1732 break;
1733 #endif
1736 #if 0
1737 printf("%s: set exception to %d %02x\n", __func__,
1738 env->exception, env->error_code);
1739 #endif
1740 ret = 1;
1743 return ret;
1746 /*****************************************************************************/
1747 /* BATs management */
1748 #if !defined(FLUSH_ALL_TLBS)
1749 static always_inline void do_invalidate_BAT (CPUPPCState *env,
1750 target_ulong BATu,
1751 target_ulong mask)
1753 target_ulong base, end, page;
1755 base = BATu & ~0x0001FFFF;
1756 end = base + mask + 0x00020000;
1757 #if defined (DEBUG_BATS)
1758 if (loglevel != 0) {
1759 fprintf(logfile, "Flush BAT from " ADDRX " to " ADDRX " (" ADDRX ")\n",
1760 base, end, mask);
1762 #endif
1763 for (page = base; page != end; page += TARGET_PAGE_SIZE)
1764 tlb_flush_page(env, page);
1765 #if defined (DEBUG_BATS)
1766 if (loglevel != 0)
1767 fprintf(logfile, "Flush done\n");
1768 #endif
1770 #endif
1772 static always_inline void dump_store_bat (CPUPPCState *env, char ID,
1773 int ul, int nr, target_ulong value)
1775 #if defined (DEBUG_BATS)
1776 if (loglevel != 0) {
1777 fprintf(logfile, "Set %cBAT%d%c to " ADDRX " (" ADDRX ")\n",
1778 ID, nr, ul == 0 ? 'u' : 'l', value, env->nip);
1780 #endif
1783 target_ulong do_load_ibatu (CPUPPCState *env, int nr)
1785 return env->IBAT[0][nr];
1788 target_ulong do_load_ibatl (CPUPPCState *env, int nr)
1790 return env->IBAT[1][nr];
1793 void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
1795 target_ulong mask;
1797 dump_store_bat(env, 'I', 0, nr, value);
1798 if (env->IBAT[0][nr] != value) {
1799 mask = (value << 15) & 0x0FFE0000UL;
1800 #if !defined(FLUSH_ALL_TLBS)
1801 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1802 #endif
1803 /* When storing valid upper BAT, mask BEPI and BRPN
1804 * and invalidate all TLBs covered by this BAT
1806 mask = (value << 15) & 0x0FFE0000UL;
1807 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1808 (value & ~0x0001FFFFUL & ~mask);
1809 env->IBAT[1][nr] = (env->IBAT[1][nr] & 0x0000007B) |
1810 (env->IBAT[1][nr] & ~0x0001FFFF & ~mask);
1811 #if !defined(FLUSH_ALL_TLBS)
1812 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1813 #else
1814 tlb_flush(env, 1);
1815 #endif
1819 void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
1821 dump_store_bat(env, 'I', 1, nr, value);
1822 env->IBAT[1][nr] = value;
1825 target_ulong do_load_dbatu (CPUPPCState *env, int nr)
1827 return env->DBAT[0][nr];
1830 target_ulong do_load_dbatl (CPUPPCState *env, int nr)
1832 return env->DBAT[1][nr];
1835 void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
1837 target_ulong mask;
1839 dump_store_bat(env, 'D', 0, nr, value);
1840 if (env->DBAT[0][nr] != value) {
1841 /* When storing valid upper BAT, mask BEPI and BRPN
1842 * and invalidate all TLBs covered by this BAT
1844 mask = (value << 15) & 0x0FFE0000UL;
1845 #if !defined(FLUSH_ALL_TLBS)
1846 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1847 #endif
1848 mask = (value << 15) & 0x0FFE0000UL;
1849 env->DBAT[0][nr] = (value & 0x00001FFFUL) |
1850 (value & ~0x0001FFFFUL & ~mask);
1851 env->DBAT[1][nr] = (env->DBAT[1][nr] & 0x0000007B) |
1852 (env->DBAT[1][nr] & ~0x0001FFFF & ~mask);
1853 #if !defined(FLUSH_ALL_TLBS)
1854 do_invalidate_BAT(env, env->DBAT[0][nr], mask);
1855 #else
1856 tlb_flush(env, 1);
1857 #endif
1861 void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
1863 dump_store_bat(env, 'D', 1, nr, value);
1864 env->DBAT[1][nr] = value;
1867 void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
1869 target_ulong mask;
1870 int do_inval;
1872 dump_store_bat(env, 'I', 0, nr, value);
1873 if (env->IBAT[0][nr] != value) {
1874 do_inval = 0;
1875 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1876 if (env->IBAT[1][nr] & 0x40) {
1877 /* Invalidate BAT only if it is valid */
1878 #if !defined(FLUSH_ALL_TLBS)
1879 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1880 #else
1881 do_inval = 1;
1882 #endif
1884 /* When storing valid upper BAT, mask BEPI and BRPN
1885 * and invalidate all TLBs covered by this BAT
1887 env->IBAT[0][nr] = (value & 0x00001FFFUL) |
1888 (value & ~0x0001FFFFUL & ~mask);
1889 env->DBAT[0][nr] = env->IBAT[0][nr];
1890 if (env->IBAT[1][nr] & 0x40) {
1891 #if !defined(FLUSH_ALL_TLBS)
1892 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1893 #else
1894 do_inval = 1;
1895 #endif
1897 #if defined(FLUSH_ALL_TLBS)
1898 if (do_inval)
1899 tlb_flush(env, 1);
1900 #endif
1904 void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
1906 target_ulong mask;
1907 int do_inval;
1909 dump_store_bat(env, 'I', 1, nr, value);
1910 if (env->IBAT[1][nr] != value) {
1911 do_inval = 0;
1912 if (env->IBAT[1][nr] & 0x40) {
1913 #if !defined(FLUSH_ALL_TLBS)
1914 mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL;
1915 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1916 #else
1917 do_inval = 1;
1918 #endif
1920 if (value & 0x40) {
1921 #if !defined(FLUSH_ALL_TLBS)
1922 mask = (value << 17) & 0x0FFE0000UL;
1923 do_invalidate_BAT(env, env->IBAT[0][nr], mask);
1924 #else
1925 do_inval = 1;
1926 #endif
1928 env->IBAT[1][nr] = value;
1929 env->DBAT[1][nr] = value;
1930 #if defined(FLUSH_ALL_TLBS)
1931 if (do_inval)
1932 tlb_flush(env, 1);
1933 #endif
1937 /*****************************************************************************/
1938 /* TLB management */
1939 void ppc_tlb_invalidate_all (CPUPPCState *env)
1941 switch (env->mmu_model) {
1942 case POWERPC_MMU_SOFT_6xx:
1943 case POWERPC_MMU_SOFT_74xx:
1944 ppc6xx_tlb_invalidate_all(env);
1945 break;
1946 case POWERPC_MMU_SOFT_4xx:
1947 case POWERPC_MMU_SOFT_4xx_Z:
1948 ppc4xx_tlb_invalidate_all(env);
1949 break;
1950 case POWERPC_MMU_REAL:
1951 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1952 break;
1953 case POWERPC_MMU_MPC8xx:
1954 /* XXX: TODO */
1955 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
1956 break;
1957 case POWERPC_MMU_BOOKE:
1958 /* XXX: TODO */
1959 cpu_abort(env, "BookE MMU model is not implemented\n");
1960 break;
1961 case POWERPC_MMU_BOOKE_FSL:
1962 /* XXX: TODO */
1963 cpu_abort(env, "BookE MMU model is not implemented\n");
1964 break;
1965 case POWERPC_MMU_32B:
1966 case POWERPC_MMU_601:
1967 #if defined(TARGET_PPC64)
1968 case POWERPC_MMU_620:
1969 case POWERPC_MMU_64B:
1970 #endif /* defined(TARGET_PPC64) */
1971 tlb_flush(env, 1);
1972 break;
1973 default:
1974 /* XXX: TODO */
1975 cpu_abort(env, "Unknown MMU model\n");
1976 break;
1980 void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
1982 #if !defined(FLUSH_ALL_TLBS)
1983 addr &= TARGET_PAGE_MASK;
1984 switch (env->mmu_model) {
1985 case POWERPC_MMU_SOFT_6xx:
1986 case POWERPC_MMU_SOFT_74xx:
1987 ppc6xx_tlb_invalidate_virt(env, addr, 0);
1988 if (env->id_tlbs == 1)
1989 ppc6xx_tlb_invalidate_virt(env, addr, 1);
1990 break;
1991 case POWERPC_MMU_SOFT_4xx:
1992 case POWERPC_MMU_SOFT_4xx_Z:
1993 ppc4xx_tlb_invalidate_virt(env, addr, env->spr[SPR_40x_PID]);
1994 break;
1995 case POWERPC_MMU_REAL:
1996 cpu_abort(env, "No TLB for PowerPC 4xx in real mode\n");
1997 break;
1998 case POWERPC_MMU_MPC8xx:
1999 /* XXX: TODO */
2000 cpu_abort(env, "MPC8xx MMU model is not implemented\n");
2001 break;
2002 case POWERPC_MMU_BOOKE:
2003 /* XXX: TODO */
2004 cpu_abort(env, "BookE MMU model is not implemented\n");
2005 break;
2006 case POWERPC_MMU_BOOKE_FSL:
2007 /* XXX: TODO */
2008 cpu_abort(env, "BookE FSL MMU model is not implemented\n");
2009 break;
2010 case POWERPC_MMU_32B:
2011 case POWERPC_MMU_601:
2012 /* tlbie invalidate TLBs for all segments */
2013 addr &= ~((target_ulong)-1ULL << 28);
2014 /* XXX: this case should be optimized,
2015 * giving a mask to tlb_flush_page
2017 tlb_flush_page(env, addr | (0x0 << 28));
2018 tlb_flush_page(env, addr | (0x1 << 28));
2019 tlb_flush_page(env, addr | (0x2 << 28));
2020 tlb_flush_page(env, addr | (0x3 << 28));
2021 tlb_flush_page(env, addr | (0x4 << 28));
2022 tlb_flush_page(env, addr | (0x5 << 28));
2023 tlb_flush_page(env, addr | (0x6 << 28));
2024 tlb_flush_page(env, addr | (0x7 << 28));
2025 tlb_flush_page(env, addr | (0x8 << 28));
2026 tlb_flush_page(env, addr | (0x9 << 28));
2027 tlb_flush_page(env, addr | (0xA << 28));
2028 tlb_flush_page(env, addr | (0xB << 28));
2029 tlb_flush_page(env, addr | (0xC << 28));
2030 tlb_flush_page(env, addr | (0xD << 28));
2031 tlb_flush_page(env, addr | (0xE << 28));
2032 tlb_flush_page(env, addr | (0xF << 28));
2033 break;
2034 #if defined(TARGET_PPC64)
2035 case POWERPC_MMU_620:
2036 case POWERPC_MMU_64B:
2037 /* tlbie invalidate TLBs for all segments */
2038 /* XXX: given the fact that there are too many segments to invalidate,
2039 * and we still don't have a tlb_flush_mask(env, n, mask) in Qemu,
2040 * we just invalidate all TLBs
2042 tlb_flush(env, 1);
2043 break;
2044 #endif /* defined(TARGET_PPC64) */
2045 default:
2046 /* XXX: TODO */
2047 cpu_abort(env, "Unknown MMU model\n");
2048 break;
2050 #else
2051 ppc_tlb_invalidate_all(env);
2052 #endif
2055 /*****************************************************************************/
2056 /* Special registers manipulation */
2057 #if defined(TARGET_PPC64)
2058 target_ulong ppc_load_asr (CPUPPCState *env)
2060 return env->asr;
2063 void ppc_store_asr (CPUPPCState *env, target_ulong value)
2065 if (env->asr != value) {
2066 env->asr = value;
2067 tlb_flush(env, 1);
2070 #endif
2072 target_ulong do_load_sdr1 (CPUPPCState *env)
2074 return env->sdr1;
2077 void do_store_sdr1 (CPUPPCState *env, target_ulong value)
2079 #if defined (DEBUG_MMU)
2080 if (loglevel != 0) {
2081 fprintf(logfile, "%s: " ADDRX "\n", __func__, value);
2083 #endif
2084 if (env->sdr1 != value) {
2085 /* XXX: for PowerPC 64, should check that the HTABSIZE value
2086 * is <= 28
2088 env->sdr1 = value;
2089 tlb_flush(env, 1);
2093 #if 0 // Unused
2094 target_ulong do_load_sr (CPUPPCState *env, int srnum)
2096 return env->sr[srnum];
2098 #endif
2100 void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
2102 #if defined (DEBUG_MMU)
2103 if (loglevel != 0) {
2104 fprintf(logfile, "%s: reg=%d " ADDRX " " ADDRX "\n",
2105 __func__, srnum, value, env->sr[srnum]);
2107 #endif
2108 if (env->sr[srnum] != value) {
2109 env->sr[srnum] = value;
2110 #if !defined(FLUSH_ALL_TLBS) && 0
2112 target_ulong page, end;
2113 /* Invalidate 256 MB of virtual memory */
2114 page = (16 << 20) * srnum;
2115 end = page + (16 << 20);
2116 for (; page != end; page += TARGET_PAGE_SIZE)
2117 tlb_flush_page(env, page);
2119 #else
2120 tlb_flush(env, 1);
2121 #endif
2124 #endif /* !defined (CONFIG_USER_ONLY) */
2126 target_ulong ppc_load_xer (CPUPPCState *env)
2128 return hreg_load_xer(env);
2131 void ppc_store_xer (CPUPPCState *env, target_ulong value)
2133 hreg_store_xer(env, value);
2136 /* GDBstub can read and write MSR... */
2137 void ppc_store_msr (CPUPPCState *env, target_ulong value)
2139 hreg_store_msr(env, value, 0);
2142 /*****************************************************************************/
2143 /* Exception processing */
2144 #if defined (CONFIG_USER_ONLY)
2145 void do_interrupt (CPUState *env)
2147 env->exception_index = POWERPC_EXCP_NONE;
2148 env->error_code = 0;
2151 void ppc_hw_interrupt (CPUState *env)
2153 env->exception_index = POWERPC_EXCP_NONE;
2154 env->error_code = 0;
2156 #else /* defined (CONFIG_USER_ONLY) */
2157 static always_inline void dump_syscall (CPUState *env)
2159 fprintf(logfile, "syscall r0=" REGX " r3=" REGX " r4=" REGX
2160 " r5=" REGX " r6=" REGX " nip=" ADDRX "\n",
2161 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
2162 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6), env->nip);
2165 /* Note that this function should be greatly optimized
2166 * when called with a constant excp, from ppc_hw_interrupt
2168 static always_inline void powerpc_excp (CPUState *env,
2169 int excp_model, int excp)
2171 target_ulong msr, new_msr, vector;
2172 int srr0, srr1, asrr0, asrr1;
2173 int lpes0, lpes1, lev;
2175 if (0) {
2176 /* XXX: find a suitable condition to enable the hypervisor mode */
2177 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
2178 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
2179 } else {
2180 /* Those values ensure we won't enter the hypervisor mode */
2181 lpes0 = 0;
2182 lpes1 = 1;
2185 if (loglevel & CPU_LOG_INT) {
2186 fprintf(logfile, "Raise exception at " ADDRX " => %08x (%02x)\n",
2187 env->nip, excp, env->error_code);
2189 msr = env->msr;
2190 new_msr = msr;
2191 srr0 = SPR_SRR0;
2192 srr1 = SPR_SRR1;
2193 asrr0 = -1;
2194 asrr1 = -1;
2195 msr &= ~((target_ulong)0x783F0000);
2196 switch (excp) {
2197 case POWERPC_EXCP_NONE:
2198 /* Should never happen */
2199 return;
2200 case POWERPC_EXCP_CRITICAL: /* Critical input */
2201 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2202 switch (excp_model) {
2203 case POWERPC_EXCP_40x:
2204 srr0 = SPR_40x_SRR2;
2205 srr1 = SPR_40x_SRR3;
2206 break;
2207 case POWERPC_EXCP_BOOKE:
2208 srr0 = SPR_BOOKE_CSRR0;
2209 srr1 = SPR_BOOKE_CSRR1;
2210 break;
2211 case POWERPC_EXCP_G2:
2212 break;
2213 default:
2214 goto excp_invalid;
2216 goto store_next;
2217 case POWERPC_EXCP_MCHECK: /* Machine check exception */
2218 if (msr_me == 0) {
2219 /* Machine check exception is not enabled.
2220 * Enter checkstop state.
2222 if (loglevel != 0) {
2223 fprintf(logfile, "Machine check while not allowed. "
2224 "Entering checkstop state\n");
2225 } else {
2226 fprintf(stderr, "Machine check while not allowed. "
2227 "Entering checkstop state\n");
2229 env->halted = 1;
2230 env->interrupt_request |= CPU_INTERRUPT_EXITTB;
2232 new_msr &= ~((target_ulong)1 << MSR_RI);
2233 new_msr &= ~((target_ulong)1 << MSR_ME);
2234 if (0) {
2235 /* XXX: find a suitable condition to enable the hypervisor mode */
2236 new_msr |= (target_ulong)MSR_HVB;
2238 /* XXX: should also have something loaded in DAR / DSISR */
2239 switch (excp_model) {
2240 case POWERPC_EXCP_40x:
2241 srr0 = SPR_40x_SRR2;
2242 srr1 = SPR_40x_SRR3;
2243 break;
2244 case POWERPC_EXCP_BOOKE:
2245 srr0 = SPR_BOOKE_MCSRR0;
2246 srr1 = SPR_BOOKE_MCSRR1;
2247 asrr0 = SPR_BOOKE_CSRR0;
2248 asrr1 = SPR_BOOKE_CSRR1;
2249 break;
2250 default:
2251 break;
2253 goto store_next;
2254 case POWERPC_EXCP_DSI: /* Data storage exception */
2255 #if defined (DEBUG_EXCEPTIONS)
2256 if (loglevel != 0) {
2257 fprintf(logfile, "DSI exception: DSISR=" ADDRX" DAR=" ADDRX "\n",
2258 env->spr[SPR_DSISR], env->spr[SPR_DAR]);
2260 #endif
2261 new_msr &= ~((target_ulong)1 << MSR_RI);
2262 if (lpes1 == 0)
2263 new_msr |= (target_ulong)MSR_HVB;
2264 goto store_next;
2265 case POWERPC_EXCP_ISI: /* Instruction storage exception */
2266 #if defined (DEBUG_EXCEPTIONS)
2267 if (loglevel != 0) {
2268 fprintf(logfile, "ISI exception: msr=" ADDRX ", nip=" ADDRX "\n",
2269 msr, env->nip);
2271 #endif
2272 new_msr &= ~((target_ulong)1 << MSR_RI);
2273 if (lpes1 == 0)
2274 new_msr |= (target_ulong)MSR_HVB;
2275 msr |= env->error_code;
2276 goto store_next;
2277 case POWERPC_EXCP_EXTERNAL: /* External input */
2278 new_msr &= ~((target_ulong)1 << MSR_RI);
2279 if (lpes0 == 1)
2280 new_msr |= (target_ulong)MSR_HVB;
2281 goto store_next;
2282 case POWERPC_EXCP_ALIGN: /* Alignment exception */
2283 new_msr &= ~((target_ulong)1 << MSR_RI);
2284 if (lpes1 == 0)
2285 new_msr |= (target_ulong)MSR_HVB;
2286 /* XXX: this is false */
2287 /* Get rS/rD and rA from faulting opcode */
2288 env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
2289 goto store_current;
2290 case POWERPC_EXCP_PROGRAM: /* Program exception */
2291 switch (env->error_code & ~0xF) {
2292 case POWERPC_EXCP_FP:
2293 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
2294 #if defined (DEBUG_EXCEPTIONS)
2295 if (loglevel != 0) {
2296 fprintf(logfile, "Ignore floating point exception\n");
2298 #endif
2299 env->exception_index = POWERPC_EXCP_NONE;
2300 env->error_code = 0;
2301 return;
2303 new_msr &= ~((target_ulong)1 << MSR_RI);
2304 if (lpes1 == 0)
2305 new_msr |= (target_ulong)MSR_HVB;
2306 msr |= 0x00100000;
2307 if (msr_fe0 == msr_fe1)
2308 goto store_next;
2309 msr |= 0x00010000;
2310 break;
2311 case POWERPC_EXCP_INVAL:
2312 #if defined (DEBUG_EXCEPTIONS)
2313 if (loglevel != 0) {
2314 fprintf(logfile, "Invalid instruction at " ADDRX "\n",
2315 env->nip);
2317 #endif
2318 new_msr &= ~((target_ulong)1 << MSR_RI);
2319 if (lpes1 == 0)
2320 new_msr |= (target_ulong)MSR_HVB;
2321 msr |= 0x00080000;
2322 break;
2323 case POWERPC_EXCP_PRIV:
2324 new_msr &= ~((target_ulong)1 << MSR_RI);
2325 if (lpes1 == 0)
2326 new_msr |= (target_ulong)MSR_HVB;
2327 msr |= 0x00040000;
2328 break;
2329 case POWERPC_EXCP_TRAP:
2330 new_msr &= ~((target_ulong)1 << MSR_RI);
2331 if (lpes1 == 0)
2332 new_msr |= (target_ulong)MSR_HVB;
2333 msr |= 0x00020000;
2334 break;
2335 default:
2336 /* Should never occur */
2337 cpu_abort(env, "Invalid program exception %d. Aborting\n",
2338 env->error_code);
2339 break;
2341 goto store_current;
2342 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
2343 new_msr &= ~((target_ulong)1 << MSR_RI);
2344 if (lpes1 == 0)
2345 new_msr |= (target_ulong)MSR_HVB;
2346 goto store_current;
2347 case POWERPC_EXCP_SYSCALL: /* System call exception */
2348 /* NOTE: this is a temporary hack to support graphics OSI
2349 calls from the MOL driver */
2350 /* XXX: To be removed */
2351 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
2352 env->osi_call) {
2353 if (env->osi_call(env) != 0) {
2354 env->exception_index = POWERPC_EXCP_NONE;
2355 env->error_code = 0;
2356 return;
2359 if (loglevel & CPU_LOG_INT) {
2360 dump_syscall(env);
2362 new_msr &= ~((target_ulong)1 << MSR_RI);
2363 lev = env->error_code;
2364 if (lev == 1 || (lpes0 == 0 && lpes1 == 0))
2365 new_msr |= (target_ulong)MSR_HVB;
2366 goto store_next;
2367 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
2368 new_msr &= ~((target_ulong)1 << MSR_RI);
2369 goto store_current;
2370 case POWERPC_EXCP_DECR: /* Decrementer exception */
2371 new_msr &= ~((target_ulong)1 << MSR_RI);
2372 if (lpes1 == 0)
2373 new_msr |= (target_ulong)MSR_HVB;
2374 goto store_next;
2375 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
2376 /* FIT on 4xx */
2377 #if defined (DEBUG_EXCEPTIONS)
2378 if (loglevel != 0)
2379 fprintf(logfile, "FIT exception\n");
2380 #endif
2381 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2382 goto store_next;
2383 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
2384 #if defined (DEBUG_EXCEPTIONS)
2385 if (loglevel != 0)
2386 fprintf(logfile, "WDT exception\n");
2387 #endif
2388 switch (excp_model) {
2389 case POWERPC_EXCP_BOOKE:
2390 srr0 = SPR_BOOKE_CSRR0;
2391 srr1 = SPR_BOOKE_CSRR1;
2392 break;
2393 default:
2394 break;
2396 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2397 goto store_next;
2398 case POWERPC_EXCP_DTLB: /* Data TLB error */
2399 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2400 goto store_next;
2401 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
2402 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2403 goto store_next;
2404 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
2405 switch (excp_model) {
2406 case POWERPC_EXCP_BOOKE:
2407 srr0 = SPR_BOOKE_DSRR0;
2408 srr1 = SPR_BOOKE_DSRR1;
2409 asrr0 = SPR_BOOKE_CSRR0;
2410 asrr1 = SPR_BOOKE_CSRR1;
2411 break;
2412 default:
2413 break;
2415 /* XXX: TODO */
2416 cpu_abort(env, "Debug exception is not implemented yet !\n");
2417 goto store_next;
2418 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
2419 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2420 goto store_current;
2421 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
2422 /* XXX: TODO */
2423 cpu_abort(env, "Embedded floating point data exception "
2424 "is not implemented yet !\n");
2425 goto store_next;
2426 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
2427 /* XXX: TODO */
2428 cpu_abort(env, "Embedded floating point round exception "
2429 "is not implemented yet !\n");
2430 goto store_next;
2431 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
2432 new_msr &= ~((target_ulong)1 << MSR_RI);
2433 /* XXX: TODO */
2434 cpu_abort(env,
2435 "Performance counter exception is not implemented yet !\n");
2436 goto store_next;
2437 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
2438 /* XXX: TODO */
2439 cpu_abort(env,
2440 "Embedded doorbell interrupt is not implemented yet !\n");
2441 goto store_next;
2442 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
2443 switch (excp_model) {
2444 case POWERPC_EXCP_BOOKE:
2445 srr0 = SPR_BOOKE_CSRR0;
2446 srr1 = SPR_BOOKE_CSRR1;
2447 break;
2448 default:
2449 break;
2451 /* XXX: TODO */
2452 cpu_abort(env, "Embedded doorbell critical interrupt "
2453 "is not implemented yet !\n");
2454 goto store_next;
2455 case POWERPC_EXCP_RESET: /* System reset exception */
2456 new_msr &= ~((target_ulong)1 << MSR_RI);
2457 if (0) {
2458 /* XXX: find a suitable condition to enable the hypervisor mode */
2459 new_msr |= (target_ulong)MSR_HVB;
2461 goto store_next;
2462 case POWERPC_EXCP_DSEG: /* Data segment exception */
2463 new_msr &= ~((target_ulong)1 << MSR_RI);
2464 if (lpes1 == 0)
2465 new_msr |= (target_ulong)MSR_HVB;
2466 goto store_next;
2467 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
2468 new_msr &= ~((target_ulong)1 << MSR_RI);
2469 if (lpes1 == 0)
2470 new_msr |= (target_ulong)MSR_HVB;
2471 goto store_next;
2472 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
2473 srr0 = SPR_HSRR0;
2474 srr1 = SPR_HSRR1;
2475 new_msr |= (target_ulong)MSR_HVB;
2476 goto store_next;
2477 case POWERPC_EXCP_TRACE: /* Trace exception */
2478 new_msr &= ~((target_ulong)1 << MSR_RI);
2479 if (lpes1 == 0)
2480 new_msr |= (target_ulong)MSR_HVB;
2481 goto store_next;
2482 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
2483 srr0 = SPR_HSRR0;
2484 srr1 = SPR_HSRR1;
2485 new_msr |= (target_ulong)MSR_HVB;
2486 goto store_next;
2487 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
2488 srr0 = SPR_HSRR0;
2489 srr1 = SPR_HSRR1;
2490 new_msr |= (target_ulong)MSR_HVB;
2491 goto store_next;
2492 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
2493 srr0 = SPR_HSRR0;
2494 srr1 = SPR_HSRR1;
2495 new_msr |= (target_ulong)MSR_HVB;
2496 goto store_next;
2497 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
2498 srr0 = SPR_HSRR0;
2499 srr1 = SPR_HSRR1;
2500 new_msr |= (target_ulong)MSR_HVB;
2501 goto store_next;
2502 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
2503 new_msr &= ~((target_ulong)1 << MSR_RI);
2504 if (lpes1 == 0)
2505 new_msr |= (target_ulong)MSR_HVB;
2506 goto store_current;
2507 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
2508 #if defined (DEBUG_EXCEPTIONS)
2509 if (loglevel != 0)
2510 fprintf(logfile, "PIT exception\n");
2511 #endif
2512 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2513 goto store_next;
2514 case POWERPC_EXCP_IO: /* IO error exception */
2515 /* XXX: TODO */
2516 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
2517 goto store_next;
2518 case POWERPC_EXCP_RUNM: /* Run mode exception */
2519 /* XXX: TODO */
2520 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
2521 goto store_next;
2522 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
2523 /* XXX: TODO */
2524 cpu_abort(env, "602 emulation trap exception "
2525 "is not implemented yet !\n");
2526 goto store_next;
2527 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
2528 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2529 if (lpes1 == 0) /* XXX: check this */
2530 new_msr |= (target_ulong)MSR_HVB;
2531 switch (excp_model) {
2532 case POWERPC_EXCP_602:
2533 case POWERPC_EXCP_603:
2534 case POWERPC_EXCP_603E:
2535 case POWERPC_EXCP_G2:
2536 goto tlb_miss_tgpr;
2537 case POWERPC_EXCP_7x5:
2538 goto tlb_miss;
2539 case POWERPC_EXCP_74xx:
2540 goto tlb_miss_74xx;
2541 default:
2542 cpu_abort(env, "Invalid instruction TLB miss exception\n");
2543 break;
2545 break;
2546 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
2547 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2548 if (lpes1 == 0) /* XXX: check this */
2549 new_msr |= (target_ulong)MSR_HVB;
2550 switch (excp_model) {
2551 case POWERPC_EXCP_602:
2552 case POWERPC_EXCP_603:
2553 case POWERPC_EXCP_603E:
2554 case POWERPC_EXCP_G2:
2555 goto tlb_miss_tgpr;
2556 case POWERPC_EXCP_7x5:
2557 goto tlb_miss;
2558 case POWERPC_EXCP_74xx:
2559 goto tlb_miss_74xx;
2560 default:
2561 cpu_abort(env, "Invalid data load TLB miss exception\n");
2562 break;
2564 break;
2565 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
2566 new_msr &= ~((target_ulong)1 << MSR_RI); /* XXX: check this */
2567 if (lpes1 == 0) /* XXX: check this */
2568 new_msr |= (target_ulong)MSR_HVB;
2569 switch (excp_model) {
2570 case POWERPC_EXCP_602:
2571 case POWERPC_EXCP_603:
2572 case POWERPC_EXCP_603E:
2573 case POWERPC_EXCP_G2:
2574 tlb_miss_tgpr:
2575 /* Swap temporary saved registers with GPRs */
2576 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
2577 new_msr |= (target_ulong)1 << MSR_TGPR;
2578 hreg_swap_gpr_tgpr(env);
2580 goto tlb_miss;
2581 case POWERPC_EXCP_7x5:
2582 tlb_miss:
2583 #if defined (DEBUG_SOFTWARE_TLB)
2584 if (loglevel != 0) {
2585 const unsigned char *es;
2586 target_ulong *miss, *cmp;
2587 int en;
2588 if (excp == POWERPC_EXCP_IFTLB) {
2589 es = "I";
2590 en = 'I';
2591 miss = &env->spr[SPR_IMISS];
2592 cmp = &env->spr[SPR_ICMP];
2593 } else {
2594 if (excp == POWERPC_EXCP_DLTLB)
2595 es = "DL";
2596 else
2597 es = "DS";
2598 en = 'D';
2599 miss = &env->spr[SPR_DMISS];
2600 cmp = &env->spr[SPR_DCMP];
2602 fprintf(logfile, "6xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2603 " H1 " ADDRX " H2 " ADDRX " %08x\n",
2604 es, en, *miss, en, *cmp,
2605 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
2606 env->error_code);
2608 #endif
2609 msr |= env->crf[0] << 28;
2610 msr |= env->error_code; /* key, D/I, S/L bits */
2611 /* Set way using a LRU mechanism */
2612 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
2613 break;
2614 case POWERPC_EXCP_74xx:
2615 tlb_miss_74xx:
2616 #if defined (DEBUG_SOFTWARE_TLB)
2617 if (loglevel != 0) {
2618 const unsigned char *es;
2619 target_ulong *miss, *cmp;
2620 int en;
2621 if (excp == POWERPC_EXCP_IFTLB) {
2622 es = "I";
2623 en = 'I';
2624 miss = &env->spr[SPR_TLBMISS];
2625 cmp = &env->spr[SPR_PTEHI];
2626 } else {
2627 if (excp == POWERPC_EXCP_DLTLB)
2628 es = "DL";
2629 else
2630 es = "DS";
2631 en = 'D';
2632 miss = &env->spr[SPR_TLBMISS];
2633 cmp = &env->spr[SPR_PTEHI];
2635 fprintf(logfile, "74xx %sTLB miss: %cM " ADDRX " %cC " ADDRX
2636 " %08x\n",
2637 es, en, *miss, en, *cmp, env->error_code);
2639 #endif
2640 msr |= env->error_code; /* key bit */
2641 break;
2642 default:
2643 cpu_abort(env, "Invalid data store TLB miss exception\n");
2644 break;
2646 goto store_next;
2647 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
2648 /* XXX: TODO */
2649 cpu_abort(env, "Floating point assist exception "
2650 "is not implemented yet !\n");
2651 goto store_next;
2652 case POWERPC_EXCP_DABR: /* Data address breakpoint */
2653 /* XXX: TODO */
2654 cpu_abort(env, "DABR exception is not implemented yet !\n");
2655 goto store_next;
2656 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
2657 /* XXX: TODO */
2658 cpu_abort(env, "IABR exception is not implemented yet !\n");
2659 goto store_next;
2660 case POWERPC_EXCP_SMI: /* System management interrupt */
2661 /* XXX: TODO */
2662 cpu_abort(env, "SMI exception is not implemented yet !\n");
2663 goto store_next;
2664 case POWERPC_EXCP_THERM: /* Thermal interrupt */
2665 /* XXX: TODO */
2666 cpu_abort(env, "Thermal management exception "
2667 "is not implemented yet !\n");
2668 goto store_next;
2669 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
2670 new_msr &= ~((target_ulong)1 << MSR_RI);
2671 if (lpes1 == 0)
2672 new_msr |= (target_ulong)MSR_HVB;
2673 /* XXX: TODO */
2674 cpu_abort(env,
2675 "Performance counter exception is not implemented yet !\n");
2676 goto store_next;
2677 case POWERPC_EXCP_VPUA: /* Vector assist exception */
2678 /* XXX: TODO */
2679 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
2680 goto store_next;
2681 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
2682 /* XXX: TODO */
2683 cpu_abort(env,
2684 "970 soft-patch exception is not implemented yet !\n");
2685 goto store_next;
2686 case POWERPC_EXCP_MAINT: /* Maintenance exception */
2687 /* XXX: TODO */
2688 cpu_abort(env,
2689 "970 maintenance exception is not implemented yet !\n");
2690 goto store_next;
2691 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
2692 /* XXX: TODO */
2693 cpu_abort(env, "Maskable external exception "
2694 "is not implemented yet !\n");
2695 goto store_next;
2696 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
2697 /* XXX: TODO */
2698 cpu_abort(env, "Non maskable external exception "
2699 "is not implemented yet !\n");
2700 goto store_next;
2701 default:
2702 excp_invalid:
2703 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
2704 break;
2705 store_current:
2706 /* save current instruction location */
2707 env->spr[srr0] = env->nip - 4;
2708 break;
2709 store_next:
2710 /* save next instruction location */
2711 env->spr[srr0] = env->nip;
2712 break;
2714 /* Save MSR */
2715 env->spr[srr1] = msr;
2716 /* If any alternate SRR register are defined, duplicate saved values */
2717 if (asrr0 != -1)
2718 env->spr[asrr0] = env->spr[srr0];
2719 if (asrr1 != -1)
2720 env->spr[asrr1] = env->spr[srr1];
2721 /* If we disactivated any translation, flush TLBs */
2722 if (new_msr & ((1 << MSR_IR) | (1 << MSR_DR)))
2723 tlb_flush(env, 1);
2724 /* reload MSR with correct bits */
2725 new_msr &= ~((target_ulong)1 << MSR_EE);
2726 new_msr &= ~((target_ulong)1 << MSR_PR);
2727 new_msr &= ~((target_ulong)1 << MSR_FP);
2728 new_msr &= ~((target_ulong)1 << MSR_FE0);
2729 new_msr &= ~((target_ulong)1 << MSR_SE);
2730 new_msr &= ~((target_ulong)1 << MSR_BE);
2731 new_msr &= ~((target_ulong)1 << MSR_FE1);
2732 new_msr &= ~((target_ulong)1 << MSR_IR);
2733 new_msr &= ~((target_ulong)1 << MSR_DR);
2734 #if 0 /* Fix this: not on all targets */
2735 new_msr &= ~((target_ulong)1 << MSR_PMM);
2736 #endif
2737 new_msr &= ~((target_ulong)1 << MSR_LE);
2738 if (msr_ile)
2739 new_msr |= (target_ulong)1 << MSR_LE;
2740 else
2741 new_msr &= ~((target_ulong)1 << MSR_LE);
2742 /* Jump to handler */
2743 vector = env->excp_vectors[excp];
2744 if (vector == (target_ulong)-1ULL) {
2745 cpu_abort(env, "Raised an exception without defined vector %d\n",
2746 excp);
2748 vector |= env->excp_prefix;
2749 #if defined(TARGET_PPC64)
2750 if (excp_model == POWERPC_EXCP_BOOKE) {
2751 if (!msr_icm) {
2752 new_msr &= ~((target_ulong)1 << MSR_CM);
2753 vector = (uint32_t)vector;
2754 } else {
2755 new_msr |= (target_ulong)1 << MSR_CM;
2757 } else {
2758 if (!msr_isf) {
2759 new_msr &= ~((target_ulong)1 << MSR_SF);
2760 vector = (uint32_t)vector;
2761 } else {
2762 new_msr |= (target_ulong)1 << MSR_SF;
2765 #endif
2766 /* XXX: we don't use hreg_store_msr here as already have treated
2767 * any special case that could occur. Just store MSR and update hflags
2769 env->msr = new_msr & env->msr_mask;
2770 hreg_compute_hflags(env);
2771 env->nip = vector;
2772 /* Reset exception state */
2773 env->exception_index = POWERPC_EXCP_NONE;
2774 env->error_code = 0;
2777 void do_interrupt (CPUState *env)
2779 powerpc_excp(env, env->excp_model, env->exception_index);
2782 void ppc_hw_interrupt (CPUPPCState *env)
2784 int hdice;
2786 #if 0
2787 if (loglevel & CPU_LOG_INT) {
2788 fprintf(logfile, "%s: %p pending %08x req %08x me %d ee %d\n",
2789 __func__, env, env->pending_interrupts,
2790 env->interrupt_request, (int)msr_me, (int)msr_ee);
2792 #endif
2793 /* External reset */
2794 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
2795 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
2796 powerpc_excp(env, env->excp_model, POWERPC_EXCP_RESET);
2797 return;
2799 /* Machine check exception */
2800 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
2801 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
2802 powerpc_excp(env, env->excp_model, POWERPC_EXCP_MCHECK);
2803 return;
2805 #if 0 /* TODO */
2806 /* External debug exception */
2807 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
2808 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
2809 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DEBUG);
2810 return;
2812 #endif
2813 if (0) {
2814 /* XXX: find a suitable condition to enable the hypervisor mode */
2815 hdice = env->spr[SPR_LPCR] & 1;
2816 } else {
2817 hdice = 0;
2819 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
2820 /* Hypervisor decrementer exception */
2821 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
2822 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
2823 powerpc_excp(env, env->excp_model, POWERPC_EXCP_HDECR);
2824 return;
2827 if (msr_ce != 0) {
2828 /* External critical interrupt */
2829 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
2830 /* Taking a critical external interrupt does not clear the external
2831 * critical interrupt status
2833 #if 0
2834 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
2835 #endif
2836 powerpc_excp(env, env->excp_model, POWERPC_EXCP_CRITICAL);
2837 return;
2840 if (msr_ee != 0) {
2841 /* Watchdog timer on embedded PowerPC */
2842 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
2843 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
2844 powerpc_excp(env, env->excp_model, POWERPC_EXCP_WDT);
2845 return;
2847 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
2848 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
2849 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORCI);
2850 return;
2852 /* Fixed interval timer on embedded PowerPC */
2853 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
2854 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
2855 powerpc_excp(env, env->excp_model, POWERPC_EXCP_FIT);
2856 return;
2858 /* Programmable interval timer on embedded PowerPC */
2859 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
2860 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
2861 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PIT);
2862 return;
2864 /* Decrementer exception */
2865 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
2866 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
2867 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DECR);
2868 return;
2870 /* External interrupt */
2871 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
2872 /* Taking an external interrupt does not clear the external
2873 * interrupt status
2875 #if 0
2876 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
2877 #endif
2878 powerpc_excp(env, env->excp_model, POWERPC_EXCP_EXTERNAL);
2879 return;
2881 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
2882 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
2883 powerpc_excp(env, env->excp_model, POWERPC_EXCP_DOORI);
2884 return;
2886 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
2887 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
2888 powerpc_excp(env, env->excp_model, POWERPC_EXCP_PERFM);
2889 return;
2891 /* Thermal interrupt */
2892 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
2893 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
2894 powerpc_excp(env, env->excp_model, POWERPC_EXCP_THERM);
2895 return;
2899 #endif /* !CONFIG_USER_ONLY */
2901 void cpu_dump_EA (target_ulong EA)
2903 FILE *f;
2905 if (logfile) {
2906 f = logfile;
2907 } else {
2908 f = stdout;
2909 return;
2911 fprintf(f, "Memory access at address " ADDRX "\n", EA);
2914 void cpu_dump_rfi (target_ulong RA, target_ulong msr)
2916 FILE *f;
2918 if (logfile) {
2919 f = logfile;
2920 } else {
2921 f = stdout;
2922 return;
2924 fprintf(f, "Return from exception at " ADDRX " with flags " ADDRX "\n",
2925 RA, msr);
2928 void cpu_ppc_reset (void *opaque)
2930 CPUPPCState *env;
2931 target_ulong msr;
2933 env = opaque;
2934 msr = (target_ulong)0;
2935 if (0) {
2936 /* XXX: find a suitable condition to enable the hypervisor mode */
2937 msr |= (target_ulong)MSR_HVB;
2939 msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
2940 msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
2941 msr |= (target_ulong)1 << MSR_EP;
2942 #if defined (DO_SINGLE_STEP) && 0
2943 /* Single step trace mode */
2944 msr |= (target_ulong)1 << MSR_SE;
2945 msr |= (target_ulong)1 << MSR_BE;
2946 #endif
2947 #if defined(CONFIG_USER_ONLY)
2948 msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
2949 msr |= (target_ulong)1 << MSR_PR;
2950 #else
2951 env->nip = env->hreset_vector | env->excp_prefix;
2952 if (env->mmu_model != POWERPC_MMU_REAL)
2953 ppc_tlb_invalidate_all(env);
2954 #endif
2955 env->msr = msr;
2956 hreg_compute_hflags(env);
2957 env->reserve = (target_ulong)-1ULL;
2958 /* Be sure no exception or interrupt is pending */
2959 env->pending_interrupts = 0;
2960 env->exception_index = POWERPC_EXCP_NONE;
2961 env->error_code = 0;
2962 /* Flush all TLBs */
2963 tlb_flush(env, 1);
2966 CPUPPCState *cpu_ppc_init (const char *cpu_model)
2968 CPUPPCState *env;
2969 const ppc_def_t *def;
2971 def = cpu_ppc_find_by_name(cpu_model);
2972 if (!def)
2973 return NULL;
2975 env = qemu_mallocz(sizeof(CPUPPCState));
2976 if (!env)
2977 return NULL;
2978 cpu_exec_init(env);
2979 env->cpu_model_str = cpu_model;
2980 cpu_ppc_register_internal(env, def);
2981 cpu_ppc_reset(env);
2982 return env;
2985 void cpu_ppc_close (CPUPPCState *env)
2987 /* Should also remove all opcode tables... */
2988 qemu_free(env);