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