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