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