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