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